mcpengine/servers/meta-ads/fix-tier2-tools.js
Jake Shore f3c4cd817b Add all MCP servers + factory infra to MCPEngine — 2026-02-06
=== 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.
2026-02-06 06:32:29 -05:00

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.');