Overview

Stop a raid without burning your rate limit

Scenario: a moderator says "ban the 10 spam accounts that joined our server in the last hour, their usernames look like crypto-airdrop-NNNN."

members_bulk_ban is destructive and irreversible without a manual unban. It requires __confirm:true in addition to your environment having MCP_DRY_RUN=false. That blocks unarmed or unconfirmed calls, but it doesn't prove a human approved them, an autonomous caller can set the flag itself. Require approval in your MCP client or UI before re-issuing the destructive call.

Step 1: list members with the fields you need#

This request needs joined_at and roles, so use members_list (paginate with after past 1,000 members) rather than members_search, whose result carries only user_id, username, global_name, and nick, not join time or roles.

{ "name": "members_list", "arguments": { "guild_id": "111122223333444455", "limit": 1000 } }

Step 2: filter as a 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.

Step 3: confirm with the human#

Surface the candidate list to the moderator and don't call members_bulk_ban until they explicitly approve. The server checks __confirm:true, but it can't distinguish a human-approved assertion from one the agent produced itself, the user-experience confirmation step is your responsibility.

Step 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",
    "__confirm": true
  }
}

A partial failure looks like this, Discord returns HTTP 200 with both arrays populated:

{
  "banned_users": ["999988887777666601", "999988887777666603"],
  "failed_users": ["999988887777666602"],
  "banned_count": 2,
  "failed_count": 1
}

Error handling#

  • Missing __confirm:true returns DRY_RUN_PREVIEW immediately without touching Discord. Re-issue with __confirm:true after human approval.
  • MCP_DRY_RUN=true returns a planned-action envelope with no API call, useful in CI to verify the agent's reasoning path without side effects.
  • Partial failure most commonly carries Discord error code 50013 (missing permissions on a user with a higher role), audit both arrays before reporting success.
  • Rate limits still apply to the bulk endpoint. Prefer one batch over hundreds of individual ban calls.

members_bulk_ban, members_search, and members_list full schemas.

Next steps#

Chain search and ban into one sequential call instead of two round-trips: chain three calls with a pipeline. Understand the mechanical guard behind __confirm: how it works. Back to all recipes or the overview.

Updated

Was this page helpful?