A small, stateless Model Context Protocol server for Discord. It speaks to the Discord REST API on every call, so there is no gateway socket and nothing to babysit - just connect MCP clients and ask.
The server reads these environment variables at startup. Both must be set on the deployment that hosts the MCP endpoint.
Environment variables
# Required: a Discord bot token with the right guild intents.
DISCORD_TOKEN=your-bot-token-here
# Optional: shared-secret auth for the MCP endpoint.
# If set, every request must send the same value in:
# Authorization: Bearer <key> or x-mcp-api-key: <key>
MCP_API_KEY=your-mcp-api-key
Connect a client
Point any MCP client at this URL. The handshake is a normal Streamable HTTP POST with JSON-RPC 2.0 bodies.
Every call is stateless. The Nitro route constructs a fresh discord.js REST client from DISCORD_TOKEN, routes one JSON-RPC envelope through the MCP transport, then closes both. There is no gateway WebSocket and no per-instance cache, so deploys, cold starts, and route changes are non-events.
Discord rate limits (429s) are honored automatically by the REST client. Permission failures surface as 403 forbidden with a message that names the missing permission, and token problems surface as 401 unauthorizedwith a hint to check DISCORD_TOKEN. Every tool result is wrapped in a stable shape: { ok, ... } on success, { code, message, status } on failure.
Auth - if MCP_API_KEY is set, every request must include the matching value in Authorization: Bearer <key> or the x-mcp-api-key header. When unset, the endpoint is open.
Health - GET /mcp returns the tool list and the current auth mode.