@quadslab.io/discord-mcp 1.0.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.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +474 -0
  3. package/dist/discord-client.d.ts +57 -0
  4. package/dist/discord-client.js +188 -0
  5. package/dist/discord-client.js.map +1 -0
  6. package/dist/index.d.ts +9 -0
  7. package/dist/index.js +135 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/mcp-server.d.ts +15 -0
  10. package/dist/mcp-server.js +65 -0
  11. package/dist/mcp-server.js.map +1 -0
  12. package/dist/tools/automod.d.ts +6 -0
  13. package/dist/tools/automod.js +376 -0
  14. package/dist/tools/automod.js.map +1 -0
  15. package/dist/tools/channels.d.ts +6 -0
  16. package/dist/tools/channels.js +840 -0
  17. package/dist/tools/channels.js.map +1 -0
  18. package/dist/tools/emojis.d.ts +6 -0
  19. package/dist/tools/emojis.js +295 -0
  20. package/dist/tools/emojis.js.map +1 -0
  21. package/dist/tools/events.d.ts +6 -0
  22. package/dist/tools/events.js +304 -0
  23. package/dist/tools/events.js.map +1 -0
  24. package/dist/tools/forums.d.ts +6 -0
  25. package/dist/tools/forums.js +276 -0
  26. package/dist/tools/forums.js.map +1 -0
  27. package/dist/tools/guild.d.ts +6 -0
  28. package/dist/tools/guild.js +88 -0
  29. package/dist/tools/guild.js.map +1 -0
  30. package/dist/tools/index.d.ts +13 -0
  31. package/dist/tools/index.js +142 -0
  32. package/dist/tools/index.js.map +1 -0
  33. package/dist/tools/members.d.ts +6 -0
  34. package/dist/tools/members.js +628 -0
  35. package/dist/tools/members.js.map +1 -0
  36. package/dist/tools/messages.d.ts +6 -0
  37. package/dist/tools/messages.js +688 -0
  38. package/dist/tools/messages.js.map +1 -0
  39. package/dist/tools/reactions.d.ts +6 -0
  40. package/dist/tools/reactions.js +137 -0
  41. package/dist/tools/reactions.js.map +1 -0
  42. package/dist/tools/roles.d.ts +6 -0
  43. package/dist/tools/roles.js +469 -0
  44. package/dist/tools/roles.js.map +1 -0
  45. package/dist/tools/server.d.ts +6 -0
  46. package/dist/tools/server.js +607 -0
  47. package/dist/tools/server.js.map +1 -0
  48. package/dist/tools/stage.d.ts +6 -0
  49. package/dist/tools/stage.js +153 -0
  50. package/dist/tools/stage.js.map +1 -0
  51. package/dist/tools/threads.d.ts +6 -0
  52. package/dist/tools/threads.js +331 -0
  53. package/dist/tools/threads.js.map +1 -0
  54. package/dist/tools/utils.d.ts +21 -0
  55. package/dist/tools/utils.js +315 -0
  56. package/dist/tools/utils.js.map +1 -0
  57. package/dist/tools/webhooks.d.ts +6 -0
  58. package/dist/tools/webhooks.js +195 -0
  59. package/dist/tools/webhooks.js.map +1 -0
  60. package/package.json +48 -0
