Security Model

Security Goals #

  • Prevent cross-tenant token misuse
  • Restrict upstream Discord scope per request
  • Reduce abuse impact from invalid tokens and hostile traffic
  • Keep policy decisions explicit and observable

Authentication and Identity Anchoring #

  • Authorization: Bot <token> is required on protected API routes.
  • APP_ID is extracted from the token's first base64url segment.
  • Signature validation is not required by design, so identity is anchored with Discord verification (GET /applications/@me) plus token hash checks.

Header-Based Policy Controls #

Request-time controls:

  • X-Allowed-Methods
  • X-Allowed-Paths
  • X-Target-Guilds
  • X-Target-Channels
  • X-Target-Users
  • X-Permission-Bits
  • X-Privileged-Intents
  • X-Allowed-Mentions
  • X-Current-User
  • X-Current-Guild
  • X-Current-Channel
  • X-Current-Message
  • X-Image-Model
  • X-Owner-Access
  • X-Privileged-Call

Detailed formats and examples are documented in headers.md.

Important X-Target-* notes:

  • accepted values are CSV snowflakes, *, or 0
  • 0 is a valid deny-all sentinel (never matches Discord snowflakes)
  • for defense in depth, combine target restrictions with narrow X-Allowed-Paths / X-Allowed-Methods
  • X-Target-Users: 0 can hide DM-only tools entirely
  • explicit X-Target-Users values can still narrow DM-oriented tools to a fixed user allowlist
  • if X-Privileged-Intents omits server_members, member-name resolution falls back to user-name resolution (ID-based targeting still enforced)

X-Allowed-Methods also applies to Discord MCP-local tools:

  • read Discord MCP tools: GET or POST
  • write Discord MCP tools: POST

X-Allowed-Mentions gives the integrator final control over how outgoing message mentions are handled.

X-Current-User lets the Discord MCP reuse the current user as the default user scope for user-targeted tools and DM-capable message flows.

X-Current-Guild lets the Discord MCP reuse the current guild as the default guild scope for many guild-scoped tools.

X-Current-Channel helps stop redundant message-sending flows when the model is already replying in the right place, and it can also act as the default channel scope for many channel-scoped tools.

X-Current-Message gives the Discord MCP an exact message anchor. When guild and channel context are also present, the Discord MCP can use it to build a more precise DM attribution link. It remains contextual metadata even if the message was ephemeral or has already been deleted.

App-level defaults are applied when request headers are omitted:

  • default_allowed_methods
  • default_allowed_paths
  • default_target_users
  • default_target_guilds
  • default_target_channels
  • default_permission_bits
  • default_cache_max_ttl

These defaults are managed by the service operator.

Owner and Privileged Paths #

  • mcp_* tools require X-Owner-Access.
  • Operator-only administrative tools require explicit owner/privileged headers and privileged app configuration.

This prevents accidental exposure of high-impact administrative tools.

Abuse Controls #

Abuse protection behavior:

  • repeated invalid tokens from one IP hash increase counter
  • IP can be blocked when threshold is reached
  • token markers and counters expire automatically (TTL-driven)

Fail-Closed Behavior #

  • if the backing store is unavailable, the Discord MCP returns an error and blocks processing
  • invalid headers are rejected early
  • policy mismatch returns 403 before Discord call
  • oversized API payloads are blocked before request handling

For routes where scope is not directly visible in path IDs, the Discord MCP uses resolved-scope safeguards:

  • delete_invite can resolve invite metadata first and enforce X-Target-Guilds / X-Target-Channels on the resolved payload
  • edit_webhook / delete_webhook can resolve webhook metadata first and enforce target checks before mutation
  • get_webhook enforces target checks from the returned payload when target headers are restrictive
  • extra lookups are skipped when target headers are absent or unrestricted

Trusted Proxy Handling #

Source IP extraction uses an operator-configured forwarded-IP header (default: X-Forwarded-For).

That header is used only when source proxy IP is inside configured trusted_proxy_cidrs.

If trusted_proxy_cidrs is empty, the Discord MCP ignores forwarded headers and uses the remote socket address.

If not trusted, remote socket address is used instead.

Operator Checklist #

  1. Keep X-Allowed-Paths narrow.
  2. Use X-Target-* for all user-influenced workflows.
  3. Use minimal X-Permission-Bits.
  4. Use X-Allowed-Mentions when mention scope matters.
  5. Use X-Current-User, X-Current-Guild, and X-Current-Channel when your client already knows the active Discord context.
  6. Avoid exposing owner or privileged headers to untrusted callers.
  7. Monitor repeated 403 and token verification failures.
  8. Rotate compromised bot tokens immediately.