O que vamos construir
Um servidor chamado utilitarios-br, com uma ferramenta, validar_cpf, que confere os dígitos verificadores de um CPF. O exemplo é pequeno de propósito: a lógica cabe em dez linhas, e o resto é o que todo servidor tem. Você precisa do Node.js 20 ou mais recente.
1. Crie o projeto
mkdir utilitarios-br
cd utilitarios-br
npm init -y
npm install @modelcontextprotocol/server zod
npm install -D @types/node typescript
mkdir srcO pacote @modelcontextprotocol/server é o SDK oficial para servidores em TypeScript. O zod descreve os parâmetros de cada ferramenta.
2. Ajuste package.json e tsconfig.json
O projeto precisa ser um módulo ES e ter um script de build. Deixe o package.json com estes campos (o npm install já acrescentou as dependências):
{
"name": "utilitarios-br",
"version": "1.0.0",
"type": "module",
"scripts": { "build": "tsc" }
}{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"types": ["node"],
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}3. Escreva o servidor
import { McpServer } from "@modelcontextprotocol/server";
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import { z } from "zod";
const server = new McpServer({ name: "utilitarios-br", version: "1.0.0" });
function cpfValido(cpf: string): boolean {
const d = cpf.replace(/\D/g, "");
if (d.length !== 11 || /^(\d)\1{10}$/.test(d)) return false;
const digito = (n: number) => {
let soma = 0;
for (let i = 0; i < n; i++) soma += Number(d[i]) * (n + 1 - i);
const resto = (soma * 10) % 11;
return resto === 10 ? 0 : resto;
};
return digito(9) === Number(d[9]) && digito(10) === Number(d[10]);
}
server.registerTool(
"validar_cpf",
{
description: "Confere os dígitos verificadores de um CPF. Não consulta a Receita Federal.",
inputSchema: z.object({
cpf: z.string().describe("CPF com ou sem pontuação, ex.: 529.982.247-25"),
}),
},
async ({ cpf }) => ({
content: [{ type: "text", text: cpfValido(cpf) ? "CPF com dígitos válidos." : "CPF inválido." }],
}),
);
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("utilitarios-br rodando em stdio");
}
main().catch((erro) => {
console.error("Erro fatal:", erro);
process.exit(1);
});Quatro partes merecem atenção:
new McpServerdá nome e versão ao servidor. O cliente mostra esse nome.registerToolrecebe o nome da ferramenta, a descrição com o esquema de entrada e a função. A descrição é lida pelo modelo: diga o que a ferramenta faz e também o que ela não faz.- A função devolve
content, uma lista de blocos. Aqui, um bloco de texto. StdioServerTransportliga o servidor à entrada e saída padrão. Por isso o aviso de início vai emconsole.error: a saída padrão é só do protocolo.
4. Compile
npm run buildO resultado é build/index.js.
5. Teste antes de ligar ao cliente
Um servidor stdio conversa em JSON-RPC, uma mensagem por linha. No nosso teste, enviamos tools/list e tools/call direto ao processo. Esta é a troca registrada:
→ {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"validar_cpf","arguments":{"cpf":"529.982.247-25"}}}
← {"result":{"content":[{"type":"text","text":"CPF com dígitos válidos."}]},"jsonrpc":"2.0","id":2}Para explorar o servidor com uma interface, use o MCP Inspector, a ferramenta de depuração oficial: npx @modelcontextprotocol/inspector node build/index.js.
6. Ligue ao cliente
No Claude Desktop, acrescente o servidor ao arquivo de configuração, com o caminho absoluto do arquivo compilado:
{
"mcpServers": {
"utilitarios-br": {
"command": "node",
"args": ["<CAMINHO_ABSOLUTO>/utilitarios-br/build/index.js"]
}
}
}Reinicie o aplicativo e peça: “O CPF 529.982.247-25 é válido?”. Em outros clientes muda o arquivo, e não o servidor: veja os guias por cliente.
Próximos passos
- Acrescente outra ferramenta com um segundo
registerTool. - Para chamar uma API com chave, leia a chave de
process.enve declare a variável emenv, na configuração do cliente. Nunca escreva a chave no código. - Antes de dar a um servidor acesso a dados reais, leia Segurança no MCP.
- O mesmo servidor em Python está no tutorial seguinte.