Construa provedores de ferramentas poderosos que permitem à IA executar ações, executar comandos e interagir com seus sistemas com segurança
Enquanto recursos fornecem dados para a IA ler, ferramentas dão à IA o poder de tomar ações. Ferramentas são a ponte entre a inteligência da IA e sistemas do mundo real, permitindo tudo desde manipulação de arquivos até chamadas de API e administração de sistemas.
Ferramentas representam uma mudança fundamental do acesso passivo a dados para interação ativa com sistemas. Com grande poder vem grande responsabilidade - ferramentas devem ser projetadas com segurança, validação e tratamento de erros como preocupações primárias.
Segurança em Primeiro Lugar: Ferramentas podem modificar seu sistema, chamar APIs externas e realizar ações irreversíveis. Sempre implemente validação adequada, controles de acesso e verificações de segurança.
Aspecto | Recursos | Ferramentas |
---|---|---|
Propósito | Ler dados | Executar ações |
Mutabilidade | Somente leitura | Pode modificar estado |
Parâmetros | Baseado em URI | Argumentos estruturados |
Segurança | Menor risco | Maior risco |
Exemplos | Arquivos, bancos de dados, APIs | Escrever arquivos, enviar e-mails, executar comandos |
<CodeExample title="Estrutura de Ferramenta" language="typescript" code={`interface Tool { name: string; // Identificador único da ferramenta description: string; // O que a ferramenta faz inputSchema: { type: 'object'; properties: Record<string, any>; // Definições de parâmetros required?: string[]; // Parâmetros obrigatórios }; }
interface ToolResult { content: Array<{ type: 'text' | 'image' | 'resource'; text?: string; // Saída de texto data?: string; // Dados codificados em Base64 resource?: { uri: string }; // Referência de recurso }>; isError?: boolean; // Indica se a ferramenta falhou }`} highlightLines={[1, 2, 3, 11, 16, 17]} />
Entender o ciclo de vida de execução da ferramenta ajuda você a construir implementações robustas:
tools/list
para ver ferramentas disponíveisA anatomia de uma definição de ferramenta MCP
Vamos começar com ferramentas simples para entender os padrões básicos, depois construir implementações mais complexas.
<CodeExample title="Ferramenta Echo Simples" language="typescript" code={`// Registrar a ferramenta echo server.setRequestHandler('tools/list', async () => { return { tools: [ { name: 'echo', description: 'Repetir o texto fornecido de volta ao usuário', inputSchema: { type: 'object', properties: { text: { type: 'string', description: 'O texto para repetir de volta' } }, required: ['text'] } } ] }; });
// Lidar com execução da ferramenta server.setRequestHandler('tools/call', async (request) => { const { name, arguments: args } = request.params;
if (name === 'echo') { return { content: [ { type: 'text', text: `Echo: ${args.text}` } ] }; }
throw new Error(`Ferramenta desconhecida: ${name}`); });`} highlightLines={[6, 7, 27, 28, 29, 30, 31, 32, 33, 34]} />
Este exemplo simples demonstra:
text
obrigatório<CodeExample title="Ferramenta Calculadora" language="typescript" code={`const calculatorTool = { name: 'calculator', description: 'Realizar cálculos matemáticos básicos', inputSchema: { type: 'object', properties: { expression: { type: 'string', description: 'Expressão matemática para avaliar (ex: "2 + 2", "10 * 5")' } }, required: ['expression'] } };
// Avaliador seguro de expressões function evaluateExpression(expr: string): number { // Permitir apenas números, operadores básicos e parênteses const safePattern = /^[0-9+\-*/().\s]+$/;
if (!safePattern.test(expr)) { throw new Error('Expressão inválida: apenas números e operadores básicos permitidos'); }
try { // Usar construtor Function para avaliação mais segura return Function('"use strict"; return (' + expr + ')')(); } catch (error) { throw new Error('Expressão matemática inválida'); } }
// Manipulador de execução da ferramenta if (name === 'calculator') { try { const result = evaluateExpression(args.expression); return { content: [ { type: 'text', text: `${args.expression} = ${result}` } ] }; } catch (error) { return { content: [ { type: 'text', text: `Erro: ${error.message}` } ], isError: true }; } }`} />
Este exemplo mostra padrões importantes:
isError: true
indica falha da ferramentaMelhor Prática: Sempre valide entrada completamente. Nunca use eval()
ou execução de código dinâmica similar sem sanitização estrita de entrada.
Uma ferramenta básica que ecoa o texto de entrada
Uma ferramenta que realiza cálculos matemáticos
Module content not available.
Ferramentas de API permitem que seu servidor MCP interaja com serviços externos, tornando-o um poderoso hub de integração.
<CodeExample title="Ferramenta de Requisição HTTP" language="typescript" code={`const httpRequestTool = { name: 'http_request', description: 'Fazer requisições HTTP para APIs externas', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'A URL para requisitar' }, method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], default: 'GET', description: 'Método HTTP a usar' }, headers: { type: 'object', description: 'Cabeçalhos HTTP a incluir', additionalProperties: { type: 'string' } }, body: { type: 'string', description: 'Corpo da requisição (para POST, PUT, PATCH)' }, timeout: { type: 'number', default: 30000, description: 'Timeout da requisição em milissegundos' } }, required: ['url'] } };
// Manipulador de requisição HTTP com verificações de segurança async function executeHttpRequest(args: any) { const { url, method = 'GET', headers = {}, body, timeout = 30000 } = args;
// Segurança: Validar URL try { const urlObj = new URL(url);
// Bloquear localhost e IPs privados por segurança
if (urlObj.hostname === 'localhost' ||
urlObj.hostname.startsWith('127.') ||
urlObj.hostname.startsWith('192.168.') ||
urlObj.hostname.startsWith('10.')) {
throw new Error('Requisições para redes locais/privadas não são permitidas');
}
} catch (error) { throw new Error(`URL inválida: ${error.message}`); }
try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeout);
const response = await fetch(url, {
method,
headers: {
'User-Agent': 'MCP-Server/1.0',
...headers
},
body: method !== 'GET' && method !== 'HEAD' ? body : undefined,
signal: controller.signal
});
clearTimeout(timeoutId);
const responseText = await response.text();
return {
content: [
{
type: 'text',
text: \`HTTP \${method} \${url}\\n\` +
\`Status: \${response.status} \${response.statusText}\\n\` +
\`Headers: \${JSON.stringify(Object.fromEntries(response.headers.entries()), null, 2)}\\n\\n\` +
\`Resposta:\\n\${responseText}\`
}
]
};
} catch (error) { return { content: [ { type: 'text', text: `Requisição HTTP falhou: ${error.message}` } ], isError: true }; } }`} />
Medidas de Segurança Críticas:
Considere construir ferramentas especializadas para APIs comuns:
Ferramenta de Mensagem Slack:
Ferramenta de E-mail:
Uma ferramenta para fazer requisições HTTP para APIs externas
À medida que suas ferramentas se tornam mais sofisticadas, você precisará de padrões avançados para cenários complexos.
<CodeExample title="Ferramenta de Longa Duração com Progresso" language="typescript" code={`class LongRunningTool { async executeLongOperation(args: any, progressCallback?: (progress: number, message: string) => void) { const totalSteps = 100;
for (let step = 0; step < totalSteps; step++) {
// Simular trabalho
await new Promise(resolve => setTimeout(resolve, 100));
// Reportar progresso
if (progressCallback) {
progressCallback((step + 1) / totalSteps * 100, \`Processando passo \${step + 1}\`);
}
// Verificar cancelamento
if (this.shouldCancel) {
throw new Error('Operação cancelada');
}
}
return {
content: [
{
type: 'text',
text: 'Operação longa concluída com sucesso!'
}
]
};
} }`} />
<CodeExample title="Disponibilidade Condicional de Ferramentas" language="typescript" code={`class ConditionalToolProvider { constructor(private config: { adminMode: boolean; apiKey?: string }) {}
getAvailableTools() { const tools = [ // Sempre disponível { name: 'status', description: 'Obter status do sistema', inputSchema: { type: 'object', properties: {} } } ];
// Ferramentas apenas para admin
if (this.config.adminMode) {
tools.push({
name: 'restart_service',
description: 'Reiniciar um serviço do sistema',
inputSchema: {
type: 'object',
properties: {
service: { type: 'string', description: 'Nome do serviço' }
},
required: ['service']
}
});
}
// Ferramentas dependentes de API
if (this.config.apiKey) {
tools.push({
name: 'external_api_call',
description: 'Chamar API externa',
inputSchema: {
type: 'object',
properties: {
endpoint: { type: 'string', description: 'Endpoint da API' }
},
required: ['endpoint']
}
});
}
return tools;
} }`} />
Servidores MCP avançados podem compor ferramentas para fluxos de trabalho complexos:
Lidar com operações longas com atualizações de progresso
Mostrar ferramentas apenas quando certas condições são atendidas