Skip to main content
Glama
index.ts8.68 kB
#!/usr/bin/env node import 'dotenv/config'; import express, { Request, Response } from 'express'; import { randomUUID } from 'node:crypto'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js'; import { getDiscordClient, destroyClient } from './utils/discord-client.js'; import { registerServerTools } from './tools/server-tools.js'; import { registerChannelTools } from './tools/channel-tools.js'; import { registerMemberTools } from './tools/member-tools.js'; import { registerRoleTools } from './tools/role-tools.js'; import { registerPermissionTools } from './tools/permission-tools.js'; import { registerMessageTools } from './tools/message-tools.js'; import { registerEmojiTools } from './tools/emoji-tools.js'; import { registerWebhookTools } from './tools/webhook-tools.js'; import { registerInviteTools } from './tools/invite-tools.js'; import { registerEventTools } from './tools/event-tools.js'; import { registerThreadTools } from './tools/thread-tools.js'; import { registerAuditTools } from './tools/audit-tools.js'; /** * Discord MCP Server * * This MCP server provides comprehensive tools for managing Discord servers. * It requires the DISCORD_BOT_TOKEN environment variable to be set. * * Available tool categories: * - Server Management: list_servers, get_server_info, modify_server * - Channel Management: list_channels, get_channel_info, create_channel, delete_channel, modify_channel * - Member Management: list_members, get_member_info, modify_member, kick_member, ban_member, unban_member, list_bans * - Role Management: list_roles, get_role_info, create_role, delete_role, modify_role, assign_role, remove_role * - Permission Management: get_channel_permissions, set_channel_permission, delete_channel_permission, list_permissions, sync_channel_permissions * - Message Management: send_message, get_messages, edit_message, delete_message, bulk_delete_messages, pin/unpin, reactions * - Emoji & Sticker Management: list_emojis, create_emoji, delete_emoji, modify_emoji, sticker operations * - Webhook Management: list_channel_webhooks, list_guild_webhooks, create_webhook, delete_webhook, modify_webhook, send_webhook_message * - Invite Management: list_invites, get_invite_info, create_invite, delete_invite * - Event Management: list_events, get_event_info, create_event, modify_event, delete_event, get_event_subscribers * - Thread Management: list_threads, create_thread, create_forum_post, modify_thread, delete_thread, join/leave, member management * - Audit & Moderation: get_audit_logs, list_audit_log_types, list_automod_rules, get_automod_rule, delete_automod_rule, toggle_automod_rule */ // Create a configured MCP server instance function createMcpServer(): McpServer { const server = new McpServer({ name: 'discord-mcp', version: '1.0.5', }); // Register all tool categories registerServerTools(server); registerChannelTools(server); registerMemberTools(server); registerRoleTools(server); registerPermissionTools(server); registerMessageTools(server); registerEmojiTools(server); registerWebhookTools(server); registerInviteTools(server); registerEventTools(server); registerThreadTools(server); registerAuditTools(server); return server; } // Run server with stdio transport (for mcp-proxy and Claude Desktop) async function runStdioServer() { // Create MCP server and connect via stdio // Note: We don't require DISCORD_BOT_TOKEN at startup to allow the server // to start and respond to capability queries. The token is only required // when tools are actually called (handled in discord-client.ts). const server = createMcpServer(); const transport = new StdioServerTransport(); // Setup graceful shutdown const cleanup = async () => { await destroyClient(); process.exit(0); }; process.on('SIGINT', cleanup); process.on('SIGTERM', cleanup); await server.connect(transport); } // Run server with HTTP transport async function runHttpServer() { // Check for Discord token if (!process.env.DISCORD_BOT_TOKEN) { console.error('Error: DISCORD_BOT_TOKEN environment variable is required'); console.error('Please set it before running the server:'); console.error(' export DISCORD_BOT_TOKEN=your_bot_token_here'); process.exit(1); } // Get port from environment or default to 3000 const PORT = parseInt(process.env.PORT || '3000', 10); // Initialize Discord client console.log('Initializing Discord client...'); try { await getDiscordClient(); console.log('Discord client initialized successfully'); } catch (error) { console.error('Failed to initialize Discord client:', error); process.exit(1); } // Create Express app const app = express(); app.use(express.json()); // Store active transports by session ID const transports: Record<string, StreamableHTTPServerTransport> = {}; // Health check endpoint app.get('/health', (_req: Request, res: Response) => { res.json({ status: 'ok', service: 'discord-mcp', version: '1.0.5' }); }); // MCP endpoint - POST for requests app.post('/mcp', async (req: Request, res: Response) => { const sessionId = req.headers['mcp-session-id'] as string | undefined; let transport: StreamableHTTPServerTransport; if (sessionId && transports[sessionId]) { // Reuse existing session transport = transports[sessionId]; } else if (!sessionId && isInitializeRequest(req.body)) { // New session initialization transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => randomUUID(), onsessioninitialized: (id) => { transports[id] = transport; console.log('Session initialized:', id); }, }); transport.onclose = () => { if (transport.sessionId) { delete transports[transport.sessionId]; console.log('Session closed:', transport.sessionId); } }; // Create and connect MCP server for this session const server = createMcpServer(); await server.connect(transport); } else { res.status(400).json({ jsonrpc: '2.0', error: { code: -32000, message: 'Invalid session or missing initialization' }, id: null, }); return; } await transport.handleRequest(req, res, req.body); }); // MCP endpoint - GET for SSE streams app.get('/mcp', async (req: Request, res: Response) => { const sessionId = req.headers['mcp-session-id'] as string; const transport = transports[sessionId]; if (transport) { await transport.handleRequest(req, res); } else { res.status(400).json({ jsonrpc: '2.0', error: { code: -32000, message: 'Invalid or missing session' }, id: null, }); } }); // MCP endpoint - DELETE for session cleanup app.delete('/mcp', async (req: Request, res: Response) => { const sessionId = req.headers['mcp-session-id'] as string; const transport = transports[sessionId]; if (transport) { await transport.handleRequest(req, res); } else { res.status(400).json({ jsonrpc: '2.0', error: { code: -32000, message: 'Invalid or missing session' }, id: null, }); } }); // Setup graceful shutdown const cleanup = async () => { console.log('Shutting down...'); // Close all active transports for (const sessionId of Object.keys(transports)) { try { await transports[sessionId].close(); } catch { // Ignore errors during cleanup } } await destroyClient(); process.exit(0); }; process.on('SIGINT', cleanup); process.on('SIGTERM', cleanup); // Start HTTP server app.listen(PORT, () => { console.log(`Discord MCP HTTP server is running on http://localhost:${PORT}`); console.log(`MCP endpoint: http://localhost:${PORT}/mcp`); console.log(`Health check: http://localhost:${PORT}/health`); }); } async function main() { // Check for --http flag or TRANSPORT environment variable // Default to stdio mode for npm/npx compatibility (standard for MCP servers) const useHttp = process.argv.includes('--http') || process.env.MCP_TRANSPORT === 'http'; if (useHttp) { await runHttpServer(); } else { await runStdioServer(); } } main().catch((error) => { console.error('Fatal error:', error); process.exit(1); });

Implementation Reference

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

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