Skip to content

Instantly share code, notes, and snippets.

@cjavdev
Created August 5, 2025 14:19
Show Gist options
  • Save cjavdev/5505b24f6998b17d06df6a2c01c2f563 to your computer and use it in GitHub Desktop.
Save cjavdev/5505b24f6998b17d06df6a2c01c2f563 to your computer and use it in GitHub Desktop.
Minimal MCP server.ts
import express, { Request, Response } from "express";
import { randomUUID } from "crypto";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
const app = express();
app.use(express.json());
// Session management for stateful connections
const transports: { [sessionId: string]: StreamableHTTPServerTransport } = {};
function createMcpServer(): McpServer {
const server = new McpServer(
{
name: "math-mcp-server",
version: "1.0.0"
}
);
server.registerTool("add",
{
title: "Addition Tool",
description: "Add two numbers",
inputSchema: { a: z.number(), b: z.number() }
},
async ({ a, b }) => ({
content: [{ type: "text", text: String(a + b) }]
})
);
server.registerTool("multiply",
{
title: "Multiplication Tool",
description: "Multiply two numbers",
inputSchema: { a: z.number(), b: z.number() }
},
async ({ a, b }) => ({
content: [{ type: "text", text: String(a * b) }]
})
);
return server;
}
// Initialze and start session connect requests
app.post('/mcp', async (req: Request, res: Response) => {
const sessionId = req.headers['mcp-session-id'] as string | undefined;
let transport: StreamableHTTPServerTransport;
try {
if (sessionId && transports[sessionId]) {
// Reuse existing transport
transport = transports[sessionId];
} else if (!sessionId && isInitializeRequest(req.body)) {
// New initialization request
transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => randomUUID(),
onsessioninitialized: (sessionId) => {
transports[sessionId] = transport;
},
enableDnsRebindingProtection: process.env.NODE_ENV === 'production',
allowedHosts: ['localhost:3000'] // env.ALLOWED_DOMAINS
});
// Clean up transport when closed
transport.onclose = () => {
if (transport.sessionId) {
delete transports[transport.sessionId];
}
};
const server = createMcpServer();
await server.connect(transport);
} else {
res.status(400).json({
jsonrpc: '2.0',
error: {
code: -32000,
message: 'Bad Request: No valid session ID provided',
},
id: null,
});
return;
}
await transport.handleRequest(req, res, req.body);
} catch (error) {
if (!res.headersSent) {
res.status(500).json({
jsonrpc: '2.0',
error: {
code: -32603,
message: 'Internal server error',
},
id: null,
});
}
}
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`🔗 Streamable HTTP MCP endpoint: http://localhost:${PORT}/mcp`);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment