@mahesvara/discord-mcpserver 1.0.7 → 1.0.9

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 (54) hide show
  1. package/dist/index.js +7 -2835
  2. package/dist/schemas/channel.d.ts +158 -0
  3. package/dist/schemas/channel.js +128 -0
  4. package/dist/schemas/common.d.ts +23 -0
  5. package/dist/schemas/common.js +71 -0
  6. package/dist/schemas/community.d.ts +181 -0
  7. package/dist/schemas/community.js +60 -0
  8. package/dist/schemas/emoji.d.ts +59 -0
  9. package/dist/schemas/emoji.js +29 -0
  10. package/dist/schemas/event.d.ts +62 -0
  11. package/dist/schemas/event.js +33 -0
  12. package/dist/schemas/guild.d.ts +85 -0
  13. package/dist/schemas/guild.js +42 -0
  14. package/dist/schemas/index.d.ts +12 -855
  15. package/dist/schemas/index.js +13 -617
  16. package/dist/schemas/invite.d.ts +40 -0
  17. package/dist/schemas/invite.js +32 -0
  18. package/dist/schemas/member.d.ts +60 -0
  19. package/dist/schemas/member.js +33 -0
  20. package/dist/schemas/message.d.ts +121 -0
  21. package/dist/schemas/message.js +61 -0
  22. package/dist/schemas/moderation.d.ts +343 -0
  23. package/dist/schemas/moderation.js +152 -0
  24. package/dist/schemas/role.d.ts +126 -0
  25. package/dist/schemas/role.js +73 -0
  26. package/dist/schemas/webhook.d.ts +51 -0
  27. package/dist/schemas/webhook.js +33 -0
  28. package/dist/server.d.ts +2 -0
  29. package/dist/server.js +6 -0
  30. package/dist/tools/channel.d.ts +2 -0
  31. package/dist/tools/channel.js +510 -0
  32. package/dist/tools/community.d.ts +2 -0
  33. package/dist/tools/community.js +259 -0
  34. package/dist/tools/emoji.d.ts +2 -0
  35. package/dist/tools/emoji.js +247 -0
  36. package/dist/tools/event.d.ts +2 -0
  37. package/dist/tools/event.js +170 -0
  38. package/dist/tools/guild.d.ts +2 -0
  39. package/dist/tools/guild.js +198 -0
  40. package/dist/tools/index.d.ts +2 -0
  41. package/dist/tools/index.js +24 -0
  42. package/dist/tools/invite.d.ts +2 -0
  43. package/dist/tools/invite.js +143 -0
  44. package/dist/tools/member.d.ts +2 -0
  45. package/dist/tools/member.js +200 -0
  46. package/dist/tools/message.d.ts +2 -0
  47. package/dist/tools/message.js +386 -0
  48. package/dist/tools/moderation.d.ts +2 -0
  49. package/dist/tools/moderation.js +641 -0
  50. package/dist/tools/role.d.ts +2 -0
  51. package/dist/tools/role.js +420 -0
  52. package/dist/tools/webhook.d.ts +2 -0
  53. package/dist/tools/webhook.js +199 -0
  54. package/package.json +1 -1
