@mahesvara/discord-mcpserver 1.0.8 → 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.
- package/dist/index.js +4 -2833
- package/dist/schemas/channel.d.ts +158 -0
- package/dist/schemas/channel.js +128 -0
- package/dist/schemas/common.d.ts +23 -0
- package/dist/schemas/common.js +71 -0
- package/dist/schemas/community.d.ts +181 -0
- package/dist/schemas/community.js +60 -0
- package/dist/schemas/emoji.d.ts +59 -0
- package/dist/schemas/emoji.js +29 -0
- package/dist/schemas/event.d.ts +62 -0
- package/dist/schemas/event.js +33 -0
- package/dist/schemas/guild.d.ts +85 -0
- package/dist/schemas/guild.js +42 -0
- package/dist/schemas/index.d.ts +12 -855
- package/dist/schemas/index.js +13 -617
- package/dist/schemas/invite.d.ts +40 -0
- package/dist/schemas/invite.js +32 -0
- package/dist/schemas/member.d.ts +60 -0
- package/dist/schemas/member.js +33 -0
- package/dist/schemas/message.d.ts +121 -0
- package/dist/schemas/message.js +61 -0
- package/dist/schemas/moderation.d.ts +343 -0
- package/dist/schemas/moderation.js +152 -0
- package/dist/schemas/role.d.ts +126 -0
- package/dist/schemas/role.js +73 -0
- package/dist/schemas/webhook.d.ts +51 -0
- package/dist/schemas/webhook.js +33 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +6 -0
- package/dist/tools/channel.d.ts +2 -0
- package/dist/tools/channel.js +510 -0
- package/dist/tools/community.d.ts +2 -0
- package/dist/tools/community.js +259 -0
- package/dist/tools/emoji.d.ts +2 -0
- package/dist/tools/emoji.js +247 -0
- package/dist/tools/event.d.ts +2 -0
- package/dist/tools/event.js +170 -0
- package/dist/tools/guild.d.ts +2 -0
- package/dist/tools/guild.js +198 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.js +24 -0
- package/dist/tools/invite.d.ts +2 -0
- package/dist/tools/invite.js +143 -0
- package/dist/tools/member.d.ts +2 -0
- package/dist/tools/member.js +200 -0
- package/dist/tools/message.d.ts +2 -0
- package/dist/tools/message.js +386 -0
- package/dist/tools/moderation.d.ts +2 -0
- package/dist/tools/moderation.js +641 -0
- package/dist/tools/role.d.ts +2 -0
- package/dist/tools/role.js +420 -0
- package/dist/tools/webhook.d.ts +2 -0
- package/dist/tools/webhook.js +199 -0
- 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,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,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
|
+
}
|