Back to Langfuse

Langfuse MCP Server

web/src/features/mcp/README.md

3.175.09.0 KB
Original Source

Langfuse MCP Server

Model Context Protocol (MCP) server for Langfuse, enabling AI assistants to interact with Langfuse prompts and read observation data programmatically.

Quick Start (Local Development)

Prerequisites

  • Langfuse instance running locally
  • Project-scoped API key (Public Key + Secret Key)
  • Claude Code or another MCP-compatible client

Steps

  1. Get API Keys

    • Navigate to http://localhost:3000/project/{project-id}/settings
    • Create or copy a project-scoped API key (pk-lf-... and sk-lf-...)
    • Note: Organization-level keys are not supported
  2. Encode Credentials

    bash
    echo -n "pk-lf-xxx:sk-lf-xxx" | base64
    

    Output:

    // Example. Real token will be much longer
    cGstbGYteHh4OnNrLWxmLXh4eA==
    
  3. Add to Claude Code

    bash
    claude mcp add --transport http langfuse http://localhost:3000/api/public/mcp \
        --header "Authorization: Basic {your-base64-token}"
    
  4. Verify prompt tools In Claude Code: List all prompts in the project

  5. Verify observation tools In Claude Code: List recent Langfuse observations


Available Tools

The MCP server provides prompt-management tools and read-only observation tools.

Prompt Tools

  • getPrompt - Fetch a specific prompt by name with optional label or version (fully resolved with dependencies)
  • getPromptUnresolved - Fetch a specific prompt WITHOUT resolving dependencies (useful for prompt composition analysis)
  • listPrompts - List all prompts in the project with filtering (name/label/tag/updatedAt range) and pagination
  • createTextPrompt - Create a new text prompt version
  • createChatPrompt - Create a new chat prompt version (OpenAI-style messages)
  • updatePromptLabels - Add/move labels across prompt versions

Implementation: See /web/src/features/mcp/features/prompts/tools/ for detailed schemas, parameters, and examples for each prompt tool.

Observation Tools

Observation tools read from the events table v2 and are project-scoped to the authenticated API key.

  • listObservations - Find observations in the current project with filters, field projection, and cursor pagination
  • getObservation - Fetch one observation by observation ID
  • getObservationFieldSchema - List fields that can be requested from listObservations and getObservation
  • getObservationFilterSchema - List fields and operators that can be used in listObservations advanced filters
  • getObservationFilterValues - Discover available values for supported filter fields, such as names, types, levels, environments, model names, tags, users, or sessions

Implementation: See /web/src/features/mcp/features/observations/tools/ for detailed schemas and handlers.

Prompt Resolution: getPrompt vs getPromptUnresolved

Langfuse supports prompt composition where prompts can reference other prompts via dependency tags like @@@langfusePrompt:name=xxx|label=yyy@@@. The MCP server provides two tools for fetching prompts with different resolution behaviors:

getPrompt (Fully Resolved)

  • Use when: You want the final, executable prompt ready to send to an LLM
  • Behavior: Recursively resolves all dependency tags by fetching and inserting referenced prompts
  • Returns: Final prompt content with all dependencies replaced
  • Example:
    Input:  "You are helpful. @@@langfusePrompt:name=base-rules|label=production@@@"
    Output: "You are helpful. Always be kind and respectful."
    

getPromptUnresolved (Raw)

  • Use when: You want to analyze prompt composition, debug dependencies, or understand the prompt structure
  • Behavior: Returns raw prompt content with dependency tags intact
  • Returns: Original prompt content with @@@langfusePrompt:...@@@ tags preserved
  • Example:
    Input:  "You are helpful. @@@langfusePrompt:name=base-rules|label=production@@@"
    Output: "You are helpful. @@@langfusePrompt:name=base-rules|label=production@@@"
    

Use Cases for getPromptUnresolved:

  • Understanding how prompts compose together (prompt stacking)
  • Debugging dependency chains before execution
  • Analyzing prompt structure and references
  • Building tools that manage prompt composition

Observation Inspection

Observation tools let MCP clients inspect traces at the observation level: generations, spans, events, agent steps, tool calls, model usage, cost, latency, payloads, and metadata.

