Skip to content

Gateway — subscribe to live guild state

The default discord-mcp transport is REST-only — every read is a fresh HTTP call. For dashboards, presence indicators, or any UI that should reflect the guild as it changes, polling burns rate limits and lags. The optional --gateway mode replaces polling with MCP resource subscriptions backed by the Discord Gateway WebSocket.

A dashboard agent says: “Notify me whenever someone goes voice-active in guild XYZ, or when a moderator deletes a message.”

REST polling would mean spinning a 5-second loop hitting /voice-states and /audit-logs per guild — expensive, slow, blunt. Gateway subscriptions give the agent push notifications instead.

URIPushed by Gateway event
discord://guild/{id}/infoGUILD_UPDATE
discord://guild/{id}/members/onlinePRESENCE_UPDATE (debounced)
discord://channel/{id}/typingTYPING_START
discord://voice/{guild_id}/stateVOICE_STATE_UPDATE
discord://guild/{id}/audit-log/recentGUILD_AUDIT_LOG_ENTRY_CREATE (polled fallback)
  1. Start the server with gateway mode.

    Terminal window
    pnpm add discord.js
    discord-mcp --gateway

    On startup the server connects to the Discord Gateway, authenticates with the bot token, and registers handlers for the five event types above.

  2. Discover available resources.

    The MCP method is resources/list. The server returns the URIs above plus the standard tool-discovery resources.

    { "method": "resources/list" }
  3. Subscribe to the URIs you care about.

    The MCP method is resources/subscribe. Subscribe individually per URI; the server records intent in an in-memory registry and only forwards events for subscribed resources.

    {
    "method": "resources/subscribe",
    "params": { "uri": "discord://voice/111122223333444455/state" }
    }
  4. Handle update notifications.

    Whenever the underlying Gateway event fires, the server emits a JSON-RPC notification using the standard MCP method notifications/resources/updated. The agent reacts by calling resources/read to fetch the latest state — or by treating the notification itself as the signal, depending on the use case.

    {
    "method": "notifications/resources/updated",
    "params": { "uri": "discord://voice/111122223333444455/state" }
    }
  5. Unsubscribe when done.

    Long-lived agents should release subscriptions to keep the registry small. The server otherwise tears them down on disconnect.

    {
    "method": "resources/unsubscribe",
    "params": { "uri": "discord://voice/111122223333444455/state" }
    }
  • REST polling → push. Replacing a 5s polling loop with an event handler cuts both latency and rate-limit burn.
  • Discord Gateway events → MCP resources. The Gateway speaks WebSocket events; MCP speaks resources. The server bridges the two so MCP clients can use the standard subscription primitive.
  • discord.js is optional. The Gateway path imports discord.js lazily. Users who only need REST tools never pay the install cost.

PRESENCE_UPDATE and TYPING_START can fire dozens of times per second on a busy guild. The server debounces notifications per resource — rapid events within a short window coalesce into one notifications/resources/updated emission, so the agent’s notification stream stays sane.

ClientResource subscription support
Claude Desktopyes
Claude Codeyes
Cursorno (use REST polling)
ChatGPTno
Cline, Continue, Windsurfno

Clients that don’t advertise the capability should stick with the REST tools (voice_get_user_state, audit_log_get, etc.) and a polling loop.