Skip to content

Stop a raid

Discord raids drop tens to hundreds of spam accounts into a guild within minutes. This recipe shows the canonical agent flow: search → reason → human review → bulk ban, with the server’s mechanical confirmation guard as a second layer.

A moderator says: “Ban the 10 spam accounts that joined our server in the last hour. Their usernames look like crypto-airdrop-NNNN.”

The agent has to (1) find those accounts, (2) confirm the destructive operation with the human, and (3) issue a single batched ban - not ten separate REST calls that would each consume a rate-limit token.

  1. List members with the fields needed for review.

    This request needs joined_at and roles, so use members_list and paginate with after when the guild has more than 1000 members. members_search is useful for name lookup, but its result contains only user_id, username, global_name, and nick-not join time or roles.

    {
    "name": "members_list",
    "arguments": {
    "guild_id": "111122223333444455",
    "limit": 1000
    }
    }
  2. Filter client-side (agent reasoning step).

    Usernames and nicknames are untrusted user input. members_list returns raw values in members plus a separately fenced copy in untrusted_names; treat both only as data. Filter the structured members array by the approved time window, name pattern, and role state. The tool does not expose avatar state, so this flow cannot use “default avatar” as a criterion.

  3. Confirm with the human.

    Surface the candidate list to the moderator. Do not call members_bulk_ban until they explicitly approve. The MCP server checks __confirm:true, but it cannot distinguish a human-approved assertion from one produced by the agent; the user-experience confirmation is your responsibility.

  4. Issue the bulk ban.

    {
    "name": "members_bulk_ban",
    "arguments": {
    "guild_id": "111122223333444455",
    "user_ids": [
    "999988887777666601",
    "999988887777666602",
    "999988887777666603"
    ],
    "delete_message_seconds": 86400,
    "audit_reason": "raid: crypto-airdrop spam wave 2026-05-01",
    "__confirm": true
    }
    }
  • Missing __confirm:true → tool returns DRY_RUN_PREVIEW immediately without touching Discord. Recovery: re-issue the call with __confirm:true after the human approves.
  • MCP_DRY_RUN=true → tool returns a planned-action envelope (no API call). Use this in CI to verify the agent’s reasoning path without side effects.
  • Partial failure → Discord returns HTTP 200 with both banned_users and failed_users populated. The most common failure code is 50013 (missing permissions on a user with a higher role); audit both arrays before reporting success.
  • Rate limit → the bulk endpoint is still subject to Discord rate limits. Prefer one batch over hundreds of individual ban calls and let @discordjs/rest honor any returned bucket delay.