Install
$ agentstack add mcp-drishtantkaushal-langfusemcp ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Langfuse MCP Server
[](https://opensource.org/licenses/MIT) [](https://www.python.org/downloads/)
Model Context Protocol server for Langfuse observability. Query traces, analyze accuracy, detect failures, track costs, debug latency, manage prompts and datasets.
56 tools across data access and analytics. Multi-project support so one instance can serve several Langfuse projects. Works with Claude Code, Codex CLI, Cursor, and any MCP-compatible client.
Why this MCP server?
Comparison with official Langfuse MCP (as of March 2026):
| Capability | This server | Official Langfuse MCP | |---|:---:|:---:| | Traces & Observations | Yes | No | | Sessions & Users | Yes | No | | Exception Tracking | Yes | No | | Prompt Management | Yes | Yes | | Dataset Management | Yes | No | | Annotation Queues | Yes | No | | Scores v2 API | Yes | No | | Score Write-back | Yes | No | | Multi-project support | Yes | No | | Accuracy Metrics | Yes | No | | Failure Detection | Yes | No | | Token Percentiles | Yes | No | | Cost Breakdown | Yes | No | | Latency Analysis | Yes | No | | Session Analytics | Yes | No | | Context Breach Scanning | Yes | No | | User Group Aggregation | Yes | No |
The official MCP focuses on prompt management. This server provides a full observability and analytics toolkit — traces, observations, sessions, scores, exceptions, prompts, datasets, annotation queues, plus 9 built-in analytics tools that compute insights server-side and return LLM-sized summaries. Multi-project routing lets a single instance serve several Langfuse projects behind one connector URL.
Quick Start
1. Get your API keys
- Langfuse Cloud: cloud.langfuse.com → Settings → API Keys
- Self-hosted: Your Langfuse instance → Settings → API Keys. Set
LANGFUSE_HOSTto your instance URL (e.g.,https://langfuse.yourcompany.com)
2. Add the MCP server
Claude Code
claude mcp add \
-e LANGFUSE_PUBLIC_KEY=pk-lf-... \
-e LANGFUSE_SECRET_KEY=sk-lf-... \
-e LANGFUSE_HOST=https://cloud.langfuse.com \
--scope project \
langfuse-mcp -- uvx langfuse-mcp-server
Codex CLI
codex mcp add langfuse-mcp \
--env LANGFUSE_PUBLIC_KEY=pk-lf-... \
--env LANGFUSE_SECRET_KEY=sk-lf-... \
--env LANGFUSE_HOST=https://cloud.langfuse.com \
-- uvx langfuse-mcp-server
Cursor
Add to .cursor/mcp.json:
{
"mcpServers": {
"langfuse-mcp": {
"command": "uvx",
"args": ["langfuse-mcp-server"],
"env": {
"LANGFUSE_PUBLIC_KEY": "pk-lf-...",
"LANGFUSE_SECRET_KEY": "sk-lf-...",
"LANGFUSE_HOST": "https://cloud.langfuse.com"
}
}
}
}
3. Verify
Restart your CLI, then test with /mcp (Claude Code) or codex mcp list (Codex).
Manual install (alternative to uvx)
pip install langfuse-mcp-server
langfuse-mcp-server
Hosting as a remote service
Run as a long-lived HTTP service so multiple users connect to a single instance — required for Claude.ai custom Connectors, and useful for team-wide access without distributing Langfuse API keys per user.
Enabled via env vars; no code changes.
Minimum setup
MCP_TRANSPORT=streamable-http
MCP_BASE_URL=https://mcp.yourcompany.com
LANGFUSE_PUBLIC_KEY=pk-lf-...
LANGFUSE_SECRET_KEY=sk-lf-...
LANGFUSE_HOST=https://your-langfuse-instance.example
Without OAuth env vars, the endpoint is unauthenticated — suitable only for local testing. See Google OAuth setup below for production.
Docker
A production-ready Dockerfile is checked into the repo (non-root user, pinned base, .dockerignore to prevent secret leakage). Each tagged release auto-publishes a multi-arch image to GitHub Container Registry via [.github/workflows/docker-publish.yml](.github/workflows/docker-publish.yml).
Pull the published image:
docker pull ghcr.io/drishtantkaushal/langfusemcp:latest
Or build from source:
docker build -t langfuse-mcp .
Run (all secrets injected via -e, never baked into the image):
docker run -d \
--name langfuse-mcp \
--restart unless-stopped \
-p 8000:8000 \
-e MCP_TRANSPORT=streamable-http \
-e MCP_BASE_URL=https://mcp.yourcompany.com \
-e LANGFUSE_PUBLIC_KEY=pk-lf-... \
-e LANGFUSE_SECRET_KEY=sk-lf-... \
-e LANGFUSE_HOST=https://cloud.langfuse.com \
-e GOOGLE_CLIENT_ID=... \
-e GOOGLE_CLIENT_SECRET=... \
-e ALLOWED_EMAIL_DOMAINS=yourcompany.com \
ghcr.io/drishtantkaushal/langfusemcp:latest
Reverse proxy
Terminate TLS in front (nginx, Caddy, Cloudflare). MCP endpoint is at /mcp/ (trailing slash). Because responses stream, the proxy must:
- Disable response buffering — nginx:
proxy_buffering off; - Allow read timeout ≥ 5 minutes — some analytics queries legitimately run several minutes
- Speak HTTP/1.1 with keepalive upstream
Google OAuth
In your Google Cloud project:
- APIs & Services → OAuth consent screen
- User type: Internal (restricts sign-in to your Google Workspace domain)
- Scopes:
openid,https://www.googleapis.com/auth/userinfo.email
- Credentials → Create OAuth client ID → Web application
- Authorized redirect URI:
https://{your-base-url}/auth/callback - Copy the Client ID and Client Secret
Set:
GOOGLE_CLIENT_ID=....apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-...
OAuth activates when GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and MCP_BASE_URL are all set. With an Internal consent screen, Google rejects non-Workspace sign-ins at the identity layer — the server never sees those attempts.
Optional email allowlist
For narrower control than "anyone in the Workspace":
# either, or both
ALLOWED_EMAIL_DOMAINS=yourcompany.com
ALLOWED_EMAILS=alice@yourcompany.com,bob@yourcompany.com
When set, every tool call verifies the caller's email_verified claim and checks membership before proceeding. When unset, the server trusts whatever the OAuth provider returns.
Adding to Claude.ai
Once hosted at https://mcp.yourcompany.com:
- Claude.ai → Settings → Connectors → Add custom connector
- Remote MCP server URL:
https://mcp.yourcompany.com/mcp/ - Leave the OAuth Client ID / Secret fields empty — the server uses Dynamic Client Registration; those fields are for a different deployment pattern.
- Click Add → Google sign-in popup → done.
Verifying the deploy
Auth enabled, expect 401:
curl -i -X POST https://mcp.yourcompany.com/mcp/ \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'
OAuth metadata endpoint returns JSON (used by Claude.ai to auto-register):
curl https://mcp.yourcompany.com/.well-known/oauth-authorization-server
Liveness/readiness probe — unauthenticated GET /health returns HTTP 200 with {"status": "ok"}, suitable for Kubernetes probes:
curl -i https://mcp.yourcompany.com/health
Multi-project support
A single server instance can route to multiple Langfuse projects. Every tool accepts an optional project argument; when omitted, the server-configured default is used. Call list_projects to discover what's available.
Configuring projects
Declare each project via indexed env vars. Project names are data, not part of variable names — use whatever scheme you like.
LANGFUSE_PROJECT_1_NAME=production
LANGFUSE_PROJECT_1_PUBLIC_KEY=pk-lf-...
LANGFUSE_PROJECT_1_SECRET_KEY=sk-lf-...
LANGFUSE_PROJECT_1_HOST=https://cloud.langfuse.com
LANGFUSE_PROJECT_2_NAME=staging
LANGFUSE_PROJECT_2_PUBLIC_KEY=pk-lf-...
LANGFUSE_PROJECT_2_SECRET_KEY=sk-lf-...
LANGFUSE_PROJECT_2_HOST=https://cloud.langfuse.com
LANGFUSE_DEFAULT_PROJECT=production
Usage from the client
Claude: "Show me failing traces in production today."
→ fetch_traces(project="production", ...) routed to project 1's credentials.
Claude: "Compare that with staging."
→ fetch_traces(project="staging", ...) routed to project 2's credentials.
Each project has its own cache, rate limiter, and connection pool. Claude.ai sees one connector; users authenticate once via OAuth and can query any configured project within the session.
Single-project (legacy) mode
If LANGFUSE_PROJECT_1_NAME is not set, the server falls back to the legacy LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY / LANGFUSE_HOST vars and registers them as a project called default. Existing deployments keep working without changes.
Configuration
| Env Variable | Default | Description | |---|---|---| | LANGFUSE_PUBLIC_KEY | (required) | Langfuse public API key | | LANGFUSE_SECRET_KEY | (required) | Langfuse secret API key | | LANGFUSE_HOST | https://cloud.langfuse.com | Langfuse instance URL (cloud or self-hosted) | | LANGFUSE_INTERNAL_DOMAINS | "" | Comma-separated internal domains to exclude from analytics (e.g., mycompany.com,test.com). Applies when using group_by='domain'. | | LANGFUSE_MCP_READ_ONLY | false | Disable write operations (score_traces, create_dataset, etc.) | | LANGFUSE_PAGE_LIMIT | 100 | Traces per API page | | LANGFUSE_PROJECT_{N}_NAME | (unset) | Multi-project: name for project N (e.g. production). See [Multi-project](#multi-project-support). | | LANGFUSE_PROJECT_{N}_PUBLIC_KEY | (unset) | Public key for project N. | | LANGFUSE_PROJECT_{N}_SECRET_KEY | (unset) | Secret key for project N. | | LANGFUSE_PROJECT_{N}_HOST | https://cloud.langfuse.com | Host URL for project N. | | LANGFUSE_DEFAULT_PROJECT | first configured | Default project name used when a tool call omits project. | | MCP_TRANSPORT | stdio | stdio or streamable-http. HTTP mode listens on a port instead of stdin/stdout. See [Hosting](#hosting-as-a-remote-service). | | MCP_HOST | 0.0.0.0 | Bind address when MCP_TRANSPORT=streamable-http. | | MCP_PORT | 8000 | Port when MCP_TRANSPORT=streamable-http. | | MCP_BASE_URL | (unset) | Public base URL of the hosted server. Required for Google OAuth. | | GOOGLE_CLIENT_ID | (unset) | Google OAuth client ID. OAuth activates when all three Google vars are set. | | GOOGLE_CLIENT_SECRET | (unset) | Google OAuth client secret. | | ALLOWED_EMAILS | (unset) | Comma-separated emails allowed to call tools. Requires OAuth. | | ALLOWED_EMAIL_DOMAINS | (unset) | Comma-separated email domains allowed to call tools. Requires OAuth. |
Tools
Analytics (9 tools)
Tools that compute insights server-side and return compact summaries. These go beyond raw data access — they aggregate, detect patterns, and compute statistics so the LLM can reason over results without hitting context window limits.
| Tool | Description | Key Parameters | |---|---|---| | aggregate_by_group | Aggregate trace metrics by user group. Returns per-group: trace count, unique sessions, unique users, accuracy rate, average latency, total cost. | group_by (name/userId/domain/tag), time_range, top_n, exclude_internal | | compute_accuracy | Compute accuracy from feedback scores. Accuracy = correct / (correct + incorrect). Supports grouping and time bucketing for trend analysis. | group_by, bucket_by (week/day), score_name, time_range | | detect_failures | Detect LLM output quality failures using pattern matching ("unable to", "I can't", etc.) and negative feedback scores. NOT Python exceptions — use find_exceptions for those. | group_by, include_examples, max_examples, time_range | | compute_token_percentiles | Compute token usage percentiles (TP50/TP90/TP95/TP99) at trace level. Fetches generation observations for accurate per-trace token counts. | group_by, percentiles, time_range | | detect_context_breaches | Scan for traces where any single generation exceeds a token threshold. Catches context window overflow causing degraded LLM performance or silent truncation. | threshold (default 256000), check_per_generation, time_range | | analyze_sessions | Analyze multi-turn session behavior. Returns session count, depth distribution (single vs multi-turn), engagement metrics, and session-level cost/latency. | group_by, time_range | | estimate_costs | Compute cost breakdown using Langfuse's built-in totalCost field (model-aware, computed by Langfuse). Groups by user, agent, or time bucket. | group_by, bucket_by (week/day), time_range | | analyze_latency | Analyze latency distribution at trace level and optionally per LLM generation. Identifies which model is the bottleneck. | group_by, percentiles, include_per_generation, time_range | | score_traces | Write scores back to Langfuse. Use after analysis to annotate traces with findings — tag failures for review, mark high-quality traces for dataset creation. | trace_ids, score_name, score_value, comment |
Data Access (25 tools)
Full Langfuse API coverage for querying and managing your observability data.
Traces
| Tool | Description | |---|---| | fetch_traces | List traces with filters — user ID, name, tags, time range, ordering. Returns paginated results. | | fetch_trace | Get a single trace by ID with full details including all observations (spans, generations, events). | | diff_traces | Compare two traces side-by-side (name, user, latency, cost, tags, release, version). |
Observations
| Tool | Description | |---|---| | fetch_observations | List observations with filters — trace ID, type (GENERATION/SPAN/EVENT), name, time range. | | fetch_observation | Get a single observation by ID. Returns input/output, token usage, model, latency, and cost. |
Sessions
| Tool | Description | |---|---| | fetch_sessions | List sessions with optional time filters. | | get_session_details | Get full details of a session including all its traces. | | get_user_sessions | Get sessions for a specific user. Fetches user's traces and extracts unique sessions. |
Errors
| Tool | Description | |---|---| | find_exceptions | Find observations with error status. For LLM output quality issues, use detect_failures instead. | | get_exception_details | Get full error details for a trace — returns all observations with error status highlighted. | | get_error_count | Get total error count within a time period. |
Scores
| Tool | Description | |---|---| | fetch_scores | List scores/evaluations with filters — trace ID, score name, time range. | | list_scores_v2 | v2 Scores API with richer filters (session ID, dataset run ID, queue ID, config ID, operator/value, etc.). | | get_score_v2 | Get a single score by ID via the v2 Scores API. |
Prompts
| Tool | Description | |---|---| | list_prompts | List all prompts in the project with optional name filter. | | get_prompt | Fetch a specific prompt by name, version, or label. | | get_prompt_unresolved | Fetch a prompt with placeholders/dependencies intact (debugging prompt composition). | | create_text_prompt | Create a new text prompt version with optional labels and model config. | | create_chat_prompt | Create a new chat prompt version with message array and optional config. | | update_prompt_labels | Update labels for a specific prompt version (e.g., promote to "production"). |
Datasets
| Tool | Description | |---|---| | list_datasets | List all datasets in the project. | | get_dataset | Get meta
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: DrishtantKaushal
- Source: DrishtantKaushal/LangfuseMCP
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.