better-discord-mcp
Allows reading and controlling Discord through a BetterDiscord plugin, including reading channels, sending messages, searching, and moderation actions like ban, kick, timeout, and delete.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@better-discord-mcp show me recent messages in #general"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
better-discord-mcp
An MCP server that lets an AI client (Claude Desktop / Claude Code) read and control Discord through a BetterDiscord plugin. It drives your logged-in Discord client, so it can read any channel you can see, send messages, and perform moderation (ban / kick / timeout / delete) wherever your account has permission.
Claude ──stdio──▶ MCP server ──WebSocket(127.0.0.1:6473)──▶ BD plugin ──▶ Discord⚠️ Important: Terms of Service
This automates a user account, not a bot account. Automating a user account ("selfbotting") violates Discord's Terms of Service and can result in account termination, regardless of intent. Use only on your own or explicitly authorized servers, ideally with a test account. You accept the risk.
For ToS-compliant moderation, build a real Discord bot instead — but that cannot "see your client" the way this does.
Related MCP server: Discord MCP Server
Setup
1. Install the BetterDiscord plugin
Copy
plugin/DiscordMCP.plugin.jsinto your BetterDiscord plugins folder:Windows:
%AppData%\BetterDiscord\plugins\
Open Discord → Settings → Plugins → enable DiscordMCP.
It will keep trying to connect to the bridge every 3s (toast shows status).
2. Install server deps
npm install3. Register the MCP server with your client
Claude Code:
claude mcp add discord -- node "/absolute/path/to/better-discord-mcp/server/index.js"Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"discord": {
"command": "node",
"args": ["/absolute/path/to/better-discord-mcp/server/index.js"]
}
}
}The server hosts the WebSocket bridge; the plugin connects to it. Start order
doesn't matter — the plugin auto-reconnects. Use the discord_status tool to
confirm the link is up.
Tools
Read / info
Tool | Purpose |
| Is the plugin connected? |
| Current guild / channel / user |
| List your servers |
| Channels in a guild |
| Recent messages in a channel |
| Search a guild or channel |
| User / guild-member info |
| List a guild's roles |
| List open DM channels |
Messaging
Tool | Purpose |
| Send a message |
| Edit your own message |
| React to a message |
| Show typing indicator |
| Open/fetch a DM with a user |
Moderation (🔒 gated — need confirm:true)
Tool | Purpose |
| Delete a message |
| Bulk-delete recent messages (<14 days) |
| Ban (needs Ban Members) |
| Kick (needs Kick Members) |
| Timeout / un-timeout a member |
| Add a role (Manage Roles) |
| Remove a role (Manage Roles) |
🔒 = destructive: the first call returns a confirmation preview and does
nothing; re-call with confirm:true to execute. Disable with
DISCORD_MCP_REQUIRE_CONFIRM=false.
Full surface (~100 tools)
This exposes essentially all of Discord's REST-driven features. Beyond the
common tools above, there are named tools for: audit log, bans (list/get/unban),
threads (create/edit/join/leave/members/archived lists), forum posts, channel
permission overwrites, channel/role reordering, polls, replies & embeds,
crossposting, scheduled events, AutoMod rules, stickers, integrations,
webhooks (create/edit/execute), invites (resolve/join), friends/block/notes,
status, prune, voice mute/deafen & status, welcome screen, vanity url, and more.
See COVERAGE.md for the complete map and what is not reachable.
discord_request — raw escape hatch
For anything without a named tool (templates, onboarding, slash-command registration, brand-new endpoints), call any REST endpoint directly:
discord_request(method="post", path="/guilds/123/templates", body={ "name": "..." })Non-GET raw calls are also gated by the confirmation rule.
What is NOT possible via this bridge
Voice audio (joining/streaming/listening), live event streaming, and the
full online-member list are gateway/WebRTC, not REST — this bridge can't
drive them. It can move/mute/deafen members and set voice channel status.
Use polling (get_messages) instead of live message events.
Config
DISCORD_MCP_PORT(default6473) — must matchthis.portin the plugin.DISCORD_MCP_TIMEOUT(default15000ms) — per-request timeout.DISCORD_MCP_REQUIRE_CONFIRM(defaulttrue) — gate destructive tools.
How API calls are authenticated
Current Discord builds obfuscate the internal REST client (getAPIBaseURL) and
the token module (getToken), so the plugin doesn't rely on them. Instead it
sniffs your Authorization header from Discord's own outgoing requests
(hooking XMLHttpRequest/fetch) and then calls https://discord.com/api/v9
directly with fetch. This is version-proof — it survives Discord updates.
One consequence: the token is only captured after Discord makes an authenticated request. Most live traffic goes over the gateway WebSocket, so right after enabling the plugin you may need to switch channels once to trigger a REST call. After that the token is cached for the session.
Troubleshooting
not connected: Discord must be running with the plugin enabled. Check the plugin toast / Discord devtools console (Ctrl+Shift+I) for errors.Auth token not captured yet: click into a different channel once (forces a REST request the plugin can read the token from), then retry.Discord API 401/403: your account lacks permission for that action, or the captured token is stale — toggle the plugin off/on and switch channels.Diagnostics:
discord_request(path="__debug__")dumps module/token state for debugging without touching devtools.
Available Tools
128 toolsdiscord_accept_inviteB
Join a server via invite code.
Inputs: code (required), confirm.
discord_add_friendB
Send a friend request (by userId, or username+discriminator).
Inputs: userId, username, discriminator.
discord_add_reactionB
Add a reaction. Use a unicode emoji (e.g. 👍) or custom as name:id.
Inputs: emoji (required), channelId (required), messageId (required).
discord_add_roleB
Add a role to a member (requires Manage Roles).
Inputs: roleId (required), userId (required), guildId (required), reason.
discord_ban_userA
Ban a user from a guild (requires your account to have Ban Members).
Inputs: userId (required), guildId (required), reason, confirm, +1 more.
discord_block_userC
Block a user.
Inputs: userId (required).
discord_bulk_banB
Ban many users at once (up to 200). Requires Ban Members + Manage Guild.
Inputs: guildId (required), userIds (required), reason, confirm, +1 more.
discord_create_automod_ruleC
Create an AutoMod rule. rule = raw Discord AutoMod rule object.
Inputs: rule (required), guildId (required).
discord_create_channelB
Create a channel or category in a guild. type: 0=text, 2=voice, 4=category, 5=announcement, 13=stage, 15=forum. Put a channel under a category with parentId.
Inputs: name (required), guildId (required), nsfw, type, +7 more.
discord_create_emojiB
Create a custom emoji. imageDataUri must be a data URI (data:image/png;base64,...).
Inputs: name (required), guildId (required), imageDataUri (required).
discord_create_forum_postC
Create a forum post (thread + starter message).
Inputs: name (required), content (required), channelId (required), tagIds, +1 more.
discord_create_group_dmB
Create a group DM with the given user IDs.
Inputs: userIds (required).
discord_create_guildA
Create a new server (you become owner). icon is a data URI or URL.
Inputs: name (required), icon.
discord_create_inviteB
Create an invite link for a channel.
Inputs: channelId (required), unique, maxUses, temporary, +1 more.
discord_create_pollC
Create a poll message.
Inputs: answers (required), question (required), channelId (required), multiselect, +1 more.
discord_create_roleC
Create a role. permissions is a permission bitfield as a string.
Inputs: name (required), guildId (required), color, hoist, +3 more.
discord_create_scheduled_eventC
Create a scheduled event. entityType: 1=stage,2=voice,3=external. Times are ISO8601.
Inputs: name (required), guildId (required), startTime (required), entityType (required), +4 more.
discord_create_threadC
Create a thread. Pass messageId to thread off a message, otherwise a standalone thread in the channel.
Inputs: name (required), channelId (required), type, messageId, +2 more.
discord_create_webhookC
Create a webhook on a channel.
Inputs: name (required), channelId (required).
discord_crosspost_messageC
Publish (crosspost) a message from an announcement channel.
Inputs: channelId (required), messageId (required).
discord_delete_automod_ruleC
Delete an AutoMod rule.
Inputs: ruleId (required), guildId (required), confirm.
discord_delete_channelA
Delete a channel or category (deleting a category does NOT delete its channels).
Inputs: channelId (required), reason, confirm.
discord_delete_channel_permissionC
Remove a permission overwrite.
Inputs: channelId (required), overwriteId (required).
discord_delete_emojiC
Delete a custom emoji.
Inputs: emojiId (required), guildId (required), confirm.
discord_delete_guildB
Delete a server you own. Irreversible.
Inputs: guildId (required), confirm.
discord_delete_integrationC
Delete a guild integration.
Inputs: guildId (required), integrationId (required), confirm.
discord_delete_inviteC
Revoke an invite by code.
Inputs: code (required), confirm.
discord_delete_messageB
Delete a message in a channel.
Inputs: channelId (required), messageId (required), confirm.
discord_delete_roleC
Delete a role from a guild.
Inputs: roleId (required), guildId (required), reason, confirm.
discord_delete_scheduled_eventC
Delete a scheduled event.
Inputs: eventId (required), guildId (required), confirm.
discord_delete_stickerC
Delete a guild sticker.
Inputs: guildId (required), stickerId (required), confirm.
discord_delete_webhookA
Delete a webhook.
Inputs: webhookId (required), confirm.
discord_edit_automod_ruleC
Edit an AutoMod rule. fields = raw Discord AutoMod fields.
Inputs: fields (required), ruleId (required), guildId (required).
discord_edit_channelC
Edit a channel/category (name, topic, parent/category, position, slowmode, nsfw, voice bitrate/limit).
Inputs: channelId (required), name, nsfw, topic, +6 more.
discord_edit_emojiB
Rename a custom emoji (or restrict to roleIds).
Inputs: emojiId (required), guildId (required), name, roleIds.
discord_edit_guildC
Edit guild name/description/icon (iconDataUri is a data URI).
Inputs: guildId (required), name, reason, description, +1 more.
discord_edit_messageA
Edit one of your own messages.
Inputs: content (required), channelId (required), messageId (required).
discord_edit_profileB
Edit your own account: username, avatar, banner (data URI or URL), bio.
Inputs: bio, avatar, banner, username.
discord_edit_roleB
Edit a role's name/permissions/color/hoist/mentionable.
Inputs: roleId (required), guildId (required), name, color, +4 more.
discord_edit_scheduled_eventC
Edit a scheduled event. fields = raw Discord event fields.
Inputs: fields (required), eventId (required), guildId (required).
discord_edit_stageC
Edit the current Stage topic.
Inputs: topic (required), channelId (required).
discord_edit_stickerB
Edit a guild sticker's name/description/tags.
Inputs: guildId (required), stickerId (required), name, tags, +1 more.
discord_edit_threadC
Archive/unarchive, lock/unlock, or rename a thread.
Inputs: threadId (required), name, locked, archived, +1 more.
discord_edit_webhookB
Edit a webhook's name/channel.
Inputs: webhookId (required), name, channelId.
discord_edit_welcome_screenC
Edit the welcome screen. fields = raw Discord welcome-screen fields.
Inputs: fields (required), guildId (required).
discord_edit_widget_settingsB
Enable/disable the guild widget and set its invite channel.
Inputs: guildId (required), enabled, channelId.
discord_end_pollC
End a poll early.
Inputs: channelId (required), messageId (required).
discord_end_stageC
End the current Stage.
Inputs: channelId (required), confirm.
discord_execute_webhookC
Post a message via a webhook (needs webhook token).
Inputs: token (required), webhookId (required), embeds, content, +2 more.
discord_follow_announcementC
Follow an announcement channel into a target channel.
Inputs: channelId (required), targetChannelId (required).
discord_get_audit_logC
Read the guild audit log.
Inputs: guildId (required), limit, userId, actionType.
discord_get_banC
Get a single ban entry.
Inputs: userId (required), guildId (required).
discord_get_channelB
Get a single channel's details.
Inputs: channelId (required).
discord_get_channel_invitesC
List invites for a channel.
Inputs: channelId (required).
discord_get_channelsA
List channels in a guild.
Inputs: guildId (required).
discord_get_connectionsA
List your linked accounts (Steam, Spotify, etc.).
Inputs: no named parameters.
discord_get_contextA
Get the currently selected guild, channel, and the logged-in user.
Inputs: no named parameters.
discord_get_dmsA
List your open DM and group-DM channels.
Inputs: no named parameters.
discord_get_guild_infoC
Get details about a guild.
Inputs: guildId (required).
discord_get_guildsA
List all guilds (servers) the user is in.
Inputs: no named parameters.
discord_get_inviteB
Resolve an invite code (with member counts).
Inputs: code (required).
discord_get_invitesC
List a guild's invites.
Inputs: guildId (required).
discord_get_messageC
Fetch a single message.
Inputs: channelId (required), messageId (required).
discord_get_messagesA
Read messages from a channel. Use before/after/around (message IDs) to page through history beyond the latest 100.
Inputs: channelId (required), after, limit, around, +1 more.
discord_get_noteC
Get your private note on a user.
Inputs: userId (required).
discord_get_pinnedB
List pinned messages in a channel.
Inputs: channelId (required).
discord_get_poll_votersC
List users who voted for a poll answer.
Inputs: answerId (required), channelId (required), messageId (required), limit.
discord_get_prune_countB
Count members who would be pruned for inactivity.
Inputs: guildId (required), days.
discord_get_reactionsB
List users who reacted with an emoji.
Inputs: emoji (required), channelId (required), messageId (required), limit.
discord_get_rolesC
List a guild's roles.
Inputs: guildId (required).
discord_get_userB
Get info about a user by ID (optionally as a guild member).
Inputs: userId (required), guildId.
discord_get_vanity_urlC
Get the guild's vanity invite.
Inputs: guildId (required).
discord_get_welcome_screenC
Get the guild welcome screen.
Inputs: guildId (required).
discord_get_widget_settingsC
Get the guild widget settings.
Inputs: guildId (required).
discord_grant_permissionC
Add one or more permissions to a role by name (e.g. BAN_MEMBERS). Reads current perms and ORs in the new ones — does not clobber existing perms.
Inputs: roleId (required), guildId (required), permissions (required).
discord_kick_userC
Kick a user from a guild (requires Kick Members).
Inputs: userId (required), guildId (required), reason, confirm.
discord_leave_guildC
Leave a guild.
Inputs: guildId (required), confirm.
discord_list_active_threadsC
List active threads in a guild.
Inputs: guildId (required).
discord_list_archived_threadsC
List archived threads in a channel.
Inputs: channelId (required), limit, private.
discord_list_automod_rulesC
List a guild's AutoMod rules.
Inputs: guildId (required).
discord_list_bansD
List a guild's bans.
Inputs: guildId (required), limit.
discord_list_emojisC
List a guild's custom emojis.
Inputs: guildId (required).
discord_list_guild_webhooksB
List all webhooks in a guild.
Inputs: guildId (required).
discord_list_integrationsC
List guild integrations.
Inputs: guildId (required).
discord_list_permissionsA
List all Discord permission names and their bit values. Use these names with grant/revoke.
Inputs: no named parameters.
discord_list_relationshipsB
List friends/blocked (relationships).
Inputs: no named parameters.
discord_list_scheduled_eventsC
List a guild's scheduled events.
Inputs: guildId (required).
discord_list_stickersA
List a guild's stickers.
Inputs: guildId (required).
discord_list_thread_membersC
List members of a thread.
Inputs: threadId (required).
discord_list_webhooksC
List a channel's webhooks.
Inputs: channelId (required).
discord_modify_user_voice_stateA
Stage moderation: invite a user to speak (suppress:false) or move them to audience (suppress:true).
Inputs: userId (required), guildId (required), channelId (required), suppress.
discord_move_member_voiceA
Move a member to another voice channel (they must already be connected). Omit channelId to disconnect.
Inputs: userId (required), guildId (required), channelId.
discord_open_dmB
Open (or fetch) a DM channel with a user; returns the channelId.
Inputs: userId (required).
discord_pin_messageC
Pin a message.
Inputs: channelId (required), messageId (required).
discord_prune_membersC
Prune (kick) inactive members.
Inputs: guildId (required), days, reason, confirm.
discord_purge_messagesA
Bulk-delete recent messages in a channel (optionally only from one user). Only affects messages newer than 14 days; requires Manage Messages.
Inputs: channelId (required), limit, userId, confirm.
discord_remove_all_reactionsB
Remove all reactions (or all of one emoji) from a message.
Inputs: channelId (required), messageId (required), emoji, confirm.
discord_remove_reactionC
Remove your reaction from a message.
Inputs: emoji (required), channelId (required), messageId (required).
discord_remove_relationshipB
Remove a friend / cancel request / unblock.
Inputs: userId (required), confirm.
discord_remove_roleC
Remove a role from a member (requires Manage Roles).
Inputs: roleId (required), userId (required), guildId (required), reason, +1 more.
discord_remove_user_reactionC
Remove a specific user's reaction.
Inputs: emoji (required), userId (required), channelId (required), messageId (required).
discord_reorder_channelsB
Reorder channels. positions: array of {id, position, parent_id?}.
Inputs: guildId (required), positions (required).
discord_reorder_rolesB
Reorder roles. positions: array of {id, position}.
Inputs: guildId (required), positions (required).
discord_reply_messageB
Reply to a message (set ping:false to not ping the author).
Inputs: channelId (required), messageId (required), ping, embeds, +1 more.
discord_requestA
Advanced: call ANY Discord REST endpoint directly (covers every feature not wrapped by a named tool). path is relative, e.g. /guilds/{id}/templates.
Inputs: path (required), body, query, method, +1 more.
discord_request_to_speakB
Raise your hand to speak in a Stage (set cancel:true to lower).
Inputs: guildId (required), channelId (required), cancel.
discord_revoke_permissionB
Remove one or more permissions from a role by name. Reads current perms and ANDs them out — leaves other perms intact.
Inputs: roleId (required), guildId (required), permissions (required).
discord_search_membersC
Search guild members by username/nickname prefix.
Inputs: query (required), guildId (required), limit.
discord_search_messagesC
Search messages in a guild (set guildId) or a DM/channel (set channelId).
Inputs: query (required), limit, guildId, authorId, +1 more.
discord_send_embedC
Send a message with rich embeds (Discord embed objects).
Inputs: embeds (required), channelId (required), content.
discord_send_fileA
Send a file/image to a channel. source is a data URI or http(s) URL. For multiple files use the files array.
Inputs: channelId (required), files, source, content, +1 more.
discord_send_messageC
Send a message to a channel.
Inputs: content (required), channelId (required).
discord_set_channel_permissionB
Set a permission overwrite. type 0=role, 1=member. allow/deny are bitfield strings.
Inputs: type (required), channelId (required), overwriteId (required), deny, +2 more.
discord_set_nicknameA
Set a member's nickname (omit userId to set your own). Pass empty/no nickname to clear.
Inputs: guildId (required), reason, userId, nickname.
discord_set_noteC
Set your private note on a user.
Inputs: note (required), userId (required).
discord_set_statusA
Set your status (online/idle/dnd/invisible) and/or custom status text.
Inputs: status, customText.
discord_set_voice_stateC
Server mute/deafen a member (mute/deaf booleans).
Inputs: userId (required), guildId (required), deaf, mute, +1 more.
discord_set_voice_statusC
Set a voice channel's status text (empty to clear).
Inputs: channelId (required), status.
discord_start_stageC
Start a Stage in a stage channel.
Inputs: topic (required), channelId (required), privacyLevel.
discord_statusA
Check whether the BetterDiscord plugin bridge is connected.
Inputs: no named parameters.
discord_thread_add_memberC
Add a member to a thread.
Inputs: userId (required), threadId (required).
discord_thread_joinB
Join a thread.
Inputs: threadId (required).
discord_thread_leaveB
Leave a thread.
Inputs: threadId (required).
discord_thread_remove_memberC
Remove a member from a thread.
Inputs: userId (required), threadId (required).
discord_timeout_userC
Time out (mute) a guild member for a duration in seconds. Pass 0 to remove the timeout.
Inputs: userId (required), guildId (required), durationSeconds (required), reason, +1 more.
discord_trigger_typingC
Show the typing indicator in a channel.
Inputs: channelId (required).
discord_unban_userC
Unban a user.
Inputs: userId (required), guildId (required), reason.
discord_unpin_messageC
Unpin a message.
Inputs: channelId (required), messageId (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 128 tools
Most tools have clearly distinct purposes, but there are several overlapping tools for sending messages (send_message, reply_message, send_embed, send_file, execute_webhook) that could cause confusion for an agent. Overall, the descriptions help disambiguate.
All tools follow a consistent verb_noun pattern with the 'discord_' prefix in snake_case, e.g., discord_send_message, discord_create_role. No naming inconsistencies.
With 128 tools, the server is massively over-scoped. This far exceeds the typical well-scoped range of 3-15 tools, making it difficult for agents to navigate and select the correct tool.
The tool set covers virtually all Discord API features, including guild, channel, role, permission, webhook, emoji, thread, scheduled events, automod, voice, and user management. A generic discord_request tool ensures no endpoint is missing.
Maintenance
Related MCP Connectors
The AI admin for Discord: manage channels, roles, members, moderation and automations.
Build Discord communities with AI: roles, channels, modules, automations and reviewed announcements.
An MCP server that integrates with Discord to provide AI-powered features.
Control your Discord community: send/read messages, manage channels and forums, and handle webhook…
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceLets any MCP-compatible AI client interact with Discord — send messages, manage channels, create webhooks, assign roles, and more.74 npm2MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to interact with Discord through the REST API and real-time events, supporting message management, user info, channel operations, and more with security controls.16 npm1MIT
- AlicenseAqualityCmaintenanceEnables AI assistants to interact with Discord through the REST API, supporting message reading and sending, channel and guild management, threads, pins, and reactions.17MIT
- AlicenseAqualityBmaintenanceEnables AI assistants to read and control a local Discord desktop client, including viewing channels and messages, managing voice calls and volumes, and setting Rich Presence.91MIT