Skip to main content
Glama
ericzaim
by ericzaim

MCPTeste — MCP server + client com Claude Haiku e compressão de contexto

Teste end-to-end de um MCP server que expõe tools de leitura de documentos JSON, um MCP client que consome essas tools, e o Claude Haiku 4.5 decidindo quais chamar dentro de um loop de tool use. Os outputs das tools passam pelo Headroom antes de entrar no contexto do modelo.

Setup

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

cp .env.example .env   # preencha ANTHROPIC_API_KEY

Related MCP server: mcp-model-proxy

Uso

# server sozinho (stdio — fica aguardando o protocolo em stdin)
python -m src.server

# client: sobe o server como subprocesso e conversa com o modelo
python -m src.client "Qual o valor total da invoice 001?"
python -m src.client "Resuma o relatorio do primeiro trimestre de 2026"

# mesma pergunta sem compressão, para comparar input_tokens
python -m src.client "Resuma o relatorio do primeiro trimestre de 2026" --no-compression

O client imprime input_tokens, output_tokens e tokens_saved_by_compression ao final.

Decisões e por quê

stdio, não HTTP. O client sobe o server como subprocesso. Tira rede da equação: o que falhar é o protocolo ou a lógica, nunca porta ocupada ou timeout de socket.

documents.py separado do MCP. A camada de dados não importa nada de mcp, então dá para testá-la direto no interpretador — inclusive a validação de path, que é a parte com consequência de segurança. O server.py fica sendo só a fachada MCP.

Loop de tool use manual, não o tool_runner. O SDK da Anthropic tem um tool runner que esconde o ciclo request → tool_use → tool_result. Aqui o objetivo é justamente ver esse ciclo, então o loop está escrito à mão em client.py. Também evita depender de uma API beta.

Headroom como biblioteca no client, não como segundo MCP server. O Headroom expõe headroom_compress como tool MCP, mas nesse formato o modelo precisa ler o output inteiro para depois pedir a compressão — o token já foi gasto. Como biblioteca, a compressão acontece entre session.call_tool() e o tool_result, antes de qualquer coisa chegar ao modelo. O ganho aparece já na primeira iteração.

Compressão nunca derruba o loop. Qualquer falha do Headroom (erro, retorno inesperado, pacote ausente) cai no texto original e segue, apenas logando em stderr. É otimização, não caminho crítico.

Compressão — números medidos

O report-2026-q1.json tem 420 transações com a mesma forma. O Headroom converte esse array de objetos em uma linha de schema seguida de linhas CSV, eliminando a repetição das chaves. Nenhuma linha é descartada — as 420 continuam lá.

Payload

Antes

Depois

Redução

Arquivo indentado (176 KB)

50.305 tokens

20.338 tokens

−59,6%

Output real da tool read_document (JSON compacto)

38.933 tokens

26.040 tokens

−33,1%

Documentos pequenos (invoice, contract, list_documents) ficam abaixo do piso de MIN_CHARS_TO_COMPRESS e passam sem alteração — comprimir 700 caracteres não paga o custo.

Dois detalhes de configuração que não são óbvios:

  • O Headroom protege mensagens user recentes por padrão. Como a tool output é entregue a ele como uma única mensagem user, sem compress_user_messages=True e protect_recent=0 a chamada vira passthrough silencioso (0% de ganho).

  • Os contadores tokens_before/tokens_after do Headroom são estimativas neste ambiente: o download do vocabulário do tiktoken não completa offline e a lib cai para estimativa. Os números que valem para custo são os usage.input_tokens da própria API, comparáveis via --no-compression.

Segurança

document_id vem do modelo, então é input não confiável. documents.py valida contra um regex restritivo, resolve o caminho com Path.resolve() e confirma is_relative_to() da pasta de documentos. Traversal (../../etc/passwd, ..%2f.., caminho absoluto) é rejeitado antes de qualquer acesso a disco, e a mensagem de erro não expõe caminho do sistema.

Nenhuma credencial no código: ANTHROPIC_API_KEY vem de .env (via python-dotenv) ou do ambiente. O client verifica a credencial antes de subir o server, para falhar com uma linha legível em vez de um traceback do SDK.

Limitações conhecidas

  • CCR (compressão reversível) não está integrado. O Headroom documenta o Compress-Cache-Retrieve, mas a referência da API não expõe o método de retrieve em Python (só cita ccrHashes no SDK TypeScript). Como o formato CSV-com-schema preserva todas as linhas, a perda prática é baixa — o system prompt avisa o modelo sobre o formato. Se o retrieve em Python aparecer, vira uma tool retrieve_original no client.

  • mcp 2.0 renomeou a API. FastMCP virou MCPServer e os campos do protocolo passaram a snake_case (input_schema, is_error, structured_content). Código de exemplo escrito para mcp 1.x não roda aqui sem ajuste.

  • Sem testes automatizados. documents.py e compression.py são as camadas naturais para pytest (validação de path e fallback de compressão).

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    A Machine Context Protocol server that enables Claude AI to interact with tools through a structured communication interface, following standard MCP patterns with server initialization and stdio transport.
    681 npm
    2
    MIT
  • A
    license
    B
    quality
    D
    maintenance
    A minimal local MCP server that wraps any Claude Messages API-compatible upstream into a unified ask_model tool. It enables MCP clients to interact with these models through a standard tool interface using stdio transport.
    1
    8
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Stdio MCP server for sandboxed file access — read files, search content, safely edit with checksums, and manage file structure.
    6 npm
    ISC