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.
Notification URI patterns
Section titled “Notification URI patterns”| URI | Signal source | Handler |
|---|---|---|
discord://guild/{id}/info | GUILD_UPDATE | guild_update.ts |
discord://voice/{guild_id}/state | VOICE_STATE_UPDATE | voice_state_update.ts |
discord://channel/{id}/typing | TYPING_START | typing_start.ts |
discord://guild/{id}/members/online | PRESENCE_UPDATE, debounced | presence_update.ts |
discord://guild/{id}/audit-log/recent | 60-second REST polling | audit_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.
Startup and fallback
Section titled “Startup and fallback”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.
npm install -g @discord-mcp/cli discord.jsdiscord-mcp serve --gatewaySubscription registry
Section titled “Subscription registry”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.
Debounce and polling
Section titled “Debounce and polling”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.
Known limitations
Section titled “Known limitations”- Live URIs are not returned by
resources/list. resources/readcannot 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.
Source map
Section titled “Source map”| Concern | File |
|---|---|
| Lazy-loaded Discord client and intents | gateway/client.ts |
| In-memory subscription registry | gateway/subscription_registry.ts |
| Debounce helper | gateway/debounce.ts |
| Event handlers | gateway/handlers/ |
| Stdio startup fallback | mcp-server/src/transports/stdio.ts |
Follow the verification recipe or return to Client compatibility.