Typical workflow:

  1. Discover fields: call getObservationFieldSchema
  2. Discover filters: call getObservationFilterSchema
  3. Find observations: call listObservations with time, trace, type, level, environment, or advanced filters
  4. Inspect one observation: call getObservation with the returned observation ID

Field projection controls response size:

  • Omit fields for compact defaults
  • Use fields: ["*"] for all available fields
  • Pass explicit fields such as ["id", "name", "type", "latency", "totalCost"] for focused responses

Payload and metadata fields can be large and may contain sensitive application data. MCP clients should request input, output, metadata, and modelParameters only when needed.


Architecture

Stateless Design

The Langfuse MCP server uses a stateless per-request architecture:

  1. Fresh server instance per request: Each MCP request creates a new server instance
  2. Context captured in closures: Authentication context is captured in handler closures
  3. No session storage: Server is discarded after request completes
  4. No state between requests: Each request is independent

This design:

  • Eliminates session management complexity
  • Prevents state leaks between projects
  • Simplifies authentication (project context derived from API key)

Authentication Flow

1. Client sends request with Authorization header
   ↓
2. API endpoint validates BasicAuth (PUBLIC_KEY:SECRET_KEY)
   ↓
3. Verify API key has project-level scope
   ↓
4. Build ServerContext from API key metadata
   ↓
5. Create fresh MCP server with context in closure
   ↓
6. Handle request (context auto-injected to handlers)
   ↓
7. Discard server instance

ServerContext:

typescript
{
  projectId: "proj-123",      // Auto-injected from API key
  orgId: "org-456",           // Auto-injected from API key
  apiKeyId: "key-789",        // For audit logging
  accessLevel: "project",     // Required for MCP
  publicKey: "pk-lf-..."      // For reference
}

Tool Annotations

Tools include hints for clients about their behavior:

  • readOnlyHint: true: Safe operations that don't modify data (getPrompt, getPromptUnresolved, listPrompts, all observation tools)
  • destructiveHint: true: Operations that create/modify data (createTextPrompt, createChatPrompt, updatePromptLabels)

Clients like Claude Code can use these annotations to:

  • Auto-approve read-only operations
  • Require user confirmation for destructive operations

Audit Logging

All write operations (createTextPrompt, createChatPrompt, updatePromptLabels) automatically create audit log entries with before/after snapshots. Observation tools are read-only and do not create audit log entries.


Connecting Clients

Authentication

All clients require BasicAuth authentication using your Langfuse API keys.

1. Generate Basic Auth Token

Encode your Langfuse API keys (Public Key:Secret Key) to base64:

bash
echo -n "pk-lf-your-public-key:sk-lf-your-secret-key" | base64

This outputs your BasicAuth token (e.g., cGstbGYt...).

2. Choose Your Langfuse URL

Langfuse Cloud:

  • EU Region: https://cloud.langfuse.com
  • US Region: https://us.langfuse.com
  • HIPAA: https://hipaa.langfuse.com

Self-Hosted:

  • Use your domain with HTTPS: https://your-domain.com

Local Development:

  • http://localhost:3000

Claude Code

Register the Langfuse MCP server:

bash
# Langfuse Cloud (EU)
claude mcp add --transport http langfuse https://cloud.langfuse.com/api/public/mcp \
    --header "Authorization: Basic {your-base64-token}"

# Langfuse Cloud (US)
claude mcp add --transport http langfuse https://us.langfuse.com/api/public/mcp \
    --header "Authorization: Basic {your-base64-token}"

# Self-Hosted (HTTPS required)
claude mcp add --transport http langfuse https://your-domain.com/api/public/mcp \
    --header "Authorization: Basic {your-base64-token}"

# Local Development
claude mcp add --transport http langfuse http://localhost:3000/api/public/mcp \
    --header "Authorization: Basic {your-base64-token}"

Cursor

Add to your Cursor MCP settings:

json
{
  "mcp": {
    "servers": {
      "langfuse": {
        "url": "https://cloud.langfuse.com/api/public/mcp",
        "headers": {
          "Authorization": "Basic {your-base64-token}"
        }
      }
    }
  }
}

Replace https://cloud.langfuse.com with your Langfuse URL (see Choose Your Langfuse URL).