@@ -0,0 +1,188 @@
1
+ import { Client, GatewayIntentBits, Partials, ChannelType } from 'discord.js';
2
+ let client = null;
3
+ let guildId = null;
4
+ let serverCache = null;
5
+ /**
6
+ * Initialize the Discord client for MCP server
7
+ * Uses minimal intents needed for server management
8
+ */
9
+ export async function initializeClient() {
10
+ const token = process.env['DISCORD_TOKEN'];
11
+ guildId = process.env['DISCORD_GUILD_ID'] || null;
12
+ if (!token) {
13
+ throw new Error('DISCORD_TOKEN environment variable is required');
14
+ }
15
+ if (!guildId) {
16
+ throw new Error('DISCORD_GUILD_ID environment variable is required');
17
+ }
18
+ client = new Client({
19
+ intents: [
20
+ GatewayIntentBits.Guilds,
21
+ GatewayIntentBits.GuildMembers,
22
+ GatewayIntentBits.GuildMessages,
23
+ GatewayIntentBits.GuildModeration,
24
+ GatewayIntentBits.MessageContent,
25
+ GatewayIntentBits.GuildMessageReactions,
26
+ GatewayIntentBits.GuildScheduledEvents,
27
+ GatewayIntentBits.AutoModerationConfiguration,
28
+ GatewayIntentBits.GuildWebhooks,
29
+ GatewayIntentBits.GuildInvites,
30
+ ],
31
+ partials: [
32
+ Partials.Message,
33
+ Partials.Channel,
34
+ Partials.GuildMember,
35
+ Partials.Reaction,
36
+ ],
37
+ });
38
+ await client.login(token);
39
+ // Wait for client to be ready
40
+ await new Promise((resolve) => {
41
+ if (client.isReady()) {
42
+ resolve();
43
+ }
44
+ else {
45
+ client.once('ready', () => resolve());
46
+ }
47
+ });
48
+ return client;
49
+ }
50
+ /**
51
+ * Get the Discord client instance
52
+ */
53
+ export function getClient() {
54
+ if (!client) {
55
+ throw new Error('Discord client not initialized. Call initializeClient() first.');
56
+ }
57
+ return client;
58
+ }
59
+ /**
60
+ * Get the configured guild ID
61
+ */
62
+ export function getGuildId() {
63
+ if (!guildId) {
64
+ throw new Error('Guild ID not configured. Set DISCORD_GUILD_ID environment variable.');
65
+ }
66
+ return guildId;
67
+ }
68
+ /**
69
+ * Get the configured guild
70
+ */
71
+ export async function getGuild() {
72
+ const guild = getClient().guilds.cache.get(getGuildId());
73
+ if (!guild) {
74
+ throw new Error(`Bot is not in guild ${getGuildId()}`);
75
+ }
76
+ return guild;
77
+ }
78
+ /**
79
+ * Destroy the Discord client connection
80
+ */
81
+ export async function destroyClient() {
82
+ if (client) {
83
+ client.destroy();
84
+ client = null;
85
+ }
86
+ serverCache = null;
87
+ }
88
+ /**
89
+ * Get channel type as string
90
+ */
91
+ function getChannelTypeName(type) {
92
+ switch (type) {
93
+ case ChannelType.GuildText: return 'text';
94
+ case ChannelType.GuildVoice: return 'voice';
95
+ case ChannelType.GuildCategory: return 'category';
96
+ case ChannelType.GuildAnnouncement: return 'announcement';
97
+ case ChannelType.GuildStageVoice: return 'stage';
98
+ case ChannelType.GuildForum: return 'forum';
99
+ default: return 'unknown';
100
+ }
101
+ }
102
+ /**
103
+ * Refresh the server cache with current data
104
+ * Called on startup and can be called to refresh
105
+ */
106
+ export async function refreshServerCache() {
107
+ const guild = await getGuild();
108
+ // Fetch all members
109
+ await guild.members.fetch();
110
+ // Build channel cache
111
+ const channels = [...guild.channels.cache.values()].map(c => {
112
+ const parent = c.parentId ? guild.channels.cache.get(c.parentId) : null;
113
+ return {
114
+ id: c.id,
115
+ name: c.name,
116
+ type: getChannelTypeName(c.type),
117
+ categoryId: c.parentId,
118
+ categoryName: parent?.name ?? null,
119
+ };
120
+ });
121
+ // Build role cache (exclude @everyone)
122
+ const roles = [...guild.roles.cache.values()]
123
+ .filter(r => r.id !== guild.id)
124
+ .sort((a, b) => b.position - a.position)
125
+ .map(r => ({
126
+ id: r.id,
127
+ name: r.name,
128
+ color: r.hexColor,
129
+ position: r.position,
130
+ }));
131
+ // Build member cache (exclude bots for simpler list)
132
+ const members = [...guild.members.cache.values()]
133
+ .filter(m => !m.user.bot)
134
+ .map(m => ({
135
+ id: m.id,
136
+ username: m.user.username,
137
+ displayName: m.displayName,
138
+ nickname: m.nickname,
139
+ }));
140
+ serverCache = {
141
+ channels,
142
+ roles,
143
+ members,
144
+ lastUpdated: new Date(),
145
+ };
146
+ console.error(`Server cache refreshed: ${channels.length} channels, ${roles.length} roles, ${members.length} members`);
147
+ return serverCache;
148
+ }
149
+ /**
150
+ * Get the server cache (refreshes if not initialized)
151
+ */
152
+ export async function getServerCache() {
153
+ if (!serverCache) {
154
+ return refreshServerCache();
155
+ }
156
+ return serverCache;
157
+ }
158
+ /**
159
+ * Get a summary of the server for context
160
+ */
161
+ export async function getServerSummary() {
162
+ const cache = await getServerCache();
163
+ const guild = await getGuild();
164
+ const textChannels = cache.channels.filter(c => c.type === 'text' || c.type === 'announcement');
165
+ const voiceChannels = cache.channels.filter(c => c.type === 'voice' || c.type === 'stage');
166
+ let summary = `# Discord Server: ${guild.name}\n\n`;
167
+ summary += `## Text Channels (${textChannels.length})\n`;
168
+ for (const ch of textChannels) {
169
+ const category = ch.categoryName ? ` (in ${ch.categoryName})` : '';
170
+ summary += `- #${ch.name}${category}\n`;
171
+ }
172
+ summary += `\n## Voice Channels (${voiceChannels.length})\n`;
173
+ for (const ch of voiceChannels) {
174
+ const category = ch.categoryName ? ` (in ${ch.categoryName})` : '';
175
+ summary += `- 🔊 ${ch.name}${category}\n`;
176
+ }
177
+ summary += `\n## Roles (${cache.roles.length})\n`;
178
+ for (const role of cache.roles.slice(0, 20)) { // Limit to top 20 roles
179
+ summary += `- @${role.name}\n`;
180
+ }
181
+ if (cache.roles.length > 20) {
182
+ summary += `- ... and ${cache.roles.length - 20} more\n`;
183
+ }
184
+ summary += `\n## Members (${cache.members.length} non-bot members)\n`;
185
+ summary += `Use list_members tool to see full member list.\n`;
186
+ return summary;
187
+ }
188
+ //# sourceMappingURL=discord-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discord-client.js","sourceRoot":"","sources":["../src/discord-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9E,IAAI,MAAM,GAAkB,IAAI,CAAC;AACjC,IAAI,OAAO,GAAkB,IAAI,CAAC;AAUlC,IAAI,WAAW,GAAuB,IAAI,CAAC;AAE3C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC3C,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,IAAI,CAAC;IAElD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,GAAG,IAAI,MAAM,CAAC;QAClB,OAAO,EAAE;YACP,iBAAiB,CAAC,MAAM;YACxB,iBAAiB,CAAC,YAAY;YAC9B,iBAAiB,CAAC,aAAa;YAC/B,iBAAiB,CAAC,eAAe;YACjC,iBAAiB,CAAC,cAAc;YAChC,iBAAiB,CAAC,qBAAqB;YACvC,iBAAiB,CAAC,oBAAoB;YACtC,iBAAiB,CAAC,2BAA2B;YAC7C,iBAAiB,CAAC,aAAa;YAC/B,iBAAiB,CAAC,YAAY;SAC/B;QACD,QAAQ,EAAE;YACR,QAAQ,CAAC,OAAO;YAChB,QAAQ,CAAC,OAAO;YAChB,QAAQ,CAAC,WAAW;YACpB,QAAQ,CAAC,QAAQ;SAClB;KACF,CAAC,CAAC;IAEH,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAE1B,8BAA8B;IAC9B,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,IAAI,MAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YACtB,OAAO,EAAE,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,MAAO,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;IACpF,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;IACzD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,uBAAuB,UAAU,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,IAAiB;IAC3C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,WAAW,CAAC,SAAS,CAAC,CAAC,OAAO,MAAM,CAAC;QAC1C,KAAK,WAAW,CAAC,UAAU,CAAC,CAAC,OAAO,OAAO,CAAC;QAC5C,KAAK,WAAW,CAAC,aAAa,CAAC,CAAC,OAAO,UAAU,CAAC;QAClD,KAAK,WAAW,CAAC,iBAAiB,CAAC,CAAC,OAAO,cAAc,CAAC;QAC1D,KAAK,WAAW,CAAC,eAAe,CAAC,CAAC,OAAO,OAAO,CAAC;QACjD,KAAK,WAAW,CAAC,UAAU,CAAC,CAAC,OAAO,OAAO,CAAC;QAC5C,OAAO,CAAC,CAAC,OAAO,SAAS,CAAC;IAC5B,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;IAE/B,oBAAoB;IACpB,MAAM,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IAE5B,sBAAsB;IACtB,MAAM,QAAQ,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QAC1D,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACxE,OAAO;YACL,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,IAAI,EAAE,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC;YAChC,UAAU,EAAE,CAAC,CAAC,QAAQ;YACtB,YAAY,EAAE,MAAM,EAAE,IAAI,IAAI,IAAI;SACnC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,uCAAuC;IACvC,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;SAC1C,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC;SAC9B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC;SACvC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACT,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,KAAK,EAAE,CAAC,CAAC,QAAQ;QACjB,QAAQ,EAAE,CAAC,CAAC,QAAQ;KACrB,CAAC,CAAC,CAAC;IAEN,qDAAqD;IACrD,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;SAC9C,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;SACxB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACT,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ;QACzB,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ;KACrB,CAAC,CAAC,CAAC;IAEN,WAAW,GAAG;QACZ,QAAQ;QACR,KAAK;QACL,OAAO;QACP,WAAW,EAAE,IAAI,IAAI,EAAE;KACxB,CAAC;IAEF,OAAO,CAAC,KAAK,CAAC,2BAA2B,QAAQ,CAAC,MAAM,cAAc,KAAK,CAAC,MAAM,WAAW,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;IAEvH,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,kBAAkB,EAAE,CAAC;IAC9B,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,KAAK,GAAG,MAAM,cAAc,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;IAE/B,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;IAChG,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;IAE3F,IAAI,OAAO,GAAG,qBAAqB,KAAK,CAAC,IAAI,MAAM,CAAC;IAEpD,OAAO,IAAI,qBAAqB,YAAY,CAAC,MAAM,KAAK,CAAC;IACzD,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,OAAO,IAAI,MAAM,EAAE,CAAC,IAAI,GAAG,QAAQ,IAAI,CAAC;IAC1C,CAAC;IAED,OAAO,IAAI,wBAAwB,aAAa,CAAC,MAAM,KAAK,CAAC;IAC7D,KAAK,MAAM,EAAE,IAAI,aAAa,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,OAAO,IAAI,QAAQ,EAAE,CAAC,IAAI,GAAG,QAAQ,IAAI,CAAC;IAC5C,CAAC;IAED,OAAO,IAAI,eAAe,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;IAClD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,wBAAwB;QACrE,OAAO,IAAI,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC;IACjC,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QAC5B,OAAO,IAAI,aAAa,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE,SAAS,CAAC;IAC3D,CAAC;IAED,OAAO,IAAI,iBAAiB,KAAK,CAAC,OAAO,CAAC,MAAM,qBAAqB,CAAC;IACtE,OAAO,IAAI,kDAAkD,CAAC;IAE9D,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ /**
3
+ * Create and configure the MCP server for Discord management
4
+ */
5
+ export declare function createMCPServer(): Server;
6
+ /**
7
+ * Start the MCP server with stdio transport
8
+ */
9
+ export declare function startMCPServer(server: Server): Promise<void>;
package/dist/index.js ADDED
@@ -0,0 +1,135 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
4
+ import { allTools, executeTool } from './tools/index.js';
5
+ import { getServerSummary, getServerCache } from './discord-client.js';
6
+ /**
7
+ * Create and configure the MCP server for Discord management
8
+ */
9
+ export function createMCPServer() {
10
+ const server = new Server({
11
+ name: 'discord-server',
12
+ version: '1.0.0',
13
+ }, {
14
+ capabilities: {
15
+ tools: {},
16
+ resources: {},
17
+ },
18
+ });
19
+ // Handle list tools request
20
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
21
+ return {
22
+ tools: allTools,
23
+ };
24
+ });
25
+ // Handle list resources request
26
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
27
+ return {
28
+ resources: [
29
+ {
30
+ uri: 'discord://server/summary',
31
+ name: 'Discord Server Summary',
32
+ description: 'Overview of the Discord server including all channels, roles, and member count. Use this to see available channels before sending messages.',
33
+ mimeType: 'text/plain',
34
+ },
35
+ {
36
+ uri: 'discord://server/channels',
37
+ name: 'Channel List',
38
+ description: 'List of all channels in the Discord server with their exact names',
39
+ mimeType: 'application/json',
40
+ },
41
+ {
42
+ uri: 'discord://server/roles',
43
+ name: 'Role List',
44
+ description: 'List of all roles in the Discord server',
45
+ mimeType: 'application/json',
46
+ },
47
+ ],
48
+ };
49
+ });
50
+ // Handle read resource request
51
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
52
+ const { uri } = request.params;
53
+ switch (uri) {
54
+ case 'discord://server/summary': {
55
+ const summary = await getServerSummary();
56
+ return {
57
+ contents: [
58
+ {
59
+ uri,
60
+ mimeType: 'text/plain',
61
+ text: summary,
62
+ },
63
+ ],
64
+ };
65
+ }
66
+ case 'discord://server/channels': {
67
+ const cache = await getServerCache();
68
+ return {
69
+ contents: [
70
+ {
71
+ uri,
72
+ mimeType: 'application/json',
73
+ text: JSON.stringify(cache.channels, null, 2),
74
+ },
75
+ ],
76
+ };
77
+ }
78
+ case 'discord://server/roles': {
79
+ const cache = await getServerCache();
80
+ return {
81
+ contents: [
82
+ {
83
+ uri,
84
+ mimeType: 'application/json',
85
+ text: JSON.stringify(cache.roles, null, 2),
86
+ },
87
+ ],
88
+ };
89
+ }
90
+ default:
91
+ throw new Error(`Unknown resource: ${uri}`);
92
+ }
93
+ });
94
+ // Handle tool execution requests
95
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
96
+ const { name, arguments: args } = request.params;
97
+ try {
98
+ const result = await executeTool(name, args ?? {});
99
+ return {
100
+ content: [
101
+ {
102
+ type: 'text',
103
+ text: result,
104
+ },
105
+ ],
106
+ };
107
+ }
108
+ catch (error) {
109
+ const errorMessage = error instanceof Error ? error.message : String(error);
110
+ return {
111
+ content: [
112
+ {
113
+ type: 'text',
114
+ text: JSON.stringify({
115
+ success: false,
116
+ error: errorMessage,
117
+ }, null, 2),
118
+ },
119
+ ],
120
+ isError: true,
121
+ };
122
+ }
123
+ });
124
+ return server;
125
+ }
126
+ /**
127
+ * Start the MCP server with stdio transport
128
+ */
129
+ export async function startMCPServer(server) {
130
+ const transport = new StdioServerTransport();
131
+ await server.connect(transport);
132
+ // Log to stderr since stdout is used for MCP communication
133
+ console.error('Discord MCP server started');
134
+ }
135
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP Server Entry Point for Discord Server Management
4
+ *
5
+ * This is a standalone entry point that starts an MCP server
6
+ * for managing Discord servers via Claude Code.
7
+ *
8
+ * Usage:
9
+ * node dist/mcp-server.js
10
+ *
11
+ * Required environment variables:
12
+ * DISCORD_TOKEN - Your Discord bot token
13
+ * DISCORD_GUILD_ID - The ID of the Discord server to manage
14
+ */
15
+ export {};
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP Server Entry Point for Discord Server Management
4
+ *
5
+ * This is a standalone entry point that starts an MCP server
6
+ * for managing Discord servers via Claude Code.
7
+ *
8
+ * Usage:
9
+ * node dist/mcp-server.js
10
+ *
11
+ * Required environment variables:
12
+ * DISCORD_TOKEN - Your Discord bot token
13
+ * DISCORD_GUILD_ID - The ID of the Discord server to manage
14
+ */
15
+ import dotenv from 'dotenv';
16
+ // Load environment variables
17
+ dotenv.config();
18
+ import { initializeClient, destroyClient, refreshServerCache } from './discord-client.js';
19
+ import { createMCPServer, startMCPServer } from './index.js';
20
+ async function main() {
21
+ // Validate required environment variables
22
+ // Support both DISCORD_TOKEN and BOT_TOKEN (fallback)
23
+ const token = process.env['DISCORD_TOKEN'] || process.env['BOT_TOKEN'];
24
+ const guildId = process.env['DISCORD_GUILD_ID'];
25
+ if (!token) {
26
+ console.error('Error: DISCORD_TOKEN or BOT_TOKEN environment variable is required');
27
+ process.exit(1);
28
+ }
29
+ if (!guildId) {
30
+ console.error('Error: DISCORD_GUILD_ID environment variable is required');
31
+ process.exit(1);
32
+ }
33
+ // Set DISCORD_TOKEN for the discord-client module
34
+ process.env['DISCORD_TOKEN'] = token;
35
+ console.error('Starting Discord MCP server...');
36
+ console.error(`Guild ID: ${guildId}`);
37
+ try {
38
+ // Initialize Discord client
39
+ console.error('Connecting to Discord...');
40
+ const client = await initializeClient();
41
+ console.error(`Logged in as ${client.user?.tag}`);
42
+ // Pre-cache server data for fast lookups
43
+ console.error('Caching server data...');
44
+ await refreshServerCache();
45
+ // Create and start MCP server
46
+ const mcpServer = createMCPServer();
47
+ await startMCPServer(mcpServer);
48
+ console.error('MCP server ready and listening');
49
+ // Handle graceful shutdown
50
+ const shutdown = async (signal) => {
51
+ console.error(`\nReceived ${signal}, shutting down...`);
52
+ await destroyClient();
53
+ process.exit(0);
54
+ };
55
+ process.on('SIGINT', () => shutdown('SIGINT'));
56
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
57
+ }
58
+ catch (error) {
59
+ console.error('Failed to start MCP server:', error);
60
+ await destroyClient();
61
+ process.exit(1);
62
+ }
63
+ }
64
+ main();
65
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +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;IACjB,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,IAAI,EAAE,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { Tool } from '@modelcontextprotocol/sdk/types.js';
2
+ /**
3
+ * Auto-moderation tools for managing Discord AutoMod rules
4
+ */
5
+ export declare const automodTools: Tool[];
6
+ export declare function executeAutomodTool(name: string, args: Record<string, unknown>): Promise<string>;