ultimate-mcp-server
Version:
The definitive all-in-one Model Context Protocol server for AI-assisted coding across 30+ platforms
329 lines • 11.6 kB
JavaScript
import express from "express";
import cors from "cors";
import { BaseTransport } from "./base.js";
import { randomUUID } from "crypto";
export class HTTPTransport extends BaseTransport {
app;
httpServer;
sessions = new Map();
sessionTimeout = 30 * 60 * 1000; // 30 minutes
constructor(server, config) {
super(server, config);
this.app = express();
this.setupMiddleware();
this.setupRoutes();
}
setupMiddleware() {
// CORS configuration
if (this.config.cors) {
this.app.use(cors({
origin: this.config.cors.origin,
credentials: this.config.cors.credentials ?? false,
}));
}
// JSON parsing with size limit
this.app.use(express.json({ limit: "10mb" }));
// Request logging
this.app.use((req, res, next) => {
this.logger.debug(`${req.method} ${req.path}`);
next();
});
// Auth middleware
this.app.use((req, res, next) => {
if (this.config.auth && this.config.auth.type !== "none") {
const headers = req.headers;
if (!this.validateAuth(headers)) {
res.status(401).json({
error: "Unauthorized",
code: "AUTH_REQUIRED"
});
return;
}
}
next();
});
}
setupRoutes() {
// Create session
this.app.post("/session", (req, res) => {
const sessionId = randomUUID();
const session = {
id: sessionId,
createdAt: Date.now(),
lastActivity: Date.now(),
context: {},
};
this.sessions.set(sessionId, session);
this.logger.info(`Session created: ${sessionId}`);
res.json({
sessionId,
expiresIn: this.sessionTimeout,
});
});
// Delete session
this.app.delete("/session/:sessionId", (req, res) => {
const { sessionId } = req.params;
if (this.sessions.delete(sessionId)) {
res.json({ success: true });
}
else {
res.status(404).json({ error: "Session not found" });
}
});
// RPC endpoint
this.app.post("/rpc", async (req, res) => {
try {
const request = req.body;
const sessionId = req.headers["x-session-id"];
// Validate session if provided
if (sessionId) {
const session = this.sessions.get(sessionId);
if (!session) {
res.status(401).json({
jsonrpc: "2.0",
error: {
code: -32001,
message: "Invalid or expired session",
},
id: request.id,
});
return;
}
session.lastActivity = Date.now();
}
// Process request
const response = await this.handleRequest(request, sessionId);
res.json(response);
}
catch (error) {
this.logger.error("RPC request failed", error);
res.status(500).json({
jsonrpc: "2.0",
error: {
code: -32603,
message: "Internal error",
},
id: req.body.id,
});
}
});
// REST-style endpoints for common operations
// List tools
this.app.get("/tools", async (req, res) => {
try {
const tools = await this.getAvailableTools();
res.json(tools);
}
catch (error) {
res.status(500).json({ error: "Failed to get tools" });
}
});
// Execute tool
this.app.post("/tools/:toolName/execute", async (req, res) => {
try {
const { toolName } = req.params;
const args = req.body;
const sessionId = req.headers["x-session-id"];
const request = {
jsonrpc: "2.0",
method: "tools/call",
params: {
name: toolName,
arguments: args,
},
id: randomUUID(),
};
const response = await this.handleRequest(request, sessionId);
if (response.error) {
res.status(400).json(response.error);
}
else {
res.json(response.result);
}
}
catch (error) {
res.status(500).json({ error: "Tool execution failed" });
}
});
// List models
this.app.get("/models", async (req, res) => {
try {
const models = await this.getAvailableModels();
res.json(models);
}
catch (error) {
res.status(500).json({ error: "Failed to get models" });
}
});
// Ask endpoint (simplified interface)
this.app.post("/ask", async (req, res) => {
try {
const { prompt, model, temperature } = req.body;
const sessionId = req.headers["x-session-id"];
const request = {
jsonrpc: "2.0",
method: "tools/call",
params: {
name: "ask",
arguments: { prompt, model, temperature },
},
id: randomUUID(),
};
const response = await this.handleRequest(request, sessionId);
if (response.error) {
res.status(400).json(response.error);
}
else {
res.json({ answer: response.result });
}
}
catch (error) {
res.status(500).json({ error: "Ask failed" });
}
});
// Health check
this.app.get("/health", (req, res) => {
res.json({
status: "ok",
transport: "http",
sessions: this.sessions.size,
uptime: process.uptime(),
version: "2.0.0",
});
});
// API documentation
this.app.get("/", (req, res) => {
res.json({
name: "Ultimate MCP Server",
version: "2.0.0",
transport: "http",
endpoints: {
session: {
create: "POST /session",
delete: "DELETE /session/:sessionId",
},
rpc: "POST /rpc",
tools: {
list: "GET /tools",
execute: "POST /tools/:toolName/execute",
},
models: "GET /models",
ask: "POST /ask",
health: "GET /health",
},
});
});
}
async handleRequest(request, sessionId) {
try {
// Add session context if available
if (sessionId) {
const session = this.sessions.get(sessionId);
if (session) {
// Attach session context to request
request.sessionContext = session.context;
}
}
// Process through MCP server - route to appropriate handler
// For now, we'll return a placeholder response
// TODO: Implement proper request routing through MCP server
return {
jsonrpc: "2.0",
result: {
message: "HTTP transport request handling in development"
},
id: request.id,
};
}
catch (error) {
return {
jsonrpc: "2.0",
error: {
code: -32603,
message: error.message || "Internal error",
data: error.stack,
},
id: request.id,
};
}
}
async getAvailableTools() {
// This would fetch from the actual tool registry
return {
tools: [
{
name: "ask",
description: "Ask AI a question",
parameters: {
prompt: { type: "string", required: true },
model: { type: "string", required: false },
temperature: { type: "number", required: false },
},
},
{
name: "orchestrate",
description: "Orchestrate multiple AI models",
parameters: {
prompt: { type: "string", required: true },
strategy: { type: "string", required: true },
models: { type: "array", required: false },
},
},
// ... other tools
],
};
}
async getAvailableModels() {
// This would fetch from the model registry
return {
models: [
{ id: "openai/gpt-4o", name: "GPT-4 Optimized" },
{ id: "anthropic/claude-3-opus", name: "Claude 3 Opus" },
{ id: "google/gemini-2.5-pro", name: "Gemini 2.5 Pro" },
{ id: "x-ai/grok-4-beta", name: "Grok 4 Beta" },
// ... other models
],
};
}
cleanupSessions() {
const now = Date.now();
for (const [sessionId, session] of this.sessions) {
if (now - session.lastActivity > this.sessionTimeout) {
this.sessions.delete(sessionId);
this.logger.info(`Session expired: ${sessionId}`);
}
}
}
async start() {
const port = this.config.port || 3001;
const host = this.config.host || "localhost";
// Start session cleanup interval
setInterval(() => this.cleanupSessions(), 60000); // Every minute
return new Promise((resolve, reject) => {
this.httpServer = this.app.listen(port, host, () => {
this.logger.info(`HTTP transport listening on http://${host}:${port}`);
resolve();
}).on("error", reject);
});
}
async stop() {
// Clear sessions
this.sessions.clear();
// Stop HTTP server
return new Promise((resolve) => {
if (this.httpServer) {
this.httpServer.close(() => {
this.logger.info("HTTP transport stopped");
resolve();
});
}
else {
resolve();
}
});
}
isRunning() {
return this.httpServer && this.httpServer.listening;
}
}
//# sourceMappingURL=http.js.map