Skip to content

Gateway notifications

The default runtime uses Discord’s HTTP API. With --gateway, discord-mcp also attempts to start a discord.js client and can emit MCP notifications/resources/updated for subscribed URI patterns. The implementation wires 5 handlers: four event-driven paths and one audit-log poller.

URISignal sourceHandler
discord://guild/{id}/infoGUILD_UPDATEguild_update.ts
discord://voice/{guild_id}/stateVOICE_STATE_UPDATEvoice_state_update.ts
discord://channel/{id}/typingTYPING_STARTtyping_start.ts
discord://guild/{id}/members/onlinePRESENCE_UPDATE, debouncedpresence_update.ts
discord://guild/{id}/audit-log/recent60-second REST pollingaudit_log_poll.ts

The notification carries the URI as a signal. It does not contain current guild, voice, typing, presence, or audit-log state. A consumer must call an appropriate REST tool when it needs data after the update.

discord.js is lazy-imported only when Gateway mode starts. The client requests Guilds, Guild Voice States, and Guild Presences intents.

If import, login, or handler startup fails, the stdio transport catches the error, logs a warning, and continues in REST-only mode. This keeps the core tool server available, but it means operators must inspect startup logs when live notifications matter.

Terminal window
npm install -g @discord-mcp/cli discord.js
discord-mcp serve --gateway

SubscriptionRegistry is an in-memory Set<string> with subscribe, unsubscribe, membership, list, pattern-match, and clear operations. It does not currently store a session identifier or persist subscriptions across process restarts.

When an event handler receives a Discord event, it computes a URI, checks whether that exact URI is registered, and calls the MCP notification callback only for a match. Unknown URI strings can be registered but no handler will ever match them.

Presence and typing handlers use the shared debounce helper to coalesce bursts before sending an update notification. Voice and guild updates notify directly. Audit-log change detection is not a Gateway event in this implementation; a 60-second poll compares the newest entry for each subscribed guild URI.

  • Live URIs are not returned by resources/list.
  • resources/read cannot fetch their state.
  • Subscribe capability is registered even without a working Gateway client.
  • Gateway startup failure degrades silently to REST-only except for a warning log.
  • Subscriptions are process-local and in-memory.
  • A notification does not include the changed state.

These limits should shape the product contract. A production consumer needs health evidence, a matching REST fallback, and an end-to-end notification check.

ConcernFile
Lazy-loaded Discord client and intentsgateway/client.ts
In-memory subscription registrygateway/subscription_registry.ts
Debounce helpergateway/debounce.ts
Event handlersgateway/handlers/
Stdio startup fallbackmcp-server/src/transports/stdio.ts

Follow the verification recipe or return to Client compatibility.