Principle
The bot holds wide permissions so it can serve everyone. It must never become a way around Discord's own rules. Every action is therefore evaluated as if you clicked it in the Discord client, and refused if you couldn't.
A request, step by step
- Token. The bearer token is looked up on every request. Revoked or expired tokens are rejected before anything else runs.
- Server. MCP must be activated on that server, the bot must still be a member, and you must still be a member.
- Owner policy. The server's access policy (owner & admins, allow list, everyone, disabled) must include you, and you must not be on the owner's block list.
- Allowed actions. The kind of request (read, create, assign, edit, delete) must be allowed by the owner, and the server's action limit per minute must not be used up.
- Ownership of IDs. Every channel, role, thread, message, webhook and invite in the request must belong to that server. IDs from other servers are treated as not found.
- Your permissions. Computed from @everyone, your roles, channel overwrites (threads use their parent), timeouts and implicit rules — the same algorithm Discord uses.
- Hierarchy. Moderating members, assigning or editing roles and changing role overwrites require the target to be below your highest role.
- Second opinion. Bans, kicks, timeouts, deleting channels and roles, bulk deletes, role permission edits, overwrite changes, webhooks and server settings are re-checked against Discord's member-permission endpoints right before execution.
- Last check. Immediately before the call to Discord the token is validated again, so a revocation during the request still stops it.
- Audit. The action carries a Discord audit-log reason with your username and ID, and every call — reads included — is recorded in our own log for 90 days, visible to the owner in the dashboard.
Permission rules worth knowing
- You can only grant or deny permissions you have yourself — in roles and in channel overwrites — unless you are an administrator.
- By default nobody is pinged: messages go out with
allowed_mentions.parse = []. Owners can allow selected roles and members, or fall back to each member's own mention permissions. - Every message the bot writes carries a disabled Actioned by button and is logged;
/explainshows who asked for it and when. - The bot never opens direct messages — enforced in the Discord client itself, not just in the tools.
- Only the server owner can change settings, in Discord or in the dashboard. The dashboard checks ownership against what Discord reports to the bot and protects every form with a CSRF token.
- Channel slowmode applies to you even though the bot itself is exempt.
- Messages can only be edited if they were sent through MCP on your behalf; Discord lets nobody edit other people's messages.
- Forum post creators may rename, tag and close their own posts; moderated tags need Manage Threads.
- Message search results are filtered to channels you can read.
Tokens & revocation
- OAuth 2.1 with mandatory PKCE (S256). Redirect URIs must match the registered client exactly.
- A consent screen names the client and where it returns to before any code is issued.
- Access tokens are opaque, valid for one hour and stored only as SHA-256 hashes.
- Refresh tokens rotate on every use. Re-using an old refresh token revokes the whole chain.
- Your Discord OAuth token (used only to list your servers) is stored encrypted with AES-256-GCM.
- Removing the app in Discord sends us a signed webhook; all tokens are deleted on receipt.
Infrastructure
- Written in Rust. The HTTP service is stateless and scales horizontally; the gateway is sharded.
- Webhooks and interactions from Discord are verified with Ed25519 and rejected when older than five minutes.
- Strict security headers: CSP without inline scripts, no framing, no referrer, HSTS.
- Per-user rate limits on tool calls and per-IP limits on the OAuth endpoints.
- Cached server data (roles, channels) expires after 14 days without activity.
Reporting issues
Found a way to make the bot do something you shouldn't be able to? Please report it privately via a GitHub security advisory instead of opening a public issue.