Pular para conteúdo

OpenTelemetry

Tradução automática

Esta página foi traduzida automaticamente a partir da documentação em inglês, e a página em inglês é a versão de referência. Se algo parecer errado, Traduções explica como avisar.

Seu servidor já é rastreado. Você não precisa adicionar nada.

Todo servidor que você cria emite um span do OpenTelemetry para cada mensagem que processa. Você não escreveu isso e não importa isso. Está lá no momento em que você chama MCPServer(...).

server.py
from mcp.server import MCPServer

mcp = MCPServer("Bookshop")


@mcp.tool()
def search_books(query: str) -> str:
    """Search the catalog by title or author."""
    return f"Found 3 books matching {query!r}."

Esse é um servidor completo e rastreado. Chame search_books e um span é criado para a chamada. O mesmo vale para o Server de baixo nível: o rastreamento vive nos dois.

O que você recebe

Cada mensagem recebida vira um span SERVER com o nome do método e do seu alvo. Então um tools/call para search_books é o span tools/call search_books, e um tools/list simples é apenas tools/list.

Cada span carrega alguns atributos:

  • mcp.method.name e mcp.protocol.version, em todo span.
  • jsonrpc.request.id, em uma requisição (uma notificação não tem).
  • Um handler que lança uma exceção define o status do span como erro. Um resultado de ferramenta com is_error=True também.

E como rastrear uma chamada de ferramenta é algo tão comum de se querer, os spans tools/call falam as convenções semânticas GenAI do OpenTelemetry:

  • gen_ai.operation.name, definido como "execute_tool".
  • gen_ai.tool.name, definido como a ferramenta sendo chamada.

Um span prompts/get recebe gen_ai.prompt.name no mesmo espírito. Os métodos de listagem não carregam chaves gen_ai.*, porque não há nada para nomear.

Tip

Esses atributos GenAI são o motivo pelo qual uma interface de rastreamento agrupa suas chamadas de ferramenta do mesmo jeito que agrupa as de qualquer outro agente. Você ganha esse agrupamento de graça, sem código extra.

Não custa nada até você querer

Aqui está a parte que faz de "ligado por padrão" um padrão confortável.

O SDK depende apenas de opentelemetry-api, a metade leve do OpenTelemetry. Sem nenhum SDK e nenhum exporter instalados, criar um span é um no-op. Então os spans que seu servidor está emitindo agora mesmo não custam quase nada, e ninguém os está coletando.

No dia em que você quiser vê-los, instale a outra metade e aponte-a para algum lugar:

uv add opentelemetry-sdk opentelemetry-exporter-otlp

Configure um exporter do jeito habitual do OpenTelemetry, e cada span que o SDK vinha criando em silêncio se acende. O código do seu servidor não muda. Nem uma linha.

Info

O Pydantic Logfire é um desses backends, e faz a configuração para você: pip install logfire, logfire.configure(), e seus spans MCP aparecem na visualização ao vivo. Ele é construído sobre o OpenTelemetry, então tudo o que vem abaixo também se aplica a ele.

Traces que atravessam a rede

Um trace é mais útil quando acompanha uma requisição do cliente até o servidor, em uma única imagem conectada.

Quando o cliente e o servidor rodam o SDK, essa conexão é automática. O cliente injeta o contexto de trace W3C na requisição, e o servidor o lê de volta, de modo que o span do servidor fica aninhado sob o span do cliente no mesmo trace. Isso é a SEP-414, e você ganha isso sem pedir.

Se a mensagem recebida não carrega contexto de trace, por exemplo uma requisição de um cliente que não é o SDK, o span do servidor simplesmente fica sob o span que já estiver ativo no servidor, em vez de iniciar um trace órfão novo.

Desligando

O rastreamento é um middleware, o primeiro da lista do seu servidor. Se você quer mesmo um servidor que não emite spans, retire-o:

from mcp.server._otel import OpenTelemetryMiddleware

mcp._lowlevel_server.middleware[:] = [
    m for m in mcp._lowlevel_server.middleware if not isinstance(m, OpenTelemetryMiddleware)
]

Warning

Esse import tem um underscore inicial, e isso é de propósito. A classe é provisória, do mesmo jeito que Server.middleware é provisório, então o caminho de import é algo que você deve esperar que mude. Você quase nunca precisa disso: sem um exporter instalado os spans são gratuitos, então a resposta habitual é deixá-los ligados e não instalar um exporter.

Recapitulando

  • Todo MCPServer e todo Server de baixo nível emite um span SERVER por mensagem recebida, por padrão. Você não escreve nada.
  • Os spans carregam mcp.method.name e mcp.protocol.version; tools/call e prompts/get também carregam atributos GenAI para que suas chamadas de ferramenta se agrupem como as de qualquer outro agente.
  • Não custa nada até você instalar um SDK do OpenTelemetry e um exporter, e aí tudo se acende sem nenhuma mudança no seu servidor.
  • O contexto de trace do cliente para o servidor se propaga automaticamente quando os dois lados rodam o SDK.

O que decide se uma requisição chega a rodar é a Autorização.