Exact member voice-state audit and reviewed changes
Member voice access is independent of the member directory, Stage lifecycle, and general moderation surfaces. Set capabilities.memberVoiceAudit: true, configure non-empty exact scopes.memberVoiceGuildIds and scopes.memberVoiceChannelIds, and keep each allowlist inside the corresponding read allowlist when one exists. get_member_voice_state accepts one exact guild and user ID, verifies the pinned connector identity, exact membership, current voice-state identity, source channel type and ownership, complete roles and overwrites, and effective connector VIEW_CHANNEL plus CONNECT, and never enumerates channel occupants. A disconnected target is reported explicitly without guessing a prior channel.
The audit returns the target ID and bounded username, exact scoped source channel when connected, server mute and deafen booleans, a discarded unknown-field count, complete read-permission evidence, and an explicit privacy projection. Session IDs, embedded member objects, self mute and deafen state, stream and camera state, Stage suppression and request-to-speak state, unknown-field values, and every other raw field are discarded before the result is built. The exact discord://guilds/{guildId}/members/{userId}/voice-state resource applies the same gate and projection. No voice-state read is cached, persisted, journaled, or exported.
Set capabilities.memberVoiceChanges: true only after audit scope is working. Changes accept one exact action: move requires one exact destination channel ID, disconnect has no action-specific field, and set-server-mute or set-server-deafen requires one boolean enabled value. Only ordinary voice channels can be mutated. Stage channels may be audited but every Stage participant change is rejected, keeping Stage lifecycle and participant moderation as separate security boundaries.
- Call
plan_member_voice_changewith the exact guild and user IDs, strict action-specific fields, a Discord audit-log reason, and a unique one-shot operation key. - Review the verified identities, exact target and minimized current state, source and optional destination, required permissions, destination access for both connector and target, strict role hierarchy, privacy projection, risks, warnings, operation-key hash, and keyed digest.
- Call
execute_member_voice_changewith identical intent plus the digest. - Approve the signed MCP confirmation only if every identity, state transition, destination or enabled value, permission, hierarchy, reason, hash, and digest remains intended.
- Review the exact readback, activity ID, verification state, and outcome before any related operation.
Every real change rejects the connector bot, guild owner, pending members, administrators, configured protected users, and targets not strictly below the connector's unique highest role. Disconnect requires complete connector VIEW_CHANNEL, CONNECT, and MOVE_MEMBERS on the source. Move requires those permissions on both source and destination plus target VIEW_CHANNEL and CONNECT on the destination. Server mute and deafen changes require connector VIEW_CHANNEL and CONNECT plus MUTE_MEMBERS or DEAFEN_MEMBERS on the source. Unknown permission bits, incomplete roles or overwrites, unsupported channel types, mismatched identities, or ambiguous hierarchy fail closed.
The process-keyed digest binds exact application and bot identities, guild ownership, bot and target memberships, complete role evidence, source and destination channel snapshots and overwrites, current state, action-specific permissions, target destination access, strict hierarchy, privacy projection, audit reason, and the domain-separated operation-key hash. Any relevant drift invalidates approval. An already disconnected disconnect, same-channel move, or already matching mute or deafen request returns a record-free no-op without confirmation, reservation, or mutation.
A real execution atomically reserves the one-shot key, appends pending content-free activity, issues one non-retried PATCH containing only channel_id, mute, or deaf, strictly validates the response identity and every response-carried voice field, and performs an exact fresh voice-state readback to prove the requested result. A controlled result with unrelated state drift is reported as completed-with-drift. A known Discord 4xx refusal other than a rate limit may settle as failed; rate limits, transport or server failures, malformed success, mismatched response, readback failure, or any other indeterminate post-reservation state are uncertain and potentially completed. Every reserved key remains spent. The production facade acquires a durable exact member claim, so connector processes sharing the activity-state root exclude overlapping voice changes and uncertainty retains the claim for operator review without persisting voice-channel IDs. The workflow never retries, rolls back, compensates, or performs fuzzy lookup.
Durable member-voice records contain only the action, exact guild and user IDs, plan digest, domain-separated operation-key hash, timestamps, fixed status and verification values, activity ID, and sanitized error category. They never contain source or destination channel IDs, state booleans, member or channel names, permission or hierarchy evidence, audit reasons, raw operation keys, response bodies, or transport causes. Inspect the exact member voice state and Discord audit log before forming a new intent after uncertainty.
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.