Ligar um modelo de linguagem a ficheiros, bases de dados ou APIs costumava significar escrever um conector à medida para cada combinação de modelo e ferramenta. O Model Context Protocol (MCP) resolve esse problema com uma interface única: escreve-se um servidor MCP uma vez e qualquer cliente compatível, seja o Claude Desktop, o Claude Code ou o VS Code, consegue falar com ele. Este tutorial mostra como construir, testar e publicar o seu próprio servidor MCP em Python, do zero até um projeto funcional que gere tarefas através de ferramentas, recursos e prompts.
O que é o Model Context Protocol e porque importa em 2026
O MCP nasceu na Anthropic como um protocolo aberto para conectar aplicações de IA a fontes de dados e ferramentas externas sem depender de integrações fechadas. A ideia central é simples: em vez de cada fornecedor de modelos inventar o seu próprio formato de “plugin”, o MCP define um contrato comum entre três papéis. O host é a aplicação que o utilizador vê (o Claude Desktop, por exemplo). O cliente vive dentro do host e mantém uma ligação individual a cada servidor. O servidor é o programa que expõe dados ou ações, como aceder a um repositório Git, consultar uma base de dados ou marcar uma tarefa como concluída.
Em 2026, a especificação evoluiu bastante desde a primeira versão pública. A revisão mais recente, publicada como especificação estável a 28 de julho de 2026 e identificada pela data 2026-07-28, foi descrita pela própria equipa do protocolo como a maior atualização desde o lançamento do MCP. A mudança principal foi tornar o núcleo do protocolo sem estado (stateless), eliminando o handshake de sessão e o ID de sessão que obrigavam quem fazia deploy em produção a manter balanceadores de carga com sessões fixas (sticky sessions) e armazenamento partilhado em Redis. Isto simplifica bastante colocar um servidor MCP atrás de um balanceador de carga comum.
A governação do protocolo também mudou de mãos: a especificação e a documentação passaram a ser mantidas sob a Aggent AI Foundation, dentro da Linux Foundation, o que sinaliza a intenção de tornar o MCP um padrão neutro em vez de ficar ligado apenas à Anthropic. Do lado das ferramentas, o GitHub anunciou a atualização do seu próprio GitHub MCP Server para a nova especificação a 23 de julho de 2026, com a versão a ficar disponível no dia seguinte. Isto é relevante para quem segue este tipo de tutorial: já não estamos a falar de um protocolo experimental usado por early adopters, mas de infraestrutura com produtos reais de grandes empresas a acompanhar cada revisão.
Como funciona a arquitetura do MCP: hosts, clientes e servidores
Antes de escrever código vale a pena perceber os três blocos que compõem qualquer sistema MCP. O host é a aplicação final, como o Claude Desktop ou um IDE com suporte a MCP. Dentro do host corre um ou mais clientes, cada um responsável por manter a ligação com exatamente um servidor. Isto significa que, se ligar três servidores diferentes ao Claude Desktop, o host cria três clientes internos, um por servidor, todos isolados uns dos outros.
O servidor é o código que o programador escreve. Pode correr localmente, lançado pelo próprio host através de um comando (transporte stdio), ou pode correr remotamente e ser acedido por HTTP. A especificação 2026-07-28 reforçou precisamente o transporte HTTP: passou a exigir cabeçalhos HTTP obrigatórios que dão aos gateways informação suficiente para registo e deteção de segredos sem terem de inspecionar o corpo de cada pedido. Isto elimina a necessidade de deep packet inspection nos proxies à frente do servidor, um problema comum em ambientes empresariais com firewalls de aplicação.
Para este tutorial vamos começar pelo transporte mais simples, stdio, porque é o que os SDKs oficiais testam primeiro e o que o Claude Desktop usa nativamente para servidores locais. Mais à frente, no passo 9, mostramos como migrar o mesmo servidor para HTTP, o caminho recomendado assim que o servidor precisa de correr num ambiente partilhado ou de ser acedido por múltiplos utilizadores.
Tools, resources e prompts: as três primitivas do protocolo
Todo o vocabulário do MCP assenta em três primitivas. As tools (ferramentas) representam ações que o servidor pode executar, cada uma com um nome, uma descrição e um esquema de parâmetros em JSON Schema. É o modelo que decide quando chamar uma tool, com base na descrição que o programador escreveu, por isso a qualidade da descrição importa tanto como a qualidade do código.
Os resources (recursos) representam dados que o cliente pode ler, como o conteúdo de um ficheiro, uma linha de uma base de dados ou o resultado de uma consulta. Ao contrário das tools, os resources não costumam ter efeitos secundários: servem para dar contexto ao modelo, não para desencadear ações. Cada resource tem um identificador URI próprio, o que permite ao cliente listar, obter ou subscrever atualizações de um recurso específico.
Os prompts são modelos de texto reutilizáveis que o servidor expõe para padronizar interações comuns, por exemplo um prompt “resumir_ficheiro” que já vem com a estrutura certa para o caso de uso do servidor. Na especificação 2026-07-28, as respostas de listagem destas três primitivas (list tools, list resources, list prompts) passaram a poder ser colocadas em cache pelo cliente, o que reduz round-trips desnecessários quando o mesmo servidor é consultado várias vezes seguidas.
Pré-requisitos: o que precisa antes de começar
Este tutorial usa Python porque é a linguagem com o SDK oficial mais maduro neste momento. Precisa de:
- Python 3.10 ou superior (o SDK oficial
mcpexige explicitamente esta versão mínima) - Gestor de pacotes
pipatualizado, ouuvse preferir um fluxo mais rápido - Pacote
mcpversão 2.2.0 (a linha estável atual no PyPI, já fora das fases alpha, beta e release candidate por que passou ao longo de 2026) - Claude Desktop instalado, para os passos de ligação a um host real
- Node.js 18 ou superior, apenas se quiser experimentar também o SDK em TypeScript (pacote
@modelcontextprotocol/sdk, atualmente na versão 1.30.0) - Um editor de código e acesso a um terminal com permissões para instalar pacotes
Não precisa de chave de API da Anthropic só para construir e testar o servidor localmente com o MCP Inspector. Só vai precisar de uma conta Claude (gratuita ou paga) quando ligar o servidor ao Claude Desktop nos passos finais.
Passo 1: Preparar o ambiente Python e instalar o SDK
Comece por criar uma pasta dedicada e um ambiente virtual isolado. Isto evita conflitos entre versões do SDK em diferentes projetos, algo relevante porque a linha v2 do mcp trouxe mudanças de arquitetura em relação à v1.
mkdir servidor-mcp-tarefas
cd servidor-mcp-tarefas
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install "mcp[cli]"==2.2.0
O extra [cli] instala também o MCP Inspector como dependência, que vamos usar no passo 6 para testar o servidor sem precisar de um host completo como o Claude Desktop. Confirme a instalação:
python3 -c "import mcp; print(mcp.__version__)"
# saída esperada: 2.2.0
Passo 2: Estruturar o projeto do servidor MCP
Vamos construir um servidor de gestão de tarefas simples, com armazenamento em memória, para manter o foco no protocolo e não na complexidade do domínio. Crie a estrutura de ficheiros seguinte:
servidor-mcp-tarefas/
├── .venv/
├── servidor.py
├── armazenamento.py
└── pyproject.toml
O ficheiro armazenamento.py vai guardar a lógica de dados, separada do protocolo em si. Isto é importante: um erro comum é misturar a lógica de negócio com as chamadas ao SDK, o que torna o servidor difícil de testar sem um cliente MCP ligado.
# armazenamento.py
from dataclasses import dataclass, field
from datetime import datetime
@dataclass
class Tarefa:
id: int
titulo: str
concluida: bool = False
criada_em: str = field(default_factory=lambda: datetime.now().isoformat())
class ArmazenamentoTarefas:
def __init__(self):
self._tarefas: dict[int, Tarefa] = {}
self._proximo_id = 1
def adicionar(self, titulo: str) -> Tarefa:
tarefa = Tarefa(id=self._proximo_id, titulo=titulo)
self._tarefas[tarefa.id] = tarefa
self._proximo_id += 1
return tarefa
def listar(self) -> list[Tarefa]:
return list(self._tarefas.values())
def concluir(self, id_tarefa: int) -> Tarefa | None:
tarefa = self._tarefas.get(id_tarefa)
if tarefa:
tarefa.concluida = True
return tarefa
Passo 3: Criar a primeira ferramenta (tool)
Com a camada de dados pronta, o próximo passo é expor uma tool que permita ao modelo criar tarefas. O SDK Python usa decoradores para reduzir código repetitivo: em vez de escrever manualmente o esquema JSON da ferramenta, o SDK gera-o a partir das anotações de tipo da função Python.
# servidor.py
from mcp.server.fastmcp import FastMCP
from armazenamento import ArmazenamentoTarefas
app = FastMCP("gestor-de-tarefas")
dados = ArmazenamentoTarefas()
@app.tool()
def criar_tarefa(titulo: str) -> str:
"""Cria uma nova tarefa com o título indicado e devolve a confirmação."""
tarefa = dados.adicionar(titulo)
return f"Tarefa #{tarefa.id} criada: {tarefa.titulo}"
@app.tool()
def concluir_tarefa(id_tarefa: int) -> str:
"""Marca a tarefa com o ID indicado como concluída."""
tarefa = dados.concluir(id_tarefa)
if tarefa is None:
return f"Não existe nenhuma tarefa com o ID {id_tarefa}."
return f"Tarefa #{tarefa.id} marcada como concluída."
if __name__ == "__main__":
app.run()
Repare que o texto na docstring de cada função não é um comentário decorativo: é o que o modelo lê para decidir quando e como chamar a ferramenta. Descrições vagas como “gere tarefas” levam o modelo a invocar a tool errada ou a passar argumentos incorretos. Seja específico sobre o que a ferramenta faz e que valores espera.
Passo 4: Expor um recurso (resource) ao cliente
Agora vamos adicionar um resource, que dá ao modelo uma vista só de leitura sobre o estado atual das tarefas, sem que isso conte como uma “ação”. A diferença prática é que os resources aparecem no cliente como algo que o utilizador pode anexar ao contexto da conversa manualmente, e não apenas como algo que o modelo decide chamar sozinho.
@app.resource("tarefas://lista")
def listar_tarefas_resource() -> str:
"""Devolve todas as tarefas em formato de texto simples."""
tarefas = dados.listar()
if not tarefas:
return "Não há tarefas registadas."
linhas = [
f"#{t.id} [{'x' if t.concluida else ' '}] {t.titulo}"
for t in tarefas
]
return "\n".join(linhas)
O URI tarefas://lista é arbitrário, mas deve seguir um esquema consistente se o servidor vier a expor vários recursos, por exemplo tarefas://lista para todas as tarefas e tarefas://{id} para uma tarefa específica.
Passo 5: Adicionar um prompt reutilizável
Os prompts servem para encapsular instruções que, de outra forma, o utilizador teria de escrever manualmente todas as vezes. Um prompt bem desenhado poupa tempo e reduz a inconsistência entre conversas diferentes.
@app.prompt()
def resumo_diario() -> str:
"""Gera um prompt que pede um resumo das tarefas pendentes do dia."""
return (
"Consulta o recurso tarefas://lista e produz um resumo curto "
"com o número de tarefas pendentes e concluídas, destacando "
"as três tarefas pendentes mais antigas."
)
Com isto, o servidor já expõe as três primitivas do protocolo: duas tools (criar_tarefa, concluir_tarefa), um resource (tarefas://lista) e um prompt (resumo_diario). É o suficiente para testar a ligação de ponta a ponta.
Passo 6: Testar o servidor com o MCP Inspector
Antes de ligar o servidor a um host real como o Claude Desktop, use o MCP Inspector, uma ferramenta oficial que abre uma interface web local para inspecionar tools, resources e prompts sem precisar de um cliente completo.
mcp dev servidor.py
Este comando arranca o servidor e abre o Inspector no navegador, normalmente em http://localhost:6274. Na interface deve conseguir:
- Ver as duas tools listadas com os respetivos esquemas de parâmetros gerados automaticamente
- Chamar
criar_tarefamanualmente com um título de teste e confirmar que a resposta aparece corretamente - Ler o resource
tarefas://listae confirmar que reflete a tarefa criada - Ver o prompt
resumo_diariolistado, mesmo sem o poder “executar” fora de um cliente de conversa
Se algo não aparecer, o problema está quase sempre na forma como o decorador foi aplicado ou num erro silencioso na inicialização do módulo. Correr o servidor diretamente com python servidor.py antes de usar o Inspector costuma revelar erros de sintaxe ou de importação mais depressa.
Passo 7: Ligar o servidor ao Claude Desktop
Com o servidor validado no Inspector, o próximo passo é registá-lo no Claude Desktop. A aplicação lê a configuração de servidores MCP de um ficheiro JSON local. No macOS este ficheiro fica normalmente em ~/Library/Application Support/Claude/claude_desktop_config.json; no Windows em %APPDATA%\Claude\claude_desktop_config.json.
{
"mcpServers": {
"gestor-de-tarefas": {
"command": "/caminho/completo/para/.venv/bin/python",
"args": ["/caminho/completo/para/servidor.py"]
}
}
}
Use sempre caminhos absolutos, tanto para o interpretador Python do ambiente virtual como para o ficheiro do servidor. É o erro mais comum nesta fase: o Claude Desktop não herda o PATH do terminal onde o ambiente virtual foi ativado, por isso um caminho relativo ou o simples python falha silenciosamente. Depois de guardar o ficheiro, reinicie completamente o Claude Desktop (feche pela bandeja do sistema, não apenas a janela) para que a configuração seja recarregada.
Se a ligação funcionar, deve ver um ícone de ferramenta (martelo) na caixa de texto da conversa, e ao clicar nele aparecem as duas tools do servidor disponíveis para o modelo usar.
Passo 8: Ligar o servidor à Claude Code CLI
Para quem trabalha mais na linha de comandos do que na aplicação de desktop, a Claude Code também suporta servidores MCP, com uma configuração equivalente mas gerida por um comando próprio em vez de edição manual de JSON:
claude mcp add gestor-de-tarefas \
-- /caminho/completo/para/.venv/bin/python /caminho/completo/para/servidor.py
claude mcp list
O comando claude mcp list confirma que o servidor está registado e mostra o estado da ligação. Isto é útil para depurar em CI ou em ambientes sem interface gráfica, onde editar um ficheiro de configuração do Claude Desktop não é prático.
Passo 9: Migrar de stdio para transporte HTTP
O transporte stdio funciona bem para desenvolvimento local, mas não serve para um servidor que várias pessoas ou serviços precisam de aceder ao mesmo tempo. Para isso, o SDK permite expor o mesmo servidor por HTTP com uma mudança mínima de código:
if __name__ == "__main__":
app.run(transport="streamable-http", host="0.0.0.0", port=8080)
Vale a pena repetir o ponto arquitetural referido antes: a especificação 2026-07-28 tornou o protocolo sem estado ao nível do transporte HTTP, o que significa que já não é preciso manter sessões fixas num balanceador de carga. Isto simplifica bastante colocar o servidor atrás de um proxy reverso comum, como o Nginx, sem configuração especial de afinidade de sessão. Ainda assim, para produção deve sempre colocar o servidor atrás de HTTPS, nunca expor a porta diretamente à internet.
Passo 10: Autenticação e autorização do servidor MCP
Assim que o servidor deixa de correr apenas na máquina local, a autenticação passa a ser obrigatória. A revisão 2026-07-28 da especificação incluiu explicitamente aquilo que a própria documentação chama de endurecimento da autorização (authorization hardening), com regras mais claras sobre que operações um cliente pode invocar depois de autenticado.
Na prática, para um servidor HTTP simples, a abordagem mais direta é validar um token Bearer em cada pedido antes de o encaminhar para a lógica do servidor:
import os
from starlette.requests import Request
from starlette.responses import JSONResponse
TOKEN_ESPERADO = os.environ["MCP_AUTH_TOKEN"]
@app.custom_route("/mcp", methods=["POST"])
async def validar_pedido(request: Request):
cabecalho = request.headers.get("authorization", "")
if cabecalho != f"Bearer {TOKEN_ESPERADO}":
return JSONResponse({"erro": "não autorizado"}, status_code=401)
# encaminha para o handler MCP normal depois da validação
Guarde sempre o token em variáveis de ambiente ou num gestor de segredos, nunca diretamente no código-fonte. Se o servidor expõe tools que escrevem dados (como o nosso criar_tarefa), este passo não é opcional: um servidor MCP sem autenticação exposto por HTTP é, na prática, um endpoint de escrita aberto a quem souber o URL.
Passo 11: Publicar o servidor num registo MCP
Depois de testado e protegido, o passo seguinte é distribuí-lo. Para servidores Python, isto significa embalar o projeto com um pyproject.toml correto e publicá-lo no PyPI, tal como qualquer outra biblioteca:
[project]
name = "servidor-mcp-tarefas"
version = "0.1.0"
requires-python = ">=3.10"
dependencies = ["mcp[cli]==2.2.0"]
[project.scripts]
servidor-mcp-tarefas = "servidor:app.run"
Com o pyproject.toml configurado, pip install servidor-mcp-tarefas instala o pacote e o comando definido em project.scripts fica disponível globalmente, o que facilita a configuração no Claude Desktop de quem for usar o servidor sem clonar o código-fonte.
Passo 12: Monitorizar, testar em CI e distribuir
O último passo é garantir que o servidor continua a funcionar depois de publicado. Escreva testes unitários para a camada de dados (independentes do protocolo MCP) e um teste de fumo que arranque o servidor e confirme que a lista de tools é devolvida corretamente:
import subprocess
import json
def test_servidor_lista_tools():
resultado = subprocess.run(
["mcp", "dev", "servidor.py", "--list-tools"],
capture_output=True, text=True, timeout=10
)
dados = json.loads(resultado.stdout)
nomes = [t["name"] for t in dados["tools"]]
assert "criar_tarefa" in nomes
assert "concluir_tarefa" in nomes
Integre este teste no seu pipeline de integração contínua (GitHub Actions, GitLab CI, ou equivalente) para detetar rutura de compatibilidade sempre que atualizar o SDK mcp para uma nova versão menor.
Projeto completo: servidor MCP de gestão de tarefas
Juntando tudo, o ficheiro servidor.py final fica assim, pronto a correr com python servidor.py localmente ou a ser importado como pacote depois de publicado:
from mcp.server.fastmcp import FastMCP
from armazenamento import ArmazenamentoTarefas
app = FastMCP("gestor-de-tarefas")
dados = ArmazenamentoTarefas()
@app.tool()
def criar_tarefa(titulo: str) -> str:
"""Cria uma nova tarefa com o título indicado e devolve a confirmação."""
tarefa = dados.adicionar(titulo)
return f"Tarefa #{tarefa.id} criada: {tarefa.titulo}"
@app.tool()
def concluir_tarefa(id_tarefa: int) -> str:
"""Marca a tarefa com o ID indicado como concluída."""
tarefa = dados.concluir(id_tarefa)
if tarefa is None:
return f"Não existe nenhuma tarefa com o ID {id_tarefa}."
return f"Tarefa #{tarefa.id} marcada como concluída."
@app.resource("tarefas://lista")
def listar_tarefas_resource() -> str:
"""Devolve todas as tarefas em formato de texto simples."""
tarefas = dados.listar()
if not tarefas:
return "Não há tarefas registadas."
return "\n".join(
f"#{t.id} [{'x' if t.concluida else ' '}] {t.titulo}" for t in tarefas
)
@app.prompt()
def resumo_diario() -> str:
"""Gera um prompt que pede um resumo das tarefas pendentes do dia."""
return (
"Consulta o recurso tarefas://lista e produz um resumo curto "
"com o número de tarefas pendentes e concluídas, destacando "
"as três tarefas pendentes mais antigas."
)
if __name__ == "__main__":
app.run()
Este servidor, com menos de 40 linhas de lógica própria, já é suficiente para o Claude criar tarefas, marcá-las como concluídas e ler o estado atual, tudo através do protocolo padrão em vez de uma integração à medida.
Erros comuns a evitar ao construir servidores MCP
Estes são os problemas que mais aparecem a quem está a começar com o protocolo:
- Descrições de tools demasiado vagas. O modelo escolhe qual ferramenta chamar com base na descrição da função. Uma docstring como “processa dados” não dá contexto suficiente e leva a chamadas erradas.
- Caminhos relativos na configuração do host. O Claude Desktop e a Claude Code correm o comando do servidor a partir do seu próprio diretório de trabalho, não do diretório do projeto. Use sempre caminhos absolutos.
- Misturar lógica de negócio com chamadas ao SDK. Torna os testes unitários dependentes de um cliente MCP a correr, o que atrasa o desenvolvimento.
- Ignorar limites de tamanho da resposta. Devolver ficheiros inteiros ou resultados de consultas sem paginação em resources pode esgotar rapidamente o contexto disponível para o modelo.
- Expor tools destrutivas sem confirmação. Uma tool que apaga dados deve, sempre que possível, exigir um passo de confirmação explícita, e nunca correr sem autenticação num transporte remoto.
Resolução de problemas: situações frequentes
Uma lista das falhas mais reportadas ao ligar servidores MCP e como as resolver:
- O ícone de ferramentas não aparece no Claude Desktop. Confirme que o JSON de configuração é válido (uma vírgula a mais quebra o ficheiro inteiro) e que reiniciou a aplicação completamente, não apenas fechou a janela.
- “Command not found” ao arrancar o servidor. O caminho para o interpretador Python no
claude_desktop_config.jsontem de ser absoluto e apontar para dentro do ambiente virtual, não para umpythonglobal que pode não ter o pacotemcpinstalado. - O servidor arranca mas as tools não aparecem. Verifique se os decoradores
@app.tool()estão mesmo a ser executados antes deapp.run()ser chamado; um erro de importação silencioso pode saltar essa parte do ficheiro. - Erro de timeout na primeira chamada a uma tool. Se a função fizer uma operação de I/O lenta (chamada de rede, leitura de ficheiro grande), considere torná-la assíncrona com
async defem vez de bloquear o loop de eventos do servidor. - O MCP Inspector não abre no navegador. Verifique se a porta 6274 já está ocupada por outro processo; encerre-o ou defina outra porta com a variável de ambiente correspondente do Inspector.
- Autenticação falha com 401 mesmo com o token correto. Confirme se o cabeçalho está a ser enviado exatamente como
Authorization: Bearer <token>, sem espaços extra, e que a variável de ambienteMCP_AUTH_TOKENestá definida no processo do servidor, não apenas no terminal onde foi testada. - Cliente e servidor não concordam na versão da especificação. Se o host for mais antigo e não suportar a revisão 2026-07-28, confirme que o SDK negoceia automaticamente uma versão anterior compatível; não force manualmente uma versão de especificação sem verificar a documentação do cliente.
- Resource devolve dados desatualizados. Como as listagens passaram a ser colocadas em cache pelo cliente na revisão mais recente da especificação, um recurso que muda com frequência pode precisar de cabeçalhos de invalidação de cache explícitos em vez de depender do comportamento padrão.
Dicas avançadas para produção
Depois de o servidor funcionar localmente e estar ligado a um host, há um conjunto de práticas que fazem diferença quando o mesmo servidor passa a ser usado por várias pessoas ou integrado noutros sistemas. Separe sempre as credenciais por ambiente: o token usado em desenvolvimento nunca deve ser o mesmo usado em produção, e ambos devem ser rodados periodicamente.
Registe métricas básicas por tool, como número de chamadas, tempo de resposta e taxa de erro. Isto ajuda a perceber rapidamente se um modelo está a chamar uma tool de forma inesperadamente repetitiva, o que normalmente indica uma descrição pouco clara ou um esquema de parâmetros ambíguo. Quando o servidor cresce e passa a ter dezenas de tools, agrupe-as por ficheiro ou módulo em vez de as manter todas no mesmo servidor.py, e considere versionar o próprio protocolo interno do servidor para poder introduzir mudanças sem quebrar clientes já ligados.
Por fim, trate as tools destrutivas como operações privilegiadas: exija sempre um passo humano de confirmação antes de qualquer ação irreversível, e documente claramente no README do servidor quais tools têm efeitos secundários e quais são apenas de leitura, para que quem for integrar o servidor perceba os riscos antes de o ligar a um agente autónomo.
MCP vs function calling tradicional: qual escolher
Antes do MCP, a forma mais comum de dar ferramentas a um modelo era o function calling direto de cada fornecedor: definir o esquema da função no pedido à API e tratar a chamada devolvida no seu próprio código. Isto continua a funcionar e, para uma integração única e simples, pode ser mais rápido de implementar. A diferença aparece na reutilização: um servidor MCP escrito uma vez funciona em qualquer host compatível, enquanto uma integração de function calling fica presa ao SDK e ao formato específico de cada fornecedor.
| Critério | MCP | Function calling direto |
|---|---|---|
| Reutilização entre hosts | Um servidor serve vários clientes compatíveis | Preso ao SDK e formato do fornecedor |
| Complexidade inicial | Requer montar um servidor e um transporte | Apenas define o esquema no pedido à API |
| Descoberta dinâmica de ferramentas | Sim, via listagem de tools/resources/prompts | Não, esquema fixo por integração |
| Padrão aberto e governação | Aggent AI Foundation, sob a Linux Foundation | Cada fornecedor define o próprio formato |
| Ideal para | Ferramentas partilhadas por vários agentes/hosts | Integração única dentro de uma só aplicação |
SDKs oficiais do MCP: Python, TypeScript e versões atuais
Neste momento existem SDKs oficiais mantidos para várias linguagens, com maturidade diferente entre eles. A tabela seguinte resume o estado de cada um, com as versões verificadas diretamente nos respetivos registos de pacotes.
| SDK | Pacote | Versão atual | Requisito mínimo |
|---|---|---|---|
| Python | mcp (PyPI) | 2.2.0 | Python 3.10+ |
| TypeScript / Node.js | @modelcontextprotocol/sdk | 1.30.0 | Node.js 18+ |
| Java | modelcontextprotocol/java-sdk | Linha 3.x planeada para a spec 2026-07-28 | JDK 17+ |
Vale notar que o SDK Python já concluiu a transição completa para a linha v2 (passando por várias versões alpha, beta e release candidate ao longo de 2026 até chegar à 2.2.0 estável), enquanto o SDK TypeScript continua, à data deste tutorial, a distribuir o pacote monolítico @modelcontextprotocol/sdk na versão 1.30.0. Antes de escolher uma linguagem para o seu servidor, confirme sempre a versão mais recente diretamente no PyPI ou no npm, porque este ecossistema está a evoluir rapidamente.
Quem já suporta o MCP: o ecossistema em 2026
Um protocolo só é útil se houver quem o implemente dos dois lados, servidor e cliente. Do lado dos servidores, o exemplo mais visível é o próprio GitHub, que mantém um MCP Server oficial capaz de ler código, pesquisar ficheiros e interagir com repositórios em nome de um agente. Esse servidor foi atualizado para acompanhar a especificação 2026-07-28 assim que esta ficou disponível, o que mostra que projetos com utilização massiva já tratam o MCP como uma dependência de produção, não como uma experiência lateral.
Do lado dos clientes, a documentação oficial da Anthropic sobre o MCP, disponível em docs.anthropic.com, continua a servir de referência central para quem liga o Claude Desktop ou a Claude Code a servidores externos, com exemplos de configuração e boas práticas atualizados a par de cada revisão da especificação. A cobertura da imprensa técnica especializada também reflete a dimensão da mudança: um artigo da Tech Times descreveu a transição para um modelo sem sessões como a maior mudança de arquitetura desde o lançamento do protocolo, citando diretamente o impacto na forma como equipas de infraestrutura configuram balanceadores de carga e gateways.
Este tipo de adoção cruzada, entre um fornecedor de modelos, uma plataforma de código como o GitHub e a imprensa técnica a documentar cada revisão, é o sinal mais claro de que o MCP deixou de ser um projeto interno da Anthropic para se tornar uma peça de infraestrutura partilhada. Para quem está a decidir se vale a pena investir tempo a aprender o protocolo agora, essa combinação de fatores pesa mais do que qualquer previsão isolada sobre o futuro de uma única ferramenta.
Segurança: o que mudou na especificação 2026-07-28
A revisão mais recente da especificação, disponível na íntegra no site oficial, trouxe várias mudanças com impacto direto na segurança de quem opera servidores MCP em produção. Além do já referido endurecimento da autorização, a eliminação do handshake de sessão retira uma superfície de ataque conhecida: sessões antigas que ficavam “penduradas” em memória partilhada e podiam, em teoria, ser reutilizadas por um cliente diferente do que as criou.
O encaminhamento baseado em cabeçalhos (header-based routing) também facilita auditoria: como cada pedido HTTP transporta a informação de encaminhamento em cabeçalhos legíveis, ferramentas de registo e deteção de segredos conseguem inspecionar o tráfego sem decifrar o corpo do pedido, o que reduz a necessidade de inspeção profunda de pacotes em gateways empresariais. Isto não elimina, no entanto, a responsabilidade de quem escreve o servidor: continuar a validar tokens, limitar o âmbito de cada tool ao mínimo necessário e nunca confiar cegamente em texto vindo de um resource antes de o passar para uma tool que executa ações continuam a ser boas práticas essenciais, independentemente das melhorias ao nível do protocolo. Para quem já testa modelos e agentes com outras ferramentas de segurança de IA, o changelog oficial do MCP vale a pena acompanhar a cada revisão trimestral.
Há ainda um risco que o protocolo por si só não resolve: instalar um servidor MCP de terceiros é, na prática, dar a esse código a mesma confiança que se daria a uma dependência de software normal. Um servidor malicioso ou mal escrito pode devolver texto manipulado através de um resource com o único objetivo de fazer o modelo executar uma tool que não devia, uma técnica conhecida como injeção indireta de prompt. Antes de ligar um servidor MCP que não escreveu, leia o código-fonte, confirme quem o publica e trate-o com o mesmo escrutínio que aplicaria a qualquer pacote com permissões de escrita instalado no seu sistema. Nunca ligue, a um agente com autonomia para agir sozinho, um servidor cuja origem não consiga verificar.
Perguntas frequentes
O que é exatamente o Model Context Protocol?
É um protocolo aberto que define como aplicações de IA (hosts) se ligam a servidores externos que expõem ferramentas, dados e prompts, através de um contrato comum em vez de integrações específicas por fornecedor.
Preciso de saber Python para construir um servidor MCP?
Não necessariamente. O SDK oficial em TypeScript (@modelcontextprotocol/sdk, versão 1.30.0) permite construir servidores em Node.js com uma API equivalente à do Python, e existem SDKs para outras linguagens em maturidade variável.
O MCP funciona só com o Claude?
Não. Apesar de ter nascido na Anthropic, o protocolo é agora mantido pela Aggent AI Foundation sob a Linux Foundation, com o objetivo explícito de ser um padrão aberto usado por vários hosts e não apenas pelos produtos da Anthropic.
Qual a diferença entre uma tool e um resource?
Uma tool representa uma ação que o modelo pode decidir executar sozinho, com possíveis efeitos secundários. Um resource representa dados de leitura que o utilizador ou o modelo podem consultar para dar contexto, normalmente sem alterar estado.
Posso usar o mesmo servidor MCP em vários hosts diferentes?
Sim, essa é uma das vantagens centrais do protocolo. O mesmo servidor, sem qualquer alteração, pode ser ligado ao Claude Desktop, à Claude Code ou a qualquer outro host que implemente um cliente MCP compatível com a especificação usada.
É seguro expor um servidor MCP na internet?
Só com autenticação e HTTPS obrigatórios. Um servidor MCP sem validação de token, acessível publicamente, permite que qualquer pessoa com o URL invoque as suas tools, incluindo as que escrevem ou apagam dados.
O que muda com a especificação 2026-07-28 em relação a versões anteriores?
A mudança principal é tornar o protocolo sem estado ao nível do transporte HTTP, eliminando o handshake e o ID de sessão, além de reforçar regras de autorização e tornar as respostas de listagem de tools, resources e prompts colocáveis em cache.
Preciso de migrar servidores antigos para a nova especificação imediatamente?
Não de forma urgente. Os SDKs oficiais mantiveram compatibilidade retroativa durante a transição, pelo que servidores existentes continuam a funcionar enquanto planeia a migração para tirar partido das melhorias de desempenho e segurança da revisão mais recente.




