Skip to content

Role inventory and reviewed additive role creation

list_roles returns a guild's complete bounded role inventory, while get_role uses Discord's exact guild-role endpoint. Both normalize Discord's solid colors object, hierarchy position, hoist and mention settings, icon and Unicode emoji fields, flags, managed-role provenance, known permission names, raw decimal permission bitfield, unknown future permission bits, and a count of unknown top-level fields. Inventory validation requires exactly one valid @everyone role and rejects duplicate IDs, malformed evidence, and a response above Discord's documented guild-role limit.

Role creation has no immediate-call path. Set capabilities.roleCreation: true and list every eligible guild in scopes.roleCreationGuildIds. The role-creation guild allowlist must be a subset of readScope.guildIds when the read allowlist is present. Grant the bot Manage Roles, keep its highest role above the default new-role position, and grant the bot only permissions this workflow may place on new roles. Do not grant the bot Administrator; the planner warns if it detects that permission.

The narrow surface accepts an exact role name, a unique list of official permission names, one solid RGB primary color, hoist and mentionable booleans, a Discord audit-log reason, and a unique one-shot operation key. Permission arrays are canonicalized into arbitrary-width decimal bitfields. ADMINISTRATOR is always rejected, every requested permission must be a subset of the connector bot's effective guild permissions, and a defined high-risk set receives an explicit plan warning. The workflow never edits, moves, assigns, deletes, rolls back, adds icons or emoji, or creates gradient roles.

  1. Call plan_role_creation with the exact guild, name, named permissions, optional properties, audit reason, and one-shot operation key.
  2. Review the exact guild and owner IDs, untrusted names, named permissions and bitfield, high-risk permissions, color and display settings, complete role count, bot effective permissions and hierarchy, warnings, hashed operation key, action, and keyed digest.
  3. If the action is none, one exact standard role already has the requested state and no confirmation or write is needed.
  4. Call execute_role_creation with identical inputs plus the digest.
  5. Approve the signed MCP confirmation only if every exact ID, permission, property, warning, reason, operation-key hash, and digest remains intended.
  6. Review the returned role ID, exact readback state, activity ID, and outcome before any assignment or follow-up.

Planning fetches the exact guild, connector bot member, and complete role inventory together. It requires complete effective-permission evidence, guild-level MANAGE_ROLES, a connector role above @everyone, available capacity, and an unambiguous logical name. Logical matching normalizes Unicode compatibility forms, letter case, spaces, underscores, and hyphens. A managed role or a standard role with different properties at the logical name is a blocking conflict rather than an implicit edit.

The process-keyed digest covers the normalized request without the raw operation key, the operation-key hash, bot identity and role IDs, effective permissions and highest-role evidence, guild identity and features, every normalized role snapshot, logical-name candidates, action, and role limit. A connector restart invalidates the digest. The MCP adapter rebuilds the plan before approval, and the service rebuilds it immediately before mutation. Both require the exact same digest.

Discord's create-role endpoint has no idempotency token, so execute_role_creation is accurately annotated as non-idempotent even though the connector surrounds it with replay defenses. Before the single POST, the connector atomically reserves the operation-key hash in a durable private receipt and appends a pending content-free activity record. The raw key, role name, named permissions, audit reason, and other Discord content are absent from both records. A reserved key is permanently spent after a known failure or uncertain result. Do not retry it; inspect get_role, list_roles, and the Discord audit log before considering a new reviewed request with a new key.

Inside one connector process, executions for the same guild and normalized logical role name serialize across operation keys. A queued execution rebuilds its plan after the preceding write and is blocked without reserving its key if that write ends uncertain. The production facade additionally acquires a durable exact guild roles-collection claim, so connector processes sharing the activity-state root exclude overlapping role creation and retain the claim after uncertainty. This does not imply logical-name uniqueness; Discord permits duplicate role names.

After the POST, the connector validates the returned role identity and performs an exact role GET. A matching readback returns completed; a safe identity with server-adjusted properties returns completed-with-drift and the observed role. Known Discord 4xx rejections before a role ID is known are failed; transport failures, Discord 5xx responses, or failed exact verification are uncertain. The connector never automatically retries the POST and never deletes a newly created role as compensation. See Discord's role resource reference and create guild role reference.

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.