discord-dm-mcp
Allows sending direct messages to Discord users via a bot, using Discord's REST API.
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., "@discord-dm-mcpSend a DM to user 123456789: 'Your PR is merged.'"
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.
discord-dm-mcp
A tiny MCP server that lets Claude send Discord direct messages through a bot — with nothing to host.
Sending a DM is just two stateless HTTPS POSTs to Discord's REST API, so there is no
gateway/websocket connection to keep alive and no server to run. This package is a
stdio MCP server: it runs as a subprocess of whatever launches it — your local
Claude client, or a Claude cloud routine via a committed .mcp.json. Each user
brings their own Discord bot token; the package itself holds no secrets.
It exposes a single tool, send_discord_dm.
How "no hosting" works
Where you use it | Where the server runs | You host a machine? |
Local Claude Code / Desktop / Cursor | your laptop (a subprocess) | No |
Claude cloud routine (via | Anthropic's ephemeral sandbox | No |
The only path that would require hosting is a remote ("Connector chip") MCP server, because a remote MCP must be reachable at a URL. This package avoids that by using stdio. (See the trade-off.)
Related MCP server: Discord Bridge MCP Server
Prerequisites (one-time Discord setup)
Create a bot. https://discord.com/developers/applications → New Application → Bot → Reset Token → copy the token. This is your
DISCORD_BOT_TOKEN.You do not need any privileged intents (Message Content, etc.) — those gate the gateway, not REST sends. This bot never reads messages.
Invite the bot to your server with the
botscope and zero permissions (DMs aren't governed by a permission bit):https://discord.com/oauth2/authorize?client_id=YOUR_APP_ID&scope=bot&permissions=0The bot must share that server with every recipient. Discord only delivers a DM if the bot and the user have a mutual guild. Otherwise the send fails with error
50007("Cannot send messages to this user"). The recipient must also not have DMs disabled / the bot blocked.Get recipient user IDs. In Discord: Settings → Advanced → Developer Mode on, then right-click a user → Copy User ID. (Or build a consented GitHub→Discord mapping.)
Install — local Claude clients
No repo, no GitHub needed — just npm:
claude mcp add discord-dm \
--env DISCORD_BOT_TOKEN="your-bot-token" \
-- npx -y discord-dm-mcpFor Claude Desktop / Cursor, add the equivalent to the client's MCP config:
{
"mcpServers": {
"discord-dm": {
"command": "npx",
"args": ["-y", "discord-dm-mcp"],
"env": { "DISCORD_BOT_TOKEN": "your-bot-token" }
}
}
}Install — Claude cloud routine
A cloud routine can't use a local stdio server you added with claude mcp add
(that lives on your machine). Instead the routine clones a repo and reads
.mcp.json from it. So:
Point the routine at a repo that contains a
.mcp.json(the one at the root of this repo works as-is — itnpx-installs the published package):{ "mcpServers": { "discord-dm": { "command": "npx", "args": ["-y", "discord-dm-mcp"], "env": { "DISCORD_BOT_TOKEN": "${DISCORD_BOT_TOKEN}" } } } }The repo can be a near-empty stub — its only job is to carry this file. The
${DISCORD_BOT_TOKEN}is expanded from the routine's environment variable.Set the env var. In the routine's environment ("Default" or a custom one) add an Environment variable
DISCORD_BOT_TOKEN=....⚠️ Claude routines have no dedicated secrets store yet — env vars are visible to anyone who can edit the environment and may appear in transcripts. Treat this token as low-confidentiality and scope the bot to least privilege (it needs no guild permissions). Rotate it if a transcript is shared.
Allow Discord egress. The Default environment's "Trusted" network access blocks
discord.com(requests fail with403 host_not_allowed). Edit the environment's Network access to Full, or Custom withdiscord.comadded to the allowlist. (Custom-allowlist propagation has had bugs; if Discord still 403s, use Full.)Reference the tool from the routine Instructions, e.g. "If you're unsure whether to merge, call
send_discord_dmto ask the PR author."
Running from a checkout instead of npm (e.g. before publishing): copy
examples/.mcp.local-repo.json to the repo root as
.mcp.json and set the environment Setup script to npm ci && npm run build.
Tool: send_discord_dm
Field | Type | Notes |
| string | Recipient's numeric Discord ID. One of this or |
| string | Resolved to a Discord ID via |
| string | Plain message text, sent as-is. |
| object | Structured decision request (formatted into the body). Fields below. |
| string | Link to the PR / item. |
| string | What the agent is unsure about. |
| string | Relevant evidence / context. |
| string[] | Rendered as |
| string | The agent's recommended option. |
| boolean | Resolve + format but never call Discord. |
Provide content, escalation, or both. Mentions are always disabled
(allowed_mentions: { parse: [] }), so messages never accidentally ping @everyone,
roles, or users.
Errors are returned as tool errors (isError: true), not thrown: unknown recipient,
missing token, the no-mutual-guild 50007/50278 case (not retried), and other Discord
API failures. Rate-limit 429s are retried automatically honoring Retry-After.
Configuration (environment variables)
Var | Required | Purpose |
| to send | Bot token. Not needed for dry runs. |
| no |
|
| no | Inline JSON or path to a |
| no | Override |
Mapping GitHub logins to Discord IDs
Set DISCORD_USER_MAP to inline JSON ({"octocat":"123..."}) or a file path (see
examples/mapping.example.json). Keys match the GitHub
login case-insensitively. For a consented mapping, have users link their own GitHub
via Discord OAuth2 (identify + connections scopes) and only DM logins present in the
map.
Develop / verify
npm install
npm run build # tsc -> dist/
npm test # unit tests (pure functions)
npm run smoke # builds, starts the server over stdio, calls the tool in dry-runnpm run smoke proves the full MCP round-trip with no token and no network.
Why stdio and not a remote connector?
A custom connector (the chip in Claude's "Connectors" UI) is a remote MCP server: Claude connects out to a URL, so it must be hosted (even serverless = a deployment). A stdio server runs as a child process of the client, so it needs no host. The trade:
stdio (this package): no hosting; works locally and in cloud routines via
.mcp.json. Not shown as a Connector chip.remote connector: shown as a chip and reusable across clients, but you must host (serverless like Cloudflare Workers is the lightest option).
Responsible use
Discord's Developer Policy requires consent before initiating processes on a user's behalf and prohibits unsolicited / bulk DMs. Use this for opted-in, transactional, one-at-a-time notifications (e.g. asking a PR author a question), never to broadcast. Using a user token / selfbot to DM is forbidden by Discord and can get the account terminated — this package uses a proper bot token only.
License
MIT
Available Tools
1 toolsend_discord_dmSend Discord DMA
Send a direct message to a Discord user via a bot (REST only, no gateway). Provide either discordUserId or githubLogin (resolved via the configured mapping). Supply content for a plain message, and/or escalation to format a decision request. Mentions are always disabled (allowed_mentions.parse=[]). The bot must share a server with the recipient or Discord returns error 50007. Only DM users who have opted in — never mass-DM.
| Name | Required | Description | Default |
|---|---|---|---|
| dryRun | No | If true, resolve + format but do NOT call Discord | |
| content | No | Plain message text to send as-is | |
| escalation | No | Structured decision request; formatted into the message body | |
| githubLogin | No | GitHub login; resolved to a Discord user ID via DISCORD_USER_MAP | |
| discordUserId | No | Discord numeric user ID (snowflake) of the recipient |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses key behaviors: mentions always disabled, server sharing requirement, opt-in policy, and dryRun flag. No annotations exist, so description carries full burden. Does not cover rate limits or authentication, but sufficient for safe usage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Five sentences efficiently cover purpose, parameters, constraints, and policy. Front-loaded with core purpose, no redundancy. Every sentence is informative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers all critical aspects: identification, message types, constraints, and opt-in policy. Missing description of return value or error handling beyond error 50007, but sufficient for a direct message tool with no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, baseline 3. Description adds value by explaining usage patterns (e.g., 'Supply content for a plain message, and/or escalation'), resolving githubLogin via mapping, and detailing dryRun behavior. Escalation object purpose is clarified.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool sends a direct message to a Discord user via a bot, specifying REST-only and no gateway. It distinguishes between plain messages and structured escalation requests, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear usage context: when to DM (for opted-in users), how to identify recipients (discordUserId or githubLogin), and prerequisites (bot must share server). Lacks explicit 'when not to use' but given no siblings, this is adequate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.1.0- First observed
send_discord_dm
TDQS
Scored across 1 tool
Only one tool exists, so there is no ambiguity. An agent cannot confuse it with another tool.
The single tool name follows a clear verb_noun pattern (send_discord_dm), consistent with common MCP conventions.
A single tool for sending DMs is minimal but arguably appropriate if the server's sole purpose is to send DMs. However, it feels thin and could benefit from at least one more tool (e.g., to verify user availability).
The server only supports sending messages, lacking any way to check user opt-in status, retrieve conversation history, or handle errors like 50007. This leaves significant gaps for an agent.
Maintenance
Related MCP Connectors
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
An MCP server that integrates with Discord to provide AI-powered features.
Cloud-hosted MCP server for durable AI memory
MCP server for AI dialogue using various LLM models via AceDataCloud
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA simple MCP server that allows Claude to access your Telegram account to read and send messages on your behalf.7Apache 2.0
- AlicenseAqualityDmaintenanceAn MCP server that provides native Discord tools for Claude Code, enabling bidirectional communication with remote agents or humans via the Discord REST API. It allows users to send messages, read channel history, and manage reactions directly from their local environment.615 npm3MIT
- FlicenseNot gradedqualityDmaintenanceAn MCP server that enables Claude Desktop to interact with Discord through a dedicated bot. It allows users to list channels, read message history, and send messages directly from the AI interface.2-
- AlicenseNot gradedqualityFmaintenanceA simple MCP server that enables Claude to communicate with locally running LLM models via LM Studio.9MIT