We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/jmagar/homelab-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
#!/usr/bin/env node
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import express from "express";
import {
createDestructiveRateLimitMiddleware,
createHealthRateLimiter,
createMcpRateLimiter,
} from "./health-rate-limiter.js";
import {
asyncHandler,
authMiddleware,
csrfProtectionMiddleware,
errorHandler,
fallbackErrorHandler,
requestIdMiddleware,
} from "./middleware/index.js";
import { createDefaultContainer, type ServiceContainer } from "./services/container.js";
import { registerTools } from "./tools/index.js";
import { getCurrentTimestamp } from "./utils/time.js";
// Server metadata
const SERVER_NAME = "synapse-mcp";
const SERVER_VERSION = "1.0.0";
// Global service container instance
let globalContainer: ServiceContainer | undefined;
/**
* Create and configure the MCP server
*/
async function createServer(): Promise<McpServer> {
const server = new McpServer({
name: SERVER_NAME,
version: SERVER_VERSION,
});
// Create and initialize service container (preloads host configs, enables caching)
globalContainer = createDefaultContainer();
await globalContainer.initialize();
// Register all tools
registerTools(server, globalContainer);
return server;
}
/**
* Run server with stdio transport (for Claude Code, local integrations)
*/
async function runStdio(): Promise<void> {
const server = await createServer();
const transport = new StdioServerTransport();
await server.connect(transport);
}
/**
* Run server with HTTP transport (for remote access, multiple clients)
*/
async function runHTTP(): Promise<void> {
// SECURITY (CWE-306): Warn when HTTP mode runs without authentication
if (!process.env.SYNAPSE_API_KEY) {
console.error(
"[SECURITY WARNING] HTTP transport active without SYNAPSE_API_KEY. " +
"All requests will be unauthenticated. Set SYNAPSE_API_KEY to enable API key authentication."
);
}
const server = await createServer();
const app = express();
// Create transport once at startup and reuse across requests
// This eliminates 50-200ms per-request overhead from repeated server.connect() calls
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
enableJsonResponse: true,
});
await server.connect(transport);
// Request ID middleware MUST be first
app.use(requestIdMiddleware);
app.use(express.json({ limit: "100kb" }));
// Request logging middleware
app.use((req, _res, next) => {
const _timestamp = getCurrentTimestamp();
const _forwarded = req.headers["x-forwarded-for"] || req.headers["x-real-ip"] || "";
next();
});
// Health check endpoint with rate limiting to prevent DDoS
const healthLimiter = createHealthRateLimiter();
app.get("/health", healthLimiter, (req, res) => {
res.json({
status: "ok",
server: SERVER_NAME,
version: SERVER_VERSION,
requestId: req.requestId,
});
});
// MCP endpoint - reuses shared transport
// Rate limiting (S-C1) to prevent DoS attacks from expensive operations:
// 1. General limiter: 60 req/min/IP for all MCP operations
// 2. Destructive limiter: 10 req/min/IP for destructive ops (prune, remove, exec, etc.)
// CSRF protection middleware (S-M6) BEFORE auth to prevent CSRF attacks
// Auth middleware (S-C1) protects this endpoint when SYNAPSE_API_KEY is configured
const mcpLimiter = createMcpRateLimiter();
const destructiveLimiter = createDestructiveRateLimitMiddleware();
app.post(
"/mcp",
mcpLimiter,
destructiveLimiter,
csrfProtectionMiddleware,
authMiddleware,
asyncHandler(async (req, res) => {
await transport.handleRequest(req, res, req.body);
})
);
// Error handling middleware MUST be after all routes
app.use(errorHandler);
app.use(fallbackErrorHandler);
const port = Number.parseInt(process.env.SYNAPSE_PORT || "53000", 10);
const host = process.env.SYNAPSE_HOST || "127.0.0.1";
app.listen(port, host, () => {
/* Server started successfully - intentionally no logging to preserve stdio for MCP protocol */
});
}
/**
* Print usage information
*/
function printUsage(): void {
/* Reserved for future CLI usage documentation */
}
/**
* Graceful shutdown handler
*/
async function shutdown(_signal: string): Promise<void> {
if (globalContainer) {
await globalContainer.shutdown();
}
process.exit(0);
}
// Register signal handlers for graceful shutdown
process.on("SIGINT", () => {
shutdown("SIGINT").catch((_error) => {
process.exit(1);
});
});
process.on("SIGTERM", () => {
shutdown("SIGTERM").catch((_error) => {
process.exit(1);
});
});
// Main entry point
const args = process.argv.slice(2);
if (args.includes("--help") || args.includes("-h")) {
printUsage();
process.exit(0);
}
const transportMode = args.includes("--http") ? "http" : "stdio";
if (transportMode === "http") {
runHTTP().catch((_error) => {
process.exit(1);
});
} else {
runStdio().catch((_error) => {
process.exit(1);
});
}