criar-tool-mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited criar-tool-mcp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
src/
index.js — Entrypoint (não alterar)
registerTools.js — Um registerTool() por tool
handlers/
<toolName>.js — Handler exportado (nome em inglês)
tests/
<toolName>.test.js — Testes do handlersrc/handlers/<toolName>.jsExportar função nomeada. Padrão do projeto:
Handler síncrono (validação, geração):
export function minhaTool(input) {
// lógica
return { /* resultado */ };
}Handler assíncrono (consulta API externa):
export async function minhaTool(input) {
try {
const response = await fetch(url, { signal: AbortSignal.timeout(3000) });
if (!response.ok) return { erro: "Mensagem de erro" };
const data = await response.json();
return { /* campos do resultado */ };
} catch {
return { erro: "Erro ao consultar API" };
}
}Convenções:
validateX, searchX, generateX){ erro: "mensagem" }AbortSignal.timeout(3000) para fetch externo (3s)console.log() (stdout reservado pro protocolo MCP)src/registerTools.jsAdicionar import no topo:
import { minhaTool } from "./handlers/minhaTool.js";Adicionar server.registerTool() dentro de registerTools():
Síncrono:
server.registerTool(
"nome_da_tool_ptbr",
{
description: "Descrição em pt-BR do que a tool faz.",
inputSchema: z.object({
param: z.string()
})
},
({ param }) => ({
content: [{ type: "text", text: JSON.stringify(minhaTool(param)) }]
})
);Assíncrono:
server.registerTool(
"nome_da_tool_ptbr",
{
description: "Descrição em pt-BR. Mencionar fonte de dados se for API externa.",
inputSchema: z.object({
param: z.string()
})
},
async ({ param }) => ({
content: [{ type: "text", text: JSON.stringify(await minhaTool(param)) }]
})
);Convenções:
validar_cep, consultar_cep, gerar_cpf)z.object() do zodtests/<toolName>.test.jsimport { describe, it, expect, vi, beforeEach } from "vitest";
import { minhaTool } from "../src/handlers/minhaTool.js";
describe("minhaTool", () => {
it("deve fazer X quando Y", () => {
expect(minhaTool("input")).toEqual({ /* esperado */ });
});
});Para handlers com fetch — mockar fetch global:
beforeEach(() => {
vi.restoreAllMocks();
});
it("deve retornar sucesso", async () => {
vi.stubGlobal("fetch", vi.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve({ /* dados mockados */ }),
}));
const result = await minhaTool("input");
expect(result).toEqual({ /* esperado */ });
});Casos de teste obrigatórios:
npm testTodos os testes devem passar (existentes + novos).
Após todos os testes passarem, commitar os 3 arquivos criados/editados:
git add src/handlers/<toolName>.js src/registerTools.js tests/<toolName>.test.js
git commit -m "Adicionando tool <nome em pt-BR>"Exemplos de mensagem:
Adicionando tool validador de CEPAdicionando tool consulta de CEPAdicionando tool gerador de CPFsrc/handlers/<toolName>.jsregisterTools.jsserver.registerTool() adicionado com nome pt-BR, descrição, schema e handlertests/<toolName>.test.jsnpm test passa tudo~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.