mcp-lab-00-raw-protocol
mcp-lab-00-raw-protocol
Nível 00 da trilha MCP Lab: implementação manual do protocolo MCP (Model Context Protocol) sobre stdio, sem usar o SDK oficial. O objetivo não é construir um servidor útil — é ver as mensagens JSON-RPC trocando de lado a lado com as próprias mãos, antes de deixar um SDK esconder isso de você.
Termos técnicos (Tool, Server, Client, Transport...) seguem o glossário em ../CONTEXT.md.
O que este Server faz
Um único Tool, de propósito — add, que soma dois números. É só o suficiente pra passar pelo ciclo completo: handshake → listar Tools → chamar um Tool.
sequenceDiagram
participant H as Host (Claude Code)
participant S as Server (este projeto)
H->>S: initialize (id: 1, protocolVersion)
S-->>H: result (protocolVersion, capabilities, serverInfo)
H->>S: notifications/initialized
Note over S: sem resposta — é uma Notification
H->>S: tools/list (id: 2)
S-->>H: result (lista de Tools: "add")
H->>S: tools/call (id: 3, name: "add", arguments: {a, b})
S-->>H: result (content: texto com a soma)Como rodar
uv sync # instala as dependências
uv run pytest -q # roda os 15 testes
uv run ruff check . # lint
uv run mypy # checagem de tipos (modo strict)Pra ver o protocolo funcionando de verdade, sem o SDK, sem o Claude Code — só você mandando as mensagens na mão:
printf '%s\n' \
'{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2025-06-18"}}' \
'{"jsonrpc": "2.0", "method": "notifications/initialized"}' \
'{"jsonrpc": "2.0", "id": 2, "method": "tools/list"}' \
'{"jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": {"name": "add", "arguments": {"a": 4, "b": 5}}}' \
| uv run raw-mcp-protocolEstrutura do código
src/raw_mcp_protocol/
├── jsonrpc.py → camada de transporte: lê/escreve linhas JSON, não entende o conteúdo
├── server.py → camada de lógica: decide a resposta pra cada "method"
└── __init__.py → ponto de entrada: liga as duas camadas num loopCada camada tem seu próprio .md em docs/ explicando o pra-quê, o quê e como:
O que este nível deliberadamente NÃO faz
Não valida rigorosamente o ciclo de vida (chamar
tools/callantes doinitializenão é bloqueado) — fica como leitura, não como bloqueio ativo.Não implementa Resources, Prompts, Sampling, Roots nem Elicitation — isso é o Nível
02-resources-promptsem diante.Não roda sobre HTTP — isso é o Nível
04-remote-http-auth.
Referência oficial
modelcontextprotocol.io/specification — a fonte da verdade. As versões de protocolo hardcoded em server.py (SUPPORTED_PROTOCOL_VERSIONS) devem ser conferidas contra essa página se você estiver lendo isto muito tempo depois de escrito.