@quadslab.io/discord-mcp 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +183 -158
- package/dist/cli.d.ts +10 -0
- package/dist/cli.js +621 -0
- package/dist/cli.js.map +1 -0
- package/dist/mcp-server.d.ts +1 -1
- package/dist/mcp-server.js +6 -2
- package/dist/mcp-server.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -4,9 +4,84 @@
|
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
[](https://nodejs.org/)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**Manage your entire Discord server from Claude Code.** 99 admin tools across 14 categories — roles, channels, members, messages, moderation, forums, stages, webhooks, events, and more. Just talk to Claude in plain English.
|
|
8
8
|
|
|
9
|
-
Built with [Discord.js v14](https://discord.js.org/) and the [MCP SDK](https://github.com/modelcontextprotocol/sdk).
|
|
9
|
+
Built by [QuadsLab.io](https://quadslab.io) with [Discord.js v14](https://discord.js.org/) and the [MCP SDK](https://github.com/modelcontextprotocol/sdk).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Setup in 60 Seconds
|
|
14
|
+
|
|
15
|
+
One command. No manual config files. No copying IDs.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx @quadslab.io/discord-mcp init
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The interactive wizard walks you through everything:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
____ __ __ __
|
|
25
|
+
/ __ \__ ______ _____/ /____/ / ____ _/ /_
|
|
26
|
+
/ / / / / / / __ `/ __ / ___/ / / __ `/ __ \
|
|
27
|
+
/ /_/ / /_/ / /_/ / /_/ (__ ) /___/ /_/ / /_/ /
|
|
28
|
+
\___\_\__,_/\__,_/\__,_/____/_____/\__,_/_.___/
|
|
29
|
+
.io
|
|
30
|
+
|
|
31
|
+
┌────────────────────────────────────────────────────────┐
|
|
32
|
+
│ Discord MCP Server — Interactive Setup │
|
|
33
|
+
│ 99 admin tools for managing Discord from Claude Code │
|
|
34
|
+
└────────────────────────────────────────────────────────┘
|
|
35
|
+
|
|
36
|
+
● ● ● ○ ○ ○ (3/6)
|
|
37
|
+
Connecting to Discord
|
|
38
|
+
|
|
39
|
+
✔ Authenticated as MyBot#1234
|
|
40
|
+
Application ID: 123456789
|
|
41
|
+
Servers: 2 found
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
It will:
|
|
45
|
+
1. Guide you through creating a Discord bot (or use an existing one)
|
|
46
|
+
2. Validate your bot token live
|
|
47
|
+
3. Auto-generate the invite URL with all required permissions
|
|
48
|
+
4. Let you pick which server to manage
|
|
49
|
+
5. Write your `.mcp.json` automatically
|
|
50
|
+
|
|
51
|
+
Then open Claude Code and type `/mcp` to connect. Done.
|
|
52
|
+
|
|
53
|
+
### Verify Your Setup
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx @quadslab.io/discord-mcp check
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
QuadsLab.io [discord-mcp] — Health Check
|
|
61
|
+
────────────────────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
Token ............ present
|
|
64
|
+
Bot .............. MyBot#1234
|
|
65
|
+
Server ........... My Gaming Server (1,024 members)
|
|
66
|
+
|
|
67
|
+
Permissions
|
|
68
|
+
────────────────────────────────────────────────────
|
|
69
|
+
|
|
70
|
+
✔ Manage Roles .............. yes
|
|
71
|
+
✔ Manage Channels ........... yes
|
|
72
|
+
✔ Kick Members .............. yes
|
|
73
|
+
✔ Ban Members ............... yes
|
|
74
|
+
...
|
|
75
|
+
|
|
76
|
+
██████████████████████████████ 100% (24/24)
|
|
77
|
+
|
|
78
|
+
✔ All 24 permissions granted
|
|
79
|
+
|
|
80
|
+
┌──────────────────────────────────────────────────┐
|
|
81
|
+
│ MCP server is ready! │
|
|
82
|
+
│ Run discord-mcp or use via .mcp.json in Claude │
|
|
83
|
+
└──────────────────────────────────────────────────┘
|
|
84
|
+
```
|
|
10
85
|
|
|
11
86
|
---
|
|
12
87
|
|
|
@@ -27,99 +102,93 @@ Once connected to Claude Code, just ask in natural language:
|
|
|
27
102
|
- *"Bulk delete the last 50 messages in #bot-testing"*
|
|
28
103
|
- *"Give everyone with the Member role access to #private-channel"*
|
|
29
104
|
|
|
30
|
-
Claude automatically resolves channel, role, and member names using fuzzy matching
|
|
105
|
+
Claude automatically resolves channel, role, and member names using fuzzy matching — no need to look up IDs.
|
|
31
106
|
|
|
32
107
|
---
|
|
33
108
|
|
|
34
109
|
## Features
|
|
35
110
|
|
|
36
|
-
- **99 tools across 14 categories**
|
|
37
|
-
- **
|
|
38
|
-
- **
|
|
39
|
-
- **
|
|
40
|
-
- **
|
|
41
|
-
- **
|
|
42
|
-
- **
|
|
43
|
-
- **
|
|
111
|
+
- **99 tools across 14 categories** — comprehensive Discord server administration without leaving the terminal
|
|
112
|
+
- **Interactive setup wizard** — `npx init` walks you through bot creation, token validation, and config in under a minute
|
|
113
|
+
- **Health check & permission audit** — `npx check` verifies your token, server access, and all 24 required permissions with a visual progress bar
|
|
114
|
+
- **Fuzzy name resolution** — type `"bot testing"`, `"bot-testing"`, or `"bottesting"` and it resolves correctly; no need to look up IDs
|
|
115
|
+
- **Zero-config name matching** — channels, roles, and members are all resolved by name, ID, or mention format automatically
|
|
116
|
+
- **Pre-cached server data** — all channels, roles, and members are cached on startup for instant lookups without extra API calls
|
|
117
|
+
- **Structured JSON responses** — every tool returns consistent, pretty-printed JSON
|
|
118
|
+
- **Audit log integration** — all modifying operations accept a `reason` parameter that appears in the Discord audit log
|
|
119
|
+
- **Helpful error recovery** — failed lookups return suggestions (e.g., "Did you mean: #general, #bot-testing?")
|
|
120
|
+
- **MCP resources** — three read-only resources for server overview data
|
|
44
121
|
|
|
45
122
|
---
|
|
46
123
|
|
|
47
|
-
##
|
|
124
|
+
## Alternative Setup (Manual)
|
|
48
125
|
|
|
49
|
-
|
|
126
|
+
If you prefer to configure things manually instead of using the wizard:
|
|
50
127
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
cd discord-mcp
|
|
54
|
-
```
|
|
128
|
+
<details>
|
|
129
|
+
<summary><strong>Manual setup steps</strong></summary>
|
|
55
130
|
|
|
56
|
-
###
|
|
131
|
+
### 1. Create a Discord bot
|
|
57
132
|
|
|
58
|
-
|
|
59
|
-
npm install
|
|
60
|
-
```
|
|
133
|
+
Follow the [Bot Setup Guide](docs/bot-setup-guide.md) to create a bot in the Discord Developer Portal and get your token.
|
|
61
134
|
|
|
62
|
-
###
|
|
135
|
+
### 2. Add to `.mcp.json`
|
|
63
136
|
|
|
64
|
-
|
|
137
|
+
Create or edit `.mcp.json` in your project root:
|
|
65
138
|
|
|
66
|
-
```
|
|
67
|
-
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"mcpServers": {
|
|
142
|
+
"discord": {
|
|
143
|
+
"command": "npx",
|
|
144
|
+
"args": ["-y", "@quadslab.io/discord-mcp"],
|
|
145
|
+
"env": {
|
|
146
|
+
"DISCORD_TOKEN": "your-bot-token",
|
|
147
|
+
"DISCORD_GUILD_ID": "your-server-id"
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
68
152
|
```
|
|
69
153
|
|
|
70
|
-
|
|
154
|
+
### 3. Connect in Claude Code
|
|
71
155
|
|
|
72
|
-
|
|
73
|
-
DISCORD_TOKEN=your_bot_token_here
|
|
74
|
-
DISCORD_GUILD_ID=your_guild_id_here
|
|
75
|
-
```
|
|
156
|
+
Type `/mcp` in Claude Code to connect the server.
|
|
76
157
|
|
|
77
|
-
|
|
78
|
-
|----------|----------|-------------|
|
|
79
|
-
| `DISCORD_TOKEN` | Yes | Your Discord bot token (also accepts `BOT_TOKEN` as fallback) |
|
|
80
|
-
| `DISCORD_GUILD_ID` | Yes | The ID of the Discord server to manage |
|
|
158
|
+
</details>
|
|
81
159
|
|
|
82
|
-
|
|
160
|
+
<details>
|
|
161
|
+
<summary><strong>Run from source</strong></summary>
|
|
83
162
|
|
|
84
163
|
```bash
|
|
164
|
+
git clone https://github.com/HardHeadHackerHead/discord-mcp.git
|
|
165
|
+
cd discord-mcp
|
|
166
|
+
npm install
|
|
167
|
+
cp .env.example .env
|
|
168
|
+
# Edit .env with your DISCORD_TOKEN and DISCORD_GUILD_ID
|
|
85
169
|
npm run build
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### 5. Run
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
170
|
npm start
|
|
92
|
-
# or
|
|
93
|
-
node dist/mcp-server.js
|
|
94
171
|
```
|
|
95
172
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
npm run dev
|
|
100
|
-
```
|
|
173
|
+
</details>
|
|
101
174
|
|
|
102
175
|
---
|
|
103
176
|
|
|
104
|
-
##
|
|
105
|
-
|
|
106
|
-
Add the following to your `.mcp.json` file (located in your project root or home directory):
|
|
177
|
+
## CLI Reference
|
|
107
178
|
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
"mcpServers": {
|
|
111
|
-
"discord-server": {
|
|
112
|
-
"command": "node",
|
|
113
|
-
"args": ["dist/mcp-server.js"],
|
|
114
|
-
"cwd": "/path/to/discord-mcp"
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
179
|
+
```
|
|
180
|
+
$ npx @quadslab.io/discord-mcp [command]
|
|
118
181
|
```
|
|
119
182
|
|
|
120
|
-
|
|
183
|
+
| Command | Description |
|
|
184
|
+
|---------|-------------|
|
|
185
|
+
| `init` | Interactive setup wizard — creates bot, validates token, writes `.mcp.json` |
|
|
186
|
+
| `check` | Health check — verifies token, server access, and permission audit |
|
|
187
|
+
| `start` | Start the MCP server (default when no command given) |
|
|
188
|
+
| `help` | Show help message |
|
|
189
|
+
| `version` | Show version |
|
|
121
190
|
|
|
122
|
-
|
|
191
|
+
When launched via `.mcp.json` (stdin is not a TTY), the server starts automatically — no subcommand needed.
|
|
123
192
|
|
|
124
193
|
---
|
|
125
194
|
|
|
@@ -147,12 +216,15 @@ Once connected, all 99 tools are available directly in Claude Code. You can ask
|
|
|
147
216
|
|
|
148
217
|
---
|
|
149
218
|
|
|
219
|
+
<details>
|
|
220
|
+
<summary><strong>Full tool reference (click to expand)</strong></summary>
|
|
221
|
+
|
|
150
222
|
### Guild (2 tools)
|
|
151
223
|
|
|
152
224
|
| Tool | Description |
|
|
153
225
|
|------|-------------|
|
|
154
226
|
| `list_guilds` | List all servers the bot is a member of |
|
|
155
|
-
| `get_guild_info` | Detailed server info
|
|
227
|
+
| `get_guild_info` | Detailed server info — member count, channels, roles, features, boost tier |
|
|
156
228
|
|
|
157
229
|
### Roles (9 tools)
|
|
158
230
|
|
|
@@ -183,7 +255,7 @@ Once connected, all 99 tools are available directly in Claude Code. You can ask
|
|
|
183
255
|
| `view_channel_permissions` | View all permission overwrites on a channel |
|
|
184
256
|
| `lock_channel` | Deny SendMessages for @everyone (quick lock) |
|
|
185
257
|
| `unlock_channel` | Remove SendMessages deny for @everyone |
|
|
186
|
-
| `set_slowmode` | Set rate limit (0
|
|
258
|
+
| `set_slowmode` | Set rate limit (0–21600 seconds) on a text channel |
|
|
187
259
|
| `clone_channel` | Duplicate a channel with all permissions and settings |
|
|
188
260
|
| `reorder_channels` | Reorder channels by specifying new positions |
|
|
189
261
|
| `set_voice_region` | Set the RTC region for a voice channel |
|
|
@@ -194,9 +266,9 @@ Once connected, all 99 tools are available directly in Claude Code. You can ask
|
|
|
194
266
|
| Tool | Description |
|
|
195
267
|
|------|-------------|
|
|
196
268
|
| `list_members` | List members with optional role and search filters |
|
|
197
|
-
| `get_member` | Detailed member info
|
|
269
|
+
| `get_member` | Detailed member info — roles, join date, account age, permissions |
|
|
198
270
|
| `kick_member` | Kick a member from the server |
|
|
199
|
-
| `ban_member` | Ban a member with optional message deletion (0
|
|
271
|
+
| `ban_member` | Ban a member with optional message deletion (0–7 days) |
|
|
200
272
|
| `unban_member` | Remove a ban by username or user ID |
|
|
201
273
|
| `timeout_member` | Apply a timeout (10m, 1h, 1d, 1w) or remove one |
|
|
202
274
|
| `prune_members` | Remove inactive members (supports dry run and role filtering) |
|
|
@@ -216,7 +288,7 @@ Once connected, all 99 tools are available directly in Claude Code. You can ask
|
|
|
216
288
|
| `send_embed` | Send a rich embed with title, fields, images, and footer |
|
|
217
289
|
| `edit_message` | Edit a message previously sent by the bot |
|
|
218
290
|
| `delete_message` | Delete a single message by ID |
|
|
219
|
-
| `bulk_delete_messages` | Delete 2
|
|
291
|
+
| `bulk_delete_messages` | Delete 2–100 messages at once (< 14 days old), optionally filtered by user |
|
|
220
292
|
| `crosspost_message` | Publish a message in an announcement channel to all following channels |
|
|
221
293
|
| `pin_message` | Pin a message |
|
|
222
294
|
| `unpin_message` | Unpin a message |
|
|
@@ -228,7 +300,7 @@ Once connected, all 99 tools are available directly in Claude Code. You can ask
|
|
|
228
300
|
|
|
229
301
|
| Tool | Description |
|
|
230
302
|
|------|-------------|
|
|
231
|
-
| `get_reactions` | Get all reactions on a message with full reactor details
|
|
303
|
+
| `get_reactions` | Get all reactions on a message with full reactor details — account creation date, server join date, roles, avatar, boost status. Optionally filter by emoji. |
|
|
232
304
|
|
|
233
305
|
### Server Admin (13 tools)
|
|
234
306
|
|
|
@@ -313,20 +385,22 @@ Once connected, all 99 tools are available directly in Claude Code. You can ask
|
|
|
313
385
|
| Tool | Description |
|
|
314
386
|
|------|-------------|
|
|
315
387
|
| `list_automod_rules` | List all automod rules with triggers, actions, and exemptions |
|
|
316
|
-
| `create_automod_rule` | Create a rule
|
|
388
|
+
| `create_automod_rule` | Create a rule — keyword filter, spam detection, keyword presets, or mention spam |
|
|
317
389
|
| `edit_automod_rule` | Modify a rule's keywords, actions, exemptions, or enabled state |
|
|
318
390
|
| `delete_automod_rule` | Delete an automod rule |
|
|
319
391
|
|
|
392
|
+
</details>
|
|
393
|
+
|
|
320
394
|
---
|
|
321
395
|
|
|
322
396
|
## Fuzzy Matching
|
|
323
397
|
|
|
324
398
|
All tools that accept channel, role, or member names use smart fuzzy matching. You never need to look up IDs manually. The resolution order is:
|
|
325
399
|
|
|
326
|
-
1. **Exact ID match**
|
|
327
|
-
2. **Exact name match**
|
|
328
|
-
3. **Normalized match**
|
|
329
|
-
4. **Substring match**
|
|
400
|
+
1. **Exact ID match** — pass a Discord snowflake ID directly
|
|
401
|
+
2. **Exact name match** — case-insensitive
|
|
402
|
+
3. **Normalized match** — ignores hyphens, spaces, and underscores (`"bot testing"` matches `"bot-testing"`)
|
|
403
|
+
4. **Substring match** — partial name matches at 0.7+ similarity threshold
|
|
330
404
|
|
|
331
405
|
Mention formats are also handled automatically:
|
|
332
406
|
|
|
@@ -348,63 +422,29 @@ Three read-only resources are exposed for quick server overview data:
|
|
|
348
422
|
| `discord://server/channels` | JSON list of all channels organized by category |
|
|
349
423
|
| `discord://server/roles` | JSON list of all roles sorted by position |
|
|
350
424
|
|
|
351
|
-
These resources can be read by Claude Code to build context about the server before performing operations.
|
|
352
|
-
|
|
353
425
|
---
|
|
354
426
|
|
|
355
427
|
## Required Permissions
|
|
356
428
|
|
|
357
|
-
The Discord bot needs the following permissions
|
|
358
|
-
|
|
359
|
-
**General**
|
|
360
|
-
- Manage Server
|
|
361
|
-
- Manage Roles
|
|
362
|
-
- Manage Channels
|
|
363
|
-
- View Audit Log
|
|
364
|
-
- Manage Webhooks
|
|
365
|
-
- Manage Events
|
|
366
|
-
- Manage Emojis and Stickers
|
|
367
|
-
|
|
368
|
-
**Text**
|
|
369
|
-
- Send Messages
|
|
370
|
-
- Manage Messages
|
|
371
|
-
- Read Message History
|
|
372
|
-
- Add Reactions
|
|
373
|
-
- Use External Emojis
|
|
374
|
-
|
|
375
|
-
**Voice**
|
|
376
|
-
- Move Members
|
|
377
|
-
- Disconnect Members
|
|
378
|
-
|
|
379
|
-
**Moderation**
|
|
380
|
-
- Kick Members
|
|
381
|
-
- Ban Members
|
|
382
|
-
- Moderate Members
|
|
383
|
-
- Manage Auto Moderation
|
|
429
|
+
The Discord bot needs the following permissions for full functionality:
|
|
384
430
|
|
|
385
|
-
|
|
431
|
+
| Category | Permissions |
|
|
432
|
+
|----------|-------------|
|
|
433
|
+
| **General** | Manage Server, Manage Roles, Manage Channels, View Audit Log, Manage Webhooks, Manage Events, Manage Emojis and Stickers |
|
|
434
|
+
| **Text** | Send Messages, Manage Messages, Read Message History, Add Reactions, Use External Emojis |
|
|
435
|
+
| **Voice** | Move Members, Disconnect Members |
|
|
436
|
+
| **Moderation** | Kick Members, Ban Members, Moderate Members, Manage Auto Moderation |
|
|
386
437
|
|
|
387
|
-
|
|
438
|
+
The `init` wizard auto-generates an invite URL with all of these. If you set up manually, see the [Bot Setup Guide](docs/bot-setup-guide.md) for which checkboxes to select.
|
|
388
439
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
- `bot`
|
|
392
|
-
- `applications.commands`
|
|
440
|
+
The bot can only act within its role hierarchy — it cannot manage roles positioned higher than its own highest role.
|
|
393
441
|
|
|
394
442
|
### Gateway Intents
|
|
395
443
|
|
|
396
|
-
|
|
444
|
+
These privileged intents must be enabled in the [Discord Developer Portal](https://discord.com/developers/applications):
|
|
397
445
|
|
|
398
|
-
-
|
|
399
|
-
-
|
|
400
|
-
- `GuildMessages` -- message content and events
|
|
401
|
-
- `GuildModeration` -- ban and kick events
|
|
402
|
-
- `MessageContent` -- read message text
|
|
403
|
-
- `GuildMessageReactions` -- reaction data
|
|
404
|
-
- `GuildScheduledEvents` -- scheduled event management
|
|
405
|
-
- `AutoModerationConfiguration` -- automod rule management
|
|
406
|
-
- `GuildWebhooks` -- webhook events
|
|
407
|
-
- `GuildInvites` -- invite tracking
|
|
446
|
+
- **Server Members Intent** — required for member management
|
|
447
|
+
- **Message Content Intent** — required for reading message content
|
|
408
448
|
|
|
409
449
|
---
|
|
410
450
|
|
|
@@ -417,58 +457,43 @@ The bot connects with these privileged intents (must be enabled in the Discord D
|
|
|
417
457
|
├── README.md
|
|
418
458
|
├── LICENSE
|
|
419
459
|
├── .env.example
|
|
420
|
-
├── .gitignore
|
|
421
460
|
├── docs/
|
|
422
|
-
│
|
|
461
|
+
│ ├── discord-mcp-server.md # Full tool reference documentation
|
|
462
|
+
│ └── bot-setup-guide.md # Step-by-step bot creation guide
|
|
423
463
|
└── src/
|
|
424
|
-
├──
|
|
425
|
-
├──
|
|
426
|
-
├──
|
|
464
|
+
├── cli.ts # CLI — init wizard, health check, server start
|
|
465
|
+
├── mcp-server.ts # MCP server — validates env, initializes client
|
|
466
|
+
├── index.ts # Tool/resource registration and request routing
|
|
467
|
+
├── discord-client.ts # Discord.js client — intents, caching, connection
|
|
427
468
|
└── tools/
|
|
428
|
-
├── index.ts
|
|
429
|
-
├── utils.ts
|
|
430
|
-
├── guild.ts
|
|
431
|
-
├── roles.ts
|
|
432
|
-
├── channels.ts
|
|
433
|
-
├── members.ts
|
|
434
|
-
├── messages.ts
|
|
435
|
-
├── reactions.ts
|
|
436
|
-
├── server.ts
|
|
437
|
-
├── threads.ts
|
|
438
|
-
├──
|
|
439
|
-
├──
|
|
440
|
-
├──
|
|
441
|
-
├──
|
|
442
|
-
├──
|
|
443
|
-
└──
|
|
469
|
+
├── index.ts # Tool registry — routes calls to category handlers
|
|
470
|
+
├── utils.ts # Fuzzy matching for channels, roles, members
|
|
471
|
+
├── guild.ts # Server info (2)
|
|
472
|
+
├── roles.ts # Role management (9)
|
|
473
|
+
├── channels.ts # Channel management (16)
|
|
474
|
+
├── members.ts # Member management (12)
|
|
475
|
+
├── messages.ts # Messaging (13)
|
|
476
|
+
├── reactions.ts # Reactions (1)
|
|
477
|
+
├── server.ts # Server admin (13)
|
|
478
|
+
├── threads.ts # Thread management (7)
|
|
479
|
+
├── forums.ts # Forum channels (5)
|
|
480
|
+
├── emojis.ts # Emoji & stickers (7)
|
|
481
|
+
├── webhooks.ts # Webhooks (4)
|
|
482
|
+
├── events.ts # Scheduled events (4)
|
|
483
|
+
├── stage.ts # Stage instances (3)
|
|
484
|
+
└── automod.ts # Auto-moderation (4)
|
|
444
485
|
```
|
|
445
486
|
|
|
446
487
|
---
|
|
447
488
|
|
|
448
489
|
## Contributing
|
|
449
490
|
|
|
450
|
-
Contributions are welcome.
|
|
451
|
-
|
|
452
|
-
1. Fork the repository
|
|
453
|
-
2. Create a feature branch (`git checkout -b feature/my-feature`)
|
|
454
|
-
3. Make your changes
|
|
455
|
-
4. Ensure the project builds cleanly (`npm run build`)
|
|
456
|
-
5. Commit your changes with a descriptive message
|
|
457
|
-
6. Push to your fork and open a pull request
|
|
458
|
-
|
|
459
|
-
### Guidelines
|
|
460
|
-
|
|
461
|
-
- Follow the existing code style and patterns
|
|
462
|
-
- Each new tool should be added to the appropriate category file in `src/tools/`
|
|
463
|
-
- All tools must return structured JSON responses
|
|
464
|
-
- Include fuzzy matching support for any new parameters that accept channel, role, or member names
|
|
465
|
-
- Add new tools to the tool registry in `src/tools/index.ts`
|
|
466
|
-
- Update the documentation in `docs/discord-mcp-server.md` for any new or changed tools
|
|
491
|
+
Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, code style, and guidelines.
|
|
467
492
|
|
|
468
493
|
---
|
|
469
494
|
|
|
470
495
|
## License
|
|
471
496
|
|
|
472
|
-
MIT License. Copyright (c) 2026 [QuadsLab](https://
|
|
497
|
+
MIT License. Copyright (c) 2026 [QuadsLab.io](https://quadslab.io).
|
|
473
498
|
|
|
474
499
|
See [LICENSE](LICENSE) for the full text.
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,621 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI entry point for @quadslab.io/discord-mcp
|
|
4
|
+
*
|
|
5
|
+
* Subcommands:
|
|
6
|
+
* init - Interactive setup wizard
|
|
7
|
+
* check - Health check and permission audit
|
|
8
|
+
* start - Start the MCP server (default)
|
|
9
|
+
*/
|
|
10
|
+
import readline from 'readline';
|
|
11
|
+
import { Client, GatewayIntentBits, PermissionFlagsBits } from 'discord.js';
|
|
12
|
+
import fs from 'fs';
|
|
13
|
+
import path from 'path';
|
|
14
|
+
// ── ANSI Helpers ─────────────────────────────────────────────────────
|
|
15
|
+
const isColorSupported = process.stderr.isTTY && !process.env['NO_COLOR'];
|
|
16
|
+
const c = {
|
|
17
|
+
reset: isColorSupported ? '\x1b[0m' : '',
|
|
18
|
+
bold: isColorSupported ? '\x1b[1m' : '',
|
|
19
|
+
dim: isColorSupported ? '\x1b[2m' : '',
|
|
20
|
+
italic: isColorSupported ? '\x1b[3m' : '',
|
|
21
|
+
underline: isColorSupported ? '\x1b[4m' : '',
|
|
22
|
+
// Brand colors
|
|
23
|
+
cyan: isColorSupported ? '\x1b[36m' : '',
|
|
24
|
+
cyanBright: isColorSupported ? '\x1b[96m' : '',
|
|
25
|
+
magenta: isColorSupported ? '\x1b[35m' : '',
|
|
26
|
+
magentaBright: isColorSupported ? '\x1b[95m' : '',
|
|
27
|
+
green: isColorSupported ? '\x1b[32m' : '',
|
|
28
|
+
greenBright: isColorSupported ? '\x1b[92m' : '',
|
|
29
|
+
red: isColorSupported ? '\x1b[31m' : '',
|
|
30
|
+
redBright: isColorSupported ? '\x1b[91m' : '',
|
|
31
|
+
yellow: isColorSupported ? '\x1b[33m' : '',
|
|
32
|
+
yellowBright: isColorSupported ? '\x1b[93m' : '',
|
|
33
|
+
blue: isColorSupported ? '\x1b[34m' : '',
|
|
34
|
+
blueBright: isColorSupported ? '\x1b[94m' : '',
|
|
35
|
+
white: isColorSupported ? '\x1b[37m' : '',
|
|
36
|
+
whiteBright: isColorSupported ? '\x1b[97m' : '',
|
|
37
|
+
gray: isColorSupported ? '\x1b[90m' : '',
|
|
38
|
+
bgCyan: isColorSupported ? '\x1b[46m' : '',
|
|
39
|
+
bgMagenta: isColorSupported ? '\x1b[45m' : '',
|
|
40
|
+
};
|
|
41
|
+
// Stderr-only output (keeps stdout clean for MCP)
|
|
42
|
+
const out = (...args) => process.stderr.write(args.join(''));
|
|
43
|
+
const ln = (...args) => process.stderr.write(args.join('') + '\n');
|
|
44
|
+
// ── Brand Art ────────────────────────────────────────────────────────
|
|
45
|
+
const LOGO = `
|
|
46
|
+
${c.cyanBright}${c.bold} ____ __ __ __ ${c.reset}
|
|
47
|
+
${c.cyanBright}${c.bold} / __ \\__ ______ _____/ /____/ / ____ _/ /_ ${c.reset}
|
|
48
|
+
${c.cyan} / / / / / / / __ \`/ __ / ___/ / / __ \`/ __ \\ ${c.reset}
|
|
49
|
+
${c.cyan} / /_/ / /_/ / /_/ / /_/ (__ ) /___/ /_/ / /_/ / ${c.reset}
|
|
50
|
+
${c.magenta} \\___\\_\\__,_/\\__,_/\\__,_/____/_____/\\__,_/_.___/ ${c.reset}
|
|
51
|
+
${c.magentaBright}${c.bold} .io ${c.reset}${c.dim}${c.gray}v1.0${c.reset}
|
|
52
|
+
`;
|
|
53
|
+
const LOGO_MINI = `${c.cyanBright}${c.bold}QuadsLab${c.magentaBright}.io${c.reset}`;
|
|
54
|
+
const DISCORD_MCP_BADGE = `${c.gray}[${c.reset}${c.blueBright}discord-mcp${c.reset}${c.gray}]${c.reset}`;
|
|
55
|
+
// ── UI Components ────────────────────────────────────────────────────
|
|
56
|
+
function box(lines, borderColor = c.gray) {
|
|
57
|
+
const stripped = lines.map(l => l.replace(/\x1b\[[0-9;]*m/g, ''));
|
|
58
|
+
const maxLen = Math.max(...stripped.map(l => l.length));
|
|
59
|
+
const w = maxLen + 2;
|
|
60
|
+
ln(`${borderColor} ┌${'─'.repeat(w)}┐${c.reset}`);
|
|
61
|
+
lines.forEach((line, i) => {
|
|
62
|
+
const pad = maxLen - stripped[i].length;
|
|
63
|
+
ln(`${borderColor} │${c.reset} ${line}${' '.repeat(pad)} ${borderColor}│${c.reset}`);
|
|
64
|
+
});
|
|
65
|
+
ln(`${borderColor} └${'─'.repeat(w)}┘${c.reset}`);
|
|
66
|
+
}
|
|
67
|
+
function divider() {
|
|
68
|
+
ln(`${c.gray} ${'─'.repeat(52)}${c.reset}`);
|
|
69
|
+
}
|
|
70
|
+
function stepHeader(current, total, title) {
|
|
71
|
+
ln('');
|
|
72
|
+
// Progress dots
|
|
73
|
+
const dots = Array.from({ length: total }, (_, i) => {
|
|
74
|
+
if (i < current - 1)
|
|
75
|
+
return `${c.greenBright}●${c.reset}`;
|
|
76
|
+
if (i === current - 1)
|
|
77
|
+
return `${c.cyanBright}●${c.reset}`;
|
|
78
|
+
return `${c.gray}○${c.reset}`;
|
|
79
|
+
}).join(' ');
|
|
80
|
+
ln(` ${dots} ${c.gray}(${current}/${total})${c.reset}`);
|
|
81
|
+
ln(` ${c.bold}${c.whiteBright}${title}${c.reset}`);
|
|
82
|
+
ln('');
|
|
83
|
+
}
|
|
84
|
+
function success(msg) {
|
|
85
|
+
ln(` ${c.greenBright}✔${c.reset} ${msg}`);
|
|
86
|
+
}
|
|
87
|
+
function error(msg) {
|
|
88
|
+
ln(` ${c.redBright}✖${c.reset} ${c.red}${msg}${c.reset}`);
|
|
89
|
+
}
|
|
90
|
+
function warn(msg) {
|
|
91
|
+
ln(` ${c.yellowBright}⚠${c.reset} ${c.yellow}${msg}${c.reset}`);
|
|
92
|
+
}
|
|
93
|
+
function info(msg) {
|
|
94
|
+
ln(` ${c.gray}${msg}${c.reset}`);
|
|
95
|
+
}
|
|
96
|
+
function bullet(msg) {
|
|
97
|
+
ln(` ${c.cyan}›${c.reset} ${msg}`);
|
|
98
|
+
}
|
|
99
|
+
function link(url) {
|
|
100
|
+
ln(` ${c.underline}${c.blueBright}${url}${c.reset}`);
|
|
101
|
+
}
|
|
102
|
+
// ── Spinner ──────────────────────────────────────────────────────────
|
|
103
|
+
const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
104
|
+
function createSpinner(message) {
|
|
105
|
+
let i = 0;
|
|
106
|
+
const interval = setInterval(() => {
|
|
107
|
+
const frame = SPINNER_FRAMES[i % SPINNER_FRAMES.length];
|
|
108
|
+
out(`\r ${c.cyanBright}${frame}${c.reset} ${c.dim}${message}${c.reset} `);
|
|
109
|
+
i++;
|
|
110
|
+
}, 80);
|
|
111
|
+
return {
|
|
112
|
+
stop(finalMsg) {
|
|
113
|
+
clearInterval(interval);
|
|
114
|
+
out('\r' + ' '.repeat(message.length + 10) + '\r');
|
|
115
|
+
if (finalMsg)
|
|
116
|
+
ln(finalMsg);
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
// ── Readline ─────────────────────────────────────────────────────────
|
|
121
|
+
function createRL() {
|
|
122
|
+
return readline.createInterface({
|
|
123
|
+
input: process.stdin,
|
|
124
|
+
output: process.stderr,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function prompt(rl, question) {
|
|
128
|
+
return new Promise((resolve) => {
|
|
129
|
+
rl.question(` ${c.cyanBright}?${c.reset} ${question}`, (answer) => resolve(answer.trim()));
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
function promptSecret(rl, question) {
|
|
133
|
+
return new Promise((resolve) => {
|
|
134
|
+
out(` ${c.cyanBright}?${c.reset} ${question}`);
|
|
135
|
+
const stdin = process.stdin;
|
|
136
|
+
const wasRaw = stdin.isRaw;
|
|
137
|
+
if (stdin.setRawMode) {
|
|
138
|
+
stdin.setRawMode(true);
|
|
139
|
+
}
|
|
140
|
+
stdin.resume();
|
|
141
|
+
let input = '';
|
|
142
|
+
const onData = (ch) => {
|
|
143
|
+
const char = ch.toString('utf8');
|
|
144
|
+
if (char === '\r' || char === '\n') {
|
|
145
|
+
stdin.removeListener('data', onData);
|
|
146
|
+
if (stdin.setRawMode)
|
|
147
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
148
|
+
ln('');
|
|
149
|
+
resolve(input.trim());
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (char === '\x7f' || char === '\b') {
|
|
153
|
+
if (input.length > 0) {
|
|
154
|
+
input = input.slice(0, -1);
|
|
155
|
+
out('\b \b');
|
|
156
|
+
}
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (char === '\x03') {
|
|
160
|
+
// Ctrl+C
|
|
161
|
+
ln('');
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
input += char;
|
|
165
|
+
out(`${c.dim}*${c.reset}`);
|
|
166
|
+
};
|
|
167
|
+
stdin.on('data', onData);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
async function promptConfirm(rl, question, defaultYes = true) {
|
|
171
|
+
const hint = defaultYes ? `${c.dim}(Y/n)${c.reset}` : `${c.dim}(y/N)${c.reset}`;
|
|
172
|
+
const answer = (await prompt(rl, `${question} ${hint} `)).toLowerCase();
|
|
173
|
+
if (!answer)
|
|
174
|
+
return defaultYes;
|
|
175
|
+
return answer === 'y' || answer === 'yes';
|
|
176
|
+
}
|
|
177
|
+
async function promptSelect(rl, items, question) {
|
|
178
|
+
items.forEach((item, i) => {
|
|
179
|
+
ln(` ${c.cyanBright}${i + 1}${c.reset}${c.gray}.${c.reset} ${item}`);
|
|
180
|
+
});
|
|
181
|
+
ln('');
|
|
182
|
+
const choice = await prompt(rl, `${question} `);
|
|
183
|
+
return parseInt(choice, 10) - 1;
|
|
184
|
+
}
|
|
185
|
+
async function waitForEnter(rl, msg = 'Press Enter to continue...') {
|
|
186
|
+
await prompt(rl, `${c.dim}${msg}${c.reset} `);
|
|
187
|
+
}
|
|
188
|
+
// ── Permissions ──────────────────────────────────────────────────────
|
|
189
|
+
const REQUIRED_PERMISSIONS = [
|
|
190
|
+
{ flag: PermissionFlagsBits.ManageRoles, name: 'Manage Roles' },
|
|
191
|
+
{ flag: PermissionFlagsBits.ManageChannels, name: 'Manage Channels' },
|
|
192
|
+
{ flag: PermissionFlagsBits.KickMembers, name: 'Kick Members' },
|
|
193
|
+
{ flag: PermissionFlagsBits.BanMembers, name: 'Ban Members' },
|
|
194
|
+
{ flag: PermissionFlagsBits.ManageGuild, name: 'Manage Server' },
|
|
195
|
+
{ flag: PermissionFlagsBits.ViewChannel, name: 'View Channels' },
|
|
196
|
+
{ flag: PermissionFlagsBits.SendMessages, name: 'Send Messages' },
|
|
197
|
+
{ flag: PermissionFlagsBits.ManageMessages, name: 'Manage Messages' },
|
|
198
|
+
{ flag: PermissionFlagsBits.EmbedLinks, name: 'Embed Links' },
|
|
199
|
+
{ flag: PermissionFlagsBits.ReadMessageHistory, name: 'Read Message History' },
|
|
200
|
+
{ flag: PermissionFlagsBits.AddReactions, name: 'Add Reactions' },
|
|
201
|
+
{ flag: PermissionFlagsBits.ManageEmojisAndStickers, name: 'Manage Emojis & Stickers' },
|
|
202
|
+
{ flag: PermissionFlagsBits.ManageWebhooks, name: 'Manage Webhooks' },
|
|
203
|
+
{ flag: PermissionFlagsBits.ManageEvents, name: 'Manage Events' },
|
|
204
|
+
{ flag: PermissionFlagsBits.ManageThreads, name: 'Manage Threads' },
|
|
205
|
+
{ flag: PermissionFlagsBits.SendMessagesInThreads, name: 'Send Messages in Threads' },
|
|
206
|
+
{ flag: PermissionFlagsBits.ViewAuditLog, name: 'View Audit Log' },
|
|
207
|
+
{ flag: PermissionFlagsBits.ModerateMembers, name: 'Moderate Members' },
|
|
208
|
+
{ flag: PermissionFlagsBits.MuteMembers, name: 'Mute Members' },
|
|
209
|
+
{ flag: PermissionFlagsBits.DeafenMembers, name: 'Deafen Members' },
|
|
210
|
+
{ flag: PermissionFlagsBits.MoveMembers, name: 'Move Members' },
|
|
211
|
+
{ flag: PermissionFlagsBits.ManageNicknames, name: 'Manage Nicknames' },
|
|
212
|
+
{ flag: PermissionFlagsBits.CreatePublicThreads, name: 'Create Public Threads' },
|
|
213
|
+
{ flag: PermissionFlagsBits.CreatePrivateThreads, name: 'Create Private Threads' },
|
|
214
|
+
];
|
|
215
|
+
const PERMISSION_INTEGER = REQUIRED_PERMISSIONS.reduce((acc, p) => acc | p.flag, BigInt(0));
|
|
216
|
+
// ── Init Command ─────────────────────────────────────────────────────
|
|
217
|
+
async function runInit() {
|
|
218
|
+
const rl = createRL();
|
|
219
|
+
const TOTAL_STEPS = 6;
|
|
220
|
+
try {
|
|
221
|
+
// ── Welcome ──
|
|
222
|
+
ln(LOGO);
|
|
223
|
+
box([
|
|
224
|
+
`${c.bold}${c.whiteBright}Discord MCP Server${c.reset} ${c.gray}—${c.reset} ${c.dim}Interactive Setup${c.reset}`,
|
|
225
|
+
`${c.dim}99 admin tools for managing Discord from Claude Code${c.reset}`,
|
|
226
|
+
], c.cyan);
|
|
227
|
+
ln('');
|
|
228
|
+
// ── Step 1: Bot token ──
|
|
229
|
+
stepHeader(1, TOTAL_STEPS, 'Discord Bot Token');
|
|
230
|
+
const hasBot = await promptConfirm(rl, 'Do you already have a Discord bot?', false);
|
|
231
|
+
if (!hasBot) {
|
|
232
|
+
ln('');
|
|
233
|
+
box([
|
|
234
|
+
`${c.bold}Create a Discord Bot${c.reset}`,
|
|
235
|
+
``,
|
|
236
|
+
`${c.cyanBright}1.${c.reset} Open the Discord Developer Portal`,
|
|
237
|
+
`${c.cyanBright}2.${c.reset} Click ${c.bold}"New Application"${c.reset} and name it`,
|
|
238
|
+
`${c.cyanBright}3.${c.reset} Go to the ${c.bold}Bot${c.reset} tab`,
|
|
239
|
+
`${c.cyanBright}4.${c.reset} Click ${c.bold}"Reset Token"${c.reset} and copy it`,
|
|
240
|
+
], c.blue);
|
|
241
|
+
ln('');
|
|
242
|
+
link('https://discord.com/developers/applications');
|
|
243
|
+
ln('');
|
|
244
|
+
await waitForEnter(rl, 'Press Enter when you have your token...');
|
|
245
|
+
}
|
|
246
|
+
ln('');
|
|
247
|
+
const token = await promptSecret(rl, 'Paste your bot token: ');
|
|
248
|
+
if (!token) {
|
|
249
|
+
error('No token provided.');
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const masked = token.slice(0, 5) + '*'.repeat(Math.max(0, token.length - 9)) + token.slice(-4);
|
|
253
|
+
info(`Token received: ${masked}`);
|
|
254
|
+
// ── Step 2: Privileged intents ──
|
|
255
|
+
stepHeader(2, TOTAL_STEPS, 'Enable Privileged Intents');
|
|
256
|
+
box([
|
|
257
|
+
`${c.bold}Required Bot Intents${c.reset}`,
|
|
258
|
+
``,
|
|
259
|
+
`In the Developer Portal ${c.gray}>${c.reset} ${c.bold}Bot${c.reset} tab, enable:`,
|
|
260
|
+
``,
|
|
261
|
+
` ${c.greenBright}▣${c.reset} ${c.bold}Server Members Intent${c.reset}`,
|
|
262
|
+
` ${c.greenBright}▣${c.reset} ${c.bold}Message Content Intent${c.reset}`,
|
|
263
|
+
], c.blue);
|
|
264
|
+
ln('');
|
|
265
|
+
await waitForEnter(rl, 'Press Enter when both intents are enabled...');
|
|
266
|
+
// ── Step 3: Validate token ──
|
|
267
|
+
stepHeader(3, TOTAL_STEPS, 'Connecting to Discord');
|
|
268
|
+
const spinner = createSpinner('Validating bot token...');
|
|
269
|
+
const client = new Client({
|
|
270
|
+
intents: [
|
|
271
|
+
GatewayIntentBits.Guilds,
|
|
272
|
+
GatewayIntentBits.GuildMembers,
|
|
273
|
+
],
|
|
274
|
+
});
|
|
275
|
+
let appId;
|
|
276
|
+
let guilds;
|
|
277
|
+
try {
|
|
278
|
+
await client.login(token);
|
|
279
|
+
await new Promise((resolve) => {
|
|
280
|
+
if (client.isReady())
|
|
281
|
+
return resolve();
|
|
282
|
+
client.once('ready', () => resolve());
|
|
283
|
+
});
|
|
284
|
+
appId = client.application?.id || client.user?.id || '';
|
|
285
|
+
guilds = [...client.guilds.cache.values()];
|
|
286
|
+
spinner.stop();
|
|
287
|
+
success(`Authenticated as ${c.bold}${client.user?.tag}${c.reset}`);
|
|
288
|
+
info(`Application ID: ${appId}`);
|
|
289
|
+
info(`Servers: ${guilds.length} found`);
|
|
290
|
+
}
|
|
291
|
+
catch (err) {
|
|
292
|
+
spinner.stop();
|
|
293
|
+
error(`Authentication failed: ${err.message}`);
|
|
294
|
+
ln('');
|
|
295
|
+
bullet('Check that your token is correct');
|
|
296
|
+
bullet('Make sure privileged intents are enabled');
|
|
297
|
+
client.destroy();
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
// ── Step 4: Invite bot ──
|
|
301
|
+
stepHeader(4, TOTAL_STEPS, 'Invite Bot to Server');
|
|
302
|
+
const inviteUrl = `https://discord.com/oauth2/authorize?client_id=${appId}&scope=bot+applications.commands&permissions=${PERMISSION_INTEGER}`;
|
|
303
|
+
if (guilds.length === 0) {
|
|
304
|
+
warn('Bot is not in any servers yet.');
|
|
305
|
+
ln('');
|
|
306
|
+
ln(` ${c.bold}Invite URL:${c.reset}`);
|
|
307
|
+
link(inviteUrl);
|
|
308
|
+
ln('');
|
|
309
|
+
await waitForEnter(rl, 'Press Enter after inviting the bot...');
|
|
310
|
+
const refreshSpinner = createSpinner('Refreshing server list...');
|
|
311
|
+
await client.guilds.fetch();
|
|
312
|
+
guilds = [...client.guilds.cache.values()];
|
|
313
|
+
refreshSpinner.stop();
|
|
314
|
+
if (guilds.length === 0) {
|
|
315
|
+
error('Bot still not in any servers.');
|
|
316
|
+
bullet('Open the invite URL above and add the bot');
|
|
317
|
+
bullet(`Then run ${c.bold}discord-mcp init${c.reset} again`);
|
|
318
|
+
client.destroy();
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
success(`Found ${guilds.length} server${guilds.length > 1 ? 's' : ''}`);
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
success(`Bot is in ${guilds.length} server${guilds.length > 1 ? 's' : ''}`);
|
|
325
|
+
ln('');
|
|
326
|
+
info('Invite URL (for adding to more servers):');
|
|
327
|
+
link(inviteUrl);
|
|
328
|
+
}
|
|
329
|
+
// ── Step 5: Select guild ──
|
|
330
|
+
stepHeader(5, TOTAL_STEPS, 'Select Your Server');
|
|
331
|
+
let selectedGuild;
|
|
332
|
+
if (guilds.length === 1) {
|
|
333
|
+
selectedGuild = guilds[0];
|
|
334
|
+
success(`Auto-selected ${c.bold}${selectedGuild.name}${c.reset}`);
|
|
335
|
+
info(`ID: ${selectedGuild.id} | Members: ${selectedGuild.memberCount}`);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
const guildItems = guilds.map(g => `${c.bold}${g.name}${c.reset} ${c.gray}(${g.id} • ${g.memberCount} members)${c.reset}`);
|
|
339
|
+
const idx = await promptSelect(rl, guildItems, `Select a server (1-${guilds.length}):`);
|
|
340
|
+
if (isNaN(idx) || idx < 0 || idx >= guilds.length) {
|
|
341
|
+
error('Invalid selection.');
|
|
342
|
+
client.destroy();
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
selectedGuild = guilds[idx];
|
|
346
|
+
success(`Selected ${c.bold}${selectedGuild.name}${c.reset}`);
|
|
347
|
+
}
|
|
348
|
+
client.destroy();
|
|
349
|
+
// ── Step 6: Write config ──
|
|
350
|
+
stepHeader(6, TOTAL_STEPS, 'Configure Claude Code');
|
|
351
|
+
const mcpJsonPath = path.join(process.cwd(), '.mcp.json');
|
|
352
|
+
const newConfig = {
|
|
353
|
+
mcpServers: {
|
|
354
|
+
discord: {
|
|
355
|
+
command: 'npx',
|
|
356
|
+
args: ['-y', '@quadslab.io/discord-mcp'],
|
|
357
|
+
env: {
|
|
358
|
+
DISCORD_TOKEN: token,
|
|
359
|
+
DISCORD_GUILD_ID: selectedGuild.id,
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
};
|
|
364
|
+
let wrote = false;
|
|
365
|
+
if (fs.existsSync(mcpJsonPath)) {
|
|
366
|
+
const merge = await promptConfirm(rl, '.mcp.json already exists. Merge discord config?');
|
|
367
|
+
if (merge) {
|
|
368
|
+
const existing = JSON.parse(fs.readFileSync(mcpJsonPath, 'utf-8'));
|
|
369
|
+
existing.mcpServers = existing.mcpServers || {};
|
|
370
|
+
existing.mcpServers.discord = newConfig.mcpServers.discord;
|
|
371
|
+
fs.writeFileSync(mcpJsonPath, JSON.stringify(existing, null, 2) + '\n');
|
|
372
|
+
success('Merged into existing .mcp.json');
|
|
373
|
+
wrote = true;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
const write = await promptConfirm(rl, 'Create .mcp.json in current directory?');
|
|
378
|
+
if (write) {
|
|
379
|
+
fs.writeFileSync(mcpJsonPath, JSON.stringify(newConfig, null, 2) + '\n');
|
|
380
|
+
success('Created .mcp.json');
|
|
381
|
+
wrote = true;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (!wrote) {
|
|
385
|
+
ln('');
|
|
386
|
+
info('Add this to your .mcp.json manually:');
|
|
387
|
+
ln('');
|
|
388
|
+
const json = JSON.stringify(newConfig, null, 2);
|
|
389
|
+
json.split('\n').forEach(line => {
|
|
390
|
+
ln(` ${c.dim}${line}${c.reset}`);
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
// ── Done ──
|
|
394
|
+
ln('');
|
|
395
|
+
divider();
|
|
396
|
+
ln('');
|
|
397
|
+
ln(` ${c.greenBright}${c.bold}Setup complete!${c.reset} ${c.gray}🎉${c.reset}`);
|
|
398
|
+
ln('');
|
|
399
|
+
box([
|
|
400
|
+
`${c.bold}Next steps:${c.reset}`,
|
|
401
|
+
``,
|
|
402
|
+
`${c.cyanBright}1.${c.reset} Open Claude Code in any project`,
|
|
403
|
+
`${c.cyanBright}2.${c.reset} Type ${c.bold}/mcp${c.reset} to connect the Discord server`,
|
|
404
|
+
`${c.cyanBright}3.${c.reset} Ask Claude to manage your server!`,
|
|
405
|
+
``,
|
|
406
|
+
`${c.dim}Try: "List all channels in my Discord server"${c.reset}`,
|
|
407
|
+
], c.green);
|
|
408
|
+
ln('');
|
|
409
|
+
ln(` ${c.gray}Docs:${c.reset} ${c.underline}${c.blueBright}https://github.com/HardHeadHackerHead/discord-mcp${c.reset}`);
|
|
410
|
+
ln(` ${c.gray}Help:${c.reset} ${c.bold}discord-mcp check${c.reset} ${c.dim}— verify permissions${c.reset}`);
|
|
411
|
+
ln('');
|
|
412
|
+
ln(` ${c.dim}Made with ♥ by${c.reset} ${LOGO_MINI}`);
|
|
413
|
+
ln('');
|
|
414
|
+
}
|
|
415
|
+
finally {
|
|
416
|
+
rl.close();
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
// ── Check Command ────────────────────────────────────────────────────
|
|
420
|
+
async function runCheck() {
|
|
421
|
+
ln('');
|
|
422
|
+
ln(` ${LOGO_MINI} ${DISCORD_MCP_BADGE} ${c.dim}— Health Check${c.reset}`);
|
|
423
|
+
divider();
|
|
424
|
+
ln('');
|
|
425
|
+
// Load .env if present
|
|
426
|
+
const dotenv = await import('dotenv');
|
|
427
|
+
dotenv.config();
|
|
428
|
+
const token = process.env['DISCORD_TOKEN'] || process.env['BOT_TOKEN'];
|
|
429
|
+
const guildId = process.env['DISCORD_GUILD_ID'];
|
|
430
|
+
// Token check
|
|
431
|
+
out(` ${c.dim}Token ............${c.reset} `);
|
|
432
|
+
if (!token) {
|
|
433
|
+
ln(`${c.redBright}NOT SET${c.reset}`);
|
|
434
|
+
ln('');
|
|
435
|
+
error(`Set DISCORD_TOKEN or run ${c.bold}discord-mcp init${c.reset}`);
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
ln(`${c.greenBright}present${c.reset}`);
|
|
439
|
+
// Guild ID check
|
|
440
|
+
out(` ${c.dim}Guild ID .........${c.reset} `);
|
|
441
|
+
if (!guildId) {
|
|
442
|
+
ln(`${c.redBright}NOT SET${c.reset}`);
|
|
443
|
+
ln('');
|
|
444
|
+
error(`Set DISCORD_GUILD_ID or run ${c.bold}discord-mcp init${c.reset}`);
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
ln(`${c.dim}${guildId}${c.reset}`);
|
|
448
|
+
// Connect
|
|
449
|
+
const spinner = createSpinner('Connecting to Discord...');
|
|
450
|
+
const client = new Client({
|
|
451
|
+
intents: [
|
|
452
|
+
GatewayIntentBits.Guilds,
|
|
453
|
+
GatewayIntentBits.GuildMembers,
|
|
454
|
+
],
|
|
455
|
+
});
|
|
456
|
+
try {
|
|
457
|
+
await client.login(token);
|
|
458
|
+
await new Promise((resolve) => {
|
|
459
|
+
if (client.isReady())
|
|
460
|
+
return resolve();
|
|
461
|
+
client.once('ready', () => resolve());
|
|
462
|
+
});
|
|
463
|
+
spinner.stop();
|
|
464
|
+
out(` ${c.dim}Bot ..............${c.reset} `);
|
|
465
|
+
ln(`${c.greenBright}${client.user?.tag}${c.reset}`);
|
|
466
|
+
const guild = client.guilds.cache.get(guildId);
|
|
467
|
+
out(` ${c.dim}Server ...........${c.reset} `);
|
|
468
|
+
if (!guild) {
|
|
469
|
+
ln(`${c.redBright}NOT FOUND${c.reset}`);
|
|
470
|
+
ln('');
|
|
471
|
+
error(`Guild ${guildId} not accessible. Is the bot invited?`);
|
|
472
|
+
client.destroy();
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
ln(`${c.greenBright}${guild.name}${c.reset} ${c.dim}(${guild.memberCount} members)${c.reset}`);
|
|
476
|
+
// Permission audit
|
|
477
|
+
ln('');
|
|
478
|
+
ln(` ${c.bold}Permissions${c.reset}`);
|
|
479
|
+
divider();
|
|
480
|
+
ln('');
|
|
481
|
+
const botMember = guild.members.cache.get(client.user.id) || await guild.members.fetch(client.user.id);
|
|
482
|
+
const permissions = botMember.permissions;
|
|
483
|
+
let granted = 0;
|
|
484
|
+
let missing = 0;
|
|
485
|
+
for (const { flag, name } of REQUIRED_PERMISSIONS) {
|
|
486
|
+
const has = permissions.has(flag);
|
|
487
|
+
const dots = '.'.repeat(Math.max(1, 30 - name.length));
|
|
488
|
+
if (has) {
|
|
489
|
+
ln(` ${c.greenBright}✔${c.reset} ${name} ${c.dim}${dots}${c.reset} ${c.greenBright}yes${c.reset}`);
|
|
490
|
+
granted++;
|
|
491
|
+
}
|
|
492
|
+
else {
|
|
493
|
+
ln(` ${c.redBright}✖${c.reset} ${name} ${c.dim}${dots}${c.reset} ${c.redBright}MISSING${c.reset}`);
|
|
494
|
+
missing++;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
ln('');
|
|
498
|
+
divider();
|
|
499
|
+
ln('');
|
|
500
|
+
// Summary
|
|
501
|
+
const total = REQUIRED_PERMISSIONS.length;
|
|
502
|
+
const pct = Math.round((granted / total) * 100);
|
|
503
|
+
const barWidth = 30;
|
|
504
|
+
const filled = Math.round((granted / total) * barWidth);
|
|
505
|
+
const barColor = missing === 0 ? c.greenBright : missing <= 3 ? c.yellowBright : c.redBright;
|
|
506
|
+
const bar = `${barColor}${'█'.repeat(filled)}${c.gray}${'░'.repeat(barWidth - filled)}${c.reset}`;
|
|
507
|
+
ln(` ${bar} ${c.bold}${pct}%${c.reset} ${c.dim}(${granted}/${total})${c.reset}`);
|
|
508
|
+
ln('');
|
|
509
|
+
if (missing === 0) {
|
|
510
|
+
success(`All ${total} permissions granted`);
|
|
511
|
+
ln('');
|
|
512
|
+
box([
|
|
513
|
+
`${c.greenBright}${c.bold}MCP server is ready!${c.reset}`,
|
|
514
|
+
`Run ${c.bold}discord-mcp${c.reset} or use via ${c.bold}.mcp.json${c.reset} in Claude Code`,
|
|
515
|
+
], c.green);
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
warn(`${missing} permission${missing > 1 ? 's' : ''} missing`);
|
|
519
|
+
ln('');
|
|
520
|
+
bullet('Re-invite the bot with the correct permissions');
|
|
521
|
+
bullet(`Or update the bot's role in ${c.bold}${guild.name}${c.reset} > Server Settings > Roles`);
|
|
522
|
+
}
|
|
523
|
+
ln('');
|
|
524
|
+
client.destroy();
|
|
525
|
+
}
|
|
526
|
+
catch (err) {
|
|
527
|
+
spinner.stop();
|
|
528
|
+
error(`Connection failed: ${err.message}`);
|
|
529
|
+
ln('');
|
|
530
|
+
bullet('Check that your bot token is valid');
|
|
531
|
+
bullet('Ensure the bot has not been deleted');
|
|
532
|
+
ln('');
|
|
533
|
+
client.destroy();
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
// ── Version Command ──────────────────────────────────────────────────
|
|
537
|
+
function printVersion() {
|
|
538
|
+
const pkg = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
|
|
539
|
+
ln(`${LOGO_MINI} ${DISCORD_MCP_BADGE} ${c.dim}v${pkg.version}${c.reset}`);
|
|
540
|
+
}
|
|
541
|
+
// ── Help Command ─────────────────────────────────────────────────────
|
|
542
|
+
function printHelp() {
|
|
543
|
+
ln(LOGO);
|
|
544
|
+
ln(` ${c.bold}Discord MCP Server${c.reset} ${c.dim}— Manage Discord from Claude Code${c.reset}`);
|
|
545
|
+
ln(` ${c.dim}99 tools across 14 categories${c.reset}`);
|
|
546
|
+
ln('');
|
|
547
|
+
divider();
|
|
548
|
+
ln('');
|
|
549
|
+
ln(` ${c.bold}USAGE${c.reset}`);
|
|
550
|
+
ln('');
|
|
551
|
+
ln(` ${c.cyan}$${c.reset} discord-mcp ${c.dim}[command]${c.reset}`);
|
|
552
|
+
ln(` ${c.cyan}$${c.reset} npx @quadslab.io/discord-mcp ${c.dim}[command]${c.reset}`);
|
|
553
|
+
ln('');
|
|
554
|
+
ln(` ${c.bold}COMMANDS${c.reset}`);
|
|
555
|
+
ln('');
|
|
556
|
+
ln(` ${c.cyanBright}init${c.reset} Interactive setup wizard`);
|
|
557
|
+
ln(` ${c.cyanBright}check${c.reset} Health check & permission audit`);
|
|
558
|
+
ln(` ${c.cyanBright}start${c.reset} Start the MCP server ${c.dim}(default)${c.reset}`);
|
|
559
|
+
ln(` ${c.cyanBright}help${c.reset} Show this help message`);
|
|
560
|
+
ln(` ${c.cyanBright}version${c.reset} Show version`);
|
|
561
|
+
ln('');
|
|
562
|
+
ln(` ${c.bold}EXAMPLES${c.reset}`);
|
|
563
|
+
ln('');
|
|
564
|
+
ln(` ${c.dim}# First-time setup${c.reset}`);
|
|
565
|
+
ln(` ${c.cyan}$${c.reset} npx @quadslab.io/discord-mcp init`);
|
|
566
|
+
ln('');
|
|
567
|
+
ln(` ${c.dim}# Verify everything works${c.reset}`);
|
|
568
|
+
ln(` ${c.cyan}$${c.reset} npx @quadslab.io/discord-mcp check`);
|
|
569
|
+
ln('');
|
|
570
|
+
ln(` ${c.dim}# In .mcp.json (auto-detected)${c.reset}`);
|
|
571
|
+
ln(` ${c.cyan}$${c.reset} npx @quadslab.io/discord-mcp`);
|
|
572
|
+
ln('');
|
|
573
|
+
divider();
|
|
574
|
+
ln('');
|
|
575
|
+
ln(` ${c.dim}Docs${c.reset} ${c.underline}${c.blueBright}https://github.com/HardHeadHackerHead/discord-mcp${c.reset}`);
|
|
576
|
+
ln(` ${c.dim}npm${c.reset} ${c.underline}${c.blueBright}https://www.npmjs.com/package/@quadslab.io/discord-mcp${c.reset}`);
|
|
577
|
+
ln('');
|
|
578
|
+
ln(` ${c.dim}Made with ♥ by${c.reset} ${LOGO_MINI}`);
|
|
579
|
+
ln('');
|
|
580
|
+
}
|
|
581
|
+
// ── Start Command ────────────────────────────────────────────────────
|
|
582
|
+
async function runStart() {
|
|
583
|
+
const { main } = await import('./mcp-server.js');
|
|
584
|
+
await main();
|
|
585
|
+
}
|
|
586
|
+
// ── Main ─────────────────────────────────────────────────────────────
|
|
587
|
+
const subcommand = process.argv[2];
|
|
588
|
+
// If not a TTY (i.e., launched by MCP via stdio), always start the server
|
|
589
|
+
if (!process.stdin.isTTY && subcommand !== 'check' && subcommand !== 'help' && subcommand !== 'version' && subcommand !== '--version' && subcommand !== '-v' && subcommand !== '--help' && subcommand !== '-h') {
|
|
590
|
+
runStart();
|
|
591
|
+
}
|
|
592
|
+
else {
|
|
593
|
+
switch (subcommand) {
|
|
594
|
+
case 'init':
|
|
595
|
+
runInit();
|
|
596
|
+
break;
|
|
597
|
+
case 'check':
|
|
598
|
+
runCheck();
|
|
599
|
+
break;
|
|
600
|
+
case 'start':
|
|
601
|
+
case undefined:
|
|
602
|
+
runStart();
|
|
603
|
+
break;
|
|
604
|
+
case 'help':
|
|
605
|
+
case '--help':
|
|
606
|
+
case '-h':
|
|
607
|
+
printHelp();
|
|
608
|
+
break;
|
|
609
|
+
case 'version':
|
|
610
|
+
case '--version':
|
|
611
|
+
case '-v':
|
|
612
|
+
printVersion();
|
|
613
|
+
break;
|
|
614
|
+
default:
|
|
615
|
+
error(`Unknown command: ${subcommand}`);
|
|
616
|
+
ln('');
|
|
617
|
+
printHelp();
|
|
618
|
+
process.exit(1);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp-server.d.ts
CHANGED
package/dist/mcp-server.js
CHANGED
|
@@ -17,7 +17,7 @@ import dotenv from 'dotenv';
|
|
|
17
17
|
dotenv.config();
|
|
18
18
|
import { initializeClient, destroyClient, refreshServerCache } from './discord-client.js';
|
|
19
19
|
import { createMCPServer, startMCPServer } from './index.js';
|
|
20
|
-
async function main() {
|
|
20
|
+
export async function main() {
|
|
21
21
|
// Validate required environment variables
|
|
22
22
|
// Support both DISCORD_TOKEN and BOT_TOKEN (fallback)
|
|
23
23
|
const token = process.env['DISCORD_TOKEN'] || process.env['BOT_TOKEN'];
|
|
@@ -61,5 +61,9 @@ async function main() {
|
|
|
61
61
|
process.exit(1);
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
-
|
|
64
|
+
// Auto-run only when executed directly (not imported by cli.ts)
|
|
65
|
+
const isDirectRun = process.argv[1]?.replace(/\\/g, '/').endsWith('mcp-server.js');
|
|
66
|
+
if (isDirectRun) {
|
|
67
|
+
main();
|
|
68
|
+
}
|
|
65
69
|
//# sourceMappingURL=mcp-server.js.map
|
package/dist/mcp-server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,6BAA6B;AAC7B,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC1F,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE7D,KAAK,UAAU,IAAI;
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,6BAA6B;AAC7B,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC1F,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,0CAA0C;IAC1C,sDAAsD;IACtD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACvE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAEhD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,oEAAoE,CAAC,CAAC;QACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,kDAAkD;IAClD,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC;IAErC,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAChD,OAAO,CAAC,KAAK,CAAC,aAAa,OAAO,EAAE,CAAC,CAAC;IAEtC,IAAI,CAAC;QACH,4BAA4B;QAC5B,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,gBAAgB,EAAE,CAAC;QACxC,OAAO,CAAC,KAAK,CAAC,gBAAgB,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAElD,yCAAyC;QACzC,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACxC,MAAM,kBAAkB,EAAE,CAAC;QAE3B,8BAA8B;QAC9B,MAAM,SAAS,GAAG,eAAe,EAAE,CAAC;QACpC,MAAM,cAAc,CAAC,SAAS,CAAC,CAAC;QAEhC,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAEhD,2BAA2B;QAC3B,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE;YACxC,OAAO,CAAC,KAAK,CAAC,cAAc,MAAM,oBAAoB,CAAC,CAAC;YACxD,MAAM,aAAa,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC;QAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC/C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IAEnD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;QACpD,MAAM,aAAa,EAAE,CAAC;QACtB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,gEAAgE;AAChE,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;AACnF,IAAI,WAAW,EAAE,CAAC;IAChB,IAAI,EAAE,CAAC;AACT,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quadslab.io/discord-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Full Discord server administration through Claude Code via MCP. 99 tools across 14 categories covering roles, channels, members, messages, moderation, forums, stages, webhooks, events, and more.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/mcp-server.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"discord-mcp": "dist/
|
|
8
|
+
"discord-mcp": "dist/cli.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build": "tsc",
|
|
12
|
-
"start": "node dist/
|
|
13
|
-
"dev": "npx tsx src/
|
|
12
|
+
"start": "node dist/cli.js",
|
|
13
|
+
"dev": "npx tsx src/cli.ts"
|
|
14
14
|
},
|
|
15
15
|
"keywords": [
|
|
16
16
|
"discord",
|