Skip to main content
Glama
transport.ts5.53 kB
import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import express, { Request, Response } from "express"; import { toolList } from './toolList.js'; import { createToolContext, loginHandler, sendMessageHandler, getForumChannelsHandler, createForumPostHandler, getForumPostHandler, replyToForumHandler, deleteForumPostHandler, createTextChannelHandler, deleteChannelHandler, readMessagesHandler, getServerInfoHandler, addReactionHandler, addMultipleReactionsHandler, removeReactionHandler, deleteMessageHandler, createWebhookHandler, sendWebhookMessageHandler, editWebhookHandler, deleteWebhookHandler, editCategoryHandler, createCategoryHandler, deleteCategoryHandler, listServersHandler, searchMessagesHandler } from './tools/tools.js'; import { Client, GatewayIntentBits } from "discord.js"; import { info, error } from './logger.js'; export interface MCPTransport { start(server: Server): Promise<void>; stop(): Promise<void>; } export class StdioTransport implements MCPTransport { private transport: StdioServerTransport | null = null; async start(server: Server): Promise<void> { this.transport = new StdioServerTransport(); await server.connect(this.transport); } async stop(): Promise<void> { if (this.transport) { await this.transport.close(); this.transport = null; } } } export class StreamableHttpTransport implements MCPTransport { private app: express.Application; private server: Server | null = null; private httpServer: any = null; private transport: StreamableHTTPServerTransport | null = null; private toolContext: ReturnType<typeof createToolContext> | null = null; private sessionId: string = ''; constructor(private port: number = 8080) { this.app = express(); this.app.use(express.json()); this.sessionId = `session_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`; info(`Created HTTP transport with session ID: ${this.sessionId}`); } async start(server: Server): Promise<void> { this.server = server; info('Starting HTTP transport with server: ' + String(!!this.server)); // Try to get client from the DiscordMCPServer instance if (server) { const anyServer = server as any; let client: Client | undefined; if (anyServer._context?.client) { client = anyServer._context.client; info('Found client in server._context'); } else if (anyServer.client instanceof Client) { client = anyServer.client; info('Found client directly on server object'); } else if (anyServer._parent?.client instanceof Client) { client = anyServer._parent.client; info('Found client in server._parent'); } if (client) { this.toolContext = createToolContext(client); info('Tool context initialized with Discord client'); } else { info('Creating new Discord client for transport'); const newClient = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMessageReactions ] }); this.toolContext = createToolContext(newClient); info('Tool context initialized with new Discord client'); } } // Create transport this.transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined // stateless }); // Connect the transport await this.server.connect(this.transport); info('Transport connected'); // Setup /mcp endpoint to use transport.handleRequest() this.app.all('/mcp', async (req: Request, res: Response) => { try { await this.transport!.handleRequest(req, res, req.body); } catch (err) { error('Error handling MCP request: ' + String(err)); if (!res.headersSent) { res.status(500).json({ error: 'Internal server error' }); } } }); return new Promise((resolve) => { this.httpServer = this.app.listen(this.port, '0.0.0.0', () => { info(`MCP Server listening on 0.0.0.0:${this.port}`); resolve(); }); }); } async stop(): Promise<void> { if (this.transport) { await this.transport.close(); this.transport = null; } if (this.server) { await this.server.close(); this.server = null; } if (this.httpServer) { return new Promise((resolve) => { this.httpServer.close(() => { info('HTTP server closed'); this.httpServer = null; resolve(); }); }); } } }

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/barryyip0625/mcp-discord'

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