304 lines
10 KiB
JavaScript
304 lines
10 KiB
JavaScript
/**
|
|
* @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 };
|