Skip to main content
Glama
tensakulabs

discord-mcp

by tensakulabs
README.md
# discord-mcp

Discord selfbot MCP server — read & send Discord messages from Claude Code or OpenClaw.

> ⚠️ **Selfbot Warning:** This uses your Discord user token, which violates Discord's ToS. Your account may be banned. Use at your own risk.

## What it does

Exposes 6 Discord tools via MCP (Model Context Protocol):

| Tool | Description |
|------|-------------|
| `discord_list_guilds` | List all servers you're in |
| `discord_list_channels` | List text channels in a server |
| `discord_get_messages` | Fetch recent messages from a channel |
| `discord_get_dms` | List your open DM conversations |
| `discord_send_message` | Send a message (channel or DM) |
| `discord_get_unread` | Get messages you haven't seen yet |

A background daemon maintains a persistent WebSocket to the Discord Gateway, ingesting messages into a local SQLite database so `discord_get_unread` works even while Claude isn't running.

## Setup

### 1. Install & configure

```bash
npx @tensakulabs/discord-mcp setup
```

This will:
1. Show you how to extract your Discord token from the desktop app
2. Save it securely to your OS keychain (macOS: uses built-in `security` CLI — no native module required)
3. Start the background daemon via launchd (macOS) or systemd (Linux)
4. Auto-register the MCP server in Claude's config

### 2. Token extraction (step shown during setup)

Open Discord desktop app → Press **Ctrl+Shift+I** (or **Cmd+Option+I** on Mac) → **Network** tab → Send any message in Discord → filter requests by `messages` → click any request → **Headers** tab → find the `Authorization` header → copy its value.

### 3. Restart Claude

Restart Claude Code. You'll see Discord tools available.

### Verify it's working

```bash
npx @tensakulabs/discord-mcp status
# ✅ Connected as: yourname#0
```

## Manual MCP config (if auto-config fails)

Add to `~/.claude/settings.json`:

```json
{
  "mcpServers": {
    "discord": {
      "command": "npx",
      "args": ["-y", "@tensakulabs/discord-mcp"]
    }
  }
}
```

## Usage with Claude

Once registered, Claude can use Discord tools directly:

```
"What did I miss in the #general channel of the Tensaku server?"
→ Claude calls discord_list_guilds, discord_list_channels, discord_get_unread

"Reply to Alex saying I'll be there at 5pm"
→ Claude calls discord_send_message with replyToMessageId
```

## Hooks

Fire shell commands or HTTP webhooks when Discord events occur. Configure in `~/.config/discord-mcp/config.json`:

```json
{
  "hooks": {
    "on_mention": [
      {
        "type": "command",
        "enabled": true,
        "command": "osascript -e 'display notification \"{content}\" with title \"Mention from {author}\"'"
      }
    ],
    "on_everyone": [],
    "on_here": [],
    "on_message": []
  }
}
```

### Hook types

| Hook | Fires when |
|------|-----------|
| `on_mention` | Someone directly @username mentions you |
| `on_everyone` | Someone uses @everyone in a server you're in |
| `on_here` | Someone uses @here in a server you're in |
| `on_message` | Any non-bot message (use sparingly — fires a lot) |

### Hook config fields

| Field | Values | Description |
|-------|--------|-------------|
| `type` | `"command"` \| `"http"` | Shell command or HTTP POST |
| `enabled` | `true` \| `false` | Toggle without removing |
| `command` | string | Shell command (type: command) |
| `url` | string | Endpoint to POST to (type: http) |

### Template variables

Available in `command` strings and HTTP POST body:

| Variable | Value |
|----------|-------|
| `{author}` | Username of message sender |
| `{content}` | Message text |
| `{channel}` | Channel ID |
| `{guild}` | Guild/server ID (or `"dm"` for DMs) |
| `{is_dm}` | `true` or `false` |

### HTTP hook payload

```json
{
  "author": "username",
  "content": "message text",
  "channel": "channel-id",
  "guild": "guild-id",
  "is_dm": false
}
```

## OpenClaw integration

Add to OpenClaw's MCP config:

```json
{
  "mcp": {
    "servers": [{
      "name": "discord",
      "transport": "stdio",
      "command": "npx",
      "args": ["-y", "@tensakulabs/discord-mcp"]
    }]
  }
}
```

## Security

- Token stored in OS keychain (macOS: `security` CLI — no native module compilation needed; Linux: keytar; fallback: AES-256-CBC encrypted file)
- Token never written to config files or logs
- Local files at `~/.config/discord-mcp/`: `messages.db`, `config.json`, `token.enc` (fallback only), `daemon.log`

## Architecture

```
discord-mcp/
├── src/
│   ├── index.ts          MCP server entry — registers 6 tools
│   ├── cli.ts            setup + status commands
│   ├── daemon.ts         Discord Gateway WebSocket → SQLite ingestion + hooks
│   ├── auth.ts           keychain token storage (macOS security CLI / keytar / encrypted file)
│   ├── hooks.ts          hook runner — shell commands and HTTP webhooks
│   ├── config.ts         config loader (~/.config/discord-mcp/config.json)
│   ├── db.ts             SQLite schema + queries
│   ├── ratelimit.ts      429 backoff + Discord headers
│   ├── state.ts          per-channel last-seen state
│   ├── purge.ts          scheduled message retention cleanup
│   └── tools/
│       ├── list_guilds.ts
│       ├── list_channels.ts
│       ├── get_messages.ts
│       ├── get_dms.ts
│       ├── send_message.ts
│       └── get_unread.ts
```

All Discord API calls go through `rateLimitedFetch` — automatic backoff on 429.

The daemon runs as a launchd service (`com.discord-mcp.daemon`) on macOS, connecting to `wss://gateway.discord.gg` and storing all messages locally for fast unread queries.

TDQS

A3.9/5.0

Scored across 8 tools

Disambiguation5/5

Each tool targets a distinct operation: listing DMs, getting messages, getting unread, listing channels, listing guilds, resolving user to DM channel, searching, and sending. No two tools have overlapping purposes.

Naming Consistency5/5

All tools follow a consistent 'discord_verb_noun' pattern in snake_case, using imperative verbs (get, list, resolve, search, send). No mixing of conventions.

Tool Count5/5

8 tools is well-scoped for a Discord MCP, covering essential read operations (messages, channels, guilds) and sending. Not excessive nor too sparse.

Completeness4/5

Covers core reading and sending, but lacks update/delete message operations and guild management. Minor gaps that agents can work around.

Maintenance

ActivityInactive
ResponsivenessNo issues