feat(infraestrutura): mcp-dev v3.0 — SDK TypeScript v2 e transporte HTTP obrigatórios
Regra de Ouro adicionada ao topo da skill: SDK v2 (@modelcontextprotocol/server), API de alto nível McpServer+registerTool (API de baixo nível Server+setRequestHandler proibida), transporte HTTP obrigatório (stdio só como excepção documentada), e proibição explícita de interpolação de dados em comandos shell/SSH. Motivado por revisão de segurança ao mcp-kivicare (19-08-2026): 8 bugs reais corrigidos em produção, incluindo injecção de comandos shell crítica e hooks nativos disparados com o tipo errado. Regras adicionadas para nunca mais acontecer em silêncio. - SKILL.md: nova secção Regra de Ouro, API/annotations/capabilities actualizadas para v2, transportes HTTP obrigatório, changelog v3.0.0, healing log com os 3 bugs mais graves do incidente. - references/templates.md: reescrito para createMcpHandler + createMcpExpressApp (HTTP) e serveStdio (excepção), package.json com pacotes v2. - references/best-practices.md: capabilities/annotations/error handling actualizados para API v2, checklist de segurança com regra anti-injecção de comandos shell, tabela de transportes com HTTP obrigatório. - references/evaluation-guide.md: script de evaluations reescrito para Client+StreamableHTTPClientTransport in-process (sem porta/socket). - infraestrutura: 1.2.2 -> 1.3.0
This commit is contained in:
@@ -130,12 +130,15 @@ npx @modelcontextprotocol/inspector
|
||||
# Testar cada tool manualmente
|
||||
```
|
||||
|
||||
### Método Automatizado (Script TypeScript)
|
||||
### Método Automatizado (Script TypeScript, SDK v2 — in-process, sem porta/socket)
|
||||
|
||||
`handler.fetch` do `createMcpHandler` serve pedidos em processo — o transporte de teste nunca liga de facto ao URL, por isso não há porta a reservar nem servidor a arrancar/parar à volta de cada corrida. Ver [testing.md](https://ts.sdk.modelcontextprotocol.io/v2/testing.md).
|
||||
|
||||
```typescript
|
||||
// eval/run-evals.ts
|
||||
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
||||
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
||||
import { Client, StreamableHTTPClientTransport } from '@modelcontextprotocol/client';
|
||||
import { createMcpHandler } from '@modelcontextprotocol/server';
|
||||
import { createServer } from '../src/server.js'; // a mesma factory usada em src/http.ts
|
||||
|
||||
interface EvalResult {
|
||||
id: string;
|
||||
@@ -160,7 +163,6 @@ async function runEval(
|
||||
const result = await client.callTool({ name: toolName, arguments: input });
|
||||
const duration = Date.now() - start;
|
||||
|
||||
// Verificar assertions
|
||||
if (assertions.notError && result.isError) {
|
||||
return { id: toolName, passed: false, duration, error: 'Esperava sucesso, recebeu erro' };
|
||||
}
|
||||
@@ -170,7 +172,7 @@ async function runEval(
|
||||
}
|
||||
|
||||
if (assertions.containsFields) {
|
||||
const text = result.content[0]?.text || '';
|
||||
const text = (result.content?.[0] as { text?: string })?.text || '';
|
||||
for (const field of assertions.containsFields) {
|
||||
if (!text.includes(field)) {
|
||||
return { id: toolName, passed: false, duration, error: `Campo "${field}" não encontrado` };
|
||||
@@ -191,12 +193,12 @@ async function runEval(
|
||||
|
||||
// Executar todas as evaluations
|
||||
async function main() {
|
||||
const transport = new StdioClientTransport({
|
||||
command: 'node',
|
||||
args: ['dist/index.js']
|
||||
const handler = createMcpHandler(createServer);
|
||||
const transport = new StreamableHTTPClientTransport(new URL('http://test.local/mcp'), {
|
||||
fetch: (url, init) => handler.fetch(new Request(url, init)),
|
||||
});
|
||||
|
||||
const client = new Client({ name: 'eval-client', version: '1.0.0' });
|
||||
const client = new Client({ name: 'eval-client', version: '1.0.0' }, { versionNegotiation: { mode: 'auto' } });
|
||||
await client.connect(transport);
|
||||
|
||||
const results: EvalResult[] = [];
|
||||
@@ -226,6 +228,7 @@ async function main() {
|
||||
});
|
||||
|
||||
await client.close();
|
||||
await handler.close();
|
||||
process.exit(passed === total ? 0 : 1);
|
||||
}
|
||||
|
||||
@@ -277,4 +280,4 @@ jobs:
|
||||
|
||||
---
|
||||
|
||||
*evaluation-guide.md v1.0 | 2026-03-10*
|
||||
*evaluation-guide.md v2.0 | 2026-08-19*
|
||||
|
||||
Reference in New Issue
Block a user