/** * @fileoverview Fix existing tools with correct parameter specifications * Fix all parameter mismatches in existing tools by adding missing parameters, * correcting types and requirement status, and updating descriptions to match API documentation exactly. */ import fs from 'fs'; import path from 'path'; /** * Fix existing tools with parameter mismatches */ function fixExistingTools() { try { console.log('=== FIXING EXISTING TOOLS WITH PARAMETER MISMATCHES ==='); console.log(''); // Read the audit results const auditResultsPath = path.join(process.cwd(), 'mcp-tools-audit-results.json'); const auditResultsContent = fs.readFileSync(auditResultsPath, 'utf8'); const auditResults = JSON.parse(auditResultsContent); // Read the endpoints configuration const endpointsConfigPath = path.join(process.cwd(), 'src/config/endpoints.js'); const endpointsConfigContent = fs.readFileSync(endpointsConfigPath, 'utf8'); // Read the complete API parameters const apiParametersPath = path.join(process.cwd(), 'complete-api-parameters.json'); const apiParametersContent = fs.readFileSync(apiParametersPath, 'utf8'); const apiEndpoints = JSON.parse(apiParametersContent); console.log(`🔍 Found ${auditResults.toolIssues.length} tools with parameter issues`); console.log(''); let updatedContent = endpointsConfigContent; let fixCount = 0; // Process each tool with issues auditResults.toolIssues.forEach(toolIssue => { console.log(`🔧 Fixing tool: ${toolIssue.toolName}`); // Find the corresponding API endpoint const apiEndpoint = apiEndpoints.find(ep => ep.path === toolIssue.apiPath && ep.method === toolIssue.apiMethod ); if (apiEndpoint) { const fixes = generateParameterFixes(toolIssue, apiEndpoint); if (fixes.length > 0) { updatedContent = applyParameterFixes(updatedContent, toolIssue, fixes); fixCount++; console.log(` ✅ Applied ${fixes.length} parameter fixes`); } else { console.log(` ⚠️ No fixes needed or could not generate fixes`); } } else { console.log(` ❌ Could not find API endpoint for ${toolIssue.apiPath}`); } }); // Save the updated configuration if (fixCount > 0) { // Create backup const backupPath = path.join(process.cwd(), 'src/config/endpoints_backup_' + Date.now() + '.js'); fs.writeFileSync(backupPath, endpointsConfigContent); console.log(`📁 Backup created: ${backupPath}`); // Save updated file fs.writeFileSync(endpointsConfigPath, updatedContent); console.log(`💾 Updated endpoints configuration saved`); } console.log(''); console.log('=== PARAMETER FIXES SUMMARY ==='); console.log(`Tools processed: ${auditResults.toolIssues.length}`); console.log(`Tools fixed: ${fixCount}`); console.log(`Backup created: ${fixCount > 0 ? 'Yes' : 'No'}`); return { toolsProcessed: auditResults.toolIssues.length, toolsFixed: fixCount, backupCreated: fixCount > 0 }; } catch (error) { console.error('Error fixing existing tools:', error); throw error; } } /** * Generate parameter fixes for a tool */ function generateParameterFixes(toolIssue, apiEndpoint) { const fixes = []; toolIssue.issues.forEach(issue => { if (issue.type === 'missing_parameter') { // Find the parameter in the API endpoint const apiParam = findParameterInEndpoint(apiEndpoint, issue.parameter); if (apiParam) { fixes.push({ type: 'add_parameter', parameterName: issue.parameter, parameterDefinition: { type: apiParam.type || 'string', required: apiParam.required || false, description: apiParam.description || `${issue.parameter} parameter` } }); } } else if (issue.type === 'type_mismatch') { fixes.push({ type: 'update_parameter_type', parameterName: issue.parameter, newType: issue.apiType }); } else if (issue.type === 'requirement_mismatch') { fixes.push({ type: 'update_parameter_requirement', parameterName: issue.parameter, newRequired: issue.apiRequired }); } }); return fixes; } /** * Find a parameter in an API endpoint */ function findParameterInEndpoint(apiEndpoint, parameterName) { // Check path parameters if (apiEndpoint.parameters?.path) { const pathParam = apiEndpoint.parameters.path.find(p => p.name === parameterName); if (pathParam) return pathParam; } // Check query parameters if (apiEndpoint.parameters?.query) { const queryParam = apiEndpoint.parameters.query.find(p => p.name === parameterName); if (queryParam) return queryParam; } // Check body parameters if (apiEndpoint.parameters?.body) { const bodyParam = apiEndpoint.parameters.body.find(p => p.name === parameterName); if (bodyParam) return bodyParam; } return null; } /** * Apply parameter fixes to the configuration content */ function applyParameterFixes(content, toolIssue, fixes) { let updatedContent = content; // Find the tool definition in the content const toolPath = toolIssue.apiPath; const toolMethod = toolIssue.apiMethod; // Create a regex to find the specific endpoint const pathRegex = new RegExp(`path:\\s*["']${escapeRegex(toolPath)}["']`, 'g'); const matches = [...content.matchAll(pathRegex)]; if (matches.length === 0) { console.log(` ⚠️ Could not find tool definition for ${toolPath}`); return content; } // For each match, check if it's the right method for (const match of matches) { const startIndex = match.index; // Find the endpoint object boundaries const endpointStart = content.lastIndexOf('{', startIndex); const endpointEnd = findMatchingBrace(content, endpointStart); if (endpointStart === -1 || endpointEnd === -1) continue; const endpointContent = content.substring(endpointStart, endpointEnd + 1); // Check if this is the right method const methodMatch = endpointContent.match(/method:\s*["']([^"']+)["']/); if (!methodMatch || methodMatch[1].toUpperCase() !== toolMethod) continue; // Apply fixes to this endpoint let updatedEndpoint = endpointContent; fixes.forEach(fix => { if (fix.type === 'add_parameter') { updatedEndpoint = addParameterToEndpoint(updatedEndpoint, fix); } else if (fix.type === 'update_parameter_type') { updatedEndpoint = updateParameterType(updatedEndpoint, fix); } else if (fix.type === 'update_parameter_requirement') { updatedEndpoint = updateParameterRequirement(updatedEndpoint, fix); } }); // Replace the endpoint in the full content updatedContent = updatedContent.substring(0, endpointStart) + updatedEndpoint + updatedContent.substring(endpointEnd + 1); break; } return updatedContent; } /** * Add a parameter to an endpoint definition */ function addParameterToEndpoint(endpointContent, fix) { const paramName = fix.parameterName; const paramDef = fix.parameterDefinition; // Check if parameters object exists const parametersMatch = endpointContent.match(/parameters:\s*\{([^}]*)\}/s); if (parametersMatch) { // Parameters object exists, add the new parameter const existingParams = parametersMatch[1]; const newParam = `${paramName}: { type: "${paramDef.type}", required: ${paramDef.required}, description: "${paramDef.description}" }`; let updatedParams; if (existingParams.trim()) { updatedParams = existingParams + ',\n ' + newParam; } else { updatedParams = '\n ' + newParam + '\n '; } return endpointContent.replace( /parameters:\s*\{([^}]*)\}/s, `parameters: {${updatedParams}}` ); } else { // No parameters object, create one const newParam = `${paramName}: { type: "${paramDef.type}", required: ${paramDef.required}, description: "${paramDef.description}" }`; const parametersObj = `parameters: {\n ${newParam}\n },`; // Insert before the closing brace return endpointContent.replace(/(\s*)\}(\s*)$/, `$1 ${parametersObj}\n$1}$2`); } } /** * Update parameter type in endpoint definition */ function updateParameterType(endpointContent, fix) { const paramName = fix.parameterName; const newType = fix.newType; const regex = new RegExp(`(${paramName}:\\s*\\{[^}]*type:\\s*)["'][^"']*["']`, 'g'); return endpointContent.replace(regex, `$1"${newType}"`); } /** * Update parameter requirement in endpoint definition */ function updateParameterRequirement(endpointContent, fix) { const paramName = fix.parameterName; const newRequired = fix.newRequired; const regex = new RegExp(`(${paramName}:\\s*\\{[^}]*required:\\s*)(true|false)`, 'g'); return endpointContent.replace(regex, `$1${newRequired}`); } /** * Escape regex special characters */ function escapeRegex(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } /** * Find matching closing brace */ function findMatchingBrace(content, startIndex) { let braceCount = 1; let index = startIndex + 1; while (index < content.length && braceCount > 0) { if (content[index] === '{') { braceCount++; } else if (content[index] === '}') { braceCount--; } index++; } return braceCount === 0 ? index - 1 : -1; } // Run the fixes if (import.meta.url === `file://${process.argv[1]}`) { fixExistingTools(); } export { fixExistingTools };