import { McpServer } from "@modelcontextprotocol/server"; import { serveStdio } from "@modelcontextprotocol/server/stdio"; import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node"; import { Command } from "commander"; import http from "node:http"; import crypto from "node:crypto"; import { registerAuthTools } from "./tools/auth.ts"; import { registerEmailTools } from "./tools/email.ts"; import { registerFolderTools } from "./tools/folders.ts"; const program = new Command() .name("exchange-mcp") .description("Exchange MCP Server — EWS integration via MCP") .option("--transport ", "Transport: stdio or sse", "stdio") .option("--token-hash ", "SHA-256 hash of bearer token for HTTP transport auth") .option("--host ", "HTTP host", "127.0.0.1") .option("--port ", "HTTP port", "8000"); program.parse(process.argv); const options = program.opts(); function buildServer(): McpServer { const server = new McpServer({ name: "exchange-mcp", version: "1.0.0", }); registerAuthTools(server); registerEmailTools(server); registerFolderTools(server); return server; } async function main() { const transportType: string = options.transport; if (transportType === "stdio") { serveStdio(buildServer); return; } if (transportType === "sse") { const server = buildServer(); const mcpTransport = new NodeStreamableHTTPServerTransport({ sessionIdGenerator: () => crypto.randomUUID(), }); await server.connect(mcpTransport); const httpServer = http.createServer(async (req, res) => { if (options.tokenHash) { const auth = req.headers.authorization || ""; const token = auth.startsWith("Bearer ") ? auth.slice(7) : ""; const hash = crypto.createHash("sha256").update(token).digest("hex"); if (hash !== options.tokenHash) { res.writeHead(401, { "Content-Type": "text/plain" }); res.end("Unauthorized"); return; } } res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); if (req.method === "OPTIONS") { res.writeHead(200); res.end(); return; } await mcpTransport.handleRequest(req, res); }); const port = Number(options.port); httpServer.listen(port, options.host); console.error( `Exchange MCP Server running via SSE on http://${options.host}:${port}`, ); return; } console.error(`Unsupported transport: ${transportType}. Use "stdio" or "sse".`); process.exit(1); } main().catch((error) => { console.error("Fatal error:", error); process.exit(1); });