name: add-tool description: Scaffold and implement a new MCP tool end-to-end — endpoint, handler, registration, docs argument-hint: "[tool-name and description]"
Add a new MCP tool: $ARGUMENTS
Do NOT start coding immediately. Follow this workflow.
Phase 1 — Understand
- What does this tool do? Restate in one sentence
- Which API endpoint does it call? (GET/POST/PATCH/DELETE + path)
- What category does it belong to? (testruns, testcases, manual-testcases, manual-testsuites, or new category)
- What params does it need? (required vs optional)
- What does the API response look like?
If any of these are unclear, ask before proceeding.
Phase 2 — Plan
List every file that needs to be created or modified:
src/lib/endpoints.ts— new endpoint URL buildersrc/tools/<category>/<tool-name>.ts— new tool filesrc/tools/index.ts— barrel exportsrc/index.ts— tool registration + routingdocs/TOOLS.md— tool documentationdocs/skill.md— if it affects AI agent workflows
Get user approval before writing code.
Phase 3 — Implement
Follow this exact order:
Step 1: Endpoint (src/lib/endpoints.ts)
Add a new method to the endpoints object. Follow the existing pattern:
toolName: (params: { projectId: string /* other params */ }): string => {
const baseUrl = getBaseUrl();
const { projectId, ...queryParams } = params;
const queryString = buildQueryString(queryParams);
return `${baseUrl}/api/mcp/${projectId}/endpoint-path${queryString}`;
};
Run: npm run typecheck
Step 2: Tool file (src/tools//.ts)
Create the tool file with exactly two exports:
export const toolNameTool = {
name: "tool_name",
description: "...", // Write for AI agents — be specific about when to use this
inputSchema: {
type: "object",
properties: { /* every property MUST have a description */ },
required: [/* required params */]
}
};
export async function handleToolName(args: Record<string, unknown>) {
// 1. Auth
const token = getApiKey(args);
if (!token) throw new Error("Missing TESTDINO_PAT...");
// 2. Validate required params
if (!args?.projectId) throw new Error("projectId is required");
// 3. Build URL
const url = endpoints.toolName({ projectId: String(args.projectId), ... });
// 4. Fetch
const response = await apiRequestJson(url, {
headers: { Authorization: `Bearer ${token}` }
});
// 5. Return formatted
return {
content: [{ type: "text", text: JSON.stringify(response, null, 2) }]
};
}
Run: npm run typecheck
Step 3: Barrel export (src/tools/index.ts)
Add export line following existing pattern:
export { toolNameTool, handleToolName } from "./<category>/<tool-name>.js";
Run: npm run typecheck
Step 4: Registration (src/index.ts)
Two changes:
- Add to imports at the top
- Add to the
toolsarray - Add routing if-block in the CallToolRequestSchema handler
Run: npm run typecheck && npm run lint
Step 5: Tests
Add test file at tests/tools/<category>/<tool-name>.test.ts covering:
- Missing PAT returns error
- Missing required params returns error
- Successful response is properly formatted
- API error is properly wrapped
Run: npm run test
Phase 4 — Document
- Add full documentation to
docs/TOOLS.mdfollowing existing format - Update
docs/skill.mdif the tool creates a new workflow or decision path - Update the tool count in
README.mdif applicable
Phase 5 — Final Verify
npm run format && npm run typecheck && npm run lint && npm run test && npm run build
All must pass. git diff to confirm only intentional changes.
Rules
- Follow existing patterns exactly — consistency over cleverness
- Every inputSchema property MUST have a description (AI agents depend on these)
- Tool descriptions must be specific enough for an AI to choose the right tool
- Never skip the endpoint step — all URLs go through endpoints.ts
- Run typecheck after EACH step, not just at the end