MCP Header Reference (X-*)

This document describes all supported X-* headers, their formats, edge-cases, and the effective security behavior in the Discord MCP.

Comma-separated (CSV) header values may include spaces after commas; the parser trims the whole value, splits on commas, and trims each token.

Request Headers #

X-Target-Users #

  • Purpose: restrict actions targeting specific users.
  • Format: CSV of user snowflakes.
  • Special values:
  • *: unrestricted.
  • 0: explicit deny-all for user-targeted routes.
  • Examples:
  • X-Target-Users: 123456789012345678
  • X-Target-Users: 123456789012345678,234567890123456789
  • X-Target-Users: *
  • X-Target-Users: 0
  • Notes:
  • 0 disables DM-targeted tools such as send_direct_message.
  • When omitted or set to *, the Discord MCP leaves user targeting unrestricted.
  • When it names one or more explicit users, those IDs become the DM allowlist.

X-Target-Guilds #

  • Purpose: restrict actions targeting specific guilds.
  • Format: CSV of guild snowflakes.
  • Special values:
  • *: unrestricted.
  • 0: explicit deny-all for guild-targeted routes.
  • Examples:
  • X-Target-Guilds: 345678901234567890
  • X-Target-Guilds: 345678901234567890,456789012345678901
  • X-Target-Guilds: *
  • X-Target-Guilds: 0

X-Target-Channels #

  • Purpose: restrict actions targeting specific channels.
  • Format: CSV of channel snowflakes.
  • Special values:
  • *: unrestricted.
  • 0: explicit deny-all for channel-targeted routes.
  • Examples:
  • X-Target-Channels: 567890123456789012
  • X-Target-Channels: 567890123456789012,678901234567890123
  • X-Target-Channels: *
  • X-Target-Channels: 0
  • Notes:
  • If this header locks the Discord MCP to exactly one channel, send_message is hidden.
  • In that situation, replying normally is usually the better fit.

X-Current-User #

  • Purpose: tell the Discord MCP which user is already in scope for the current request.
  • Format: one user snowflake.
  • Examples:
  • X-Current-User: 123456789012345678
  • Rules:
  • Many user-scoped tools can use this as the default user when no user_id or user_name is provided.
  • DM-capable message tools can use it as the default DM target.
  • If the Discord MCP cannot resolve this user to a visible Discord account, the request is rejected.

X-Current-Channel #

  • Purpose: tell the Discord MCP which channel is already handling the current reply.
  • Format: one channel snowflake.
  • Examples:
  • X-Current-Channel: 567890123456789012
  • Rules:
  • Many channel-scoped tools can use this as the default channel when no channel_id or channel_name is provided.
  • If send_message targets this same channel, the Discord MCP rejects the call.
  • The error explains that the model should reply normally instead of using a second send tool.
  • If the Discord MCP cannot resolve this channel to a visible Discord channel, the request is rejected.
  • Invalid values are rejected with 400.

X-Current-Guild #

  • Purpose: tell the Discord MCP which guild is already in scope for the current request.
  • Format: one guild snowflake.
  • Examples:
  • X-Current-Guild: 345678901234567890
  • Rules:
  • Many guild-scoped tools can use this as the default guild when no guild_id or guild_name is provided.
  • If the Discord MCP cannot resolve this guild to a visible Discord guild, the request is rejected.
  • Invalid values are rejected with 400.

X-Current-Message #

  • Purpose: give the Discord MCP the current message ID when your client knows the exact message that triggered the request.
  • Format: one message snowflake.
  • Examples:
  • X-Current-Message: 678901234567890123
  • Rules:
  • On its own, this header is only extra context.
  • When X-Current-Guild and X-Current-Channel are also present, the Discord MCP can build a precise message link for DM attribution.
  • The value is treated as contextual metadata only. It can still be useful even if the original message was ephemeral or already gone.
  • Invalid values are rejected with 400.

