memory / server.js
gcharanteja
feat: add intelligent routing functionality with natural language processing for knowledge management
b008b07
Raw
History Blame Contribute Delete
4.99 kB
import http from "node:http";
import fs from "node:fs";
import path from "node:path";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import {
ListToolsRequestSchema,
CallToolRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { vectorTools, handleVectorTool } from "./tools/vectorTool.js";
import { curateTools, handleCurateTool } from "./tools/curateTool.js";
import { routerTools, handleRouterTool } from "./tools/routerTool.js";
const PORT = Number(process.env.PORT || 3000);
const HOST = process.env.HOST || "0.0.0.0";
const DATA_DIR = process.env.DATA_DIR || "/data";
const CONFIG_PATH = path.join(DATA_DIR, "config.json");
function loadConfig() {
try {
if (!fs.existsSync(CONFIG_PATH)) {
console.error(`Config file not found at ${CONFIG_PATH}`);
process.exit(1);
}
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf8"));
return config;
} catch (error) {
console.error(`Failed to load config from ${CONFIG_PATH}:`, error.message);
process.exit(1);
}
}
const config = loadConfig();
function createMcpServer() {
const server = new Server(
{
name: "mcponly-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
},
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [...routerTools, ...curateTools, ...vectorTools],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args = {} } = request.params;
const routerResult = await handleRouterTool(name, args, config);
if (routerResult) return routerResult;
const curateResult = await handleCurateTool(name, args, config);
if (curateResult) return curateResult;
const vectorResult = await handleVectorTool(name, args);
if (vectorResult) return vectorResult;
return {
content: [{ type: "text", text: `Unknown tool: ${name}` }],
isError: true,
};
});
return server;
}
function sendJson(res, statusCode, payload) {
res.writeHead(statusCode, { "Content-Type": "application/json" });
res.end(JSON.stringify(payload));
}
function readBody(req) {
return new Promise((resolve, reject) => {
const chunks = [];
req.on("data", (chunk) => chunks.push(chunk));
req.on("end", () => {
if (chunks.length === 0) {
resolve(undefined);
return;
}
const text = Buffer.concat(chunks).toString("utf8");
try {
resolve(JSON.parse(text));
} catch (error) {
reject(new Error("Invalid JSON body"));
}
});
req.on("error", reject);
});
}
async function main() {
const transports = new Map();
const httpServer = http.createServer(async (req, res) => {
if (!req.url) {
sendJson(res, 400, {
jsonrpc: "2.0",
error: { code: -32600, message: "Missing request URL" },
id: null,
});
return;
}
const hostHeader = req.headers.host || `${HOST}:${PORT}`;
const url = new URL(req.url, `http://${hostHeader}`);
if (req.method === "GET" && url.pathname === "/health") {
sendJson(res, 200, { status: "ok" });
return;
}
if (req.method === "GET" && url.pathname === "/sse") {
const transport = new SSEServerTransport("/messages", res);
transports.set(transport.sessionId, transport);
transport.onclose = () => {
transports.delete(transport.sessionId);
};
res.on("close", () => {
transports.delete(transport.sessionId);
});
await createMcpServer().connect(transport);
return;
}
if (req.method === "POST" && url.pathname === "/messages") {
const sessionId = url.searchParams.get("sessionId");
if (!sessionId) {
sendJson(res, 400, {
jsonrpc: "2.0",
error: { code: -32600, message: "Missing sessionId query parameter" },
id: null,
});
return;
}
const transport = transports.get(sessionId);
if (!transport) {
sendJson(res, 404, {
jsonrpc: "2.0",
error: { code: -32000, message: "Session not found" },
id: null,
});
return;
}
const body = await readBody(req);
await transport.handlePostMessage(req, res, body);
return;
}
sendJson(res, 404, {
jsonrpc: "2.0",
error: { code: -32601, message: "Not found" },
id: null,
});
});
httpServer.listen(PORT, HOST, () => {
console.log(`MCP SSE server listening on http://${HOST}:${PORT}`);
console.log(`SSE endpoint: http://${HOST}:${PORT}/sse`);
console.log(`POST endpoint: http://${HOST}:${PORT}/messages`);
});
process.on("SIGINT", () => {
httpServer.close(() => process.exit(0));
});
}
main().catch((error) => {
console.error("MCP server failed to start:", error);
process.exit(1);
});