UNPKG

mcp-product-manager

Version:

MCP Orchestrator for task and project management with web interface

155 lines 7.12 kB
/** * 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