Skip to main content
Glama
oauth-mock.ts5.54 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; import express from "express"; import { createServer } from "http"; const WEBSERVER_PORT = 9001; // User data - each user has their own private data const USER_DATA = { user_alice: [ "Alice's secret project", "Alice's private notes", "Alice's API keys", ], user_bob: [ "Bob's confidential files", "Bob's personal data", "Bob's passwords", ], }; // Track which user is currently authorized (if any) let currentAuthorizedUser: string | null = null; // Track active sessions const activeSessions = new Map<string, StreamableHTTPServerTransport>(); function createOAuthMockServer(): McpServer { const server = new McpServer({ name: "test::oauth-mock", version: "1.0.0", }); server.registerTool( "get-user-data", { title: "Get User Data", description: "Returns the current user's private data", inputSchema: {}, }, async () => { console.log( `[OAuth Mock] Tool called, authorized user: ${currentAuthorizedUser}` ); // If no user is authorized, return 401 if (!currentAuthorizedUser) { throw new Error("Unauthorized: No user authenticated"); } // If authorized user is not recognized, return error if (!USER_DATA[currentAuthorizedUser as keyof typeof USER_DATA]) { throw new Error( `Unauthorized: User '${currentAuthorizedUser}' not recognized` ); } const userData = USER_DATA[currentAuthorizedUser as keyof typeof USER_DATA]; console.log( `[OAuth Mock] Returning data for ${currentAuthorizedUser}:`, userData ); return { content: [ { type: "text", text: `User data for ${currentAuthorizedUser}:\n${userData.join("\n")}`, }, ], }; } ); return server; } async function main(): Promise<void> { console.log("Starting OAuth Mock MCP server..."); // Create Express app for authorization endpoints const app = express(); app.use(express.json()); // Authorization endpoint - simulates OAuth completion app.post("/authorize", (req, res) => { const { user } = req.body as { user: "user_alice" | "user_bob" }; console.log(`[OAuth Mock] Authorization request for user: ${user}`); if (!user) { res.status(400).json({ error: "User is required" }); return; } // Check if user is recognized if (!USER_DATA[user]) { console.log(`[OAuth Mock] User '${user}' not recognized`); res.status(403).json({ error: `User '${user}' not recognized` }); return; } currentAuthorizedUser = user; console.log(`[OAuth Mock] User '${user}' is now authorized`); res.json({ success: true, authorizedUser: user }); return; }); // Revoke authorization endpoint app.post("/revoke", (_req, res) => { const previousUser = currentAuthorizedUser; currentAuthorizedUser = null; console.log(`[OAuth Mock] Authorization revoked for user: ${previousUser}`); res.json({ success: true, revokedUser: previousUser }); return; }); // Status endpoint to check current state app.get("/status", (_req, res) => { console.log("[OAuth Mock] Status request received"); res.json({ authorizedUser: currentAuthorizedUser, availableUsers: Object.keys(USER_DATA), }); return; }); // Create MCP server (will be connected to transports per session) // Add MCP endpoint to handle both POST and GET requests app.all("/mcp", async (req, res) => { console.log(`[OAuth Mock] MCP request received: ${req.method} /mcp`); const mcpServer = createOAuthMockServer(); const sessionId = req.headers["mcp-session-id"] as string | undefined; if (!sessionId) { // New session - create transport and connect const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => Math.random().toString(36).substring(2, 15), }); await mcpServer.connect(transport); // Store session for future requests transport.onclose = () => { if (transport.sessionId) { activeSessions.delete(transport.sessionId); } }; await transport.handleRequest(req, res, req.body); if (transport.sessionId) { activeSessions.set(transport.sessionId, transport); } } else { // Existing session - reuse transport const transport = activeSessions.get(sessionId); if (!transport) { res.status(404).send("Session not found"); return; } await transport.handleRequest(req, res, req.body); } }); const httpServer = createServer(app); // Start the HTTP server httpServer.listen(WEBSERVER_PORT, () => { console.log(`[OAuth Mock] Server running on http://127.0.0.1:${WEBSERVER_PORT}`); console.log(`[OAuth Mock] MCP endpoint: http://127.0.0.1:${WEBSERVER_PORT}/mcp`); console.log( `[OAuth Mock] Authorization endpoint: POST http://127.0.0.1:${WEBSERVER_PORT}/authorize` ); console.log( `[OAuth Mock] Available users: ${Object.keys(USER_DATA).join(", ")}` ); console.log( `[OAuth Mock] Currently authorized user: ${currentAuthorizedUser || "none"}` ); }); } // Run main().catch((error) => { console.error("Fatal error in OAuth Mock server:", error); process.exit(1); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TheLunarCompany/lunar'

If you have feedback or need assistance with the MCP directory API, please join our Discord server