@@ -0,0 +1,259 @@
1
+ import { GetWelcomeScreenSchema, EditWelcomeScreenSchema, GetOnboardingSchema, EditOnboardingSchema, } from "../schemas/index.js";
2
+ import { getClient, formatResponse, } from "../services/discord.js";
3
+ export function registerCommunityTools(server) {
4
+ // ============================================================================
5
+ // WELCOME SCREEN TOOLS
6
+ // ============================================================================
7
+ server.registerTool("discord_get_welcome_screen", {
8
+ title: "Get Welcome Screen",
9
+ description: `Get the welcome screen configuration for a server.
10
+
11
+ Requires the server to have Community features enabled.
12
+
13
+ Args:
14
+ - guild_id (string): Discord server/guild ID
15
+ - response_format ('markdown' | 'json'): Output format (default: 'json')
16
+
17
+ Returns:
18
+ Welcome screen settings including description and channels`,
19
+ inputSchema: GetWelcomeScreenSchema,
20
+ annotations: {
21
+ readOnlyHint: true,
22
+ destructiveHint: false,
23
+ idempotentHint: true,
24
+ openWorldHint: true,
25
+ },
26
+ }, async (params) => {
27
+ try {
28
+ const client = await getClient();
29
+ const guild = client.guilds.cache.get(params.guild_id);
30
+ if (!guild) {
31
+ return {
32
+ isError: true,
33
+ content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
34
+ };
35
+ }
36
+ const welcomeScreen = await guild.fetchWelcomeScreen();
37
+ const result = {
38
+ enabled: welcomeScreen.enabled,
39
+ description: welcomeScreen.description,
40
+ channels: welcomeScreen.welcomeChannels.map(ch => ({
41
+ channelId: ch.channelId,
42
+ description: ch.description,
43
+ emoji: ch.emoji ? { id: ch.emoji.id, name: ch.emoji.name } : null,
44
+ })),
45
+ };
46
+ const text = formatResponse(result, params.response_format, (data) => `**Welcome Screen**\nEnabled: ${data.enabled}\nDescription: ${data.description || 'None'}\n\n**Channels:**\n${data.channels.map(ch => `- <#${ch.channelId}>: ${ch.description} ${ch.emoji?.name || ''}`).join('\n')}`);
47
+ return {
48
+ content: [{ type: "text", text }],
49
+ };
50
+ }
51
+ catch (error) {
52
+ return {
53
+ isError: true,
54
+ content: [{ type: "text", text: `Error getting welcome screen: ${error.message}` }],
55
+ };
56
+ }
57
+ });
58
+ server.registerTool("discord_edit_welcome_screen", {
59
+ title: "Edit Welcome Screen",
60
+ description: `Edit the welcome screen configuration for a server.
61
+
62
+ Requires the server to have Community features enabled and bot must have MANAGE_GUILD permission.
63
+
64
+ Args:
65
+ - guild_id (string): Discord server/guild ID
66
+ - enabled (boolean, optional): Enable/disable the welcome screen
67
+ - description (string, optional): Server description (max 140 chars)
68
+ - welcome_channels (array, optional): Up to 5 channels to show (channel_id, description, emoji)
69
+
70
+ Returns:
71
+ Updated welcome screen settings`,
72
+ inputSchema: EditWelcomeScreenSchema,
73
+ annotations: {
74
+ readOnlyHint: false,
75
+ destructiveHint: false,
76
+ idempotentHint: true,
77
+ openWorldHint: true,
78
+ },
79
+ }, async (params) => {
80
+ try {
81
+ const client = await getClient();
82
+ const guild = client.guilds.cache.get(params.guild_id);
83
+ if (!guild) {
84
+ return {
85
+ isError: true,
86
+ content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
87
+ };
88
+ }
89
+ const updateData = {};
90
+ if (params.enabled !== undefined)
91
+ updateData.enabled = params.enabled;
92
+ if (params.description !== undefined)
93
+ updateData.description = params.description;
94
+ if (params.welcome_channels !== undefined) {
95
+ updateData.welcomeChannels = params.welcome_channels.map(ch => ({
96
+ channel: ch.channel_id,
97
+ description: ch.description,
98
+ emoji: ch.emoji_id ? { id: ch.emoji_id, name: ch.emoji_name } : ch.emoji_name ? { name: ch.emoji_name } : undefined,
99
+ }));
100
+ }
101
+ const welcomeScreen = await guild.editWelcomeScreen(updateData);
102
+ return {
103
+ content: [{ type: "text", text: `Welcome screen updated. Enabled: ${welcomeScreen.enabled}, Channels: ${welcomeScreen.welcomeChannels.size}` }],
104
+ };
105
+ }
106
+ catch (error) {
107
+ return {
108
+ isError: true,
109
+ content: [{ type: "text", text: `Error editing welcome screen: ${error.message}` }],
110
+ };
111
+ }
112
+ });
113
+ // ============================================================================
114
+ // ONBOARDING TOOLS
115
+ // ============================================================================
116
+ server.registerTool("discord_get_onboarding", {
117
+ title: "Get Server Onboarding",
118
+ description: `Get the onboarding configuration for a server.
119
+
120
+ Onboarding guides new members through a questionnaire to customize their experience.
121
+
122
+ Args:
123
+ - guild_id (string): Discord server/guild ID
124
+ - response_format ('markdown' | 'json'): Output format (default: 'json')
125
+
126
+ Returns:
127
+ Onboarding settings including prompts, options, and default channels`,
128
+ inputSchema: GetOnboardingSchema,
129
+ annotations: {
130
+ readOnlyHint: true,
131
+ destructiveHint: false,
132
+ idempotentHint: true,
133
+ openWorldHint: true,
134
+ },
135
+ }, async (params) => {
136
+ try {
137
+ const client = await getClient();
138
+ const guild = client.guilds.cache.get(params.guild_id);
139
+ if (!guild) {
140
+ return {
141
+ isError: true,
142
+ content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
143
+ };
144
+ }
145
+ const onboarding = await guild.fetchOnboarding();
146
+ const result = {
147
+ enabled: onboarding.enabled,
148
+ mode: onboarding.mode,
149
+ defaultChannelIds: onboarding.defaultChannels.map(c => c.id),
150
+ prompts: onboarding.prompts.map(p => ({
151
+ id: p.id,
152
+ type: p.type,
153
+ title: p.title,
154
+ singleSelect: p.singleSelect,
155
+ required: p.required,
156
+ inOnboarding: p.inOnboarding,
157
+ options: p.options.map(o => ({
158
+ id: o.id,
159
+ title: o.title,
160
+ description: o.description,
161
+ emoji: o.emoji ? { id: o.emoji.id, name: o.emoji.name } : null,
162
+ roleIds: o.roles.map(r => r.id),
163
+ channelIds: o.channels.map(c => c.id),
164
+ })),
165
+ })),
166
+ };
167
+ const text = formatResponse(result, params.response_format, (data) => {
168
+ let output = `**Server Onboarding**\nEnabled: ${data.enabled}\nMode: ${data.mode}\nDefault Channels: ${data.defaultChannelIds.length}\n\n**Prompts:**\n`;
169
+ data.prompts.forEach((p, i) => {
170
+ output += `\n${i + 1}. **${p.title}** (${p.type})\n`;
171
+ output += ` Required: ${p.required}, Single Select: ${p.singleSelect}\n`;
172
+ output += ` Options: ${p.options.map((o) => o.title).join(', ')}\n`;
173
+ });
174
+ return output;
175
+ });
176
+ return {
177
+ content: [{ type: "text", text }],
178
+ };
179
+ }
180
+ catch (error) {
181
+ return {
182
+ isError: true,
183
+ content: [{ type: "text", text: `Error getting onboarding: ${error.message}` }],
184
+ };
185
+ }
186
+ });
187
+ server.registerTool("discord_edit_onboarding", {
188
+ title: "Edit Server Onboarding",
189
+ description: `Edit the onboarding configuration for a server.
190
+
191
+ Configure prompts/questions that new members answer to customize their server experience.
192
+ Each prompt can assign roles or show channels based on member selections.
193
+
194
+ Args:
195
+ - guild_id (string): Discord server/guild ID
196
+ - prompts (array, optional): Onboarding prompts with options
197
+ - default_channel_ids (array, optional): Channels shown to all new members
198
+ - enabled (boolean, optional): Enable/disable onboarding
199
+ - mode ('onboarding_default' | 'onboarding_advanced', optional): Onboarding mode
200
+
201
+ Returns:
202
+ Updated onboarding configuration`,
203
+ inputSchema: EditOnboardingSchema,
204
+ annotations: {
205
+ readOnlyHint: false,
206
+ destructiveHint: false,
207
+ idempotentHint: true,
208
+ openWorldHint: true,
209
+ },
210
+ }, async (params) => {
211
+ try {
212
+ const client = await getClient();
213
+ const guild = client.guilds.cache.get(params.guild_id);
214
+ if (!guild) {
215
+ return {
216
+ isError: true,
217
+ content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
218
+ };
219
+ }
220
+ const promptTypeMap = { multiple_choice: 0, dropdown: 1 };
221
+ const modeMap = { onboarding_default: 0, onboarding_advanced: 1 };
222
+ const updateData = {};
223
+ if (params.enabled !== undefined)
224
+ updateData.enabled = params.enabled;
225
+ if (params.default_channel_ids !== undefined)
226
+ updateData.defaultChannelIds = params.default_channel_ids;
227
+ if (params.mode !== undefined)
228
+ updateData.mode = modeMap[params.mode];
229
+ if (params.prompts !== undefined) {
230
+ updateData.prompts = params.prompts.map(p => ({
231
+ id: p.id,
232
+ type: promptTypeMap[p.type],
233
+ title: p.title,
234
+ singleSelect: p.single_select,
235
+ required: p.required,
236
+ inOnboarding: p.in_onboarding,
237
+ options: p.options.map(o => ({
238
+ id: o.id,
239
+ title: o.title,
240
+ description: o.description,
241
+ emoji: o.emoji_id ? { id: o.emoji_id, name: o.emoji_name } : o.emoji_name ? { name: o.emoji_name } : undefined,
242
+ roleIds: o.role_ids,
243
+ channelIds: o.channel_ids,
244
+ })),
245
+ }));
246
+ }
247
+ const onboarding = await guild.editOnboarding(updateData);
248
+ return {
249
+ content: [{ type: "text", text: `Onboarding updated. Enabled: ${onboarding.enabled}, Prompts: ${onboarding.prompts.size}` }],
250
+ };
251
+ }
252
+ catch (error) {
253
+ return {
254
+ isError: true,
255
+ content: [{ type: "text", text: `Error editing onboarding: ${error.message}` }],
256
+ };
257
+ }
258
+ });
259
+ }
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerEmojiTools(server: McpServer): void;
@@ -0,0 +1,247 @@
1
+ import { ListEmojisSchema, CreateEmojiSchema, DeleteEmojiSchema, ListStickersSchema, DeleteStickerSchema, } from "../schemas/index.js";
2
+ import { getClient, formatResponse, truncateIfNeeded, } from "../services/discord.js";
3
+ export function registerEmojiTools(server) {
4
+ // ============================================================================
5
+ // EMOJI TOOLS
6
+ // ============================================================================
7
+ server.registerTool("discord_list_emojis", {
8
+ title: "List Emojis",
9
+ description: `List all custom emojis in a server.
10
+
11
+ Args:
12
+ - guild_id (string): Discord server/guild ID
13
+ - response_format ('json' | 'markdown'): Output format
14
+
15
+ Returns:
16
+ List of emojis with name, ID, and whether animated`,
17
+ inputSchema: ListEmojisSchema,
18
+ annotations: {
19
+ readOnlyHint: true,
20
+ destructiveHint: false,
21
+ idempotentHint: true,
22
+ openWorldHint: true,
23
+ },
24
+ }, async (params) => {
25
+ try {
26
+ const client = await getClient();
27
+ const guild = client.guilds.cache.get(params.guild_id);
28
+ if (!guild) {
29
+ return {
30
+ isError: true,
31
+ content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
32
+ };
33
+ }
34
+ const emojis = guild.emojis.cache.map(emoji => ({
35
+ id: emoji.id,
36
+ name: emoji.name,
37
+ animated: emoji.animated,
38
+ available: emoji.available,
39
+ managed: emoji.managed,
40
+ requireColons: emoji.requiresColons,
41
+ roles: emoji.roles.cache.map(r => r.name),
42
+ url: emoji.url,
43
+ }));
44
+ const result = formatResponse(emojis, params.response_format, (items) => items.map(e => `${e.animated ? '(animated) ' : ''}**${e.name}** - ID: ${e.id}`).join('\n'));
45
+ return {
46
+ content: [{ type: "text", text: truncateIfNeeded(result) }],
47
+ };
48
+ }
49
+ catch (error) {
50
+ return {
51
+ isError: true,
52
+ content: [{ type: "text", text: `Error listing emojis: ${error.message}` }],
53
+ };
54
+ }
55
+ });
56
+ server.registerTool("discord_create_emoji", {
57
+ title: "Create Emoji",
58
+ description: `Create a custom emoji in a server.
59
+
60
+ Args:
61
+ - guild_id (string): Discord server/guild ID
62
+ - name (string): Emoji name (2-32 chars, alphanumeric and underscores)
63
+ - image_url (string): URL of image (PNG, JPG, GIF under 256KB)
64
+ - roles (string[], optional): Role IDs that can use this emoji
65
+
66
+ Returns:
67
+ Created emoji details`,
68
+ inputSchema: CreateEmojiSchema,
69
+ annotations: {
70
+ readOnlyHint: false,
71
+ destructiveHint: false,
72
+ idempotentHint: false,
73
+ openWorldHint: true,
74
+ },
75
+ }, async (params) => {
76
+ try {
77
+ const client = await getClient();
78
+ const guild = client.guilds.cache.get(params.guild_id);
79
+ if (!guild) {
80
+ return {
81
+ isError: true,
82
+ content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
83
+ };
84
+ }
85
+ const emoji = await guild.emojis.create({
86
+ attachment: params.image_url,
87
+ name: params.name,
88
+ roles: params.roles,
89
+ });
90
+ return {
91
+ content: [{ type: "text", text: `Created emoji :${emoji.name}: (ID: ${emoji.id})` }],
92
+ };
93
+ }
94
+ catch (error) {
95
+ return {
96
+ isError: true,
97
+ content: [{ type: "text", text: `Error creating emoji: ${error.message}` }],
98
+ };
99
+ }
100
+ });
101
+ server.registerTool("discord_delete_emoji", {
102
+ title: "Delete Emoji",
103
+ description: `Delete a custom emoji from a server.
104
+
105
+ Args:
106
+ - guild_id (string): Discord server/guild ID
107
+ - emoji_id (string): Discord emoji ID
108
+
109
+ Returns:
110
+ Confirmation of deletion`,
111
+ inputSchema: DeleteEmojiSchema,
112
+ annotations: {
113
+ readOnlyHint: false,
114
+ destructiveHint: true,
115
+ idempotentHint: true,
116
+ openWorldHint: true,
117
+ },
118
+ }, async (params) => {
119
+ try {
120
+ const client = await getClient();
121
+ const guild = client.guilds.cache.get(params.guild_id);
122
+ if (!guild) {
123
+ return {
124
+ isError: true,
125
+ content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
126
+ };
127
+ }
128
+ const emoji = guild.emojis.cache.get(params.emoji_id);
129
+ if (!emoji) {
130
+ return {
131
+ isError: true,
132
+ content: [{ type: "text", text: `Emoji not found: ${params.emoji_id}` }],
133
+ };
134
+ }
135
+ const name = emoji.name;
136
+ await emoji.delete();
137
+ return {
138
+ content: [{ type: "text", text: `Deleted emoji :${name}:` }],
139
+ };
140
+ }
141
+ catch (error) {
142
+ return {
143
+ isError: true,
144
+ content: [{ type: "text", text: `Error deleting emoji: ${error.message}` }],
145
+ };
146
+ }
147
+ });
148
+ // ============================================================================
149
+ // STICKER TOOLS
150
+ // ============================================================================
151
+ server.registerTool("discord_list_stickers", {
152
+ title: "List Stickers",
153
+ description: `List all custom stickers in a server.
154
+
155
+ Args:
156
+ - guild_id (string): Discord server/guild ID
157
+ - response_format ('json' | 'markdown'): Output format
158
+
159
+ Returns:
160
+ List of stickers with name, description, and format`,
161
+ inputSchema: ListStickersSchema,
162
+ annotations: {
163
+ readOnlyHint: true,
164
+ destructiveHint: false,
165
+ idempotentHint: true,
166
+ openWorldHint: true,
167
+ },
168
+ }, async (params) => {
169
+ try {
170
+ const client = await getClient();
171
+ const guild = client.guilds.cache.get(params.guild_id);
172
+ if (!guild) {
173
+ return {
174
+ isError: true,
175
+ content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
176
+ };
177
+ }
178
+ const stickers = await guild.stickers.fetch();
179
+ const stickerList = stickers.map(sticker => ({
180
+ id: sticker.id,
181
+ name: sticker.name,
182
+ description: sticker.description,
183
+ tags: sticker.tags,
184
+ format: sticker.format,
185
+ available: sticker.available,
186
+ url: sticker.url,
187
+ }));
188
+ const result = formatResponse(stickerList, params.response_format, (items) => items.map(s => `**${s.name}** (ID: ${s.id})\nDescription: ${s.description || 'None'}\nTags: ${s.tags || 'None'}`).join('\n\n'));
189
+ return {
190
+ content: [{ type: "text", text: truncateIfNeeded(result) }],
191
+ };
192
+ }
193
+ catch (error) {
194
+ return {
195
+ isError: true,
196
+ content: [{ type: "text", text: `Error listing stickers: ${error.message}` }],
197
+ };
198
+ }
199
+ });
200
+ server.registerTool("discord_delete_sticker", {
201
+ title: "Delete Sticker",
202
+ description: `Delete a custom sticker from a server.
203
+
204
+ Args:
205
+ - guild_id (string): Discord server/guild ID
206
+ - sticker_id (string): Discord sticker ID
207
+
208
+ Returns:
209
+ Confirmation of deletion`,
210
+ inputSchema: DeleteStickerSchema,
211
+ annotations: {
212
+ readOnlyHint: false,
213
+ destructiveHint: true,
214
+ idempotentHint: true,
215
+ openWorldHint: true,
216
+ },
217
+ }, async (params) => {
218
+ try {
219
+ const client = await getClient();
220
+ const guild = client.guilds.cache.get(params.guild_id);
221
+ if (!guild) {
222
+ return {
223
+ isError: true,
224
+ content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
225
+ };
226
+ }
227
+ const sticker = await guild.stickers.fetch(params.sticker_id).catch(() => null);
228
+ if (!sticker) {
229
+ return {
230
+ isError: true,
231
+ content: [{ type: "text", text: `Sticker not found: ${params.sticker_id}` }],
232
+ };
233
+ }
234
+ const name = sticker.name;
235
+ await sticker.delete();
236
+ return {
237
+ content: [{ type: "text", text: `Deleted sticker: ${name}` }],
238
+ };
239
+ }
240
+ catch (error) {
241
+ return {
242
+ isError: true,
243
+ content: [{ type: "text", text: `Error deleting sticker: ${error.message}` }],
244
+ };
245
+ }
246
+ });
247
+ }
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerEventTools(server: McpServer): void;
@@ -0,0 +1,170 @@
1
+ import { ListEventsSchema, CreateEventSchema, DeleteEventSchema, } from "../schemas/index.js";
2
+ import { getClient, formatResponse, truncateIfNeeded, } from "../services/discord.js";
3
+ import { GuildScheduledEventEntityType, GuildScheduledEventPrivacyLevel } from "discord.js";
4
+ export function registerEventTools(server) {
5
+ server.registerTool("discord_list_events", {
6
+ title: "List Scheduled Events",
7
+ description: `List all scheduled events in a server.
8
+
9
+ Args:
10
+ - guild_id (string): Discord server/guild ID
11
+ - response_format ('json' | 'markdown'): Output format
12
+
13
+ Returns:
14
+ List of events with name, time, location, and status`,
15
+ inputSchema: ListEventsSchema,
16
+ annotations: {
17
+ readOnlyHint: true,
18
+ destructiveHint: false,
19
+ idempotentHint: true,
20
+ openWorldHint: true,
21
+ },
22
+ }, async (params) => {
23
+ try {
24
+ const client = await getClient();
25
+ const guild = client.guilds.cache.get(params.guild_id);
26
+ if (!guild) {
27
+ return {
28
+ isError: true,
29
+ content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
30
+ };
31
+ }
32
+ const events = await guild.scheduledEvents.fetch();
33
+ const eventList = events.map(event => ({
34
+ id: event.id,
35
+ name: event.name,
36
+ description: event.description,
37
+ status: event.status,
38
+ entityType: event.entityType,
39
+ channel: event.channel?.name,
40
+ channelId: event.channelId,
41
+ location: event.entityMetadata?.location,
42
+ scheduledStartTime: event.scheduledStartAt?.toISOString(),
43
+ scheduledEndTime: event.scheduledEndAt?.toISOString(),
44
+ userCount: event.userCount,
45
+ creator: event.creator?.username,
46
+ }));
47
+ const result = formatResponse(eventList, params.response_format, (items) => items.map(e => `**${e.name}** (ID: ${e.id})\nStatus: ${e.status}\nStart: ${e.scheduledStartTime}\nLocation: ${e.location || e.channel || 'TBD'}\nAttending: ${e.userCount || 0}`).join('\n\n'));
48
+ return {
49
+ content: [{ type: "text", text: truncateIfNeeded(result) }],
50
+ };
51
+ }
52
+ catch (error) {
53
+ return {
54
+ isError: true,
55
+ content: [{ type: "text", text: `Error listing events: ${error.message}` }],
56
+ };
57
+ }
58
+ });
59
+ server.registerTool("discord_create_event", {
60
+ title: "Create Scheduled Event",
61
+ description: `Create a scheduled event in a server.
62
+
63
+ Args:
64
+ - guild_id (string): Discord server/guild ID
65
+ - name (string): Event name
66
+ - description (string, optional): Event description
67
+ - scheduled_start_time (string): ISO8601 timestamp for start
68
+ - scheduled_end_time (string, optional): ISO8601 timestamp for end
69
+ - entity_type ('stage' | 'voice' | 'external'): Type of event
70
+ - channel_id (string, optional): Channel ID for stage/voice events
71
+ - location (string, optional): Location for external events
72
+
73
+ Returns:
74
+ Created event details`,
75
+ inputSchema: CreateEventSchema,
76
+ annotations: {
77
+ readOnlyHint: false,
78
+ destructiveHint: false,
79
+ idempotentHint: false,
80
+ openWorldHint: true,
81
+ },
82
+ }, async (params) => {
83
+ try {
84
+ const client = await getClient();
85
+ const guild = client.guilds.cache.get(params.guild_id);
86
+ if (!guild) {
87
+ return {
88
+ isError: true,
89
+ content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
90
+ };
91
+ }
92
+ const entityTypeMap = {
93
+ stage: GuildScheduledEventEntityType.StageInstance,
94
+ voice: GuildScheduledEventEntityType.Voice,
95
+ external: GuildScheduledEventEntityType.External,
96
+ };
97
+ const createOptions = {
98
+ name: params.name,
99
+ scheduledStartTime: new Date(params.scheduled_start_time),
100
+ privacyLevel: GuildScheduledEventPrivacyLevel.GuildOnly,
101
+ entityType: entityTypeMap[params.entity_type],
102
+ };
103
+ if (params.description)
104
+ createOptions.description = params.description;
105
+ if (params.scheduled_end_time)
106
+ createOptions.scheduledEndTime = new Date(params.scheduled_end_time);
107
+ if (params.channel_id)
108
+ createOptions.channel = params.channel_id;
109
+ if (params.entity_metadata?.location)
110
+ createOptions.entityMetadata = { location: params.entity_metadata.location };
111
+ const event = await guild.scheduledEvents.create(createOptions);
112
+ return {
113
+ content: [{ type: "text", text: `Created event "${event.name}" (ID: ${event.id})\nStart: ${event.scheduledStartAt?.toISOString()}` }],
114
+ };
115
+ }
116
+ catch (error) {
117
+ return {
118
+ isError: true,
119
+ content: [{ type: "text", text: `Error creating event: ${error.message}` }],
120
+ };
121
+ }
122
+ });
123
+ server.registerTool("discord_delete_event", {
124
+ title: "Delete Scheduled Event",
125
+ description: `Delete a scheduled event from a server.
126
+
127
+ Args:
128
+ - guild_id (string): Discord server/guild ID
129
+ - event_id (string): Discord scheduled event ID
130
+
131
+ Returns:
132
+ Confirmation of deletion`,
133
+ inputSchema: DeleteEventSchema,
134
+ annotations: {
135
+ readOnlyHint: false,
136
+ destructiveHint: true,
137
+ idempotentHint: true,
138
+ openWorldHint: true,
139
+ },
140
+ }, async (params) => {
141
+ try {
142
+ const client = await getClient();
143
+ const guild = client.guilds.cache.get(params.guild_id);
144
+ if (!guild) {
145
+ return {
146
+ isError: true,
147
+ content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
148
+ };
149
+ }
150
+ const event = await guild.scheduledEvents.fetch(params.event_id).catch(() => null);
151
+ if (!event) {
152
+ return {
153
+ isError: true,
154
+ content: [{ type: "text", text: `Event not found: ${params.event_id}` }],
155
+ };
156
+ }
157
+ const name = event.name;
158
+ await event.delete();
159
+ return {
160
+ content: [{ type: "text", text: `Deleted event: ${name}` }],
161
+ };
162
+ }
163
+ catch (error) {
164
+ return {
165
+ isError: true,
166
+ content: [{ type: "text", text: `Error deleting event: ${error.message}` }],
167
+ };
168
+ }
169
+ });
170
+ }
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerGuildTools(server: McpServer): void;