X-Allowed-Mentions #

  • Purpose: enforce mention rules for message-sending tools.
  • Format: serialized JSON object.
  • Examples:
  • X-Allowed-Mentions: {"parse":[]}
  • X-Allowed-Mentions: {"parse":["users"],"replied_user":false}
  • Rules:
  • The Discord MCP applies this header to message send tools instead of accepting an allowed_mentions payload argument.
  • The value must be a JSON object.
  • Invalid JSON or non-object values are rejected with 400.

X-Allowed-Methods #

  • Purpose: allow-list methods at the Discord MCP preflight stage.
  • Format: CSV of exact method names, normalized to uppercase.
  • Special value:
  • *: unrestricted.
  • Examples:
  • X-Allowed-Methods: GET,POST
  • X-Allowed-Methods: PATCH
  • X-Allowed-Methods: *
  • Rules:
  • No globbing is supported.
  • If set and method is not allowed, the Discord MCP returns 403.
  • Applies to Discord tools and Discord MCP-local tools.
  • Discord MCP-local policy:
    • read tools require GET or POST.
    • write tools require POST.

X-Allowed-Paths #

  • Purpose: allow-list upstream Discord paths.
  • Format: CSV of glob patterns, each starting with /.
  • Examples:
  • X-Allowed-Paths: /guilds/*,/channels/*/messages/*
  • X-Allowed-Paths: /guilds/123456789012345678/*
  • X-Allowed-Paths: /users/@me/guilds
  • Rules:
  • Globbing is supported.
  • This is path-level filtering, not semantic entity filtering.

X-Permission-Bits #

  • Purpose: local Discord MCP pre-filter for tool execution and listing.
  • Format: one decimal integer bitmask.
  • Examples:
  • X-Permission-Bits: 8
  • X-Permission-Bits: 8192
  • X-Permission-Bits: 536870920
  • Rules:
  • Must be a single decimal integer.
  • * is not supported.
  • If omitted, no Discord MCP-side permission prefilter is applied.
  • ADMINISTRATOR (8) bypasses the Discord MCP permission filtering.
  • Discord still enforces real upstream permissions.

X-Privileged-Intents #

  • Purpose: declare which privileged Discord intents are available to the calling bot context.
  • Format: CSV values from:
  • presence
  • server_members
  • message_content
  • *
  • Examples:
  • X-Privileged-Intents: server_members
  • X-Privileged-Intents: presence,message_content
  • X-Privileged-Intents: *
  • Rules:
  • If omitted, or if the header value is empty or only whitespace (the value is trimmed as a whole before CSV parsing, so there are no tokens), the Discord MCP assumes no privileged intent (deny-by-default).
  • The Discord MCP hides and blocks tools that require privileged intents:
    • list_guild_members requires server_members.
    • resolve_id requires server_members only when type=member.
    • fetch_messages requires at least one of message_content or server_members. When it is available through server_members without message_content, its live description warns models that Discord normally redacts message content and that they should rely on returned metadata.
  • Blocked execution returns 403 with code privileged_intents_not_authorized.
  • For member-name resolution, if server_members is not present (or *), the Discord MCP falls back from member lookup to user lookup.
  • This fallback only affects ID resolution behavior and does not bypass downstream Discord permission checks.

X-Image-Model #

  • Purpose: override the model used by util_generate_image for one request.
  • Format: non-empty string.
  • Examples:
  • X-Image-Model: image-model-a
  • X-Image-Model: image-model-b
  • Rules:
  • When present, this header takes priority over the configured default model for that request.
  • Empty values are rejected with 400.

X-Image-Content #

  • Purpose: choose how util_generate_image returns a validated image.
  • Format: url or raw (case-insensitive).
  • Rules:
  • Omitted or url: upload provider content when necessary and return a URL.
  • raw: skip the uploader and return validated base64 in structuredContent.data, with encoding and content_type metadata.
  • When the image provider returns a URL in raw mode, the Discord MCP first downloads and validates it.
  • Invalid values are rejected with 400.

X-Image-References #

  • Purpose: supply trusted request-context images to util_generate_image for image-to-image generation.
  • Format: a JSON object containing exactly source and urls.
  • Example:
  • X-Image-References: {"source":"message","urls":["https://cdn.example/image.png"]}
  • Rules:
  • source is message or previous.
  • urls contains 1 to 16 unique HTTP(S) image URLs.
  • message references are applied automatically to the image request.
  • previous references are applied only when the tool call sets use_previous_image: true; this prevents an unrelated new generation from inheriting an older image.
  • Credentials embedded in URLs, unsupported fields, invalid JSON, and malformed URLs are rejected with 400.
  • This header is request-only and is never persisted by X-Image-Persist.

X-Image-Provider #

  • Purpose: choose the image-generation provider for the current request.
  • Format: provider name.
  • Example:
  • X-Image-Provider: alibaba
  • Rules:
  • This takes priority over the stored image_provider app setting.
  • If X-Image-Persist: true is also present, the Discord MCP stores the provider name in app settings.
  • If X-Image-Persist: false is also present, the Discord MCP deletes the stored image_provider value, but only because this header was named in the request.

X-Image-Token #

  • Purpose: override the image provider credential for the current request.
  • Format: non-empty string.
  • Rules:
  • The Discord MCP maps this to the selected provider's real auth field.
  • If X-Image-Persist: true is present, the Discord MCP stores that credential in the current app's provider config.
  • If X-Image-Persist: false is present, the Discord MCP deletes the stored provider credential, but only because this header was named in the request.

X-Image-Uploader #

  • Purpose: force the uploader used specifically by util_generate_image.
  • Format: provider name.
  • Rules:
  • This takes priority over image_uploader, X-Upload-Provider, and uploader.
  • If X-Image-Persist: true is present, the Discord MCP stores it as image_uploader.
  • If X-Image-Persist: false is present, the Discord MCP deletes the stored image_uploader, but only because this header was named in the request.

X-Image-Persist #

  • Purpose: decide whether named X-Image-* overrides should stay request-only or also update app configuration.
  • Format: boolean (1|true|0|false, case-insensitive).
  • Rules:
  • Omitted: request-only override.
  • true: persist only the named X-Image-* values.
  • false: delete only the stored values named by the request.
  • Invalid values are rejected with 400.

X-Upload-Provider #

  • Purpose: choose the generic uploader provider for the current request.
  • Format: provider name.
  • Rules:
  • This takes priority over uploader.
  • util_generate_image still lets X-Image-Uploader override it afterward.
  • If X-Upload-Persist: true is present, the Discord MCP stores it as uploader only when that provider is treated as a generic uploader.
  • Image-only upload providers can still be used for the request, but they do not overwrite the stored uploader setting.

X-Upload-Token #

  • Purpose: override the selected upload provider credential for the current request.
  • Format: non-empty string.
  • Rules:
  • The Discord MCP maps this to the selected provider's real auth field.
  • If X-Image-Token and X-Upload-Token end up targeting the same provider, they must match exactly or the request fails.
  • For example, it becomes webhook_url for the Discord provider and api_key for imgfish.
  • For local, the header is ignored.
  • If X-Upload-Persist: true is present, the Discord MCP stores the mapped credential for the selected provider when that provider has one.
  • If X-Upload-Persist: false is present, the Discord MCP deletes the stored credential for the selected provider when that provider has one.

X-Upload-Persist #

  • Purpose: decide whether named X-Upload-* overrides should stay request-only or also update app configuration.
  • Format: boolean (1|true|0|false, case-insensitive).
  • Rules:
  • Omitted: request-only override.
  • true: persist only the named X-Upload-* values.
  • false: delete only the stored values named by the request.
  • Invalid values are rejected with 400.

X-Cache-Max-TTL #

  • Purpose: cap acceptable cache age for Discord MCP reads.
  • Format: integer seconds, >= 0.
  • Examples:
  • X-Cache-Max-TTL: 0
  • X-Cache-Max-TTL: 30
  • X-Cache-Max-TTL: 300
  • Rules:
  • 0 bypasses cache for cache-backed reads.

X-Owner-Access #

  • Purpose: explicit owner-mode gate for sensitive controls.
  • Format: boolean (1|true|0|false, case-insensitive).
  • Examples:
  • X-Owner-Access: 1
  • X-Owner-Access: true
  • X-Owner-Access: false
  • Rules:
  • Required by owner-gated tools (mcp_*, except mcp_get_access_context) and operator-only admin tools.
  • Required for non-GET /users/@me* routes.
  • Invalid values are rejected with 400.

X-Privileged-Call #

  • Purpose: explicit operator confirmation for admin-only operations.
  • Format: boolean (1|true|0|false, case-insensitive).
  • Examples:
  • X-Privileged-Call: 1
  • X-Privileged-Call: true
  • X-Privileged-Call: false
  • Rules:
  • Used only for operator-only admin tools.
  • Admin tool list/execute requires:
    • X-Owner-Access truthy.
    • app flagged as privileged by operator configuration.
    • X-Privileged-Call truthy.

X-Debug-Mode #

  • Purpose: return introspection payloads for JSON-RPC success responses.
  • Format: boolean (1|true|0|false, case-insensitive).
  • Examples:
  • X-Debug-Mode: 1
  • X-Debug-Mode: true
  • Rules:
  • When false, _debug is absent.
  • When true, successful JSON-RPC responses include result._debug.
  • If the original result is not an object, the Discord MCP wraps it as: { "data": <original>, "_debug": { ... } }.
  • Notifications are unchanged (204, no response body).

Source IP Header (default: X-Forwarded-For) #

  • Purpose: source-IP extraction for invalid-auth abuse counters.
  • Header name: configurable by the service operator.
  • Rules:
  • Used only if trusted proxy CIDRs are configured and requester socket IP is in that trusted range.
  • If trusted CIDRs are empty, header is ignored and remote socket IP is used.
  • The Discord MCP parses the CSV chain from right to left, skipping trusted hops and selecting first non-trusted hop as client IP.

X-Target-* Enforcement Semantics #

The Discord MCP enforces target restrictions by route path params (guild_id, channel_id, user_id) and method:

  • If guild_id is present:
  • guild is always checked.
  • if user_id is also present:
    • GET: only guild is checked.
    • non-GET: guild and user are both checked.
  • Else if channel_id is present:
  • channel is checked.
  • Else if user_id is present:
  • user is checked.

Additional resolved-scope guards:

  • delete_invite resolves invite first and enforces guild/channel targets from resolved payload when restrictive target headers are set.
  • get_webhook / edit_webhook / delete_webhook enforce resolved guild/channel targets from webhook payload when restrictive target headers are set.

Name Resolution Behavior (*_name, resolve_id) #

Many tools accept *_name as an alternative to *_id.

  • Precedence: *_id always wins when both are provided.
  • Resolution is case-insensitive and normalized.
  • Supported core entity types: user, guild, channel, role, thread, member.
  • For non-guild/user types, guild_id or guild_name is required.
  • guild_name resolution is checked against X-Target-Guilds.
  • Ambiguous names return explicit candidate lists (*_name_ambiguous).
  • No match returns explicit *_not_found.

Tool Listing Metadata #

tools/list and /v1/tools/list include per-tool metadata:

  • requiredAccess:
  • minimum owner/permission/service requirements.
  • tier:
  • coarse listing tier for clients that want to lazy-load privileged tools.
  • typically one of user, moderator, manager, or app_owner.
  • riskLevel, riskTypes:
  • coarse risk profile for models and integrators.
  • annotations.readOnlyHint:
  • present on read-oriented tools only.