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