@mahesvara/discord-mcpserver 1.0.8 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/index.js +4 -2833
  2. package/dist/schemas/channel.d.ts +176 -0
  3. package/dist/schemas/channel.js +146 -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 +572 -0
  32. package/dist/tools/community.d.ts +2 -0
  33. package/dist/tools/community.js +268 -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,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
+ }
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerRoleTools(server: McpServer): void;