Phase 13 - Lesson 10

MCP Resources e Prompts — Exposição de Contexto Além das Ferramentas

This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.

As ferramentas recebem 90 por cento da atenção do MCP. As outras duas primitivas de servidor resolvem problemas diferentes. Recursos expõem dados para leitura; prompts expõem templates reutilizáveis como comandos de barra (slash-commands). Muitos servidores deveriam usar recursos em vez de envelopar leituras em ferramentas, e prompts em vez de codificar fluxos de trabalho diretamente nos prompts do cliente. Esta lição apresenta a regra de decisão e percorre as mensagens resources/* e prompts/*.

Tipo: Build Linguagens: Python (stdlib, resource + prompt handler) Pré-requisitos: Phase 13 · 07 (MCP server) Tempo: ~45 minutos

Objetivos de Aprendizado

  • Decidir entre expor uma funcionalidade como uma ferramenta, um recurso ou um prompt para um determinado domínio.
  • Implementar resources/list, resources/read, resources/subscribe e manipular notifications/resources/updated.
  • Implementar prompts/list e prompts/get com templates de argumentos.
  • Reconhecer quando o host exibe prompts como comandos de barra versus contexto auto-injetado.

O Problema

Um servidor MCP ingênuo para um aplicativo de notas expõe tudo como ferramentas: notes_read, notes_list, notes_search. Isso envolve todo acesso a dados em uma chamada de ferramenta orientada por modelo. Consequências:

  • O modelo precisa decidir se deve chamar notes_read para cada consulta que possa se beneficiar do contexto.
  • O conteúdo somente leitura não pode ser assinado ou transmitido para o painel lateral do host.
  • As interfaces de usuário do cliente (painel de anexo de recursos do Claude Desktop, seletor "Include file" do Cursor) não conseguem exibir os dados.

A divisão correta: expor dados como um recurso, expor ações mutáveis ou calculadas como ferramentas, expor fluxos de trabalho reutilizáveis de várias etapas como prompts. Cada primitiva tem sua facilidade de experiência de usuário (UX affordance) e seu padrão de acesso.

O Conceito

Tools vs resources vs prompts — a regra de decisão

Funcionalidade Primitiva
O usuário deseja buscar, filtrar ou transformar dados tool
O usuário deseja que o host inclua esses dados como contexto resource
O usuário deseja um fluxo de trabalho com template que possa reexecutar prompt

Diretriz: se o modelo se beneficiaria ao chamá-lo em cada consulta relacionada, é uma ferramenta. Se o usuário se beneficiaria ao anexá-lo a uma conversa, é um recurso. Se um fluxo de trabalho completo de várias etapas é a unidade que o usuário deseja reutilizar, é um prompt.

Recursos

resources/list retorna {resources: [{uri, name, mimeType, description?}]}. resources/read recebe {uri} e retorna {contents: [{uri, mimeType, text | blob}]}.

URIs podem ser qualquer coisa endereçável:

  • file:///Users/alice/notes/mcp.md
  • postgres://my-db/query/SELECT ...
  • notes://note-14 (esquema personalizado)
  • memory://session-2026-04-22/recent (específico do servidor)

contents[] suporta tanto texto quanto binário. O binário usa blob como uma string codificada em base64 mais um mimeType.

Assinaturas de recursos

Declare {resources: {subscribe: true}} nas capacidades. O cliente chama resources/subscribe {uri}. O servidor envia notifications/resources/updated {uri} quando o recurso é alterado. O cliente lê novamente.

Caso de uso: um servidor de notas cujos recursos são arquivos em disco; um monitorador de arquivos (file watcher) dispara notificações de atualização; o Claude Desktop puxa novamente o arquivo para o contexto quando ele é editado fora do host.

Templates de recursos (adição de 2025-11-25)

resourceTemplates permitem expor um padrão de URI parametrizado: notes://{id} com id como um alvo de autocompletar. O cliente pode autocompletar IDs no seletor de recursos.

Prompts

prompts/list retorna {prompts: [{name, description, arguments?}]}. prompts/get recebe {name, arguments} e retorna {description, messages: [{role, content}]}.

Um prompt é um template que preenche uma lista de mensagens que o host fornece ao seu modelo. Por exemplo, um prompt code_review recebe um argumento file_path e retorna uma sequência de três mensagens: uma mensagem do sistema, uma mensagem do usuário com o corpo do arquivo e uma inicialização do assistente com um template de raciocínio.

Hosts e prompts

O Claude Desktop, VS Code e Cursor expõem prompts como comandos de barra na interface de chat. O usuário digita /code_review e escolhe os argumentos em um formulário. O prompt do servidor é o contrato entre o "atalho do usuário" e o "prompt completo enviado ao modelo".

Nem todo cliente suporta prompts ainda — verifique a negociação de capacidades. Um servidor com capacidade de prompt declarada, mas um cliente sem suporte a prompt, simplesmente não verá os comandos de barra.

A notificação "list changed"

Tanto recursos quanto prompts emitem notifications/list_changed quando o conjunto muda. Um servidor de notas que acabou de importar 20 novas notas emite notifications/resources/list_changed; o cliente chama novamente resources/list para carregar as adições.

Convenções de tipo de conteúdo

Para texto: mimeType: "text/plain", text/markdown, application/json. Para binário: image/png, application/pdf, além do campo blob. Para MCP Apps (Lição 14): text/html;profile=mcp-app em uma URI ui://.

Recursos dinâmicos

Uma URI de recurso não precisa corresponder a um arquivo estático. notes://recent pode retornar as últimas cinco notas a cada leitura. db://query/users/active pode executar uma consulta parametrizada. O servidor é livre para calcular o conteúdo dinamicamente.

Regra: se o cliente puder fazer cache por URI, a URI deve ser estável. Se o cálculo for de execução única, a URI deve incluir um timestamp ou um nonce para que o cache do cliente não expire.

Assinaturas vs polling

Clientes capazes de assinatura recebem atualizações automáticas (push) do servidor via notifications/resources/updated. Clientes anteriores à assinatura ou hosts que não oferecem suporte realizam polling relendo o recurso. Ambos estão em conformidade com a especificação. A declaração de capacidades do servidor diz ao cliente qual opção ele suporta.

Custo das assinaturas: estado por sessão no servidor (quem está assinado em quê). Mantenha o conjunto assinado limitado; clientes desconectados devem expirar por tempo limite (timeout).

Prompts vs prompts do sistema

Prompts no MCP não são prompts do sistema. O prompt do sistema do host (suas próprias instruções de operação) e os prompts do MCP (templates fornecidos pelo servidor invocados pelo usuário) vivem lado a lado. Um cliente bem-comportado nunca permite que um prompt do servidor substitua seu próprio prompt do sistema; ele os sobrepõe em camadas.

Use na Prática

O code/main.py estende o servidor de notas da Lição 07 com:

  • Recursos por nota (notes://note-1, etc.) com suporte a resources/subscribe.
  • Um prompt review_note que renderiza para um template de três mensagens.
  • Uma simulação de monitorador de arquivos (file-watcher) que emite notifications/resources/updated quando uma nota é modificada.
  • Um recurso dinâmico notes://recent que sempre retorna as últimas cinco notas.

Execute a demonstração para ver o fluxo completo.

Envie

Esta lição produz outputs/skill-primitive-splitter.md. Dado um servidor MCP proposto, a habilidade categoriza cada capacidade como tool / resource / prompt com uma justificativa.

Exercícios

  1. Execute o code/main.py. Observe a lista inicial de recursos, depois acione a edição de uma nota e verifique se o evento notifications/resources/updated é disparado.

  2. Adicione um emissor de resources/list_changed: quando uma nova nota for criada, envie a notificação para que os clientes realizem a redescoberta.

  3. Projete três prompts para um servidor MCP do GitHub: summarize_pr, triage_issue, release_notes. Cada um com esquemas de argumentos. O corpo do prompt deve ser executável sem edições adicionais.

  4. Pegue uma ferramenta existente no servidor da Lição 07 e classifique se ela deve continuar sendo uma ferramenta ou se deve ser dividida em um par de recurso e ferramenta. Justifique em uma frase.

  5. Leia as seções server/resources e server/prompts da especificação. Identifique o único campo em resources/read que é raramente preenchido, mas suportado pela especificação. Dica: olhe para _meta no conteúdo do recurso.

Termos-Chave

Termo O que as pessoas dizem O que realmente significa
Resource "Dados expostos" Conteúdo endereçável por URI que o host pode ler
Resource URI "Ponteiro para dados" Identificador com prefixo de esquema (file://, notes://, etc.)
resources/subscribe "Monitorar alterações" Atualizações via push do servidor com opt-in do cliente para uma URI específica
notifications/resources/updated "Recurso alterado" Sinal para o cliente de que um recurso assinado tem novo conteúdo
Resource template "URI parametrizada" Padrão de URI com dicas de autocompletar para o seletor do host
Prompt "Template de comando de barra" Template nomeado de várias mensagens com slots de argumentos
Prompt arguments "Entradas do template" Parâmetros tipados que o host coleta antes da renderização
prompts/get "Renderizar template" O servidor retorna a lista de mensagens preenchida
Content block "Bloco digitado" `{type: text
Slash-command UX "Atalho do usuário" O host exibe prompts como comandos começando com /

Leitura Adicional

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).