Logging
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.
Faça log de uma ferramenta (tool) do mesmo jeito que faz de qualquer outra função Python: com a biblioteca padrão.
O MCP tem uma capacidade de logging no nível do protocolo: um servidor poderia enviar suas mensagens de log para o cliente como notificações, por meio de métodos do objeto Context. A revisão 2026-07-28 da especificação torna essa capacidade obsoleta e não a substitui, por isso esta documentação não a ensina. A lista completa do que foi marcado como obsoleto e do que fazer no lugar está em Funcionalidades obsoletas.
O que você faz no lugar é o que faz em qualquer outro programa Python: a biblioteca padrão.
Uma ferramenta que faz log
import logging
from mcp.server import MCPServer
logger = logging.getLogger(__name__)
mcp = MCPServer("Bookshop")
@mcp.tool()
def search_books(query: str) -> str:
"""Search the catalog by title or author."""
logger.info("Searching for %r", query)
return f"Found 3 books matching {query!r}."
logging.getLogger(__name__)dá a você um logger com o nome do seu módulo. Crie-o uma vez, no topo.- Dentro da ferramenta você chama
logger.info(...)como em qualquer outra função. Nada para injetar, nada para fazerawait, nada específico do MCP.
Check
Chame a ferramenta e olhe o resultado inteiro:
result.content # [TextContent(text="Found 3 books matching 'dune'.")]
result.structured_content # {'result': "Found 3 books matching 'dune'."}
A linha de log não aparece em lugar nenhum. O logging é para você, a pessoa que opera o servidor. O modelo
nunca o vê. Se o modelo precisa ler alguma coisa, faça return dela.
Para onde vai
Para um servidor stdio, essa pergunta importa mais do que o normal. O host iniciou seu servidor como um subprocesso e está lendo mensagens MCP do stdout dele. O erro padrão (stderr) é seu.
A biblioteca padrão já faz a coisa certa: a saída de log vai para sys.stderr por padrão. Suas linhas de logger.info(...) caem no terminal (ou onde quer que o host colete o stderr do subprocesso), e o fluxo do protocolo fica limpo.
Tip
Não use print() em um servidor stdio. print escreve no stdout, e o stdout pertence ao protocolo.
Enquanto serve, o SDK desvia para o stderr o stdout que de fato recebe flush, então ele não consegue corromper a
comunicação, mas um print() em um processo com buffer em bloco costuma ficar sem flush no buffer de sys.stdout
até o interpretador esvaziá-lo na saída, direto no fluxo do protocolo. Mesmo quando é desviada,
a linha cai crua no meio da saída de log, sem nível, sem nome de logger e sem jeito de filtrá-la.
logger.debug("got here") dá o mesmo trabalho de uma linha e vai para o lugar certo.
O nível
Você não precisa chamar logging.basicConfig() por conta própria. Construir um MCPServer já fez isso, com um handler apontado para o erro padrão, no nível que você passa em log_level=, então MCPServer("Bookshop", log_level="DEBUG") é tudo o que precisa para ver suas linhas de logger.debug(...).
O padrão é "INFO".
logging.basicConfig() nunca substitui handlers que já existem. Se você configurar o logging por conta própria antes de criar o servidor, sua configuração vence.
Experimente
Execute o servidor com o MCP Inspector:
uv run mcp dev server.py
Chame search_books na aba Tools. O Inspector mostra o resultado: apenas o valor de retorno. A linha
Searching for 'dune'
foi para o erro padrão: o terminal, não a comunicação com o cliente.
Info
Se o que você quer de verdade é tracing (cada requisição, quanto tempo levou, se falhou), você não quer linhas de log, quer spans. Seu servidor já os emite: o SDK faz tracing de cada mensagem com OpenTelemetry por padrão. Veja OpenTelemetry.
Recapitulando
- A capacidade de logging do protocolo MCP foi tornada obsoleta pela especificação 2026-07-28 e não foi substituída. Não construa em cima dela.
logger = logging.getLogger(__name__)no nível do módulo,logger.info(...)na ferramenta. O padrão inteiro é esse.- A saída de log nunca chega ao modelo. Só o valor que você faz
returnchega. - O erro padrão é seu; o stdout pertence ao protocolo. O SDK desvia para o stderr o stdout perdido que recebe flush enquanto serve, mas um
print()sem flush ainda pode vazar para a comunicação na saída, e as linhas desviadas chegam sem rótulo; uselogging, cujo handler faz flush de cada registro. MCPServer(..., log_level="DEBUG")define o nível, e uma configuração de logging que você tenha feito antes fica intacta.
Avisar os clientes conectados de que algo no seu servidor mudou (a lista de ferramentas, um recurso) é assunto de Assinaturas.