// A minimal remote MCP server over Streamable HTTP that REQUIRES a bearer token. // Used to verify neuron-connectd's http transport + Keychain-backed auth end to // end, with no external dependency. Wrong/missing token → 401. // // TEST_MCP_TOKEN=secret-123 TEST_MCP_PORT=7795 node test/auth-http-mcp-server.mjs import http from "node:http"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; const TOKEN = process.env.TEST_MCP_TOKEN || "secret-123"; const PORT = Number(process.env.TEST_MCP_PORT || 7795); function buildServer() { const server = new McpServer({ name: "auth-test", version: "0.1.0" }); server.registerTool( "whoami", { description: "Return the authenticated identity.", inputSchema: {} }, async () => ({ content: [{ type: "text", text: "authenticated-ok: bearer token accepted" }] }) ); return server; } http .createServer(async (req, res) => { // Bearer auth gate — the whole point of the test. const auth = req.headers["authorization"] || ""; if (auth !== `Bearer ${TOKEN}`) { res.writeHead(401, { "content-type": "application/json", "www-authenticate": "Bearer" }); res.end(JSON.stringify({ error: "unauthorized" })); return; } let body = ""; for await (const chunk of req) body += chunk; const parsed = body ? JSON.parse(body) : undefined; const server = buildServer(); const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined }); res.on("close", () => { transport.close(); server.close(); }); await server.connect(transport); await transport.handleRequest(req, res, parsed); }) .listen(PORT, "127.0.0.1", () => { console.error(`[auth-test-mcp] listening on http://127.0.0.1:${PORT} (token gated)`); });