Kraft102's picture
Initial deployment - WidgeTDC Cortex Backend v2.1.0
529090e
// MCP API Gateway - Integrated from template
import express from 'express';
import { WebSocketServer } from 'ws';
import jwt from 'jsonwebtoken';
import { mcpRouter } from '../mcpRouter.js';
const app = express();
const server = app.listen(3001);
const wss = new WebSocketServer({ server });
// Auth middleware (multi-tenant)
const authMiddleware = (req: express.Request, res: express.Response, next: express.NextFunction) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) return res.status(401).json({ error: 'Unauthorized' });
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET || 'secret') as { org_id: string, user_id: string };
(req as any).org_id = decoded.org_id;
next();
} catch {
res.status(401).json({ error: 'Invalid token' });
}
};
// Routes
app.use('/api/mcp', authMiddleware, mcpRouter);
// WebSocket for events (universal comm)
wss.on('connection', (ws, req) => {
const org_id = req.url?.split('org=')[1]; // Tenant-specific
(ws as any).org_id = org_id;
ws.on('message', (data) => {
try {
const msg = JSON.parse(data.toString());
if (msg.type === 'event') {
// Broadcast to widgets in org
wss.clients.forEach(client => {
if ((client as any).org_id === org_id && client.readyState === 1) {
client.send(JSON.stringify(msg));
}
});
}
} catch (error) {
// Invalid JSON - ignore message
console.error('Invalid JSON in WebSocket message:', error);
}
});
});
// Notification route (for Epic 18)
app.post('/api/notifications/push', authMiddleware, async (req, res) => {
// const { subscription: _subscription, payload: _payload } = req.body;
// TODO: Use web-push to send
// TODO: Integrate with aulaPoller
res.json({ success: true });
});
export { app, wss };