Skip to content

Native exact message-attachment reads

read_message_attachment belongs to the existing messages toolset, while the equivalent discord://channels/{channelId}/messages/{messageId}/attachments/{attachmentId} template follows the connector's ordinary resource contract. Both consume one current guild-channel or thread attachment through the same exact read policy. They add no capability toggle, write authority, storage root, local output path, environment variable, Gateway connection, activity record, or operation receipt. Every call re-verifies the configured application and bot, reads the exact channel, applies its direct local guild and channel boundary, and fetches the exact message. Enable the Message Content privileged intent when guild attachment metadata is required; Discord otherwise withholds attachment fields outside its documented exceptions. The bot still needs effective View Channel and Read Message History access at the selected target.

The caller supplies only positive exact channel, message, and attachment snowflakes. The connector accepts no URL, filename, MIME type, path, base64, byte body, proxy choice, or alternate origin. Current message evidence must match the exact guild, channel, and message, contain a bounded unique attachment inventory, and contain the requested attachment exactly once. The selected attachment must have strict bounded metadata and a Discord-supplied signed URL on the fixed https://cdn.discordapp.com origin. Its path kind, channel ID, attachment ID, percent-decoded filename, exact ex, is, and hm query set, timestamp ordering, and signature shape must all match. Ordinary message projections discard both delivery URLs, so a model cannot feed an expiring capability back into the tool.

Delivery is one unauthenticated GET with credentials omitted, no referrer, no cache reuse, manual redirect handling, and no automatic retry. The bot token and every Discord REST authorization header stay out of the CDN request. A success must be a direct status-200 body with identity content encoding, a valid media type, an exact match to the message-declared media type when present, and an optional decimal content length equal to the message-declared size. Streaming stops if it crosses either that declared size or the conservative raw-byte ceiling derived from limits.mcpReadResponseMaxBytes; completion requires the exact declared byte count. The ceiling reserves the MCP envelope and base64 expansion before any fetch, while the ordinary whole-result budget still protects the final encoded response.

PNG, JPEG, GIF, and WebP images and MPEG, Ogg, WAV, MP4, and WebM audio receive native MCP content only after both media evidence and a conservative container signature match. A declared supported native type with mismatched bytes fails closed. An absent or unsupported declared type is delivered as application/octet-stream embedded resource content rather than being promoted from an extension or response header; this includes active image types such as SVG. The tool result contains a short text summary, an equivalent private resource_link, the native image or audio block or embedded binary resource, and strict URL-free structured metadata. The resource template returns the same verified bytes as one blob using its selected delivered media type.

Before base64 encoding, the MCP boundary scans the raw bytes for every active secret value known to its recursive result-redaction boundary. A match withholds the attachment. Whether encoding succeeds or fails, the connector overwrites its transient raw buffer; streamed chunks are also overwritten after assembly and signature-failure buffers are cleared. No byte, signed URL, proxy URL, local path, response body, attachment content, filename, description, or raw object enters connector storage, activity, receipts, diagnostics, logs, or telemetry. The host, model provider, operating system, and transcript still receive or handle the encoded result according to their own data policies, and attachment bytes and metadata remain untrusted external data rather than instructions.

DISCORD_ATTACHMENT_TOO_LARGE is a fixed non-retriable client error with guidance to raise the non-secret MCP response limit within its supported range or select a smaller attachment. DISCORD_ATTACHMENT_EVIDENCE_INVALID reports a fixed non-retriable current-evidence failure. DISCORD_ATTACHMENT_DELIVERY_FAILED is a fixed retriable read failure, but the connector never retries by itself; a new call refetches the current message and a fresh Discord-signed URL. DISCORD_ATTACHMENT_WITHHELD is a non-retriable safety result when raw bytes contain an active connector secret; do not request the same attachment again, inspect it outside the connector, and rotate an exposed credential. Resource reads map an oversized result to bounded InvalidParams and other failures to a secret-redacted protocol error without returning the URI-specific evidence, URL, response, or transport cause.

MCP defines image, audio, embedded blob, and resource-link content, but each host and model decides which media types it can render or pass through. A standards-compliant result can therefore be unavailable to a particular model even when the connector verified it. Prefer the native tool result when the host supports rich tool content, use the exact private resource URI when it supports binary resources, and treat a host with neither capability as incompatible with attachment consumption. See the official MCP content schema, Discord's attachment object, and Discord's signed attachment CDN URL contract.

Canonical source: docs/reference.md

Documentation generated for guildcontrol@0.0.0. Canonical source and edit history remain in the public repository. GuildControl is an independent project and is not affiliated with or endorsed by Discord Inc. Discord is used only to identify the platform that GuildControl connects to.