Skip to content

Privacy-bounded guild profiles and reviewed text changes

get_guild_profile returns one separately allowlisted guild's exact name and nullable description as transient untrusted text. Set capabilities.guildProfileAudit: true and list every eligible guild in scopes.guildProfileGuildIds. This allowlist must be a subset of readScope.guildIds when the outer read allowlist exists. The equivalent discord://guilds/{guildId}/profile resource applies the same scope and projection.

Every audit verifies the expected application and bot, exact guild and owner, connector membership, a complete bounded role inventory, and complete effective guild permissions. The audit remains available when the connector lacks change authority and reports authorizedForChange: false; planning requires exact guild ownership or complete MANAGE_GUILD authority. Guild and role names beyond the returned profile name, media hashes, raw payloads, and unknown values are omitted. Icon, banner, invite-splash, and discovery-splash state appear only as presence booleans. No profile text or media identifier is persisted or exported.

Changes have no immediate-call path. Set capabilities.guildProfileChanges: true in addition to audit scope. A strict sparse request must include name, description, or both, plus a bounded Discord audit-log reason and a unique one-shot operation key. Omitted fields and every media field are preserved. description: null deliberately clears the description; an empty string never means clear. Names contain 2 through 100 Unicode scalar values, while non-null descriptions contain 1 through 120. The description bound matches Discord's client contract instead of relying on longer payloads that its API has historically accepted as a bug. Desired text rejects control, formatting, and surrogate code points plus surrounding Unicode whitespace, and is neither trimmed nor otherwise transformed.

Planning returns exact requested and changed field names, complete transient current and desired profile text, presence-only media state, ownership and permission evidence, privacy and verification boundaries, presentation and potential-exposure risks, warnings, the operation-key hash, and a process-keyed digest. The digest binds the normalized sparse intent and audit reason, verified identities, exact owner, connector roles and complete permissions, full profile projection, local limits, risks, warnings, and one-shot key hash. A connector restart invalidates outstanding digests. Any identity, authority, permission, profile, media-presence, request, reason, or key drift invalidates the reviewed plan.

  1. Call get_guild_profile to inspect the transient profile, media-presence state, authority, privacy projection, and verification limits.
  2. Call plan_guild_profile_change with only the intended text fields, the Discord audit-log reason, and a unique one-shot operation key.
  3. Review the verified identities, exact guild, requested and changed fields, complete current and desired profile, media-presence state, permission evidence, risks, warnings, operation-key hash, and keyed digest.
  4. If the plan reports already-current, no confirmation, reservation, activity record, or Discord write is needed.
  5. Call execute_guild_profile_change with identical inputs plus the digest.
  6. Approve the signed MCP confirmation only if every displayed identity, field, text value, risk, warning, audit reason, operation-key hash, and digest remains intended, then inspect the verification result before any follow-up.

Execution rebuilds the plan before approval and again immediately before mutation. It acquires the production facade's durable exact guild-settings collection claim so profile and named-settings PATCHes against the same guild cannot overlap across connector processes. It then atomically reserves the operation-key hash, appends a pending content-free activity record, and sends one non-retried sparse PATCH with the encoded Discord audit-log reason. The response must project to one strict complete guild profile, and a fresh GET plus fresh identity and permission evidence verify the requested values.

Exact response and readback agreement is completed; valid requested-field divergence is completed-with-drift and exposes only field names in the durable record; a known pre-write Discord client refusal is failed; and rate limiting, transport failure, Discord server error, malformed success, failed response validation, failed readback, or failed receipt finalization is uncertain. Every reserved key remains spent, the connector never retries or compensates automatically, and a same-guild uncertain result remains quarantined for operator review.

Activity and operation records contain only the exact guild ID, plan digest, operation-key hash, timestamps, fixed verification and outcome values, activity ID, sanitized error category, and, for activity records, sorted requested field names. Profile text, media identifiers, role names, permission evidence, audit reasons, raw operation keys, raw payloads, and transport causes never enter durable records, diagnostics, or telemetry. See Discord's Get Guild endpoint, Modify Guild endpoint, 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.