Servidores MCP robustos, seguros e prontos para produção
A virada de chave
No básico, o servidor respondia. Aqui ele aprende a pedir, avisar e a rodar remotamente — o que separa um exemplo de aula de um servidor de produção.
Analogia
O servidor é um estagiário sem acesso ao Bloomberg: quando precisa de uma análise, ele pede ao chefe (o cliente), que tem as ferramentas e decide se autoriza.
Uma tool dispara, de volta ao cliente, um pedido de geração:
@mcp.tool()
async def classificar_tom_ata(texto: str, ctx: Context) -> str:
"""Classifica o tom de uma ata do COPOM como dovish/neutro/hawkish."""
resultado = await ctx.session.create_message(
messages=[
SamplingMessage(
role="user",
content=TextContent(
type="text",
text=f"Classifique o tom (dovish/neutro/hawkish):\n\n{texto}",
),
)
],
max_tokens=100,
)
return resultado.content.textNota
O servidor não chamou nenhuma API. Ele só descreveu o que queria — quem pagou e executou foi o cliente.
Analogia
É a barra de progresso do download: você não interage com ela, mas saber que vai em “3 de 4” evita a sensação de que o programa travou.
@mcp.tool()
async def baixar_series_bcb(codigos: list[int], ctx: Context) -> str:
"""Baixa várias séries do SGS do Banco Central, reportando progresso."""
total = len(codigos)
for i, codigo in enumerate(codigos, start=1):
await ctx.info(f"Baixando série {codigo}...")
# ... baixa e processa a série ...
await ctx.report_progress(progress=i, total=total)
return f"{total} séries baixadas."ctx.info(...) envia um log; ctx.report_progress(...) envia o andamentoAnalogia
É um crachá que abre só algumas portas do prédio. O servidor circula apenas onde foi autorizado — por exemplo, somente a pasta dados/ do projeto.
Nota
O servidor pergunta “onde posso trabalhar?” em vez de assumir caminhos fixos. Isso torna o mesmo servidor portátil entre máquinas e usuários — e mais seguro.
| Tipo | Tem id? |
Espera resposta? |
|---|---|---|
| Request | sim | sim |
| Response | sim (mesmo do request) | — |
| Notification | não | não |
Nota
A regra prática: se a mensagem tem id, alguém vai responder. Notificações não têm id — por isso são “avisos” e não “perguntas”.
// Request (cliente → servidor): executar uma tool
{ "jsonrpc": "2.0", "id": 7, "method": "tools/call",
"params": { "name": "baixar_series_bcb", "arguments": { "codigos": [433, 1178] } } }
// Notification (servidor → cliente): progresso, sem id
{ "jsonrpc": "2.0", "method": "notifications/progress",
"params": { "progressToken": "abc", "progress": 1, "total": 2 } }Analogia
É uma conversa por um cano direto entre dois processos na mesma máquina — sem rede, sem servidor publicado.
/mcp)Nota
Use STDIO para rodar na sua máquina; use StreamableHTTP quando vários usuários ou serviços precisam acessar o mesmo servidor publicado.
Mcp-Session-IdAccept: text/event-streamMcp-Session-Id) — mais rico, mas amarra o cliente a uma instânciaNota
Stateless é ótimo para servidores na nuvem que precisam atender muitos clientes ao mesmo tempo — o trade-off é abrir mão de estado guardado entre chamadas.
Para economia e finanças
Um servidor MCP que serve séries do BCB pode rodar remoto e stateless, expor uma tool de download com progresso, restringir o acesso via roots e usar sampling para classificar atas — sem ter um modelo próprio.
Obrigado! — Análise Macro