Skip to content

Privacy-safe guild expressions and reviewed changes

list_guild_emojis, get_guild_emoji, list_guild_stickers, and get_guild_sticker expose complete bounded inventories or one exact inventory member for a separately allowlisted guild. Set capabilities.guildExpressionAudit: true and list every eligible guild in scopes.guildExpressionGuildIds. This allowlist must be a subset of readScope.guildIds when the outer read allowlist exists. The equivalent discord://guilds/{guildId}/emojis and discord://guilds/{guildId}/stickers resources apply the same scope, projection, and permission evaluation.

Every inventory verifies the application and bot identity, exact guild and owner, connector membership, complete bounded role evidence, and effective guild permissions. Emoji results contain only exact ID, name, animation, availability, managed and colon requirements, creator user ID, and exact role restrictions. Sticker results contain only exact ID, guild ID, name, description, tags, format type, availability, and creator user ID. CDN URLs, image bytes, uploader profiles, and unknown raw fields are dropped before return, and inventory data is never cached or persisted.

Changes have no immediate-call path. Set capabilities.guildExpressionChanges: true in addition to audit scope. Creation also requires storage.guildExpressionRoots to contain one absolute canonical owned directory or a JSON array of such directories. The same unified config entry supplies reviewed local role-icon roots, without another environment variable or storage key. Emoji creation accepts JPEG, PNG, GIF, WebP, or AVIF files up to 256 KiB. Sticker creation accepts 320 by 320 PNG, APNG, GIF, or Lottie JSON files up to 512 KiB, with animated content limited to five seconds. Lottie creation additionally requires fresh guild-feature evidence showing VERIFIED or PARTNERED. The planner inspects actual file structure rather than trusting a filename extension or caller-supplied media type.

The narrow action union supports emoji create with name and optional exact role IDs, emoji update with name or role IDs, sticker create with name, description and tags, sticker update with any changed metadata field, and exact-ID deletion for either kind. A zero-length role list deliberately removes emoji role restrictions, while a null sticker description deliberately clears it. Creation never accepts a URL, data URL, base64 payload, stream, or Discord CDN reference. Update and deletion never accept file input.

  1. Call plan_guild_expression_change with the exact guild, kind, action-specific fields, Discord audit-log reason, and unique one-shot operation key.
  2. Review the verified application and bot IDs, exact guild, current and desired privacy-safe metadata, ownership-aware permission evidence, role references, inventory count, privacy omissions, local file provenance when present, warnings, operation-key hash, and keyed digest.
  3. If an update reports already-current, no confirmation, reservation, activity record, or Discord write is needed.
  4. Call execute_guild_expression_change with identical inputs plus the digest.
  5. Approve the signed MCP confirmation only if every exact identity, metadata field, file property, permission, warning, audit reason, operation-key hash, and digest remains intended.
  6. Review the returned expression ID, privacy-safe observed metadata or verified absence, activity ID, and outcome before any follow-up.

Discord requires CREATE_GUILD_EXPRESSIONS for creation. That permission also lets the bot update or delete an expression whose creator is that exact bot, while an expression owned by another user requires MANAGE_GUILD_EXPRESSIONS; guild ownership supplies both. Managed emojis cannot be mutated. Missing or duplicate role evidence, a role restriction absent from the complete guild inventory, a normalized name collision, local safety capacity, an absent target, incomplete permission evidence, or missing creator evidence when ownership is required blocks planning. Grant MANAGE_GUILD_EXPRESSIONS only when cross-owner administration is intentional.

For creation, planning opens the file without following the final symlink, verifies canonical containment, numeric process ownership, one hard link, regular-file type, exact bounded bytes, and stable metadata before and after the read. Format parsing validates container structure, dimensions where encoded, sticker dimensions, and animation duration. A process-keyed HMAC binds those bytes and stable file properties into the plan. The full plan digest also binds the normalized request, verified identities, exact guild and inventory, relevant role state, effective permission and ownership evidence, current and desired metadata, privacy projection, and warnings. A connector restart invalidates outstanding digests.

The MCP adapter rebuilds the plan before approval, and the service rebuilds it immediately before mutation. Execution atomically reserves the operation-key hash and appends a pending content-free activity record before exactly one non-retried Discord create, update, or delete. Creates and updates use an exact expression GET for readback; deletion requires exact absence from a fresh complete inventory. Matching metadata or absence is completed, valid server-adjusted state is completed-with-drift, a known pre-write Discord 4xx is failed, and transport failure, Discord 5xx, malformed success, or failed post-write verification is uncertain. Image bytes cannot be read back, so verification covers exact identity and stable metadata rather than pretending to compare Discord's stored pixels.

All expression changes in one guild serialize inside one process because create, rename, and delete can affect the same collision and capacity evidence. The production facade additionally acquires a durable exact guild expression-collection claim, so connector processes sharing the activity-state root exclude overlapping changes. An uncertain result retains that claim for operator review before another key can be reserved. Activity and operation records contain only exact guild and expression IDs, action and kind, plan digest, operation-key hash, timestamps, fixed verification and outcome values, activity ID, and sanitized error category. Names, descriptions, tags, role names, local paths, byte digests, image content, uploader profiles, audit reasons, and raw operation keys never enter durable records, diagnostics, or telemetry. See Discord's emoji resource, sticker resource, and permission flags.

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.