Langfuse-mcp-server
Servidor MCP para Langfuse — consulta trazas, depura errores, analiza sesiones y prompts desde cualquier agente de IA.
Documentación
Servidor MCP de Langfuse — Java / Spring AI
Un servidor MCP de nivel de producción que conecta cualquier agente de IA compatible con MCP a tus datos de observabilidad de Langfuse.
Consulta traces, depura errores, inspecciona sesiones, gestiona prompts, ejecuta evaluaciones, anota datos y configura modelos — todo mediante lenguaje natural.
Transporte: HTTP Streamable en el puerto 8080, compatible con Cursor, Claude Desktop, VS Code / GitHub Copilot y cualquier cliente MCP que admita transporte HTTP.
¿Por qué este servidor?
| Capacidad | Este servidor | MCP oficial de Langfuse |
|---|---|---|
| Traces y observaciones | ✅ | ❌ |
| Sesiones y usuarios | ✅ | ❌ |
| Seguimiento de excepciones | ✅ | ❌ |
| Gestión de prompts (lectura + escritura) | ✅ | ✅ solo lectura |
| Gestión de datasets y runs | ✅ | ❌ |
| Scores y configuraciones de scores | ✅ | ❌ |
| Colas de anotación | ✅ | ❌ |
| Comentarios | ✅ | ❌ |
| Definiciones de modelos | ✅ | ❌ |
| Conexiones LLM | ✅ | ❌ |
| Introspección de proyectos | ✅ | ❌ |
| Introspección de esquemas | ✅ | ❌ |
| Java / Spring AI | ✅ | ❌ (Python) |
Requisitos previos
- Java 21 o posterior
- Maven 3.9+ (o usa la compilación Docker — no se requiere Maven local)
- Una cuenta de Langfuse con un par de claves API (
public-key+secret-key)
Inicio rápido
# 1. Build
mvn clean package -DskipTests
# 2. Set credentials
export LANGFUSE_PUBLIC_KEY=pk-lf-...
export LANGFUSE_SECRET_KEY=sk-lf-...
export LANGFUSE_HOST=https://cloud.langfuse.com
# 3. Run (Streamable HTTP transport — port 8080)
java -jar target/langfuse-mcp-1.0.0.jar
# 4. Verify
curl http://localhost:8080/actuator/health
# 5. Inspect all tools
npx @modelcontextprotocol/inspector http://localhost:8080/mcp
Obtén las credenciales en Langfuse Cloud → Configuración → Claves API.
¿Langfuse autoalojado? Establece LANGFUSE_HOST con la URL de tu instancia.
Configuración
Toda la configuración se gestiona mediante variables de entorno (o application.yml para anulaciones locales).
| Propiedad | Variable de entorno | Obligatoria | Valor predeterminado | Descripción |
|---|---|---|---|---|
langfuse.public-key | LANGFUSE_PUBLIC_KEY | ✅ | — | Clave pública del proyecto Langfuse |
langfuse.secret-key | LANGFUSE_SECRET_KEY | ✅ | — | Clave secreta del proyecto Langfuse |
langfuse.host | LANGFUSE_HOST | ✅ | — | URL base de Langfuse, p. ej. https://cloud.langfuse.com |
langfuse.timeout | LANGFUSE_TIMEOUT | ❌ | 30s | Tiempo de espera de solicitudes HTTP — formato Duration de Spring, p. ej. 30s, 1m, 90s |
langfuse.read-only | — | ❌ | true | Indicador informativo; las operaciones de escritura están disponibles mediante herramientas específicas |
Manejo de la barra final
LANGFUSE_HOST puede especificarse con o sin barra final — el servidor la normaliza automáticamente.
Configuración del cliente
Cursor (.cursor/mcp.json)
{
"mcpServers": {
"langfuse": {
"url": "http://localhost:8080/mcp"
}
}
}
Claude Desktop (claude_desktop_config.json)
{
"mcpServers": {
"langfuse": {
"url": "http://localhost:8080/mcp"
}
}
}
En macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
VS Code / GitHub Copilot
Modo URL:
{
"github.copilot.chat.mcp.servers": {
"langfuse": {
"url": "http://localhost:8080/mcp"
}
}
}
Modo comando (clientes solo stdio):
{
"github.copilot.chat.mcp.servers": {
"langfuse": {
"command": "java",
"args": ["-jar", "/absolute/path/to/langfuse-mcp-1.0.0.jar"],
"env": {
"LANGFUSE_PUBLIC_KEY": "pk-lf-...",
"LANGFUSE_SECRET_KEY": "sk-lf-...",
"LANGFUSE_HOST": "https://cloud.langfuse.com"
}
}
}
}
Nota: El endpoint MCP es
/mcp(HTTP streamable). El endpoint SSE heredado/sseno lo utiliza este servidor.
Docker
El Dockerfile es una compilación de varias etapas: compila el jar de Spring Boot dentro de Docker y ejecuta el servidor MCP en el puerto 8080. No se necesita instalación local de Maven.
# Build image (compiles inside Docker)
docker build -t langfuse-mcp:latest .
# Run
docker run --rm -p 8080:8080 \
-e LANGFUSE_PUBLIC_KEY=pk-lf-... \
-e LANGFUSE_SECRET_KEY=sk-lf-... \
-e LANGFUSE_HOST=https://cloud.langfuse.com \
langfuse-mcp:latest
Después de que el contenedor se inicie:
| Endpoint | URL |
|---|---|
| Comprobación de estado | http://localhost:8080/actuator/health |
| Ping | http://localhost:8080/ping |
| Endpoint MCP | http://localhost:8080/mcp |
Langfuse ejecutándose en otro contenedor en el mismo host:
-e LANGFUSE_HOST=http://host.docker.internal:3000
Referencia de herramientas (55 en total)
Cada herramienta devuelve un envoltorio ApiResponse<T> coherente:
{ "success": true, "data": { ... }, "timestamp": "2025-01-15T10:30:00Z" }
{ "success": false, "errorCode": "TRACE_NOT_FOUND", "errorMessage": "...", "timestamp": "..." }
Las respuestas de listas paginadas envuelven sus elementos en un PagedResponse<T>:
{
"data": [ ... ],
"meta": { "page": 1, "limit": 20, "totalItems": 142, "totalPages": 8 }
}
La paginación se basa en 1 (page tiene como valor predeterminado 1). limit tiene como valor predeterminado 20 y está limitado a 100 cuando se indica. Para paginar los resultados, incrementa page manteniendo limit fijo.
Traces (8 herramientas)
| Herramienta | Descripción |
|---|---|
fetch_traces | Lista paginada de traces. Filtra por userId, name, sessionId, tags, fromTimestamp, toTimestamp. |
fetch_trace | Detalle completo de un único trace, incluidas observaciones anidadas, entrada/salida, metadatos, latencia y uso de tokens. Requiere traceId. |
find_exceptions | Traces cuyo level es igual a ERROR. Admite rango de tiempo y paginación. |
find_exceptions_in_file | Traces de nivel de error cuyos metadatos contienen una subcadena de nombre de archivo determinada. Requiere fileName. |
get_exception_details | Detalle completo de un único trace de error. Requiere traceId. |
get_error_count | Recuento de traces de nivel ERROR en un rango de tiempo (escanea hasta 500 traces). |
delete_trace | Elimina permanentemente un único trace por ID. Irreversible. |
delete_traces | Elimina permanentemente varios traces. Pasa una lista separada por comas de IDs de traces. Irreversible. |
Sesiones (3 herramientas)
| Herramienta | Descripción |
|---|---|
fetch_sessions | Lista paginada de sesiones con filtro opcional de rango de tiempo. |
get_session_details | Detalle completo de la sesión, incluidos todos sus traces. Requiere sessionId. |
get_user_sessions | Todas las sesiones de un usuario específico con paginación. Requiere userId. |
Prompts (5 herramientas)
| Herramienta | Descripción |
|---|---|
list_prompts | Lista paginada de todos los prompts del proyecto. |
get_prompt | Obtiene un prompt por nombre. Opcionalmente, fija un número de version o un label (p. ej. production, staging). |
create_prompt | Crea un nuevo prompt o añade una nueva versión a un prompt existente. type es text (cadena simple) o chat (matriz JSON de mensajes {role, content}). Admite labels y tags separados por comas. |
delete_prompt | Elimina versiones de prompts por nombre. Limita a un label o version específicos; omite ambos para eliminar todas las versiones. Irreversible. |
update_prompt_labels | Reemplaza el conjunto completo de etiquetas en una versión específica de prompt. Proporciona una cadena vacía para eliminar todas las etiquetas. La etiqueta latest está reservada por Langfuse. |
Datasets (7 herramientas)
| Herramienta | Descripción |
|---|---|
list_datasets | Lista paginada de todos los datasets de evaluación. |
get_dataset | Obtiene un dataset por nombre exacto. |
create_dataset | Crea un nuevo dataset. Opcionalmente, proporciona description, metadataJson, inputSchemaJson y expectedOutputSchemaJson (todos como cadenas JSON). |
list_dataset_items | Lista paginada de elementos de un dataset. Requiere datasetName. |
get_dataset_item | Obtiene un único elemento de dataset por ID. |
create_dataset_item | Crea o actualiza un elemento de dataset. Opcionalmente, vincula a un sourceTraceId o sourceObservationId. Admite itemId para semántica de actualización. |
delete_dataset_item | Elimina permanentemente un elemento de dataset por ID. Irreversible. |
Runs de datasets (5 herramientas)
| Herramienta | Descripción |
|---|---|
list_dataset_runs | Lista paginada de runs de experimentos para un dataset. Requiere datasetName. |
get_dataset_run | Detalle completo del run, incluidos todos sus elementos. Requiere datasetName y runName. |
delete_dataset_run | Elimina un run y todos sus elementos. Irreversible. Requiere datasetName y runName. |
list_dataset_run_items | Lista paginada de elementos de un run. Requiere datasetId y runName. |
create_dataset_run_item | Crea un elemento de run que vincula un elemento de dataset a un trace/observación. Crea el run automáticamente si aún no existe. |
Métricas (1 herramienta)
| Herramienta | Descripción |
|---|---|
get_cost_metrics | Consulta análisis de coste, tokens, latencia y uso de Langfuse mediante la API de Métricas v1. Refleja: GET /api/public/metrics?query=. Pasa la consulta completa como una cadena JSON. Toda la agregación se realiza en el servidor. |
Esta herramienta acepta un único parámetro obligatorio query que debe ser una cadena serializada en JSON que coincida con el esquema de la API de Métricas. Ejemplos (pásalos como una única cadena JSON):
-
Coste total de los últimos 7 días:
{"view":"traces","metrics":[{"measure":"totalCost","aggregation":"sum"}],"fromTimestamp":"2026-03-18T00:00:00Z","toTimestamp":"2026-03-25T23:59:59Z"}
-
Tendencia de coste diario de esta semana:
{"view":"traces","metrics":[{"measure":"totalCost","aggregation":"sum"},{"measure":"count","aggregation":"count"}],"timeDimension":{"granularity":"day"},"fromTimestamp":"2026-03-18T00:00:00Z","toTimestamp":"2026-03-25T23:59:59Z"}
-
Coste por modelo:
{"view":"observations","dimensions":[{"field":"providedModelName"}],"metrics":[{"measure":"totalCost","aggregation":"sum"},{"measure":"totalTokens","aggregation":"sum"}],"fromTimestamp":"2026-03-18T00:00:00Z","toTimestamp":"2026-03-25T23:59:59Z"}
-
Coste para un usuario específico:
{"view":"traces","metrics":[{"measure":"totalCost","aggregation":"sum"}],"filters":[{"column":"userId","operator":"=","value":"user-123","type":"string"}],"fromTimestamp":"2026-03-18T00:00:00Z","toTimestamp":"2026-03-25T23:59:59Z"}
-
Solo entorno de producción:
filters: [{"column":"environment","operator":"=","value":"production","type":"string"}]
Scores (6 herramientas)
| Herramienta | Descripción |
|---|---|
get_scores | Lista paginada de scores de evaluación. Filtra por traceId, observationId, name, dataType (NUMERIC|CATEGORICAL|BOOLEAN) y rango de tiempo. |
get_score | Obtiene un único score por ID. |
get_score_configs | Lista paginada de esquemas de configuración de scores. |
get_score_config | Obtiene una única configuración de score por ID. |
create_score_config | Crea una configuración de score. NUMERIC admite minValue/maxValue opcionales. CATEGORICAL acepta una matriz categoriesJson de objetos {label, value}. |
update_score_config | Actualiza una configuración de score existente. Opcionalmente, establece isArchived para archivarla. |
Colas de anotación (8 herramientas)
| Herramienta | Descripción |
|---|---|
list_annotation_queues | Lista paginada de colas de anotación. |
get_annotation_queue | Obtiene una única cola por ID. |
create_annotation_queue | Crea una cola para revisión humana en el circuito. Opcionalmente, vincula un scoreConfigId. |
list_annotation_queue_items | Lista paginada de elementos de una cola. Opcionalmente, filtra por status (PENDING|COMPLETED). Requiere queueId. |
get_annotation_queue_item | Obtiene un elemento específico de cola por queueId y itemId. |
create_annotation_queue_item | Añade un trace, observación o sesión a una cola para revisión. objectType es TRACE, OBSERVATION o SESSION. |
update_annotation_queue_item | Actualiza el estado de un elemento de cola (PENDING|COMPLETED). |
delete_annotation_queue_item | Elimina un elemento de una cola. Irreversible. |
Comentarios (3 herramientas)
| Herramienta | Descripción |
|---|---|
get_comments | Lista paginada de comentarios. Opcionalmente, filtra por objectType (TRACE|OBSERVATION) y objectId. |
get_comment | Obtiene un único comentario por ID. |
create_comment | Adjunta un comentario a un trace, observación, sesión o prompt. Valores de objectType: TRACE, OBSERVATION, SESSION, PROMPT. |
Modelos (4 herramientas)
| Herramienta | Descripción |
|---|---|
list_models | Lista paginada de todas las definiciones de modelos (gestionados por Langfuse y personalizados). |
get_model | Obtiene una definición de modelo por ID. |
create_model | Crea un modelo personalizado para el seguimiento de costes. Requiere modelName, matchPattern (regex) y unit (TOKENS|CHARACTERS|MILLISECONDS|SECONDS|IMAGES|REQUESTS). Opcionalmente, establece precios en USD por unidad. |
delete_model | Elimina una definición de modelo personalizado. Los modelos gestionados por Langfuse no se pueden eliminar. Irreversible. |
Conexiones LLM (2 herramientas)
| Herramienta | Descripción |
|---|---|
list_llm_connections | Lista paginada de conexiones de proveedores de LLM (las claves secretas están enmascaradas en la respuesta). |
upsert_llm_connection | Crea o actualiza una conexión de proveedor por nombre de provider (p. ej., openai, anthropic, azure, google). Realiza upsert por proveedor: si ya existe una conexión, se actualiza. |
Proyecto (1 herramienta)
| Herramienta | Descripción |
|---|---|
get_projects_for_api_key | Devuelve el/los proyecto(s) visibles para la clave API configurada. Útil para confirmar credenciales y metadatos del proyecto. |
Usuarios (1 herramienta)
| Herramienta | Descripción |
|---|---|
get_user_traces | Todos los traces para un ID de usuario específico de Langfuse con paginación. Requiere userId. |
Esquema (1 herramienta)
| Herramienta | Descripción |
|---|---|
get_data_schema | Devuelve el modelo de datos completo de Langfuse: todos los tipos de entidad, campos y valores de enumeración válidos. Llama a esto primero para comprender las estructuras de datos disponibles antes de ejecutar consultas. |
Arquitectura
MCP Client (Cursor / Claude Desktop / Copilot / other)
│ Streamable HTTP transport (/mcp)
▼
Tool class (@McpTool — validates required params, delegates to service)
▼
Service interface + impl (business logic, filtering, error mapping)
▼
LangfuseApiClient (HTTP gateway — GET / POST / PATCH / DELETE, typed exceptions)
▼
Langfuse Public REST API
La arquitectura está estrictamente en capas:
client/— límite de integración con Langfuse: HTTP con autenticación básica (Apache HttpComponents 5), excepciones tipadas,UriComponentsBuilderpara parámetros de consultaservice/— lógica de dominio: filtrado, mapeo, paginación, traducción de errores aApiResponsetools/— superficie MCP: descripciones amigables para agentes, validación de parámetros, delegación a servicios- Spring Boot — solo envoltorio de ejecución y transporte
Cliente API
LangfuseApiClient admite cuatro métodos HTTP. Todos los métodos lanzan LangfuseApiException o ResourceNotFoundException en caso de error, que la capa de servicio convierte en respuestas estructuradas de ApiResponse.error(...) — los agentes nunca ven trazas de pila sin procesar.
| Método | Se usa para |
|---|---|
GET | Todas las operaciones de lectura |
POST | Operaciones de creación |
PATCH | Operaciones de actualización |
DELETE | Operaciones de eliminación |
Estructura de Paquetes
com.langfuse.mcp
├── LangfuseMcpApplication.java @SpringBootApplication @ConfigurationPropertiesScan
├── config/
│ ├── LangfuseProperties.java @ConfigurationProperties — publicKey, secretKey, host, timeout, readOnly
│ ├── LangfuseClientConfig.java RestClient bean — Basic-Auth, Apache HttpComponents 5, configurable timeout
│ └── JacksonConfig.java Primary ObjectMapper (JSR310, ignore unknown fields)
├── client/
│ └── LangfuseApiClient.java HTTP gateway (GET/POST/PATCH/DELETE); typed exceptions; UriComponentsBuilder queries
├── controller/
│ └── PingController.java GET /ping → {"status":"ok"}
├── exception/
│ ├── LangfuseApiException.java Wraps HTTP/connectivity errors — statusCode + endpoint
│ └── ResourceNotFoundException.java Thrown on HTTP 404
├── dto/
│ ├── common/ ApiResponse · PagedResponse · PaginationMeta
│ ├── request/ Filter/get request classes (12 classes)
│ └── response/ Response classes (19 classes — JsonNode for open-schema fields)
├── service/ Interfaces (15): Trace · Session · Prompt · PromptWrite · Dataset · DatasetRun
│ │ · Score · AnnotationQueue · Comment · Model · LlmConnection · Project · User · Schema · CostMetrics
│ └── impl/ *ServiceImpl (15) — business logic, filtering, error mapping
├── tools/ @McpTool classes (15) — param validation, delegation, agent-friendly descriptions
│ ├── TraceTools.java (8 tools)
│ ├── SessionTools.java (3 tools)
│ ├── PromptTools.java (2 tools)
│ ├── PromptWriteTools.java (3 tools)
│ ├── DatasetTools.java (7 tools)
│ ├── DatasetRunTools.java (5 tools)
│ ├── ScoreTools.java (6 tools)
│ ├── AnnotationQueueTools.java (8 tools)
│ ├── CommentTools.java (3 tools)
│ ├── ModelTools.java (4 tools)
│ ├── LlmConnectionTools.java (2 tools)
│ ├── ProjectTools.java (1 tool)
│ ├── UserTools.java (1 tool)
│ ├── SchemaTools.java (1 tool)
│ └── CostMetricsTools.java (1 tool)
└── util/
└── JsonPageMapper.java Centralised JSON → PagedResponse mapper (no duplication)
Ejecución de Pruebas
mvn test
La cobertura de pruebas incluye:
LangfusePropertiesBindingTest— vinculación de configuración desdeapplication-test.ymly validación a nivel de propiedadPromptWriteServiceImplTest— lógica de servicio para creación/eliminación de prompts y actualización de etiquetasProjectServiceImplTest— mapeo de respuestas de la API de proyectosObservationServiceImplTest— obtención de observaciones y mapeo de camposMetricsServiceImplTest— lógica de agregación de métricas
Las pruebas se ejecutan con spring.ai.mcp.server.enabled=false (configurado en src/test/resources/application-test.yml) para que no se inicie ningún transporte MCP durante la ejecución de las pruebas.
Solución de Problemas
TRACE_FETCH_ERROR: HTTP/1.1 header parser received no bytes
Problema de conectividad — no es un error de código. Verifica:
LANGFUSE_HOSTapunta a una instancia de Langfuse en ejecución- El host es accesible desde el proceso JVM
- Para Docker: usa
host.docker.internalen lugar delocalhost - El esquema coincide con tu servidor (
http://vshttps://) - Confirma que la API está activa:
curl $LANGFUSE_HOST/api/public/health
INVALID_INPUT: <param> is required
No se proporcionó un parámetro requerido. Todos los parámetros de required = true se validan en la capa de herramientas antes de realizar cualquier llamada HTTP.
Tiempos de espera de conexión
Aumenta el tiempo de espera:
export LANGFUSE_TIMEOUT=60s
El agente no puede ver el servidor
- Confirma que el servidor está en ejecución:
curl http://localhost:8080/actuator/health - Confirma que el endpoint MCP es accesible:
curl http://localhost:8080/ping - Verifica que la URL de configuración del cliente apunte a
http://localhost:8080/mcp - Inspecciona todas las herramientas disponibles:
npx @modelcontextprotocol/inspector http://localhost:8080/mcp
Los modelos gestionados por Langfuse no se pueden eliminar
delete_model solo funciona para definiciones de modelos personalizados que hayas creado. Para anular el precio de un modelo gestionado por Langfuse, crea un nuevo modelo personalizado con el mismo modelName.