topic-scout-mcp
Version:
MCP Server para buscar notícias e identificar tendências sobre tópicos específicos
537 lines (449 loc) • 12.2 kB
Markdown
# 🚀 Guia Completo: Como Criar um MCP Server
Este guia mostra como criar um servidor MCP (Model Context Protocol) do zero, usando o exemplo do Weather Brazil Server que acabamos de criar.
## 📋 O que é MCP?
MCP (Model Context Protocol) é um protocolo que permite que o Claude Desktop se conecte a servidores externos para acessar ferramentas e dados específicos. É como uma "ponte" entre o Claude e sistemas externos.
## 🎯 Estrutura do Projeto
```
meu-mcp-server/
├── src/
│ └── index.ts # Código principal do servidor
├── dist/ # Arquivos compilados (gerado automaticamente)
├── package.json # Dependências e scripts
├── tsconfig.json # Configuração TypeScript
├── mcp-config.json # Configuração para Claude Desktop
├── README.md # Documentação
└── .gitignore # Arquivos ignorados pelo Git
```
## 📦 Passo 1: Inicializar o Projeto
### 1.1 Criar estrutura de pastas
```bash
mkdir meu-mcp-server
cd meu-mcp-server
mkdir src
```
### 1.2 Inicializar package.json
```bash
npm init -y
```
### 1.3 Editar package.json
```json
{
"name": "meu-mcp-server",
"version": "1.0.0",
"description": "Descrição do seu MCP server",
"main": "dist/index.js",
"type": "module",
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "tsx src/index.ts"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^0.4.0"
},
"devDependencies": {
"@types/node": "^20.0.0",
"tsx": "^4.0.0",
"typescript": "^5.0.0"
},
"keywords": ["mcp", "seu-dominio"],
"author": "Seu Nome",
"license": "MIT"
}
```
## ⚙️ Passo 2: Configurar TypeScript
### 2.1 Criar tsconfig.json
```json
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "node",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
```
### 2.2 Instalar dependências
```bash
npm install
npm install -g typescript # Se necessário
```
## 🔧 Passo 3: Criar o Servidor MCP
### 3.1 Estrutura básica do servidor
```typescript
// src/index.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
class MeuMCPServer {
private server: Server;
constructor() {
// Inicializar servidor MCP
this.server = new Server({
name: "meu-mcp-server",
version: "1.0.0",
});
this.setupToolHandlers();
}
private setupToolHandlers() {
// 1. Listar ferramentas disponíveis
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "minha_ferramenta",
description: "Descrição da sua ferramenta",
inputSchema: {
type: "object",
properties: {
// Parâmetros da sua ferramenta
parametro1: {
type: "string",
description: "Descrição do parâmetro",
},
},
required: ["parametro1"],
},
},
],
};
});
// 2. Executar ferramentas
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (name === "minha_ferramenta") {
return await this.executarMinhaFerramenta(args);
}
throw new Error(`Ferramenta desconhecida: ${name}`);
});
}
private async executarMinhaFerramenta(args: any): Promise<any> {
// Lógica da sua ferramenta aqui
const { parametro1 } = args;
// Exemplo de resposta
return {
content: [
{
type: "text",
text: `Resultado da sua ferramenta com parâmetro: ${parametro1}`,
},
],
};
}
async run() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error("🚀 Meu MCP Server iniciado");
}
}
// Executar o servidor
const server = new MeuMCPServer();
server.run().catch(console.error);
```
## 🔑 Passo 4: Adicionar Configurações (se necessário)
### 4.1 Variáveis de ambiente
```typescript
// No construtor da classe
constructor() {
this.server = new Server({
name: "meu-mcp-server",
version: "1.0.0",
});
// Obter configurações do ambiente
this.apiKey = process.env.MINHA_API_KEY || "";
if (!this.apiKey) {
console.error("⚠️ MINHA_API_KEY não encontrada no ambiente");
}
this.setupToolHandlers();
}
```
### 4.2 Tratamento de erros
```typescript
private async executarMinhaFerramenta(args: any): Promise<any> {
try {
// Sua lógica aqui
return {
content: [
{
type: "text",
text: "✅ Sucesso!",
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `❌ Erro: ${error instanceof Error ? error.message : "Erro desconhecido"}`,
},
],
};
}
}
```
## 🏗️ Passo 5: Compilar e Testar
### 5.1 Compilar
```bash
npm run build
```
### 5.2 Criar script de teste
```javascript
// test-server.js
import { spawn } from 'child_process';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
console.log('🧪 Testando MCP Server...\n');
const server = spawn('node', [join(__dirname, 'dist', 'index.js')], {
stdio: ['pipe', 'pipe', 'pipe'],
env: process.env
});
setTimeout(() => {
console.log('✅ Servidor iniciado com sucesso!');
server.kill();
process.exit(0);
}, 2000);
server.stderr.on('data', (data) => {
console.log('📋 Logs:', data.toString());
});
server.on('error', (error) => {
console.error('❌ Erro:', error);
process.exit(1);
});
```
### 5.3 Testar
```bash
node test-server.js
```
## ⚙️ Passo 6: Configurar para Claude Desktop
### 6.1 Criar arquivo de configuração MCP
```json
// mcp-config.json
{
"mcpServers": {
"meu-server": {
"command": "node",
"args": ["/caminho/completo/para/seu/projeto/dist/index.js"],
"env": {
"MINHA_API_KEY": "sua_chave_aqui"
}
}
}
}
```
### 6.2 Configurar no Claude Desktop
1. Abra o Claude Desktop
2. Vá em **Settings** > **MCP Configuration**
3. Adicione o caminho para o arquivo `mcp-config.json`
4. Adicione a ferramenta: `mcp__meu-server__minha_ferramenta`
## 📝 Passo 7: Documentação
### 7.1 Criar README.md
```markdown
# Meu MCP Server
Descrição do seu servidor MCP.
## 🚀 Funcionalidades
- ✅ Funcionalidade 1
- ✅ Funcionalidade 2
## 📋 Pré-requisitos
- Node.js (versão 18+)
- API Key (se necessário)
## 🛠️ Instalação
```bash
npm install
npm run build
```
## ⚙️ Configuração
Configure sua API key:
```bash
export MINHA_API_KEY=sua_chave_aqui
```
## 🔧 Configuração no Claude Desktop
1. Use o arquivo `mcp-config.json`
2. Adicione a ferramenta: `mcp__meu-server__minha_ferramenta`
## 📖 Como Usar
```
Claude, execute minha ferramenta com o parâmetro X
```
## 📊 Exemplo de Resposta
```
✅ Resultado da sua ferramenta com parâmetro: X
```
```
## 🔍 Passo 8: Padrões e Boas Práticas
### 8.1 Estrutura de resposta
```typescript
// Resposta de sucesso
return {
content: [
{
type: "text",
text: "✅ Sucesso! Resultado aqui...",
},
],
};
// Resposta de erro
return {
content: [
{
type: "text",
text: "❌ Erro: Descrição do erro",
},
],
};
```
### 8.2 Validação de parâmetros
```typescript
private async executarMinhaFerramenta(args: any): Promise<any> {
const { parametro1, parametro2 } = args;
// Validar parâmetros obrigatórios
if (!parametro1) {
return {
content: [
{
type: "text",
text: "❌ Erro: parametro1 é obrigatório",
},
],
};
}
// Sua lógica aqui...
}
```
### 8.3 Logs e debugging
```typescript
private async executarMinhaFerramenta(args: any): Promise<any> {
console.error("🔍 Executando ferramenta com args:", args);
try {
// Sua lógica aqui
console.error("✅ Ferramenta executada com sucesso");
} catch (error) {
console.error("❌ Erro na ferramenta:", error);
}
}
```
## 🎯 Exemplos de Casos de Uso
### Exemplo 1: Consulta de API Externa
```typescript
import fetch from "node-fetch";
private async consultarAPI(args: any): Promise<any> {
const { cidade } = args;
const response = await fetch(`https://api.exemplo.com/dados?cidade=${cidade}`);
const data = await response.json();
return {
content: [
{
type: "text",
text: `📊 Dados para ${cidade}: ${JSON.stringify(data)}`,
},
],
};
}
```
### Exemplo 2: Execução de Comando Local
```typescript
import { exec } from "child_process";
import { promisify } from "util";
const execAsync = promisify(exec);
private async executarComando(args: any): Promise<any> {
const { comando } = args;
try {
const { stdout, stderr } = await execAsync(comando);
return {
content: [
{
type: "text",
text: `📋 Resultado do comando:\n${stdout}`,
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `❌ Erro: ${error}`,
},
],
};
}
}
```
### Exemplo 3: Leitura de Arquivo
```typescript
import { readFile } from "fs/promises";
private async lerArquivo(args: any): Promise<any> {
const { caminho } = args;
try {
const conteudo = await readFile(caminho, "utf-8");
return {
content: [
{
type: "text",
text: `📄 Conteúdo do arquivo ${caminho}:\n${conteudo}`,
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `❌ Erro ao ler arquivo: ${error}`,
},
],
};
}
}
```
## 🐛 Solução de Problemas
### Problema: "Cannot find module"
```bash
# Solução: Reinstalar dependências
rm -rf node_modules package-lock.json
npm install
```
### Problema: "tsc not found"
```bash
# Solução: Instalar TypeScript globalmente
npm install -g typescript
# Ou usar npx
npx tsc
```
### Problema: "Server não inicia"
```bash
# Verificar se o arquivo foi compilado
ls dist/
# Recompilar se necessário
npm run build
```
### Problema: "Ferramenta não aparece no Claude"
1. Verificar se o caminho no `mcp-config.json` está correto
2. Verificar se a ferramenta foi adicionada corretamente
3. Reiniciar o Claude Desktop
## 📚 Recursos Adicionais
- [Documentação oficial MCP](https://modelcontextprotocol.io/)
- [SDK MCP para Node.js](https://github.com/modelcontextprotocol/sdk-js)
- [Exemplos de servidores MCP](https://github.com/modelcontextprotocol/servers)
## 🎉 Conclusão
Agora você tem um guia completo para criar MCP servers! Lembre-se:
1. **Sempre teste** antes de usar no Claude Desktop
2. **Documente bem** suas ferramentas
3. **Trate erros** adequadamente
4. **Use logs** para debugging
5. **Mantenha o código** organizado e limpo
Boa sorte com seus projetos MCP! 🚀