Skip to main content
Glama

SSE MCP Server with JWT Authentication

index.ts4.14 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js"; import { z } from "zod"; import jwt, { JwtPayload } from "jsonwebtoken"; import * as dotenv from "dotenv"; import { RequestHandler } from "express"; dotenv.config(); import express from "express"; export const authenticateToken: RequestHandler = (req, res, next) => { const authHeader = req.headers["authorization"]; const token = authHeader && authHeader.split(" ")[1]; console.log("Token", token); if (!token) { res.sendStatus(401); console.log("Unauthorized"); return; // important } try { const decoded = jwt.verify( token, process.env.JWT_SECRET || "your-secret-key" ); console.log("Decoded", decoded); req.user = decoded as JwtPayload; next(); } catch (err) { console.error("Token verification failed:", err); res.sendStatus(403); console.log("Forbidden"); return; // important } }; const app = express(); app.use((req, res, next) => { console.log("Request received", req.method, req.url); next(); }); let servers: any[] = []; app.get("/", (req, res) => { console.log("Hello World"); res.send("Hello World"); }); app.get("/sse", authenticateToken, async (req, res) => { console.log("SSE requested"); const transport = new SSEServerTransport("/message", res); const server = new McpServer({ name: "bsc-mcp", version: "1.0.0", }); // Define the test tool with a properly structured response server.tool("test", "Test description", async () => { console.log("Test tool called"); return { content: [ { type: "text", text: "Security check successful", }, ], }; }); // Tool 1: Echo Tool server.tool( "echo", "Echo back a message", { message: z.string().describe("Message to echo back"), }, async ({ message }) => { return { content: [ { type: "text", text: `Echo: ${message}`, }, ], }; } ); // Tool 2: Get Time Tool server.tool("get-time", "Get current server time", {}, async () => { const currentTime = new Date().toISOString(); return { content: [ { type: "text", text: `Current server time is: ${currentTime}`, }, ], }; }); // Tool 3: Random Number Generator server.tool( "random-number", "Generate a random number", { min: z.number().optional().default(0).describe("Minimum value"), max: z.number().optional().default(100).describe("Maximum value"), }, async ({ min, max }) => { const randomValue = Math.floor(Math.random() * (max - min + 1)) + min; return { content: [ { type: "text", text: `Random number between ${min} and ${max}: ${randomValue}`, }, ], }; } ); server.connect(transport); req.on("close", () => { console.log("Client closed connection"); }); server.server.onclose = () => { console.log("SSE connection closed"); servers = servers.filter((s) => s !== server); }; servers.push(server); }); app.get("/auth/token", (req, res) => { console.log("Auth token requested"); const username = req.query.username || "aniket"; const scope = req.query.scope || "mcp:access"; const token = jwt.sign( { username, scope }, process.env.JWT_SECRET || "your-secret-key", { expiresIn: "1h", issuer: "SSE MCP SERVER" } ); res.json({ token }); }); app.post("/message", authenticateToken, async (req, res) => { console.log("Received message"); const sessionId = req.query.sessionId; const transport = servers .map((s) => s.server.transport) .find((t) => t.sessionId === sessionId); if (!transport) { res.status(404).send("Session not found"); return; } await transport.handlePostMessage(req, res); }); const port = process.env.PORT || 3001; app.listen(port, () => { console.log(`Server running on http://localhost:${port}/sse`); });

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/anisirji/mcp-server-remote-setup-with-jwt-auth'

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