import express from "express";
import dotenv from "dotenv";
import path from "path";
import { fileURLToPath } from "url";
import { createServer } from "http";
import { WebSocketServer } from "ws";
import { createAgentSystem } from "./agent_functions/index.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Load environment variables
dotenv.config({ path: path.join(__dirname, ".env") });
// Configuration
const CHAT_APP_SERVER_PORT = process.env.PORT || 3500;
//const CLIENT_ORIGIN = process.env.CLIENT_ORIGIN || "http://localhost:3000";
const MCP_ENDPOINT = process.env.MCP_ENDPOINT;
const STRATEGY = process.env.STRATEGY || "DMR"; // "DMR", "Ollama", or "OpenAI"
console.log("MCP endpoint:", MCP_ENDPOINT);
// Create Express app and HTTP server
const app = express();
const server = createServer(app);
const wss = new WebSocketServer({ server });
// Store active WebSocket connections
const activeConnections = new Set();
// WebSocket connection handling
wss.on('connection', async (ws, req) => {
const origin = req.headers.origin;
if (!allowedOrigins.includes(origin)) {
ws.close(4001, 'Origin not allowed');
console.warn(`WebSocket connection from disallowed origin: ${origin}`);
return;
}
console.log('π New WebSocket connection established');
activeConnections.add(ws);
// Send initial connection message
let resources = null;
try {
resources = await fetch(`http://localhost:${CHAT_APP_SERVER_PORT}/api/resources`).then(res => res.json());
} catch (e) {
resources = null;
}
ws.send(JSON.stringify({
type: 'connection',
status: 'connected',
timestamp: new Date().toISOString(),
resources
}));
ws.on('close', () => {
console.log('π WebSocket connection closed');
activeConnections.delete(ws);
});
ws.on('error', (error) => {
console.error('π WebSocket error:', error);
activeConnections.delete(ws);
});
});
// Broadcast function for sending messages to all connected clients
function broadcastToClients(message) {
const messageString = JSON.stringify(message);
activeConnections.forEach(ws => {
if (ws.readyState === ws.OPEN) {
ws.send(messageString);
}
});
}
app.use(express.json());
// CORS middleware
function parseAllowedOrigins(env) {
if (!env) return [];
// JSON array format
if (env.startsWith('[')) {
try {
return JSON.parse(env);
} catch {
return [];
}
}
// Comma-separated format
if (env.includes(',')) {
return env.split(',').map(s => s.trim());
}
// Single origin
return [env.trim()];
}
const allowedOrigins = parseAllowedOrigins(process.env.ALLOWED_ORIGINS || process.env.ALLOWED_ORIGIN);
app.use((req, res, next) => {
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.header('Access-Control-Allow-Origin', origin);
}
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
if (req.method === 'OPTIONS') {
res.sendStatus(200);
} else {
next();
}
});
// Request logging
app.use((req, res, next) => {
console.log("REQ URL β", req.url);
next();
});
// Initialize the agent system
console.log("π Initializing Agent System...");
const agentSystem = await createAgentSystem({
mcpEndpoint: MCP_ENDPOINT,
auth: "Bearer local-dev",
strategy: STRATEGY,
dockerModelRunnerUrl: process.env.DOCKER_MODEL_RUNNER_URL,
ollamaUrl: process.env.OLLAMA_URL,
openaiApiKey: process.env.OPENAI_API_KEY,
dockerModelName: process.env.DOCKER_MODEL_NAME,
ollamaModelName: process.env.OLLAMA_MODEL_NAME,
openaiModelName: process.env.OPENAI_MODEL_NAME,
broadcastFunction: broadcastToClients // Pass WebSocket broadcast function
});
console.log("β
Agent System initialized successfully!");
// Set up API routes
app.get("/", (req, res) => {
res.send("MCPBurst Server is running! If you're looking for the chat UI, go to http://localhost:" + CHAT_APP_SERVER_PORT);
});
app.post("/api/plan", agentSystem.routeHandlers.handlePlanRoute);
app.post("/api/chat", agentSystem.routeHandlers.handleChatRoute);
app.post("/api/chat-tools", agentSystem.routeHandlers.handleChatToolsRoute);
app.post("/api/memory", agentSystem.routeHandlers.handleMemoryRoute); // Memory debug endpoint
app.get("/api/resources", agentSystem.routeHandlers.handleResourceRoute); // New resource listing endpoint
// Start the main server
server.listen(CHAT_APP_SERVER_PORT, () => {
console.log(`π¨ Chat UI: http://localhost:${CHAT_APP_SERVER_PORT}`);
console.log(`π WebSocket server running on ws://localhost:${CHAT_APP_SERVER_PORT}`);
});