first
This commit is contained in:
303
fix-existing-tools.js
Normal file
303
fix-existing-tools.js
Normal file
@@ -0,0 +1,303 @@
|
||||
/**
|
||||
* @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 };
|
Reference in New Issue
Block a user