mcp-product-manager
Version:
MCP Orchestrator for task and project management with web interface
155 lines • 7.12 kB
JavaScript
/**
* Tool Adapter - Creates execute methods for route-based tools
*/
import axios from 'axios';
const REST_API_URL = process.env.REST_API_URL || 'http://localhost:1234';
/**
* Manual endpoint mappings for all tools
*/
const ENDPOINT_MAPPINGS = {
// Task tools
'create_task': { method: 'POST', path: '/api/tasks' },
'list_tasks': { method: 'GET', path: '/api/tasks/:project' },
'get_task': { method: 'GET', path: '/api/tasks/detail/:id' },
'get_task_detail': { method: 'GET', path: '/api/tasks/detail/:id' },
'claim_task': { method: 'POST', path: '/api/tasks/:id/claim' },
'complete_task': { method: 'POST', path: '/api/tasks/:id/complete' },
'update_task': { method: 'PATCH', path: '/api/tasks/:id' },
'update_task_status': { method: 'PUT', path: '/api/tasks/:id/status' },
'update_task_priority': { method: 'PATCH', path: '/api/tasks/:id/priority' },
'get_blocked_tasks': { method: 'GET', path: '/api/tasks/blockers/:project' },
'get_task_performance': { method: 'GET', path: '/api/tasks/performance/:project' },
'cleanup_abandoned_tasks': { method: 'POST', path: '/api/tasks/cleanup' },
'report_task_tokens': { method: 'POST', path: '/api/tasks/:id/tokens' },
'review_task': { method: 'POST', path: '/api/tasks/:id/review' },
// Bundle tools
'bundle_analyze': { method: 'POST', path: '/api/bundles/analyze' },
'bundle_create': { method: 'POST', path: '/api/bundles' },
'bundle_get_details': { method: 'GET', path: '/api/bundles/:id' },
'bundle_get_recommendations': { method: 'GET', path: '/api/bundles/recommendations/:project' },
'claim_bundle': { method: 'POST', path: '/api/bundles/:id/claim' },
// Project tools
'list_projects': { method: 'GET', path: '/api/projects' },
'create_project': { method: 'POST', path: '/api/projects' },
'merge_project': { method: 'POST', path: '/api/projects/merge' },
'get_project_status': { method: 'GET', path: '/api/projects/:project/status' },
'get_project_summaries': { method: 'GET', path: '/api/projects/summaries' },
'recalibrate_project': { method: 'POST', path: '/api/projects/:project/recalibrate' },
'get_project_mode': { method: 'GET', path: '/api/projects/:project/mode' },
// Agent tools
'spawn_agent': { method: 'POST', path: '/api/agents/spawn' },
'list_agents': { method: 'GET', path: '/api/agents' },
'get_agent_status': { method: 'GET', path: '/api/agents/:name/status' },
'get_agent_instructions': { method: 'GET', path: '/api/agents/:agent/instructions' },
// Orchestrator tools
'orchestrate': { method: 'POST', path: '/api/orchestrator/orchestrate' },
'get_next_action': { method: 'POST', path: '/api/orchestrator/next-action' },
// Database tools
'execute_sqlite': { method: 'POST', path: '/api/database/execute' },
// MCP tools
'list_mcp_tools': { method: 'GET', path: '/api/mcp/tools' },
'execute_mcp_command': { method: 'POST', path: '/api/mcp/execute' },
// Usage tools
'check_usage_budget': { method: 'GET', path: '/api/usage/budget/check' },
'get_current_usage': { method: 'GET', path: '/api/usage/current' },
'get_usage_snapshot': { method: 'GET', path: '/api/usage/snapshot' },
'get_usage_trends': { method: 'GET', path: '/api/usage/trends' },
// SPAPS Integration Wizard
'spaps_integration_wizard': { method: 'POST', path: '/api/spaps/wizard' },
// Health tools
'health_check': { method: 'GET', path: '/api/health' }
};
/**
* Create an execute method for a tool
*/
export function createExecuteMethod(toolName) {
return async function (params) {
const endpoint = ENDPOINT_MAPPINGS[toolName];
if (!endpoint) {
throw new Error(`No endpoint mapping found for tool: ${toolName}`);
}
try {
console.error(`[Tool Adapter] Executing ${toolName} via ${endpoint.method} ${endpoint.path}`);
// Build URL with path parameters
let url = `${REST_API_URL}${endpoint.path}`;
let body = { ...params };
const queryParams = {};
// Handle path parameters
const pathParams = endpoint.path.match(/:(\w+)/g);
if (pathParams) {
for (const param of pathParams) {
const paramName = param.substring(1); // Remove the ':'
// Try different parameter name variations
const value = params[paramName] ||
params[`${paramName}_id`] ||
params.id ||
params.task_id ||
params.bundle_id ||
params.agent ||
params.project ||
params.name;
if (value) {
url = url.replace(param, value);
delete body[paramName];
delete body[`${paramName}_id`];
if (paramName === 'id') {
delete body.id;
delete body.task_id;
delete body.bundle_id;
}
}
else if (paramName === 'project' && !value) {
// Default project if not specified
url = url.replace(param, 'mcp-hybrid');
}
else {
throw new Error(`Missing required path parameter: ${paramName}`);
}
}
}
// For GET requests, move body to query params
if (endpoint.method === 'GET') {
Object.assign(queryParams, body);
body = undefined;
}
// Make the API request
const response = await axios({
method: endpoint.method,
url,
data: body,
params: queryParams,
headers: {
'Content-Type': 'application/json'
},
timeout: 30000 // 30 second timeout
});
return response.data;
}
catch (error) {
if (error.response) {
// API returned an error
const errorMessage = error.response.data?.error || error.response.data?.message || JSON.stringify(error.response.data) || error.message;
throw new Error(`API error: ${errorMessage}`);
}
else if (error.code === 'ECONNREFUSED') {
throw new Error(`REST API server is not running on ${REST_API_URL}`);
}
else {
throw error;
}
}
};
}
/**
* Enhance a tool with an execute method if it doesn't have one
*/
export function enhanceTool(toolName, tool) {
if (!tool.execute || typeof tool.execute !== 'function') {
return {
...tool,
execute: createExecuteMethod(toolName)
};
}
return tool;
}
//# sourceMappingURL=toolAdapter.js.map