Skip to content

Privacy-safe scheduled events, subscriber audit, and reviewed changes

list_scheduled_events and get_scheduled_event expose one complete bounded inventory or one exact event for a separately allowlisted guild. Set capabilities.scheduledEventAudit: true and list every eligible guild in scopes.scheduledEventGuildIds. This allowlist must be a subset of readScope.guildIds when the outer read allowlist exists. The equivalent discord://guilds/{guildId}/scheduled-events resource returns the same inventory without subscriber counts.

Every ordinary event read verifies the application and bot identity, exact guild and owner, connector membership, complete bounded roles, visibility-bounded channels, event and exact referenced-channel identities, channel type, and effective entity-specific permission evidence. An event whose channel Discord omits fails closed. Results contain exact event, guild, channel, creator, and entity IDs; name; description; location; hosting type; privacy level; status; timing; recurrence; cover presence; and an optional aggregate subscriber count. Subscriber identities, creator profiles, cover URLs and hashes, embedded objects, and unknown raw fields are dropped before return. Event strings remain untrusted Discord data, and no event result is cached or persisted.

list_scheduled_event_users is independently disabled because identities are more sensitive than aggregate counts. Set capabilities.scheduledEventUserAudit: true in addition to event audit. The tool inherits the same exact guild allowlist, accepts one exact event ID, exposes only forward after pagination, defaults to 25 users, and caps a page at Discord's documented maximum of 100. It resolves the exact event and complete entity-specific permission evidence before fetching identities, sends with_member=false explicitly, requires strictly ascending unique user IDs, and returns only each ID and bot flag. Usernames, display names, avatars, nicknames, roles, join dates, member objects, profile fields, and raw payloads are discarded inside the REST client and never returned or persisted. The tool does not require the Guild Members privileged intent.

Changes have no immediate-call path. Set capabilities.scheduledEventChanges: true in addition to audit scope. The strict action union supports creation, metadata update, status transition, and exact-ID deletion. Create accepts stage, voice, or external hosting, requires a future start, requires an end for external hosting, and can include a supported recurrence rule. Update accepts only the fields being changed; moving an event binds both its current authority and complete destination creation permissions. Active events permit only name, description, or cover changes, while completed and canceled events reject metadata updates. Changing the start of a recurring event requires an explicit recurrence replacement or removal so server-controlled recurrence fields are never guessed.

Supported recurrence is deliberately narrower than the raw Discord object: daily events use Discord's documented weekday sets, weekly events use one weekday with the documented interval choices, monthly events use one numbered weekday, and yearly events use one valid calendar date. Recurrence count, end, and year-day fields are readable but cannot be supplied because Discord controls them. Valid status transitions are scheduled to active, scheduled to canceled, and active to completed. An already-current update or transition returns without confirmation, reservation, activity, or write.

Discord requires CREATE_EVENTS to create an external event. Voice creation additionally requires channel-level VIEW_CHANNEL and CONNECT; stage creation requires the documented channel-management and voice-moderation permissions. Updating, transitioning, or deleting an event requires MANAGE_EVENTS, or exact bot ownership together with CREATE_EVENTS, plus the entity-specific channel permissions. A hosting move additionally proves the complete creation permissions at the destination. Missing creator evidence cannot satisfy ownership, malformed or incomplete permission evidence fails closed, and ADMINISTRATOR is surfaced as a least-privilege warning.

Cover creation, replacement, or removal is part of the same reviewed workflow. Configure storage.scheduledEventRoots only when local covers are needed. The planner accepts one exact absolute local JPEG or non-animated PNG path, never a URL, data URL, or base64 payload. It opens without following the final symlink, proves canonical containment, numeric process ownership, one hard link, regular-file type, stable bounded bytes, actual format, non-animation, and dimensions, then binds the file identity and bytes into the process-keyed plan. Removing a cover uses an explicit null; omitting the field preserves it.

  1. Call plan_scheduled_event_change with the exact guild, action-specific event fields, Discord audit-log reason, and unique one-shot operation key.
  2. Review the verified application and bot IDs, exact guild and event, current and desired privacy-safe state, hosting, timing, recurrence, permission and ownership evidence, visible capacity, local cover provenance when present, privacy omissions, warnings, operation-key hash, and keyed digest.
  3. If the plan reports already-current, no confirmation, reservation, activity record, or Discord write is needed.
  4. Call execute_scheduled_event_change with identical inputs plus the digest.
  5. Approve the signed MCP confirmation only if every exact identity, state, hosting target, recurrence, file property, permission, warning, audit reason, operation-key hash, and digest remains intended.
  6. Review the returned exact event state or verified absence, activity ID, and outcome before any follow-up.

The plan digest binds the normalized request, verified identities, exact guild and owner, connector member and relevant roles, complete permission evidence, current and desired event state, visible inventory and capacity for creation, local cover snapshot when present, privacy projection, operation-key hash, and warnings. A connector restart invalidates the digest. The MCP adapter rebuilds the plan before approval, and the service rebuilds it immediately before mutation. Any event, channel, role, ownership, permission, recurrence, timing, cover, or visible-capacity drift invalidates the reviewed plan.

Execution atomically reserves the operation-key hash and appends a pending content-free activity record before one non-retried POST, PATCH, or DELETE. It then performs an exact GET for created, updated, or transitioned events, or requires an exact 404 after deletion. Matching controlled state or verified absence is completed; valid server-adjusted state or an event that remains after deletion is completed-with-drift; a known pre-write Discord client error is failed; transport failure, Discord server error, malformed success, or failed post-write verification is uncertain. Cover readback verifies exact identity and cover presence because Discord does not expose stored image bytes.

All scheduled-event changes in one guild serialize inside one process because creation capacity, role evidence, and event state are shared. The production facade additionally acquires a durable exact guild scheduled-events 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 event IDs, entity type, action and transition target, plan digest, operation-key hash, timestamps, fixed verification and outcome values, activity ID, and sanitized error category. Names, descriptions, locations, recurrence, subscriber counts, roles, local paths, byte digests, image content, audit reasons, and raw operation keys never enter durable records, diagnostics, or telemetry. See Discord's guild scheduled event reference 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.