@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,641 @@
|
|
|
1
|
+
import { KickMemberSchema, BanMemberSchema, UnbanMemberSchema, TimeoutMemberSchema, ListBansSchema, PruneMembersSchema, GetAuditLogSchema, ListAutoModRulesSchema, GetAutoModRuleSchema, CreateAutoModRuleSchema, EditAutoModRuleSchema, DeleteAutoModRuleSchema, } from "../schemas/index.js";
|
|
2
|
+
import { getClient, formatResponse, truncateIfNeeded, } from "../services/discord.js";
|
|
3
|
+
export function registerModerationTools(server) {
|
|
4
|
+
server.registerTool("discord_kick_member", {
|
|
5
|
+
title: "Kick Discord Member",
|
|
6
|
+
description: `Kick a member from a Discord server.
|
|
7
|
+
|
|
8
|
+
Args:
|
|
9
|
+
- guild_id (string): Discord server/guild ID
|
|
10
|
+
- user_id (string): Discord user ID to kick
|
|
11
|
+
- reason (string, optional): Reason for kick (visible in audit log)
|
|
12
|
+
|
|
13
|
+
Returns:
|
|
14
|
+
Confirmation of kick`,
|
|
15
|
+
inputSchema: KickMemberSchema,
|
|
16
|
+
annotations: {
|
|
17
|
+
readOnlyHint: false,
|
|
18
|
+
destructiveHint: true,
|
|
19
|
+
idempotentHint: false,
|
|
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 member = await guild.members.fetch(params.user_id);
|
|
33
|
+
await member.kick(params.reason);
|
|
34
|
+
return {
|
|
35
|
+
content: [{ type: "text", text: `Kicked user ${params.user_id} from ${guild.name}` }],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
return {
|
|
40
|
+
isError: true,
|
|
41
|
+
content: [{ type: "text", text: `Error kicking member: ${error.message}` }],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
server.registerTool("discord_ban_member", {
|
|
46
|
+
title: "Ban Discord Member",
|
|
47
|
+
description: `Ban a member from a Discord server.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
- guild_id (string): Discord server/guild ID
|
|
51
|
+
- user_id (string): Discord user ID to ban
|
|
52
|
+
- reason (string, optional): Reason for ban (visible in audit log)
|
|
53
|
+
- delete_message_days (number): Days of messages to delete (0-7, default: 0)
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Confirmation of ban`,
|
|
57
|
+
inputSchema: BanMemberSchema,
|
|
58
|
+
annotations: {
|
|
59
|
+
readOnlyHint: false,
|
|
60
|
+
destructiveHint: true,
|
|
61
|
+
idempotentHint: false,
|
|
62
|
+
openWorldHint: true,
|
|
63
|
+
},
|
|
64
|
+
}, async (params) => {
|
|
65
|
+
try {
|
|
66
|
+
const client = await getClient();
|
|
67
|
+
const guild = client.guilds.cache.get(params.guild_id);
|
|
68
|
+
if (!guild) {
|
|
69
|
+
return {
|
|
70
|
+
isError: true,
|
|
71
|
+
content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
await guild.members.ban(params.user_id, {
|
|
75
|
+
reason: params.reason,
|
|
76
|
+
deleteMessageSeconds: params.delete_message_days ? params.delete_message_days * 86400 : undefined,
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
content: [{ type: "text", text: `Banned user ${params.user_id} from ${guild.name}` }],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
return {
|
|
84
|
+
isError: true,
|
|
85
|
+
content: [{ type: "text", text: `Error banning member: ${error.message}` }],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
server.registerTool("discord_unban_member", {
|
|
90
|
+
title: "Unban Discord Member",
|
|
91
|
+
description: `Remove a ban from a user.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
- guild_id (string): Discord server/guild ID
|
|
95
|
+
- user_id (string): Discord user ID to unban
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
Confirmation of unban`,
|
|
99
|
+
inputSchema: UnbanMemberSchema,
|
|
100
|
+
annotations: {
|
|
101
|
+
readOnlyHint: false,
|
|
102
|
+
destructiveHint: false,
|
|
103
|
+
idempotentHint: true,
|
|
104
|
+
openWorldHint: true,
|
|
105
|
+
},
|
|
106
|
+
}, async (params) => {
|
|
107
|
+
try {
|
|
108
|
+
const client = await getClient();
|
|
109
|
+
const guild = client.guilds.cache.get(params.guild_id);
|
|
110
|
+
if (!guild) {
|
|
111
|
+
return {
|
|
112
|
+
isError: true,
|
|
113
|
+
content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
await guild.members.unban(params.user_id);
|
|
117
|
+
return {
|
|
118
|
+
content: [{ type: "text", text: `Unbanned user ${params.user_id} from ${guild.name}` }],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
return {
|
|
123
|
+
isError: true,
|
|
124
|
+
content: [{ type: "text", text: `Error unbanning member: ${error.message}` }],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
server.registerTool("discord_timeout_member", {
|
|
129
|
+
title: "Timeout Member",
|
|
130
|
+
description: `Timeout (mute) a member for a specified duration. They cannot send messages, react, or join voice.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
- guild_id (string): Discord server/guild ID
|
|
134
|
+
- user_id (string): Discord user ID to timeout
|
|
135
|
+
- duration_minutes (number): Timeout duration in minutes (0 to remove, max 40320 = 28 days)
|
|
136
|
+
- reason (string, optional): Reason for timeout (visible in audit log)
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
Confirmation of timeout`,
|
|
140
|
+
inputSchema: TimeoutMemberSchema,
|
|
141
|
+
annotations: {
|
|
142
|
+
readOnlyHint: false,
|
|
143
|
+
destructiveHint: false,
|
|
144
|
+
idempotentHint: true,
|
|
145
|
+
openWorldHint: true,
|
|
146
|
+
},
|
|
147
|
+
}, async (params) => {
|
|
148
|
+
try {
|
|
149
|
+
const client = await getClient();
|
|
150
|
+
const guild = client.guilds.cache.get(params.guild_id);
|
|
151
|
+
if (!guild) {
|
|
152
|
+
return {
|
|
153
|
+
isError: true,
|
|
154
|
+
content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const member = await guild.members.fetch(params.user_id).catch(() => null);
|
|
158
|
+
if (!member) {
|
|
159
|
+
return {
|
|
160
|
+
isError: true,
|
|
161
|
+
content: [{ type: "text", text: `Member not found: ${params.user_id}` }],
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (params.duration_minutes === 0) {
|
|
165
|
+
await member.timeout(null, params.reason);
|
|
166
|
+
return {
|
|
167
|
+
content: [{ type: "text", text: `Removed timeout from ${member.user.username}` }],
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
const timeoutMs = params.duration_minutes * 60 * 1000;
|
|
171
|
+
await member.timeout(timeoutMs, params.reason);
|
|
172
|
+
return {
|
|
173
|
+
content: [{ type: "text", text: `Timed out ${member.user.username} for ${params.duration_minutes} minutes` }],
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
return {
|
|
178
|
+
isError: true,
|
|
179
|
+
content: [{ type: "text", text: `Error timing out member: ${error.message}` }],
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
server.registerTool("discord_list_bans", {
|
|
184
|
+
title: "List Bans",
|
|
185
|
+
description: `List all banned users in a server.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
- guild_id (string): Discord server/guild ID
|
|
189
|
+
- limit (number): Number of bans to return (1-1000, default 100)
|
|
190
|
+
- response_format ('json' | 'markdown'): Output format
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
List of banned users with reasons`,
|
|
194
|
+
inputSchema: ListBansSchema,
|
|
195
|
+
annotations: {
|
|
196
|
+
readOnlyHint: true,
|
|
197
|
+
destructiveHint: false,
|
|
198
|
+
idempotentHint: true,
|
|
199
|
+
openWorldHint: true,
|
|
200
|
+
},
|
|
201
|
+
}, async (params) => {
|
|
202
|
+
try {
|
|
203
|
+
const client = await getClient();
|
|
204
|
+
const guild = client.guilds.cache.get(params.guild_id);
|
|
205
|
+
if (!guild) {
|
|
206
|
+
return {
|
|
207
|
+
isError: true,
|
|
208
|
+
content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
const bans = await guild.bans.fetch({ limit: params.limit });
|
|
212
|
+
const banList = bans.map(ban => ({
|
|
213
|
+
userId: ban.user.id,
|
|
214
|
+
username: ban.user.username,
|
|
215
|
+
reason: ban.reason || 'No reason provided',
|
|
216
|
+
}));
|
|
217
|
+
const result = formatResponse(banList, params.response_format, (items) => items.map(b => `**${b.username}** (${b.userId})\nReason: ${b.reason}`).join('\n\n'));
|
|
218
|
+
return {
|
|
219
|
+
content: [{ type: "text", text: truncateIfNeeded(result) }],
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
return {
|
|
224
|
+
isError: true,
|
|
225
|
+
content: [{ type: "text", text: `Error listing bans: ${error.message}` }],
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
server.registerTool("discord_prune_members", {
|
|
230
|
+
title: "Prune Members",
|
|
231
|
+
description: `Remove inactive members from the server.
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
- guild_id (string): Discord server/guild ID
|
|
235
|
+
- days (number): Days of inactivity required (1-30)
|
|
236
|
+
- include_roles (string[], optional): Role IDs to include in prune (by default only members without roles)
|
|
237
|
+
- dry_run (boolean): If true, returns count without actually pruning (default true)
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
Number of members pruned (or would be pruned if dry_run)`,
|
|
241
|
+
inputSchema: PruneMembersSchema,
|
|
242
|
+
annotations: {
|
|
243
|
+
readOnlyHint: false,
|
|
244
|
+
destructiveHint: true,
|
|
245
|
+
idempotentHint: false,
|
|
246
|
+
openWorldHint: true,
|
|
247
|
+
},
|
|
248
|
+
}, async (params) => {
|
|
249
|
+
try {
|
|
250
|
+
const client = await getClient();
|
|
251
|
+
const guild = client.guilds.cache.get(params.guild_id);
|
|
252
|
+
if (!guild) {
|
|
253
|
+
return {
|
|
254
|
+
isError: true,
|
|
255
|
+
content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
if (params.dry_run) {
|
|
259
|
+
const count = await guild.members.prune({
|
|
260
|
+
days: params.days,
|
|
261
|
+
roles: params.include_roles,
|
|
262
|
+
dry: true,
|
|
263
|
+
});
|
|
264
|
+
return {
|
|
265
|
+
content: [{ type: "text", text: `Dry run: ${count} members would be pruned (inactive for ${params.days}+ days)` }],
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
const pruned = await guild.members.prune({
|
|
269
|
+
days: params.days,
|
|
270
|
+
roles: params.include_roles,
|
|
271
|
+
dry: false,
|
|
272
|
+
});
|
|
273
|
+
return {
|
|
274
|
+
content: [{ type: "text", text: `Pruned ${pruned} members (inactive for ${params.days}+ days)` }],
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
return {
|
|
279
|
+
isError: true,
|
|
280
|
+
content: [{ type: "text", text: `Error pruning members: ${error.message}` }],
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
server.registerTool("discord_get_audit_log", {
|
|
285
|
+
title: "Get Audit Log",
|
|
286
|
+
description: `Get the audit log for a server. Shows who did what actions.
|
|
287
|
+
|
|
288
|
+
Common action types:
|
|
289
|
+
1=GuildUpdate, 10=ChannelCreate, 11=ChannelUpdate, 12=ChannelDelete,
|
|
290
|
+
20=MemberKick, 22=MemberBanAdd, 23=MemberBanRemove, 24=MemberUpdate, 25=MemberRoleUpdate,
|
|
291
|
+
30=RoleCreate, 31=RoleUpdate, 32=RoleDelete,
|
|
292
|
+
72=MessageDelete, 73=MessageBulkDelete
|
|
293
|
+
|
|
294
|
+
Args:
|
|
295
|
+
- guild_id (string): Discord server/guild ID
|
|
296
|
+
- user_id (string, optional): Filter by user who performed action
|
|
297
|
+
- action_type (number, optional): Filter by action type
|
|
298
|
+
- limit (number): Number of entries (1-100, default 20)
|
|
299
|
+
- response_format ('json' | 'markdown'): Output format
|
|
300
|
+
|
|
301
|
+
Returns:
|
|
302
|
+
Audit log entries with action, user, target, and changes`,
|
|
303
|
+
inputSchema: GetAuditLogSchema,
|
|
304
|
+
annotations: {
|
|
305
|
+
readOnlyHint: true,
|
|
306
|
+
destructiveHint: false,
|
|
307
|
+
idempotentHint: true,
|
|
308
|
+
openWorldHint: true,
|
|
309
|
+
},
|
|
310
|
+
}, async (params) => {
|
|
311
|
+
try {
|
|
312
|
+
const client = await getClient();
|
|
313
|
+
const guild = client.guilds.cache.get(params.guild_id);
|
|
314
|
+
if (!guild) {
|
|
315
|
+
return {
|
|
316
|
+
isError: true,
|
|
317
|
+
content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
const fetchOptions = {
|
|
321
|
+
limit: params.limit,
|
|
322
|
+
};
|
|
323
|
+
if (params.user_id)
|
|
324
|
+
fetchOptions.user = params.user_id;
|
|
325
|
+
if (params.action_type !== undefined)
|
|
326
|
+
fetchOptions.type = params.action_type;
|
|
327
|
+
const auditLogs = await guild.fetchAuditLogs(fetchOptions);
|
|
328
|
+
const entries = auditLogs.entries.map(entry => ({
|
|
329
|
+
id: entry.id,
|
|
330
|
+
action: entry.action,
|
|
331
|
+
actionType: entry.actionType,
|
|
332
|
+
executor: entry.executor?.username || 'Unknown',
|
|
333
|
+
executorId: entry.executor?.id,
|
|
334
|
+
target: entry.target?.toString() || 'Unknown',
|
|
335
|
+
reason: entry.reason || 'No reason',
|
|
336
|
+
createdAt: entry.createdAt.toISOString(),
|
|
337
|
+
changes: entry.changes.map(c => ({
|
|
338
|
+
key: c.key,
|
|
339
|
+
old: c.old,
|
|
340
|
+
new: c.new,
|
|
341
|
+
})),
|
|
342
|
+
}));
|
|
343
|
+
const result = formatResponse(entries, params.response_format, (items) => items.map(e => `**Action ${e.action}** by ${e.executor}\nTarget: ${e.target}\nReason: ${e.reason}\nTime: ${e.createdAt}`).join('\n\n'));
|
|
344
|
+
return {
|
|
345
|
+
content: [{ type: "text", text: truncateIfNeeded(result) }],
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
catch (error) {
|
|
349
|
+
return {
|
|
350
|
+
isError: true,
|
|
351
|
+
content: [{ type: "text", text: `Error fetching audit log: ${error.message}` }],
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
server.registerTool("discord_list_automod_rules", {
|
|
356
|
+
title: "List Auto Moderation Rules",
|
|
357
|
+
description: `List all auto moderation rules for a server.
|
|
358
|
+
|
|
359
|
+
Args:
|
|
360
|
+
- guild_id (string): Discord server/guild ID
|
|
361
|
+
- response_format ('markdown' | 'json'): Output format (default: 'json')
|
|
362
|
+
|
|
363
|
+
Returns:
|
|
364
|
+
List of auto moderation rules`,
|
|
365
|
+
inputSchema: ListAutoModRulesSchema,
|
|
366
|
+
annotations: {
|
|
367
|
+
readOnlyHint: true,
|
|
368
|
+
destructiveHint: false,
|
|
369
|
+
idempotentHint: true,
|
|
370
|
+
openWorldHint: true,
|
|
371
|
+
},
|
|
372
|
+
}, async (params) => {
|
|
373
|
+
try {
|
|
374
|
+
const client = await getClient();
|
|
375
|
+
const guild = client.guilds.cache.get(params.guild_id);
|
|
376
|
+
if (!guild) {
|
|
377
|
+
return {
|
|
378
|
+
isError: true,
|
|
379
|
+
content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
const rules = await guild.autoModerationRules.fetch();
|
|
383
|
+
const ruleList = rules.map(rule => ({
|
|
384
|
+
id: rule.id,
|
|
385
|
+
name: rule.name,
|
|
386
|
+
enabled: rule.enabled,
|
|
387
|
+
eventType: rule.eventType,
|
|
388
|
+
triggerType: rule.triggerType,
|
|
389
|
+
actions: rule.actions.map(a => ({ type: a.type, metadata: a.metadata })),
|
|
390
|
+
}));
|
|
391
|
+
const text = formatResponse(ruleList, params.response_format, (items) => items.map(r => `**${r.name}** (${r.id})\nEnabled: ${r.enabled}\nTrigger: ${r.triggerType}\nActions: ${r.actions.map(a => a.type).join(', ')}`).join('\n\n'));
|
|
392
|
+
return {
|
|
393
|
+
content: [{ type: "text", text: truncateIfNeeded(text) }],
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
catch (error) {
|
|
397
|
+
return {
|
|
398
|
+
isError: true,
|
|
399
|
+
content: [{ type: "text", text: `Error listing auto moderation rules: ${error.message}` }],
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
server.registerTool("discord_get_automod_rule", {
|
|
404
|
+
title: "Get Auto Moderation Rule",
|
|
405
|
+
description: `Get details of a specific auto moderation rule.
|
|
406
|
+
|
|
407
|
+
Args:
|
|
408
|
+
- guild_id (string): Discord server/guild ID
|
|
409
|
+
- rule_id (string): Auto moderation rule ID
|
|
410
|
+
- response_format ('markdown' | 'json'): Output format (default: 'json')
|
|
411
|
+
|
|
412
|
+
Returns:
|
|
413
|
+
Auto moderation rule details`,
|
|
414
|
+
inputSchema: GetAutoModRuleSchema,
|
|
415
|
+
annotations: {
|
|
416
|
+
readOnlyHint: true,
|
|
417
|
+
destructiveHint: false,
|
|
418
|
+
idempotentHint: true,
|
|
419
|
+
openWorldHint: true,
|
|
420
|
+
},
|
|
421
|
+
}, async (params) => {
|
|
422
|
+
try {
|
|
423
|
+
const client = await getClient();
|
|
424
|
+
const guild = client.guilds.cache.get(params.guild_id);
|
|
425
|
+
if (!guild) {
|
|
426
|
+
return {
|
|
427
|
+
isError: true,
|
|
428
|
+
content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
const rule = await guild.autoModerationRules.fetch(params.rule_id);
|
|
432
|
+
const result = {
|
|
433
|
+
id: rule.id,
|
|
434
|
+
name: rule.name,
|
|
435
|
+
enabled: rule.enabled,
|
|
436
|
+
eventType: rule.eventType,
|
|
437
|
+
triggerType: rule.triggerType,
|
|
438
|
+
triggerMetadata: rule.triggerMetadata,
|
|
439
|
+
actions: rule.actions,
|
|
440
|
+
exemptRoles: rule.exemptRoles.map(r => r.id),
|
|
441
|
+
exemptChannels: rule.exemptChannels.map(c => c.id),
|
|
442
|
+
creatorId: rule.creatorId,
|
|
443
|
+
};
|
|
444
|
+
const text = formatResponse(result, params.response_format, (r) => `**${r.name}** (${r.id})\nEnabled: ${r.enabled}\nEvent: ${r.eventType}\nTrigger: ${r.triggerType}\nExempt Roles: ${r.exemptRoles.length}\nExempt Channels: ${r.exemptChannels.length}`);
|
|
445
|
+
return {
|
|
446
|
+
content: [{ type: "text", text }],
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
catch (error) {
|
|
450
|
+
return {
|
|
451
|
+
isError: true,
|
|
452
|
+
content: [{ type: "text", text: `Error getting auto moderation rule: ${error.message}` }],
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
server.registerTool("discord_create_automod_rule", {
|
|
457
|
+
title: "Create Auto Moderation Rule",
|
|
458
|
+
description: `Create a new auto moderation rule for a server.
|
|
459
|
+
|
|
460
|
+
Args:
|
|
461
|
+
- guild_id (string): Discord server/guild ID
|
|
462
|
+
- name (string): Rule name
|
|
463
|
+
- event_type ('message_send'): Event that triggers the rule
|
|
464
|
+
- trigger_type ('keyword' | 'spam' | 'keyword_preset' | 'mention_spam'): Trigger type
|
|
465
|
+
- trigger_metadata (object, optional): Trigger configuration (keyword_filter, presets, etc.)
|
|
466
|
+
- actions (array): Actions to take (block_message, send_alert_message, timeout)
|
|
467
|
+
- enabled (boolean): Whether rule is enabled (default: true)
|
|
468
|
+
- exempt_roles (array, optional): Role IDs exempt from this rule
|
|
469
|
+
- exempt_channels (array, optional): Channel IDs exempt from this rule
|
|
470
|
+
|
|
471
|
+
Returns:
|
|
472
|
+
Created rule details`,
|
|
473
|
+
inputSchema: CreateAutoModRuleSchema,
|
|
474
|
+
annotations: {
|
|
475
|
+
readOnlyHint: false,
|
|
476
|
+
destructiveHint: false,
|
|
477
|
+
idempotentHint: false,
|
|
478
|
+
openWorldHint: true,
|
|
479
|
+
},
|
|
480
|
+
}, async (params) => {
|
|
481
|
+
try {
|
|
482
|
+
const client = await getClient();
|
|
483
|
+
const guild = client.guilds.cache.get(params.guild_id);
|
|
484
|
+
if (!guild) {
|
|
485
|
+
return {
|
|
486
|
+
isError: true,
|
|
487
|
+
content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
const eventTypeMap = { message_send: 1 };
|
|
491
|
+
const triggerTypeMap = { keyword: 1, spam: 3, keyword_preset: 4, mention_spam: 5 };
|
|
492
|
+
const actionTypeMap = { block_message: 1, send_alert_message: 2, timeout: 3 };
|
|
493
|
+
const rule = await guild.autoModerationRules.create({
|
|
494
|
+
name: params.name,
|
|
495
|
+
eventType: eventTypeMap[params.event_type],
|
|
496
|
+
triggerType: triggerTypeMap[params.trigger_type],
|
|
497
|
+
triggerMetadata: params.trigger_metadata ? {
|
|
498
|
+
keywordFilter: params.trigger_metadata.keyword_filter,
|
|
499
|
+
regexPatterns: params.trigger_metadata.regex_patterns,
|
|
500
|
+
presets: params.trigger_metadata.presets?.map(p => p === 'profanity' ? 1 : p === 'sexual_content' ? 2 : 3),
|
|
501
|
+
allowList: params.trigger_metadata.allow_list,
|
|
502
|
+
mentionTotalLimit: params.trigger_metadata.mention_total_limit,
|
|
503
|
+
} : undefined,
|
|
504
|
+
actions: params.actions.map(a => ({
|
|
505
|
+
type: actionTypeMap[a.type],
|
|
506
|
+
metadata: a.metadata ? {
|
|
507
|
+
channelId: a.metadata.channel_id,
|
|
508
|
+
durationSeconds: a.metadata.duration_seconds,
|
|
509
|
+
} : undefined,
|
|
510
|
+
})),
|
|
511
|
+
enabled: params.enabled,
|
|
512
|
+
exemptRoles: params.exempt_roles,
|
|
513
|
+
exemptChannels: params.exempt_channels,
|
|
514
|
+
});
|
|
515
|
+
return {
|
|
516
|
+
content: [{ type: "text", text: `Created auto moderation rule "${rule.name}" (${rule.id})` }],
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
catch (error) {
|
|
520
|
+
return {
|
|
521
|
+
isError: true,
|
|
522
|
+
content: [{ type: "text", text: `Error creating auto moderation rule: ${error.message}` }],
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
server.registerTool("discord_edit_automod_rule", {
|
|
527
|
+
title: "Edit Auto Moderation Rule",
|
|
528
|
+
description: `Edit an existing auto moderation rule.
|
|
529
|
+
|
|
530
|
+
Args:
|
|
531
|
+
- guild_id (string): Discord server/guild ID
|
|
532
|
+
- rule_id (string): Auto moderation rule ID
|
|
533
|
+
- name (string, optional): New rule name
|
|
534
|
+
- trigger_metadata (object, optional): New trigger configuration
|
|
535
|
+
- actions (array, optional): New actions
|
|
536
|
+
- enabled (boolean, optional): Enable/disable rule
|
|
537
|
+
- exempt_roles (array, optional): New exempt roles
|
|
538
|
+
- exempt_channels (array, optional): New exempt channels
|
|
539
|
+
|
|
540
|
+
Returns:
|
|
541
|
+
Updated rule details`,
|
|
542
|
+
inputSchema: EditAutoModRuleSchema,
|
|
543
|
+
annotations: {
|
|
544
|
+
readOnlyHint: false,
|
|
545
|
+
destructiveHint: false,
|
|
546
|
+
idempotentHint: true,
|
|
547
|
+
openWorldHint: true,
|
|
548
|
+
},
|
|
549
|
+
}, async (params) => {
|
|
550
|
+
try {
|
|
551
|
+
const client = await getClient();
|
|
552
|
+
const guild = client.guilds.cache.get(params.guild_id);
|
|
553
|
+
if (!guild) {
|
|
554
|
+
return {
|
|
555
|
+
isError: true,
|
|
556
|
+
content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
const rule = await guild.autoModerationRules.fetch(params.rule_id);
|
|
560
|
+
const actionTypeMap = { block_message: 1, send_alert_message: 2, timeout: 3 };
|
|
561
|
+
const updateData = {};
|
|
562
|
+
if (params.name !== undefined)
|
|
563
|
+
updateData.name = params.name;
|
|
564
|
+
if (params.enabled !== undefined)
|
|
565
|
+
updateData.enabled = params.enabled;
|
|
566
|
+
if (params.exempt_roles !== undefined)
|
|
567
|
+
updateData.exemptRoles = params.exempt_roles;
|
|
568
|
+
if (params.exempt_channels !== undefined)
|
|
569
|
+
updateData.exemptChannels = params.exempt_channels;
|
|
570
|
+
if (params.trigger_metadata !== undefined) {
|
|
571
|
+
updateData.triggerMetadata = {
|
|
572
|
+
keywordFilter: params.trigger_metadata.keyword_filter,
|
|
573
|
+
regexPatterns: params.trigger_metadata.regex_patterns,
|
|
574
|
+
presets: params.trigger_metadata.presets?.map(p => p === 'profanity' ? 1 : p === 'sexual_content' ? 2 : 3),
|
|
575
|
+
allowList: params.trigger_metadata.allow_list,
|
|
576
|
+
mentionTotalLimit: params.trigger_metadata.mention_total_limit,
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
if (params.actions !== undefined) {
|
|
580
|
+
updateData.actions = params.actions.map(a => ({
|
|
581
|
+
type: actionTypeMap[a.type],
|
|
582
|
+
metadata: a.metadata ? {
|
|
583
|
+
channelId: a.metadata.channel_id,
|
|
584
|
+
durationSeconds: a.metadata.duration_seconds,
|
|
585
|
+
} : undefined,
|
|
586
|
+
}));
|
|
587
|
+
}
|
|
588
|
+
const updated = await rule.edit(updateData);
|
|
589
|
+
return {
|
|
590
|
+
content: [{ type: "text", text: `Updated auto moderation rule "${updated.name}" (${updated.id})` }],
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
catch (error) {
|
|
594
|
+
return {
|
|
595
|
+
isError: true,
|
|
596
|
+
content: [{ type: "text", text: `Error editing auto moderation rule: ${error.message}` }],
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
server.registerTool("discord_delete_automod_rule", {
|
|
601
|
+
title: "Delete Auto Moderation Rule",
|
|
602
|
+
description: `Delete an auto moderation rule from a server.
|
|
603
|
+
|
|
604
|
+
Args:
|
|
605
|
+
- guild_id (string): Discord server/guild ID
|
|
606
|
+
- rule_id (string): Auto moderation rule ID to delete
|
|
607
|
+
|
|
608
|
+
Returns:
|
|
609
|
+
Confirmation of deletion`,
|
|
610
|
+
inputSchema: DeleteAutoModRuleSchema,
|
|
611
|
+
annotations: {
|
|
612
|
+
readOnlyHint: false,
|
|
613
|
+
destructiveHint: true,
|
|
614
|
+
idempotentHint: false,
|
|
615
|
+
openWorldHint: true,
|
|
616
|
+
},
|
|
617
|
+
}, async (params) => {
|
|
618
|
+
try {
|
|
619
|
+
const client = await getClient();
|
|
620
|
+
const guild = client.guilds.cache.get(params.guild_id);
|
|
621
|
+
if (!guild) {
|
|
622
|
+
return {
|
|
623
|
+
isError: true,
|
|
624
|
+
content: [{ type: "text", text: `Guild not found: ${params.guild_id}` }],
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
const rule = await guild.autoModerationRules.fetch(params.rule_id);
|
|
628
|
+
const ruleName = rule.name;
|
|
629
|
+
await rule.delete();
|
|
630
|
+
return {
|
|
631
|
+
content: [{ type: "text", text: `Deleted auto moderation rule "${ruleName}" (${params.rule_id})` }],
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
catch (error) {
|
|
635
|
+
return {
|
|
636
|
+
isError: true,
|
|
637
|
+
content: [{ type: "text", text: `Error deleting auto moderation rule: ${error.message}` }],
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
});
|
|
641
|
+
}
|