MCP Server
Construa um servidor de desenvolvimento com consultar_estoque, uma política como resource e um prompt de revisão. Comece pelo executor local e depois conecte-o a uma implementação MCP compatível. Os dados são fictícios e somente leitura. O laboratório deve mostrar o contrato anunciado ao cliente e a resposta realmente produzida, incluindo casos inválidos.
A entrega completa contém versão do runtime, revisão de protocolo, transporte e mensagens capturadas. O código da leitura verifica o núcleo. A resolução integrada deste laboratório acrescenta o servidor stdio e um cliente real, para verificar também descoberta e transporte. Você vai investigar especificamente a diferença entre erro de argumentos, item desconhecido e erro interno do serviço.
JavaScriptBashMCPAo terminar esta aula
- Quantidade zero é dado válido, não erro de consulta.
- O catálogo anunciado deve corresponder ao executor testado.
- Uma falha de chamada não deve destruir o servidor nem revelar detalhes internos.
Antes de continuar: Leitura: MCP Server
Valide o executor antes de publicar a tool
FundamentosSalve estoque.cjs e execute I2. Compare as chaves retornadas com outputSchema. Envie um argumento quantidade e confirme a rejeição de campo extra; envie sku numérico e confirme a rejeição de tipo. Execute I99 e registre item desconhecido. Não use o mesmo texto de erro para todos os casos: o cliente precisa distinguir problema corrigível na chamada de ausência legítima no catálogo. Acrescente uma verificação automática de que a quantidade retornada é inteira e não negativa.
Crie um catálogo com dois itens e escreva casos de teste com quantidade zero e positiva. Zero não é falha de consulta; é uma observação válida de indisponibilidade. Ao integrar com um modelo, esse caso deve produzir uma resposta que não promete estoque. Mantenha a fonte no retorno para que o host consiga associar a afirmação ao catálogo. Se o serviço real tiver data de atualização, inclua-a e explique como o consumidor deve tratar informações antigas. O schema precisa acompanhar essa mudança.
Monte o servidor e confira a revisão
FundamentosInstale um runtime ou SDK MCP com versão fixa, verifique sua revisão suportada e siga o guia oficial correspondente. Registre o descritor e o executor, além de discovery e listagens exigidas. Configure stdio para o primeiro teste local ou HTTP em endereço de desenvolvimento. Na revisão 2026-07-28, confira _meta por requisição e server/discover. Se o pacote escolhido usar uma revisão anterior, documente o handshake legado e não produza mensagens atuais misturadas. Uma implementação pode interoperar por fallback, mas isso precisa ser observado.
Conecte um cliente e capture a tool listada. Compare nome, inputSchema e outputSchema com o arquivo de domínio. Faça a chamada I2 e confira o envelope, a correlação e o conteúdo estruturado. Provoque um argumento inválido pela chamada real e confirme que o processo continua capaz de responder a uma consulta válida posterior. Isso demonstra isolamento de falha por operação. Se o erro encerrar o servidor, revise o tratamento no adaptador em vez de mascarar a falha no domínio.
Acrescente contexto e um prompt limitado
FundamentosPublique politica://devolucao como resource permitido e uma URI privada fictícia como caso recusado. Leia o recurso pelo cliente, registre tipo de mídia e origem e confirme o limite de tamanho. Para uma URI desconhecida, devolva a condição correspondente sem tentar ler qualquer caminho de arquivo recebido. Crie um prompt que solicita pedido e motivo e retorna uma instrução de revisão informativa. Seus argumentos não devem incluir segredo, tenant arbitrário ou uma opção que confirme devolução.
Selecione o prompt e compare o texto produzido com seus argumentos. Remova um argumento obrigatório e observe o comportamento documentado da implementação. Acrescente conteúdo adversarial fictício à política e verifique que o host conserva a fronteira entre contexto e autorização. O servidor pode fornecer dados úteis, mas não deve instruir o cliente a ignorar sua política. O teste precisa mostrar uma ação proibida que permanece bloqueada, e não somente uma promessa no prompt de que ela será ignorada.
Revise logs e falhas internas
FundamentosEm stdio, provoque um erro e confira que stdout contém somente mensagens do protocolo. Envie diagnóstico a stderr ou pelo mecanismo MCP apropriado, com identificador e status. Remova qualquer valor de credencial da evidência. Simule indisponibilidade do catálogo e verifique que o cliente recebe uma falha útil sem stack interno. Termine com um README contendo comando de execução, versão, contratos e os quatro casos observados. Declare quais garantias pertencem ao núcleo local e quais foram demonstradas no transporte.
Resolução integrada, ambiente e evidência
FundamentosSalve a resolução como server.mjs e o consumidor de verificação abaixo como client.mjs. O servidor real usa McpServer2.3.1, schemas Zod, registerTool, registerResource, registerPrompt e serveStdio. O SDK publica capabilities, discovery e listagens da revisão 2026-07-28; o cliente fixa essa revisão e valida as respostas. A factory de serveStdio permite ao transporte reconhecer a era moderna, e legacy:reject impede fallback silencioso neste laboratório. O executor de estoque continua separado e não reserva itens. Erro de schema é tratado antes da consulta, item desconhecido retorna falha de domínio e stdout fica reservado ao protocolo. O teste integrado passou com nominal, schema inválido, domínio ausente, resource proibido, prompt incompleto e timeout. Esta implementação é local e sem autenticação de rede; o próximo laboratório acrescenta a fronteira remota.
↗ MCP TypeScript server SDK v2 — official package guide↗ Build an MCP server↗ Tools — MCP 2026-07-28
npm init -y
npm install --save-exact @modelcontextprotocol/server@2.3.1 @modelcontextprotocol/client@2.3.1 zod@4.6.5
node client.mjsimport { Client } from '@modelcontextprotocol/client';
import { StdioClientTransport } from '@modelcontextprotocol/client/stdio';
import { fileURLToPath } from 'node:url';
import assert from 'node:assert/strict';
const client=new Client({name:'CursoClient',version:'1.0.0'},{versionNegotiation:{mode:{pin:'2026-07-28'}}});
const transport=new StdioClientTransport({command:process.execPath,args:[fileURLToPath(new URL('./server.mjs',import.meta.url))],stderr:'inherit'});
try {
await client.connect(transport);
const descoberta=await client.discover();
assert(descoberta.supportedVersions.includes('2026-07-28'));
console.log('discovery',descoberta);
console.log('tools',await client.listTools());
const ok=await client.callTool({name:'consultar_estoque',arguments:{sku:'I2'}});
assert.equal(ok.structuredContent.quantidade,3);console.log('nominal',ok);
console.log('dominio',await client.callTool({name:'consultar_estoque',arguments:{sku:'I99'}}));
const invalido=await client.callTool({name:'consultar_estoque',arguments:{sku:2}});
assert.equal(invalido.isError,true);console.log('schema recusado',invalido);
console.log('resource',await client.readResource({uri:'politica://devolucao'}));
console.log('prompt',await client.getPrompt({name:'revisar_devolucao',arguments:{pedido:'P7'}}));
await assert.rejects(()=>client.readResource({uri:'politica://privada'}));
await assert.rejects(()=>client.getPrompt({name:'revisar_devolucao',arguments:{}}));
await assert.rejects(()=>client.callTool({name:'demorar',arguments:{}},{timeout:20}));
console.log('timeout confirmado; leitura tardia nao tem efeito');
} finally {await client.close();}
↗ MCP TypeScript server SDK v2 — official package guide↗ Discovery — MCP 2026-07-28
Exercício aplicado
Publique consulta de estoque, política de devolução e prompt de revisão para uma loja. Valide campos e preserve a disponibilidade do servidor diante de chamadas inválidas.
- Execute o núcleo com item conhecido, desconhecido, tipo errado e campo extra.
- Registre os contratos em um runtime MCP de versão conhecida.
- Capture discovery, listagem e chamada em transporte real.
- Teste resource recusado, prompt incompleto e logs sem segredos.
Abrir resolução comentada
Salve a resolução como server.mjs e o consumidor de verificação abaixo como client.mjs. O servidor real usa McpServer2.3.1, schemas Zod, registerTool, registerResource, registerPrompt e serveStdio. O SDK publica capabilities, discovery e listagens da revisão 2026-07-28; o cliente fixa essa revisão e valida as respostas. A factory de serveStdio permite ao transporte reconhecer a era moderna, e legacy:reject impede fallback silencioso neste laboratório. O executor de estoque continua separado e não reserva itens. Erro de schema é tratado antes da consulta, item desconhecido retorna falha de domínio e stdout fica reservado ao protocolo. O teste integrado passou com nominal, schema inválido, domínio ausente, resource proibido, prompt incompleto e timeout. Esta implementação é local e sem autenticação de rede; o próximo laboratório acrescenta a fronteira remota.
O executor local valida tipo e campos antes da consulta. I2 retorna quantidade 3; campo extra falha na forma; I99 falha no domínio. Na integração, cada resultado é adaptado ao envelope da revisão usada, mantendo o servidor disponível para a próxima requisição. A listagem deve mostrar exatamente os schemas que você testou.
O resource possui URI permitida, conteúdo limitado e origem identificável. O prompt organiza revisão sem executar efeito. Logs comuns de stdio ficam fora do canal de mensagens e falhas internas não revelam segredos. A aceitação do servidor depende de uma chamada real do cliente além da execução do arquivo local.
// MCP SDK v2.3.1: stdio real; stdout fica reservado ao protocolo.
import { McpServer } from '@modelcontextprotocol/server';
import { serveStdio } from '@modelcontextprotocol/server/stdio';
import { z } from 'zod';
function criarServidor() {
const server = new McpServer({name:'LojaCurso',version:'1.0.0'});
const catalogo={I2:3,I3:0};
server.registerTool('consultar_estoque',{
description:'Consulta sem reservar.',
inputSchema:z.object({sku:z.string()}).strict(),
outputSchema:z.object({sku:z.string(),quantidade:z.number().int(),fonte:z.string()})
},async ({sku})=>{
if(!(sku in catalogo))return {isError:true,content:[{type:'text',text:'item desconhecido'}]};
const out={sku,quantidade:catalogo[sku],fonte:'catalogo local'};
console.error(JSON.stringify({evento:'consulta',sku}));
return {content:[{type:'text',text:JSON.stringify(out)}],structuredContent:out};
});
server.registerTool('demorar',{inputSchema:z.object({})},async()=>{
await new Promise(r=>setTimeout(r,200));return {content:[{type:'text',text:'tarde'}]};
});
server.registerResource('politica','politica://devolucao',{mimeType:'text/plain'},async uri=>({contents:[{uri:uri.href,mimeType:'text/plain',text:'Politica ficticia: revisar devolucao com comprovante.'}]}));
server.registerPrompt('revisar_devolucao',{argsSchema:z.object({pedido:z.string()})},({pedido})=>({messages:[{role:'user',content:{type:'text',text:'Revise '+pedido+' usando a politica; nao confirme operacoes.'}}]}));
return server;
}
serveStdio(criarServidor,{legacy:'reject',onerror:e=>console.error(e.message)});
Como conferir seu resultado
- Entrada e saída correspondem aos schemas anunciados.
- Uma consulta válida funciona depois da falha.
- stdout de stdio não contém diagnóstico comum.
Aplique em um problema novo
Primeiro resolva sem consultar a resposta. Explique suas decisões e guarde a evidência. A conclusão de leitura é independente desta autoavaliação.
Confira seus pré-requisitos
- Separar executor de transporte MCP.
- Definir schemas de entrada/saída.
Servidor de biblioteca: consultar_livro aceita id: string e retorna exemplares: int. Envie id:7, depois id: 'L7' com 2 exemplares. Resource tem prazo 14 dias e prompt organiza revisão sem renovar livro.
Conferir raciocínio e critérios de domínio
id:7 viola schema e é rejeitado. A consulta L7 posterior retorna 2, demonstrando que a falha de uma operação não encerrou o servidor.
Resource informa prazo 14 dias com URI/origem; prompt prepara revisão mas não executa renovação, que exigiria outra capacidade autorizada.
Cliente real deve observar listagem/schema/call. Diagnóstico vai a stderr; stdout misturado a logs quebraria o canal stdio.
Evidências para autoavaliação ou revisão por pares
- Schema e sobrevivência: id:7 viola schema e é rejeitado. A consulta L7 posterior retorna 2, demonstrando que a falha de uma operação não encerrou o servidor.
- Resource e prompt: Resource informa prazo 14 dias com URI/origem; prompt prepara revisão mas não executa renovação, que exigiria outra capacidade autorizada.
- Evidência e canal: Cliente real deve observar listagem/schema/call. Diagnóstico vai a stderr; stdout misturado a logs quebraria o canal stdio.
Um erro frequente
Um executor local prova servidor MCP completo.
Servidor completo exige transporte e chamadas reais, além do executor.
Teste sua compreensão
Responda com suas palavras antes de abrir o comentário. Saber explicar uma decisão é parte do domínio.
1. inputSchema substitui autorização?
Não. Ele descreve e valida forma de argumentos.
O executor precisa verificar identidade e acesso ao catálogo.
2. Resource é um caminho arbitrário de arquivo?
Não. A URI deve ser resolvida dentro do conjunto permitido.
Ler caminhos livres pode expor conteúdo fora do escopo.
3. O núcleo local já é um servidor MCP completo?
Não. Falta o adaptador compatível e a evidência de transporte.
Domínio e protocolo são camadas com verificações próprias.
Seu progresso fica salvo neste navegador. Concluir a leitura não substitui demonstrar o domínio nos exercícios.
Referências e aprofundamento
Documentação oficial e trabalhos originais. As referências registram o escopo e as limitações para você conferir o que sustentam.
- Build an MCP server
Model Context Protocol • consulta: 2026-10-06
MCPCriação de servidor e tools usando SDKs oficiais; execução e teste local.
Limites: Sintaxe varia por linguagem e geração de SDK; exemplos precisam de implementação da autorização de negócio.
- Base protocol — MCP 2026-07-28
Model Context Protocol • consulta: 2026-10-06
MCPJSON-RPC, schema, versão/capabilities em _meta e JSON Schema2020-12.
Limites: Fonte aberta contém versão por requisição; compatibilidade com revisões antigas exige implementação explícita.
- Tools — MCP 2026-07-28
Model Context Protocol • consulta: 2026-10-06
MCPtools/list/call, inputSchema/outputSchema, resultados, segurança e logs para auditoria.
Limites: Anotações e descrição não concedem autorização; outputs continuam não confiáveis.
- Resources — MCP 2026-07-28
Model Context Protocol • consulta: 2026-10-06
MCPResources, URIs, leitura, templates e notificações.
Limites: Recursos são contexto fornecido por servidor, não instruções automaticamente confiáveis.
- Prompts — MCP 2026-07-28
Model Context Protocol • consulta: 2026-10-06
MCPDescobrir prompts, buscar mensagens e parametrizar templates; capability em DiscoverResult.
Limites: Prompt vem do servidor; controle do usuário sobre seleção não garante segurança do conteúdo.
- Logging — MCP 2026-07-28
Model Context Protocol • consulta: 2026-10-06
MCPMensagens de logging, níveis e logLevel por requisição.
Limites: Logging MCP não é armazenamento de auditoria imutável; evitar segredos nos logs.
- MCP TypeScript server SDK v2 — official package guide
Model Context Protocol • consulta: 2026-10-06
TypeScriptMCPPacote @modelcontextprotocol/server, linha estável v2 para MCP 2026-07-28, exposição de tools/resources/prompts, adapters e guias de migração.
Limites: README apresenta a linha de SDK e encaminha à referência de API. Fixar versão e conferir exports no pacote instalado; não confundir exemplos v1 com protocolo e packages v2.
- Discovery — MCP 2026-07-28
Model Context Protocol • consulta: 2026-10-06
MCPDiscovery do servidor e capacidades disponíveis.
Limites: Separar descoberta de capacidades de autenticação e de descoberta de endereço de servidor.