Quais são as primitivas do MCP?
O MCP tem três primitivas de servidor: tools, que o modelo aciona; resources, que a aplicação anexa ao contexto; e prompts, que o usuário escolhe de propósito. A especificação chama a divisão de hierarquia de controle, e ela não separa as três pelo formato do dado. Separa por quem decide quando aquilo entra no contexto1.
Essa é a frase que resolve quase toda dúvida de classificação. O mesmo relatório de vendas pode ser tool, resource ou prompt, e a resposta certa depende do ator que puxa o gatilho, não do conteúdo.
As três aparecem no Model Context Protocol como o que um servidor expõe. Se você só vai escrever tools, o texto que descreve cada uma merece atenção própria, porque ele entra no raciocínio do modelo. E se a dúvida é como tudo isso vira uma chamada ao provedor do modelo, a comparação está em MCP ou function calling.
Tools: o que o modelo aciona
Tools são funções executáveis. O cliente descobre com tools/list e invoca com
tools/call, passando argumentos que precisam bater com o inputSchema da tool,
um JSON Schema que assume a versão 2020-12 quando não há $schema2.
A tool pode declarar também um outputSchema. Quando declara, o servidor precisa
devolver resultado estruturado conforme o schema, no campo structuredContent, e
o cliente deve validar. Para compatibilidade, o mesmo JSON serializado costuma vir
também como bloco de texto no campo content2.
O detalhe que mais gente implementa errado é o canal de erro, porque são dois. Erro
de protocolo é para requisição malformada, tool inexistente e falha do servidor,
e volta como erro JSON-RPC comum. Erro de execução volta dentro do resultado, com
isError igual a true e o texto da falha em content. A especificação é
explícita sobre o motivo: erros de execução carregam informação acionável, e
clientes devem entregá-los ao modelo para que ele se corrija; erros de
protocolo o cliente pode entregar, mas eles dificilmente resultam em recuperação
bem-sucedida2. Um servidor que devolve -32603 quando a data está em formato
errado tira do modelo a chance de tentar de novo com a data certa.
Duas convenções pequenas com efeito prático. Nomes de tool devem ter entre 1 e 128
caracteres, usar apenas letras ASCII, dígitos, sublinhado, hífen e ponto, e ser
únicos dentro do servidor. E servidores devem devolver as tools em ordem
determinística, porque isso permite ao cliente cachear a lista e melhora a taxa de
acerto do prompt cache quando as tools entram no contexto do modelo2. Ordenar
por um Map de iteração instável custa dinheiro de verdade.
Tool ou resource para o mesmo dado
Pegue um relatório de vendas mensal e exponha das duas formas.
Como tool, get_sales_report recebe o mês como argumento e o modelo a chama no
meio da tarefa quando julga que precisa. A declaração da tool fica no contexto em
toda chamada ao modelo, use-se ou não. O modelo escolhe o argumento, o que é bom
quando o mês certo depende da conversa e ruim quando o modelo escolhe o mês
errado.
Como resource, o mesmo relatório vira sales://2026-07, com um URI estável, e
entra no contexto quando a aplicação anexa. Não ocupa nada no prompt até ser
anexado. Em compensação, alguém precisa escolher: ou o usuário, numa lista de
seleção, ou a aplicação, por alguma heurística. A especificação diz que resources
são orientados pela aplicação, com o host decidindo como incorporar o contexto, e
lista as formas possíveis, inclusive inclusão automática por heurística ou por
seleção do próprio modelo1.
A diferença de segurança sai daí e costuma passar despercebida. O protocolo não dá
ao modelo um canal para ler um resource: resources/read é uma chamada do cliente.
Texto injetado dentro de um resultado de tool pode induzir o modelo a chamar outra
tool, mas não a puxar um resource sozinho — a menos que a aplicação tenha optado
por deixar o modelo selecionar, que é uma das opções que a spec permite. Se você
está desenhando um servidor com dado sensível, expor como resource move a decisão
para fora do modelo.
Resources: o que a aplicação anexa
Todo resource é identificado por um URI. O cliente lista com resources/list e lê
com resources/read, e um único read pode devolver vários conteúdos, como acontece
quando o URI aponta para um diretório1.
Resources parametrizados existem como templates, no formato de URI template da RFC
6570, listados em resources/templates/list. Os argumentos podem ser
autocompletados pela API de completion, que é o que permite uma interface oferecer
sugestões enquanto o usuário digita o caminho.
A especificação define alguns esquemas de URI e é opinativa sobre um deles. Use
https:// apenas quando o cliente consegue buscar o recurso direto da web, sem
passar pelo servidor MCP; para os outros casos, prefira outro esquema ou defina um
próprio, mesmo que quem baixe o conteúdo pela internet seja o próprio servidor1.
Também existem file:// e git://, e nada impede um esquema seu.
Cada resource pode carregar anotações: audience, com os valores user e
assistant, priority entre 0.0 e 1.0, e lastModified em ISO 8601. Elas são
dicas para o cliente filtrar e priorizar o que entra no contexto, não regras que o
protocolo faz cumprir.
Uma regra de erro que evita bug silencioso: resource inexistente devolve -32602,
e o servidor não pode devolver um array contents vazio para um resource que
não existe, porque isso é ambíguo entre “existe e está vazio” e “não existe”1.
Prompts: o que o usuário escolhe
Prompts são templates de mensagens que o servidor expõe e o usuário invoca. O
cliente lista com prompts/list e resolve com prompts/get, passando os
argumentos declarados. O retorno é uma lista de mensagens com papel user ou
assistant e conteúdo que pode ser texto, imagem, áudio, link de resource ou
resource embutido.
A especificação define prompts como user-controlled e faz questão de qualificar a frase: isso se refere a quem decide quando o prompt é usado, não a quem escreve o conteúdo dele, que é definido pelo servidor1. A distinção importa para quem avalia risco. Um prompt não é mais confiável por ser “do usuário”; ele é texto de servidor que o usuário aceitou colar na conversa.
O caso de uso típico é o comando de barra, e a própria spec usa esse exemplo. Os argumentos aceitam autocompletar pela API de completion, e a lista pode mudar em tempo de execução, com o servidor notificando quem tiver aberto o stream de assinaturas.
Um exemplo concreto ajuda a fixar. Um servidor de repositório expõe o prompt
code_review, com um argumento obrigatório chamado code. No editor ele aparece
como um comando; o usuário seleciona um trecho, o cliente chama prompts/get com
esse trecho nos argumentos e recebe de volta uma mensagem de papel user já
montada, com a instrução de revisão escrita pelo servidor e o código embutido.
Até aqui o modelo não viu nada: o que chega a ele é a conversa com a mensagem
pronta dentro, indistinguível de algo que o usuário tivesse digitado.
Como decidir
A pergunta é quem decide quando aquilo entra no contexto.
Se a resposta é o modelo, no meio da tarefa, com parâmetros que ele escolhe na hora, é tool. Se é a aplicação ou o usuário, antes da tarefa, sobre um conteúdo com identidade estável, é resource. Se é o usuário deliberadamente iniciando um fluxo com um formato pronto, é prompt.
Um teste secundário resolve os empates: efeito colateral só existe em tool. Se a operação escreve em algum lugar, dispara e-mail ou cobra alguém, ela não é resource nem prompt, porque nem um nem outro têm semântica de execução.
Onde a divisão falha
Tudo vira tool. É a falha mais comum e a mais cara. Servidores expõem leitura como tool porque tools funcionam em qualquer cliente, e porque o modelo consegue chamá-las sozinho. O custo aparece no contexto: cada declaração de tool ocupa espaço em toda chamada, e a seleção degrada com o número de opções. Um trabalho de 2025 mediu essa degradação em um teste de estresse com MCP e reportou acurácia de seleção de tool de 43,13% contra 13,62% da linha de base, com redução de mais de 50% nos tokens de prompt ao recuperar apenas as tools relevantes por busca semântica3. Outro trabalho do mesmo ano atacou o mesmo problema organizando as tools em uma taxonomia hierárquica e filtrando por consulta, com resultado na mesma direção4. Os números são de arranjos experimentais específicos, não uma lei, mas a direção é consistente entre os dois.
As outras duas dependem do host implementar. Um resource precisa de uma interface para ser escolhido; um prompt precisa de um lugar onde comandos apareçam. Um servidor que aposta em resources pode ficar invisível em hosts que só montaram o caminho de tools. A evidência pública aqui é fraca: os levantamentos disponíveis mediram configuração, uso de SDK e controles de supervisão, não cobertura por primitiva5. Trate como risco de portabilidade, não como fato medido.
A descrição continua sendo entrada não confiável. Vale para as três primitivas, mas dói mais em tools, porque a descrição é o que orienta a escolha do modelo. O estudo de 2025 que analisou 67.057 servidores descreveu exatamente esse caminho: metadados de tool controlados pelo atacante moldam o raciocínio do modelo e induzem operações que o host executa sem verificação independente6.
“User-controlled” não quer dizer seguro. O conteúdo do prompt é do servidor. O usuário controla o momento, e só. Um prompt malicioso é injeção com convite.
O canal de erro errado apaga a chance de recuperação. Um servidor que trata falha de negócio como erro de protocolo transforma um problema que o modelo resolveria em uma parada seca. É um bug de duas linhas com efeito grande no comportamento observado.
Quanto custa cada uma
Ordem de grandeza, para ter noção da forma da conta.
Uma tool custa contexto de forma permanente. Nome, descrição e schema de argumentos ficam na casa de centenas de tokens por tool, reenviados a cada chamada ao modelo. Trinta tools finas custam bem mais que cinco tools grossas que cobrem o mesmo terreno, e ainda pioram a seleção.
Um resource custa quase nada até ser lido, e aí custa o tamanho do conteúdo. É o oposto da tool: caro por uso, barato por existir. Por isso catálogo grande de resources é viável e catálogo grande de tools não é.
Um prompt custa o tamanho das mensagens que ele devolve, e apenas quando o usuário
o invoca. A entrada em prompts/list é pequena.
A consequência prática é uma só: o que você expõe como tool, você paga sempre.
Por onde começar
- Comece com poucas tools de leitura. Elas funcionam em qualquer cliente e dão o retorno mais rápido sobre se o desenho faz sentido.
- Passe para resource o que tem URI natural. Arquivo, documento, registro com identificador estável. Isso tira peso do prompt e tira a decisão do modelo.
- Escreva a descrição da tool como se ela fosse a única documentação. É a única parte da declaração que o modelo lê para decidir.
- Separe os dois canais de erro no primeiro dia.
isErrorpara falha de domínio, erro JSON-RPC para requisição inválida. - Devolva a lista de tools sempre na mesma ordem. Custa uma linha e melhora cache de prompt.
- Meça o tamanho do seu prefixo de tools antes de acrescentar a próxima. Se a lista já passou de uma dezena, o problema seguinte é seleção, não capacidade.
O passo 2 é o que a maioria dos servidores pula, e é por isso que a lista de tools cresce até o ponto em que o modelo passa a escolher mal.
Footnotes
-
A página de primitivas de servidor da revisão
2026-07-28é a fonte para a hierarquia de controle, para o modelo orientado pela aplicação dos resources, para os esquemas de URI, para as anotações e para a definição de prompts como user-controlled. Verificada em 30 de julho de 2026. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 -
A página de tools da mesma revisão é a fonte para
inputSchemaeoutputSchema, parastructuredContent, para os dois canais de erro, para as regras de nome e para a recomendação de ordem determinística. ↩ ↩2 ↩3 ↩4 -
Gan e Sun (2025) mediram, em um teste de estresse com MCP, acurácia de seleção de tool de 43,13% contra 13,62% da linha de base, recuperando apenas as descrições relevantes por busca semântica e cortando mais de 50% dos tokens de prompt. ↩
-
Antonioni et al. (2025) organizaram tools MCP em uma taxonomia hierárquica e filtraram por consulta, reduzindo o tamanho do prompt sem perda relevante de capacidade e melhorando a seleção conforme o número de tools cresce. ↩
-
Majeed et al. (2026) caracterizaram 1.723 aplicações consumidoras de MCP por configuração, uso de SDK e mecanismos de supervisão humana, sem quebrar os dados por primitiva. ↩
-
Li e Gao (2025) descreveram como metadados de tool controlados pelo atacante moldam o raciocínio do modelo e induzem operações que o host executa sem verificação independente, a partir de 67.057 servidores em seis registros. ↩
Perguntas frequentes
- Quais são as primitivas do MCP?
- São três, todas expostas pelo servidor: tools, que o modelo aciona; resources, que a aplicação anexa; e prompts, que o usuário escolhe. A especificação chama isso de hierarquia de controle, e ela é a chave para entender a divisão: cada primitiva tem um ator diferente decidindo quando ela é usada.
- Qual a diferença entre tool e resource no MCP?
- Tool é executável e o modelo a invoca por conta própria com tools/call, podendo ter efeito colateral. Resource é conteúdo identificado por URI, lido com resources/read por decisão da aplicação. A diferença prática é o gatilho e o custo: uma tool ocupa contexto em toda chamada, um resource só quando alguém o anexa.
- Quando usar um resource em vez de uma tool?
- Quando o conteúdo é de leitura, tem identidade estável e faz sentido o usuário ou a aplicação escolherem antes da tarefa começar. Arquivo, esquema de banco, documento de política. Se o modelo precisa buscar aquilo no meio do raciocínio, com parâmetros que ele decide na hora, aí é tool.
- O que é a primitiva prompt no MCP?
- É um template de mensagens que o servidor expõe e o usuário invoca de propósito, tipicamente como comando de barra. O servidor devolve uma lista de mensagens já montadas em prompts/get, com argumentos preenchidos. Usuário controla quando o prompt é usado; quem escreve o conteúdo continua sendo o servidor.
- Uma tool pode devolver dado estruturado?
- Sim. O resultado pode trazer structuredContent, um valor JSON que segue o outputSchema declarado pela tool. Servidores que declaram outputSchema precisam devolver resultado conforme o schema, e clientes devem validar. Por compatibilidade, o mesmo JSON serializado costuma vir também como bloco de texto.
- Erro de tool é erro de protocolo?
- Não, e confundir os dois custa caro. Falha de negócio, validação de entrada e erro de API voltam no resultado com isError igual a true, e o cliente deve entregá-los ao modelo para que ele se corrija. Erro de protocolo é para tool inexistente e requisição malformada, coisas que o modelo dificilmente conserta.
Referências
- Agentic AI Foundation. Model Context Protocol specification, revision 2026-07-28 — Server primitives (2026)
- Agentic AI Foundation. Model Context Protocol specification, revision 2026-07-28 — Tools (2026)
- Gan, T., Sun, Q.. RAG-MCP: Mitigating Prompt Bloat in LLM Tool Selection via Retrieval-Augmented Generation (2025)arXiv:2505.03275
- Antonioni, E. et al.. JSPLIT: A Taxonomy-based Solution for Prompt Bloating in Model Context Protocol (2025)arXiv:2510.14537
- Li, X., Gao, X.. A First Look at the Security Issues in the Model Context Protocol Ecosystem (2025)arXiv:2510.16558
- Majeed, M. H. A., Mahmoud, M., Nadi, S.. An Empirical Study of Model Context Protocol Applications (2026)arXiv:2607.25635