=== NEW SERVERS ADDED (7) === - servers/closebot — 119 tools, 14 modules, 4,656 lines TS (Stage 7) - servers/google-console — Google Search Console MCP (Stage 7) - servers/meta-ads — Meta/Facebook Ads MCP (Stage 8) - servers/twilio — Twilio communications MCP (Stage 8) - servers/competitor-research — Competitive intel MCP (Stage 6) - servers/n8n-apps — n8n workflow MCP apps (Stage 6) - servers/reonomy — Commercial real estate MCP (Stage 1) === FACTORY INFRASTRUCTURE ADDED === - infra/factory-tools — mcp-jest, mcp-validator, mcp-add, MCP Inspector - 60 test configs, 702 auto-generated test cases - All 30 servers score 100/100 protocol compliance - infra/command-center — Pipeline state, operator playbook, dashboard config - infra/factory-reviews — Automated eval reports === DOCS ADDED === - docs/MCP-FACTORY.md — Factory overview - docs/reports/ — 5 pipeline evaluation reports - docs/research/ — Browser MCP research === RULES ESTABLISHED === - CONTRIBUTING.md — All MCP work MUST go in this repo - README.md — Full inventory of 37 servers + infra docs - .gitignore — Updated for Python venvs TOTAL: 37 MCP servers + full factory pipeline in one repo. This is now the single source of truth for all MCP work.
101 lines
3.3 KiB
JavaScript
101 lines
3.3 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Batch fix for tier-2 tool modules
|
|
* Converts from server.tool() API to registry.registerTool() API
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const files = [
|
|
'src/tools/audiences.ts',
|
|
'src/tools/budget.ts',
|
|
'src/tools/catalog.ts',
|
|
'src/tools/competitive.ts',
|
|
'src/tools/experiments.ts',
|
|
'src/tools/leads.ts',
|
|
];
|
|
|
|
function convertFile(filePath) {
|
|
console.log(`Converting ${filePath}...`);
|
|
|
|
let content = fs.readFileSync(filePath, 'utf8');
|
|
|
|
// 1. Replace imports
|
|
content = content.replace(
|
|
/import type { McpServer } from "@modelcontextprotocol\/sdk\/server\/mcp\.js";/g,
|
|
''
|
|
);
|
|
|
|
content = content.replace(
|
|
/interface MetaApiClient \{[^}]+\}/gs,
|
|
''
|
|
);
|
|
|
|
// Add ToolRegistry import if not present
|
|
if (!content.includes('import type { ToolRegistry }')) {
|
|
content = content.replace(
|
|
/(import { z } from "zod";)/,
|
|
'$1\nimport type { ToolRegistry } from "../server.js";'
|
|
);
|
|
}
|
|
|
|
// Remove ToolAnnotations from imports if present
|
|
content = content.replace(
|
|
/,\s*ToolAnnotations/g,
|
|
''
|
|
);
|
|
|
|
// 2. Replace function signature
|
|
content = content.replace(
|
|
/export function register\(server: McpServer, client: MetaApiClient\): void \{/g,
|
|
(match, offset) => {
|
|
// Get the function name from the file
|
|
const baseName = path.basename(filePath, '.ts');
|
|
const functionName = 'register' + baseName.charAt(0).toUpperCase() + baseName.slice(1).replace(/-([a-z])/g, (g) => g[1].toUpperCase()) + 'Tools';
|
|
return `export function ${functionName}(registry: ToolRegistry): void {\n const client = registry.getClient();`;
|
|
}
|
|
);
|
|
|
|
// 3. Convert server.tool() calls to registry.registerTool()
|
|
// This regex handles the basic structure
|
|
content = content.replace(
|
|
/const\s+(\w+Annotations):\s*ToolAnnotations\s*=\s*(\{[^}]+\});[\s\n]+server\.tool\(\s*"([^"]+)",\s*"([^"]+)",\s*(\{[^}]+\}),\s*async\s*\(params\)\s*=>\s*\{/gs,
|
|
(match, annotationsVar, annotations, toolName, description, schema) => {
|
|
return `registry.registerTool({\n name: "${toolName}",\n description: "${description}",\n inputSchema: z.object(${schema}),\n annotations: ${annotations},\n handler: async (args) => {\n const params = args as any;`;
|
|
}
|
|
);
|
|
|
|
// 4. Fix tool closing - replace "),\n annotationsVar\n );" with "},\n });"
|
|
content = content.replace(
|
|
/\},\s*\w+Annotations\s*\);/g,
|
|
'};\n\n return {\n content: [{\n type: \'text\',\n text: JSON.stringify(result, null, 2),\n }],\n };\n },\n });'
|
|
);
|
|
|
|
// Fix client.get calls to add type cast
|
|
content = content.replace(
|
|
/client\.get<([^>]+)>\(([^,]+),\s*([^)]+)\)/g,
|
|
'client.get<$1>($2, $3 as Record<string, unknown>)'
|
|
);
|
|
|
|
fs.writeFileSync(filePath, content, 'utf8');
|
|
console.log(` ✓ Converted ${filePath}`);
|
|
}
|
|
|
|
// Convert all files
|
|
for (const file of files) {
|
|
const filePath = path.join(__dirname, file);
|
|
if (fs.existsSync(filePath)) {
|
|
try {
|
|
convertFile(filePath);
|
|
} catch (error) {
|
|
console.error(` ✗ Error converting ${file}:`, error.message);
|
|
}
|
|
} else {
|
|
console.error(` ✗ File not found: ${filePath}`);
|
|
}
|
|
}
|
|
|
|
console.log('\nDone! Please review the changes and run npx tsc --noEmit to check.');
|