Langfuse-mcp-server
Servidor MCP para Langfuse — consultar traces, depurar erros, analisar sessões e prompts de qualquer agente de IA
Documentação
Langfuse MCP Server — Java / Spring AI
Um servidor MCP de nível de produção que conecta qualquer agente de IA compatível com MCP aos seus dados de observabilidade do Langfuse.
Consulte traces, depure erros, inspecione sessões, gerencie prompts, execute avaliações, anote dados e configure modelos — tudo por meio de linguagem natural.
Transporte: HTTP Streamable na porta 8080, compatível com Cursor, Claude Desktop, VS Code / GitHub Copilot e qualquer cliente MCP que suporte transporte HTTP.
Por que este servidor?
| Recurso | Este servidor | MCP oficial do Langfuse |
|---|---|---|
| Traces e Observações | ✅ | ❌ |
| Sessões e Usuários | ✅ | ❌ |
| Rastreamento de exceções | ✅ | ❌ |
| Gerenciamento de prompts (leitura + escrita) | ✅ | ✅ somente leitura |
| Gerenciamento de datasets e execuções | ✅ | ❌ |
| Scores e configurações de score | ✅ | ❌ |
| Filas de anotação | ✅ | ❌ |
| Comentários | ✅ | ❌ |
| Definições de modelo | ✅ | ❌ |
| Conexões LLM | ✅ | ❌ |
| Introspecção de projeto | ✅ | ❌ |
| Introspecção de esquema | ✅ | ❌ |
| Java / Spring AI | ✅ | ❌ (Python) |
Pré-requisitos
- Java 21 ou posterior
- Maven 3.9+ (ou use o build Docker — não é necessário Maven local)
- Uma conta Langfuse com um par de chaves de API (
public-key+secret-key)
Início 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
Obtenha as credenciais em Langfuse Cloud → Settings → API Keys.
Langfuse auto-hospedado? Defina LANGFUSE_HOST para a URL da sua instância.
Configuração
Toda a configuração é controlada por variáveis de ambiente (ou application.yml para substituições locais).
| Propriedade | Variável de ambiente | Obrigatório | Padrão | Descrição |
|---|---|---|---|---|
langfuse.public-key | LANGFUSE_PUBLIC_KEY | ✅ | — | Chave pública do projeto Langfuse |
langfuse.secret-key | LANGFUSE_SECRET_KEY | ✅ | — | Chave secreta do projeto Langfuse |
langfuse.host | LANGFUSE_HOST | ✅ | — | URL base do Langfuse, ex.: https://cloud.langfuse.com |
langfuse.timeout | LANGFUSE_TIMEOUT | ❌ | 30s | Tempo limite de requisição HTTP — formato Spring Duration, ex.: 30s, 1m, 90s |
langfuse.read-only | — | ❌ | true | Sinalizador informativo; operações de escrita estão disponíveis por meio de ferramentas específicas |
Tratamento de barra final
LANGFUSE_HOST pode ser especificado com ou sem barra final — o servidor a normaliza automaticamente.
Configuração do 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"
}
}
}
No 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 somente 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: O endpoint MCP é
/mcp(HTTP streamable). O endpoint SSE legado/ssenão é usado por este servidor.
Docker
O Dockerfile é um build multi-estágio: ele compila o jar do Spring Boot dentro do Docker e executa o servidor MCP na porta 8080. Não é necessária instalação local do 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
Após o contêiner iniciar:
| Endpoint | URL |
|---|---|
| Verificação de saúde | http://localhost:8080/actuator/health |
| Ping | http://localhost:8080/ping |
| Endpoint MCP | http://localhost:8080/mcp |
Langfuse executando em outro contêiner no mesmo host:
-e LANGFUSE_HOST=http://host.docker.internal:3000
Referência de Ferramentas (55 no total)
Cada ferramenta retorna um envelope ApiResponse<T> consistente:
{ "success": true, "data": { ... }, "timestamp": "2025-01-15T10:30:00Z" }
{ "success": false, "errorCode": "TRACE_NOT_FOUND", "errorMessage": "...", "timestamp": "..." }
Respostas de listas paginadas envolvem seus itens em um PagedResponse<T>:
{
"data": [ ... ],
"meta": { "page": 1, "limit": 20, "totalItems": 142, "totalPages": 8 }
}
A paginação é baseada em 1 (page tem como padrão 1). limit tem como padrão 20 e é limitado a 100 quando indicado. Para navegar pelos resultados, incremente page mantendo limit fixo.
Traces (8 ferramentas)
| Ferramenta | Descrição |
|---|---|
fetch_traces | Lista paginada de traces. Filtre por userId, name, sessionId, tags, fromTimestamp, toTimestamp. |
fetch_trace | Detalhes completos de um único trace, incluindo observações aninhadas, entrada/saída, metadados, latência e uso de tokens. Requer traceId. |
find_exceptions | Traces cujo level é igual a ERROR. Suporta intervalo de tempo e paginação. |
find_exceptions_in_file | Traces de nível de erro cujos metadados contêm uma substring de nome de arquivo. Requer fileName. |
get_exception_details | Detalhes completos de um único trace de erro. Requer traceId. |
get_error_count | Contagem de traces de nível ERROR em um intervalo de tempo (verifica até 500 traces). |
delete_trace | Exclui permanentemente um único trace por ID. Irreversível. |
delete_traces | Exclui permanentemente vários traces. Passe uma lista separada por vírgulas de IDs de trace. Irreversível. |
Sessões (3 ferramentas)
| Ferramenta | Descrição |
|---|---|
fetch_sessions | Lista paginada de sessões com filtro opcional de intervalo de tempo. |
get_session_details | Detalhes completos da sessão, incluindo todos os seus traces. Requer sessionId. |
get_user_sessions | Todas as sessões de um usuário específico com paginação. Requer userId. |
Prompts (5 ferramentas)
| Ferramenta | Descrição |
|---|---|
list_prompts | Lista paginada de todos os prompts do projeto. |
get_prompt | Busca um prompt por nome. Opcionalmente, fixe em um número de version ou em um label (ex.: production, staging). |
create_prompt | Cria um novo prompt ou adiciona uma nova versão a um prompt existente. type é text (string simples) ou chat (array JSON de mensagens {role, content}). Suporta labels e tags separados por vírgulas. |
delete_prompt | Exclui versões de prompt por nome. Escopo para um label ou version específico; omita ambos para excluir todas as versões. Irreversível. |
update_prompt_labels | Substitui o conjunto completo de rótulos em uma versão específica de prompt. Forneça uma string vazia para remover todos os rótulos. O rótulo latest é reservado pelo Langfuse. |
Datasets (7 ferramentas)
| Ferramenta | Descrição |
|---|---|
list_datasets | Lista paginada de todos os datasets de avaliação. |
get_dataset | Busca um dataset pelo nome exato. |
create_dataset | Cria um novo dataset. Opcionalmente, forneça description, metadataJson, inputSchemaJson e expectedOutputSchemaJson (todos como strings JSON). |
list_dataset_items | Lista paginada de itens em um dataset. Requer datasetName. |
get_dataset_item | Busca um único item de dataset por ID. |
create_dataset_item | Cria ou faz upsert de um item de dataset. Opcionalmente, vincule a um sourceTraceId ou sourceObservationId. Suporta itemId para semântica de upsert. |
delete_dataset_item | Exclui permanentemente um item de dataset por ID. Irreversível. |
Execuções de Dataset (5 ferramentas)
| Ferramenta | Descrição |
|---|---|
list_dataset_runs | Lista paginada de execuções de experimento para um dataset. Requer datasetName. |
get_dataset_run | Detalhes completos da execução, incluindo todos os itens da execução. Requer datasetName e runName. |
delete_dataset_run | Exclui uma execução e todos os seus itens. Irreversível. Requer datasetName e runName. |
list_dataset_run_items | Lista paginada de itens em uma execução. Requer datasetId e runName. |
create_dataset_run_item | Cria um item de execução vinculando um item de dataset a um trace/observação. Cria a execução automaticamente se ela ainda não existir. |
Métricas (1 ferramenta)
| Ferramenta | Descrição |
|---|---|
get_cost_metrics | Consulte análises de custo, tokens, latência e uso do Langfuse por meio da Metrics API v1. Espelha: GET /api/public/metrics?query=. Passe a consulta completa como uma string JSON. Toda a agregação é feita no servidor. |
Esta ferramenta aceita um único parâmetro obrigatório query que deve ser uma string serializada em JSON correspondente ao esquema da Metrics API. Exemplos (passe-os como uma única string JSON):
-
Custo total nos últimos 7 dias:
{"view":"traces","metrics":[{"measure":"totalCost","aggregation":"sum"}],"fromTimestamp":"2026-03-18T00:00:00Z","toTimestamp":"2026-03-25T23:59:59Z"}
-
Tendência diária de custo nesta 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"}
-
Custo 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"}
-
Custo para um usuário 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"}
-
Somente ambiente de produção:
filters: [{"column":"environment","operator":"=","value":"production","type":"string"}]
Scores (6 ferramentas)
| Ferramenta | Descrição |
|---|---|
get_scores | Lista paginada de scores de avaliação. Filtre por traceId, observationId, name, dataType (NUMERIC|CATEGORICAL|BOOLEAN) e intervalo de tempo. |
get_score | Busca um único score por ID. |
get_score_configs | Lista paginada de esquemas de configuração de score. |
get_score_config | Busca uma única configuração de score por ID. |
create_score_config | Cria uma configuração de score. NUMERIC suporta minValue/maxValue opcionais. CATEGORICAL aceita um array categoriesJson de objetos {label, value}. |
update_score_config | Atualiza uma configuração de score existente. Opcionalmente, defina isArchived para arquivá-la. |
Filas de Anotação (8 ferramentas)
| Ferramenta | Descrição |
|---|---|
list_annotation_queues | Lista paginada de filas de anotação. |
get_annotation_queue | Busca uma única fila por ID. |
create_annotation_queue | Cria uma fila para revisão humana no processo. Opcionalmente, vincule um scoreConfigId. |
list_annotation_queue_items | Lista paginada de itens em uma fila. Opcionalmente, filtre por status (PENDING|COMPLETED). Requer queueId. |
get_annotation_queue_item | Busca um item específico da fila por queueId e itemId. |
create_annotation_queue_item | Adiciona um trace, observação ou sessão a uma fila para revisão. objectType é TRACE, OBSERVATION ou SESSION. |
update_annotation_queue_item | Atualiza o status de um item da fila (PENDING|COMPLETED). |
delete_annotation_queue_item | Remove um item de uma fila. Irreversível. |
Comentários (3 ferramentas)
| Ferramenta | Descrição |
|---|---|
get_comments | Lista paginada de comentários. Opcionalmente, filtre por objectType (TRACE|OBSERVATION) e objectId. |
get_comment | Busca um único comentário por ID. |
create_comment | Anexa um comentário a um trace, observação, sessão ou prompt. Valores de objectType: TRACE, OBSERVATION, SESSION, PROMPT. |
Modelos (4 ferramentas)
| Ferramenta | Descrição |
|---|---|
list_models | Lista paginada de todas as definições de modelo (gerenciadas pelo Langfuse e personalizadas). |
get_model | Busca uma definição de modelo por ID. |
create_model | Cria um modelo personalizado para rastreamento de custos. Requer modelName, matchPattern (regex) e unit (TOKENS|CHARACTERS|MILLISECONDS|SECONDS|IMAGES|REQUESTS). Opcionalmente, defina preços em USD por unidade. |
delete_model | Exclui uma definição de modelo personalizada. Modelos gerenciados pelo Langfuse não podem ser excluídos. Irreversível. |
Conexões LLM (2 ferramentas)
| Ferramenta | Descrição |
|---|---|
list_llm_connections | Lista paginada de conexões de provedores de LLM (as chaves secretas são mascaradas na resposta). |
upsert_llm_connection | Cria ou atualiza uma conexão de provedor pelo nome provider (ex.: openai, anthropic, azure, google). Faz upsert por provedor — se uma conexão já existir, ela é atualizada. |
Projeto (1 ferramenta)
| Ferramenta | Descrição |
|---|---|
get_projects_for_api_key | Retorna o(s) projeto(s) visíveis para a chave de API configurada. Útil para confirmar credenciais e metadados do projeto. |
Usuários (1 ferramenta)
| Ferramenta | Descrição |
|---|---|
get_user_traces | Todos os traces para um ID de usuário Langfuse específico com paginação. Requer userId. |
Esquema (1 ferramenta)
| Ferramenta | Descrição |
|---|---|
get_data_schema | Retorna o modelo de dados completo do Langfuse: todos os tipos de entidade, campos e valores de enum válidos. Chame isso primeiro para entender as estruturas de dados disponíveis antes de executar consultas. |
Arquitetura
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
A arquitetura é estritamente em camadas:
client/— fronteira de integração Langfuse: HTTP com Basic-Auth (Apache HttpComponents 5), exceções tipadas,UriComponentsBuilderpara parâmetros de consultaservice/— lógica de domínio: filtragem, mapeamento, paginação, tradução de erros emApiResponsetools/— superfície MCP: descrições amigáveis para agentes, validação de parâmetros, delegação para serviços- Spring Boot — apenas wrapper de runtime e transporte
Cliente de API
LangfuseApiClient suporta quatro métodos HTTP. Todos os métodos lançam LangfuseApiException ou ResourceNotFoundException em caso de erro, que a camada de serviço converte em respostas estruturadas ApiResponse.error(...) — os agentes nunca veem stack traces brutos.
| Método | Usado para |
|---|---|
GET | Todas as operações de leitura |
POST | Operações de criação |
PATCH | Operações de atualização |
DELETE | Operações de exclusão |
Estrutura de Pacotes
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)
Executando Testes
mvn test
A cobertura de testes inclui:
LangfusePropertiesBindingTest— vinculação de configuração a partir deapplication-test.ymle validação em nível de propriedadePromptWriteServiceImplTest— lógica de serviço para criação / exclusão / atualização de rótulo de promptProjectServiceImplTest— mapeamento de resposta da API de projetoObservationServiceImplTest— busca de observação e mapeamento de camposMetricsServiceImplTest— lógica de agregação de métricas
Os testes são executados com spring.ai.mcp.server.enabled=false (definido em src/test/resources/application-test.yml) para que nenhum transporte MCP seja iniciado durante a execução dos testes.
Solução de Problemas
TRACE_FETCH_ERROR: HTTP/1.1 header parser received no bytes
Problema de conectividade — não é um bug de código. Verifique:
LANGFUSE_HOSTaponta para uma instância Langfuse em execução- O host é acessível a partir do processo JVM
- Para Docker: use
host.docker.internalem vez delocalhost - O esquema corresponde ao seu servidor (
http://vshttps://) - Confirme se a API está ativa:
curl $LANGFUSE_HOST/api/public/health
INVALID_INPUT: <param> is required
Um parâmetro obrigatório não foi fornecido. Todos os parâmetros required = true são validados na camada de ferramenta antes de qualquer chamada HTTP ser feita.
Timeouts de conexão
Aumente o timeout:
export LANGFUSE_TIMEOUT=60s
O agente não consegue ver o servidor
- Confirme se o servidor está em execução:
curl http://localhost:8080/actuator/health - Confirme se o endpoint MCP está acessível:
curl http://localhost:8080/ping - Verifique se a URL de configuração do cliente aponta para
http://localhost:8080/mcp - Inspecione todas as ferramentas disponíveis:
npx @modelcontextprotocol/inspector http://localhost:8080/mcp
Modelos gerenciados pelo Langfuse não podem ser excluídos
delete_model só funciona para definições de modelos personalizados que você criou. Para substituir o preço de um modelo gerenciado pelo Langfuse, crie um novo modelo personalizado com o mesmo modelName.