Voltar as noticias
Eu Quase Implementei JSON-RPC para um Servidor MCP. Oito Ferramentas Depois, Estou Feliz por Não Ter Feito.
MCP ProtocolAltaEN

Eu Quase Implementei JSON-RPC para um Servidor MCP. Oito Ferramentas Depois, Estou Feliz por Não Ter Feito.

Dev.to - MCP·18 de julho de 2026

Quando construí o servidor MCP para este projeto — que combina GitHub e DEV.to em um conjunto de ferramentas que um agente pode chamar — eu tinha uma decisão a tomar antes de escrever uma única ferramenta: conversar diretamente com o protocolo MCP de baixo nível ou usar a API de decoradores do FastMCP. Eu vi alguns artigos sobre "seu primeiro servidor MCP" ultimamente que percorrem o caminho de baixo nível porque é mais "honesto" sobre o que o MCP realmente é por trás das cenas — JSON-RPC sobre stdio, um handshake de capacidades, esquemas de solicitação/resposta tipados. Isso é verdade, e é uma coisa razoável querer entender. Mas eu quero escrever sobre o outro lado: o que realmente custa na prática uma vez que você tem mais de uma ou duas ferramentas, porque eu passei por ambos e a diferença apareceu rapidamente.

o que o caminho de baixo nível realmente pede para você escrever

Remova o decorador e o MCP é um servidor JSON-RPC. Para cada ferramenta que você adiciona, você é responsável por:

  • Registrar o nome da ferramenta, descrição e um esquema JSON para suas entradas em um manipulador list_tools
  • Escrever um despachante call_tool que combina com o nome da ferramenta e desempacota argumentos manualmente
  • Serializar o valor de retorno nos tipos de wrapper TextContent/ImageContent que o MCP espera
  • Manter o esquema que você escreveu na etapa 1 em sincronia com os argumentos que você realmente leu na etapa 2, manualmente, para sempre

Nada disso é difícil isoladamente. O problema é que é boilerplate que escala linearmente com a contagem de ferramentas e não tem nenhuma conexão com a lógica real da ferramenta. Meu servidor tem 8 ferramentas. Se eu tivesse feito manualmente, seriam 8 blocos de esquema mais uma cadeia de despachante if/elif mais 8 chamadas de empacotamento de resposta, tudo isso existe puramente para satisfazer o protocolo, não para fazer nada que uma chamada de API do GitHub ou DEV.to precise.

como é com FastMCP

Aqui está uma ferramenta real de server.py, não editada:

@mcp.tool()
def get_repo_stats(repo: str) -> dict:
    """Obter estrelas, forks, observadores, problemas abertos para enjoykumawat/<repo>."""
    r = _gh(f"/repos/{GITHUB_USERNAME}/{repo}")
    return {
        "name": r["name"],
        "stars": r["stargazers_count"],
        "forks": r["forks_count"],
        "watchers": r["watchers_count"],
        "open_issues": r["open_issues_count"],
        "language": r.get("language"),
        "description": r.get("description"),
    }

O tipo de dica (repo: str) se torna o esquema JSON. A docstring se torna a descrição da ferramenta que o agente vê ao decidir se deve chamá-la. O tipo de retorno se torna a forma da resposta. Não há esquema para manter em sincronia manualmente — ele é derivado da mesma assinatura que o Python já verifica quanto ao tipo. Adicionar uma nona ferramenta é: escrever uma função, colocar @mcp.tool() acima dela, feito. Nenhum despachante para atualizar, nenhum empacotamento TextContent, nenhum código de camada de protocolo tocado.

Nossa ADR de quando tomei essa decisão é direta sobre a troca:

Decisão: Usar FastMCP de mcp.server.fastmcp com decoradores @mcp.tool(). Chamadas HTTP via urllib da stdlib.
Alternativas Consideradas: Servidor MCP de baixo nível → rejeitado (complexidade desnecessária para este caso de uso).
Consequências: mcp[cli] é a única dependência. O servidor pode ser executado via python server.py ou mcp dev server.py.

"Complexidade desnecessária para este caso de uso" está fazendo muito trabalho nessa frase, e eu acho que é a lente certa: a API de baixo nível existe porque alguém precisa escrever bibliotecas de cliente e servidor MCP, ou precisa de controle em nível de protocolo (streaming de resultados parciais, negociação de capacidade personalizada, transportes não padronizados). Se você está expondo 8 wrappers de API REST a um agente, você não é essa pessoa, e o código de camada de protocolo que você escreveria não tem relação com o seu problema real.

onde a abordagem do decorador me prejudicou

Não é gratuito. Dois problemas reais de realmente executar este servidor:

A coerção do tipo de retorno é implícita e fácil de errar sutilmente. list_articles retorna um list[dict] construído por uma compreensão de lista sobre a resposta da API DEV.to. O FastMCP serializa isso bem — mas a primeira versão dessa função esqueceu de limitar per_page, e um chamador passando per_page=1000 teria recebido silenciosamente o que a API do DEV.to realmente retorna para um valor fora do intervalo (acontece que ele limita, mas eu tive que verificar, porque a geração de esquema do FastMCP a partir de per_page: int = 10 não impõe um limite superior apenas porque a docstring diz que um existe):

@mcp.tool()
def list_articles(per_page: int = 10) -> list:
    """Liste seus artigos publicados no DEV.to.
Contexto Triplo Up

Empresas brasileiras que utilizam agentes de IA podem se beneficiar da implementação simplificada de servidores MCP. A escolha entre uma abordagem de baixo nível e uma API decoradora pode impactar a eficiência e a manutenção do código. O uso de ferramentas como FastMCP pode facilitar a integração com APIs existentes.

Noticias relacionadas

Gostou do conteudo?

Receba toda semana as principais novidades sobre WebMCP.