Skip to main content
Glama
Elmopios

Discord MCP server

by Elmopios
README.md
# Discord MCP server

![Discord MCP server](./docs/discord-mcp-server.svg)

A local [Model Context Protocol](https://modelcontextprotocol.io/) server that lets an MCP client inspect and manage Discord through a bot account. It communicates over `stdio`, so it does not open an HTTP port.

The server uses a Discord bot token. It does not use, and must not be given, a Discord user token.

## What it does

- Lists guilds, channels, roles, messages, users, and members.
- Creates, edits, moves, and deletes channels.
- Sends messages and creates forum posts.
- Creates, renames, assigns, removes, and deletes roles.
- Kicks and bans members.
- Can write local JSON snapshots of guild channels and roles for use before destructive changes.

## Safety checks

- Every Discord write requires `confirm: true` and a non-empty `reason`.
- Destructive operations require a backup ID unless `allowWithoutBackup: true` is set.
- `DISCORD_GUILD_ID` can restrict requests to one guild.
- Backups are snapshots only. This project does not restore deleted Discord data.

## Requirements

- Node.js 20 or newer.
- A Discord application with a bot.
- An MCP client that can start local `stdio` servers.

## Setup

1. Create an application and bot in the [Discord Developer Portal](https://discord.com/developers/applications).
2. Copy the bot token. Keep it private and do not commit it.
3. Invite the bot to your server with the permissions it needs.
4. Copy the environment template:

   ```powershell
   Copy-Item .env.example .env.local
   ```

5. Set `DISCORD_BOT_TOKEN` in `.env.local`. Set `DISCORD_GUILD_ID` if the bot can access more than one guild.
6. Install dependencies and build the server:

   ```powershell
   npm install
   npm run typecheck
   npm run build
   ```

## Environment variables

| Variable | Required | Description |
| --- | --- | --- |
| `DISCORD_BOT_TOKEN` | Yes | Token for the Discord bot. |
| `DISCORD_GUILD_ID` | No | Guild ID used when a tool call does not provide one. |
| `BACKUP_DIR` | No | Backup folder. Defaults to `backups`. |

## Bot permissions

Start with the smallest set of permissions your workflow needs:

- `View Channels`
- `Read Message History`
- `Send Messages`

Add these only when you use the related tools:

- `Manage Channels`
- `Manage Roles`
- `Manage Messages`
- `Kick Members`
- `Ban Members`
- `Create Public Threads`
- `Send Messages in Threads`

Discord will not let the bot manage roles above its highest role, even when `Manage Roles` is enabled.

## Run the server

Build first, then start the compiled server:

```powershell
npm start
```

For development, run the TypeScript entry point directly:

```powershell
npm run dev
```

An MCP `stdio` server usually looks idle in the terminal. The MCP client communicates with it through standard input and output.

## MCP client configuration

Use the included [mcp-client-config.example.json](./mcp-client-config.example.json) as a starting point. Replace both `/path/to/discord-mcp-server` values with the absolute path to your checkout.

The resulting configuration looks like this:

```json
{
  "mcpServers": {
    "discord": {
      "command": "node",
      "args": [
        "/path/to/discord-mcp-server/dist/index.js"
      ],
      "cwd": "/path/to/discord-mcp-server"
    }
  }
}
```

The MCP client must be able to read `.env.local` from the configured working directory.

## Available tools

Read tools:

- `discord_list_guilds`
- `discord_get_guild`
- `discord_list_channels`
- `discord_list_roles`
- `discord_get_user_profile`
- `discord_get_member_profile`
- `discord_get_guild_member_avatar`
- `discord_read_messages`
- `discord_backup_guild`

Messaging tools:

- `discord_send_message`
- `discord_delete_message`
- `discord_create_forum_post`

Channel tools:

- `discord_create_text_channel`
- `discord_create_voice_channel`
- `discord_create_forum_channel`
- `discord_create_announcement_channel`
- `discord_create_stage_channel`
- `discord_create_category`
- `discord_rename_channel`
- `discord_update_channel`
- `discord_move_channel`
- `discord_delete_channel`
- `discord_set_channel_permissions`

Role tools:

- `discord_create_role`
- `discord_rename_role`
- `discord_delete_role`
- `discord_assign_role`
- `discord_remove_role`

Moderation tools:

- `discord_kick_member`
- `discord_ban_member`

## Input rules and options

Guild-scoped tools accept an optional `guildId`. The server uses `DISCORD_GUILD_ID` when it is set. Otherwise, `guildId` is only optional when the bot can access exactly one guild.

All Discord write tools accept:

- `confirm`: must be `true`.
- `reason`: at least three characters. Discord receives this as the audit-log reason when the API supports one.

Destructive tools also accept:

- `backupId`: the filename returned by `discord_backup_guild` for the same guild.
- `allowWithoutBackup`: set to `true` to bypass backup verification.

Other options worth noting:

- `discord_create_forum_post` accepts `autoArchiveDurationMinutes` with one of `60`, `1440`, `4320`, or `10080`.
- `discord_update_channel` accepts `name`, `topic`, `nsfw`, `rateLimitPerUser`, `bitrate`, and `userLimit`.
- `discord_move_channel` accepts `parentId`, `position`, and `lockPermissions`.
- `discord_set_channel_permissions` accepts a `targetId` plus `allow` and `deny` permission-name arrays.
- `discord_create_role` accepts `color`, `mentionable`, `hoist`, and a list of Discord permission names. New roles have no permissions unless you provide them.
- `discord_ban_member` accepts `deleteMessageSeconds` from `0` to `604800`.
- Channel creation tools accept `parentId` where Discord supports categories. Text-like channels also accept `topic`; voice channels accept `userLimit`.

## Tool call examples

Every write needs an explicit confirmation and reason:

```json
{
  "confirm": true,
  "reason": "Requested by the server owner"
}
```

Destructive calls also need the ID returned by `discord_backup_guild`:

```json
{
  "confirm": true,
  "reason": "Removing an unused channel",
  "backupId": "2026-06-07T03-12-00-000Z-123456789012345678.json"
}
```

You can intentionally skip backup verification with `allowWithoutBackup: true`. Use that only when you have another recovery plan.

## Development

```powershell
npm run dev
npm run typecheck
npm run build
```

Before opening a pull request, run the type check and build, review the diff, and confirm that no `.env`, `.env.local`, backup, or generated `dist` files are staged.

## Project structure

```text
src/index.ts                    MCP server implementation
.env.example                    Environment variable template
mcp-client-config.example.json  MCP client configuration template
```

## Security

- Never commit `.env` or `.env.local`.
- If a token is exposed, revoke it in the Discord Developer Portal and create a new one.
- Use a bot token, never a Discord user token.
- Keep bot permissions narrow and review them when adding a new tool.
- Treat files in `backups/` as private. They can contain guild names and IDs, the owner ID, channel names, and role names.

## License

MIT. See [LICENSE](./LICENSE).