Spaces:
Paused
Paused
| import { Router } from 'express'; | |
| import { v4 as uuidv4 } from 'uuid'; | |
| import { MCPMessage } from '@widget-tdc/mcp-types'; | |
| import { mcpRegistry } from './mcpRegistry.js'; | |
| import { unifiedMemorySystem } from './cognitive/UnifiedMemorySystem.js'; | |
| import { eventBus } from './EventBus.js'; | |
| export const mcpRouter = Router(); | |
| // Route MCP messages | |
| mcpRouter.post('/route', async (req, res) => { | |
| const startTime = Date.now(); | |
| let success = false; | |
| try { | |
| console.log('📨 MCP Router received request:', JSON.stringify(req.body)); | |
| const message: MCPMessage = req.body; | |
| // Context for memory enrichment | |
| const ctx = { | |
| userId: (req as any).user?.id ?? 'anonymous', | |
| orgId: (req as any).user?.orgId ?? 'default', | |
| timestamp: new Date() | |
| }; | |
| // Enrich message with memory context | |
| const enrichedMessage = await unifiedMemorySystem.enrichMCPRequest(message, ctx); | |
| // Ensure ID/timestamp | |
| if (!enrichedMessage.id) enrichedMessage.id = uuidv4(); | |
| if (!enrichedMessage.createdAt) enrichedMessage.createdAt = new Date().toISOString(); | |
| // Route the enriched message | |
| const result = await mcpRegistry.route(enrichedMessage); | |
| // Persist result in working memory for future context | |
| await unifiedMemorySystem.updateWorkingMemory(ctx, result); | |
| success = true; | |
| const duration = Date.now() - startTime; | |
| // Emit event for TaskRecorder observation | |
| eventBus.emit('mcp.tool.executed', { | |
| tool: enrichedMessage.tool, | |
| payload: enrichedMessage.payload, | |
| userId: ctx.userId, | |
| orgId: ctx.orgId, | |
| success: true, | |
| result, | |
| duration | |
| }); | |
| res.json({ | |
| success: true, | |
| messageId: enrichedMessage.id, | |
| result, | |
| }); | |
| } catch (error: any) { | |
| const duration = Date.now() - startTime; | |
| // Emit event for TaskRecorder observation (failure) | |
| eventBus.emit('mcp.tool.executed', { | |
| tool: req.body?.tool || 'unknown', | |
| payload: req.body?.payload || {}, | |
| userId: (req as any).user?.id ?? 'anonymous', | |
| orgId: (req as any).user?.orgId ?? 'default', | |
| success: false, | |
| error: error.message, | |
| duration | |
| }); | |
| console.error('MCP routing error:', error); | |
| res.status(500).json({ success: false, error: error.message || 'Internal server error' }); | |
| } | |
| }); | |
| // Get list of available tools | |
| mcpRouter.get('/tools', (req, res) => { | |
| const tools = mcpRegistry.getRegisteredTools(); | |
| res.json({ | |
| tools, | |
| count: tools.length, | |
| }); | |
| }); | |
| // Get resource content | |
| mcpRouter.get('/resources', async (req, res) => { | |
| const uri = req.query.uri as string; | |
| if (!uri) { | |
| return res.status(400).json({ error: 'Missing uri parameter' }); | |
| } | |
| try { | |
| const content = await mcpRegistry.readResource(uri); | |
| // If content is a string (JSON), try to parse it to return proper JSON object | |
| try { | |
| if (typeof content === 'string') { | |
| const jsonContent = JSON.parse(content); | |
| return res.json({ success: true, data: jsonContent }); | |
| } | |
| } catch (e) { | |
| // Not JSON, return as is | |
| } | |
| res.json({ success: true, content }); | |
| } catch (error: any) { | |
| res.status(404).json({ success: false, error: error.message }); | |
| } | |
| }); | |