Skip to main content
Glama
channel-tools.ts10 kB
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { ChannelType, PermissionFlagsBits, GuildChannel, TextChannel, VoiceChannel } from 'discord.js'; import { getDiscordClient } from '../utils/discord-client.js'; import { withErrorHandling } from '../utils/error-handler.js'; const channelTypeMap: Record<string, ChannelType> = { text: ChannelType.GuildText, voice: ChannelType.GuildVoice, category: ChannelType.GuildCategory, announcement: ChannelType.GuildAnnouncement, forum: ChannelType.GuildForum, stage: ChannelType.GuildStageVoice, }; export function registerChannelTools(server: McpServer): void { // List all channels in a server server.tool( 'list_channels', 'List all channels in a Discord server', { guildId: z.string().describe('The ID of the server (guild)'), }, async ({ guildId }) => { const result = await withErrorHandling(async () => { const client = await getDiscordClient(); const guild = await client.guilds.fetch(guildId); const channels = await guild.channels.fetch(); return channels.map((ch) => ({ id: ch?.id, name: ch?.name, type: ch?.type, typeName: ChannelType[ch?.type ?? 0], parentId: (ch as GuildChannel)?.parentId, position: (ch as GuildChannel)?.position, })).filter((ch) => ch.id); }); if (!result.success) { return { content: [{ type: 'text', text: result.error }], isError: true }; } return { content: [{ type: 'text', text: JSON.stringify(result.data, null, 2) }] }; } ); // Get channel information server.tool( 'get_channel_info', 'Get detailed information about a specific channel', { guildId: z.string().describe('The ID of the server (guild)'), channelId: z.string().describe('The ID of the channel'), }, async ({ guildId, channelId }) => { const result = await withErrorHandling(async () => { const client = await getDiscordClient(); const guild = await client.guilds.fetch(guildId); const channel = await guild.channels.fetch(channelId); if (!channel) throw new Error('Channel not found'); // Cast to GuildChannel for common properties const guildChannel = channel as GuildChannel; const baseInfo: Record<string, unknown> = { id: channel.id, name: channel.name, type: channel.type, typeName: ChannelType[channel.type], parentId: guildChannel.parentId, createdAt: channel.createdAt?.toISOString(), }; // Add position and permission overwrites for non-thread channels if ('position' in guildChannel) { baseInfo.position = guildChannel.position; } if ('permissionOverwrites' in guildChannel && guildChannel.permissionOverwrites) { baseInfo.permissionOverwrites = guildChannel.permissionOverwrites.cache.map((po) => ({ id: po.id, type: po.type, allow: po.allow.toArray(), deny: po.deny.toArray(), })); } // Add text channel specific info if (channel.type === ChannelType.GuildText || channel.type === ChannelType.GuildAnnouncement) { const textChannel = channel as TextChannel; return { ...baseInfo, topic: textChannel.topic, nsfw: textChannel.nsfw, rateLimitPerUser: textChannel.rateLimitPerUser, }; } // Add voice channel specific info if (channel.type === ChannelType.GuildVoice || channel.type === ChannelType.GuildStageVoice) { const voiceChannel = channel as VoiceChannel; return { ...baseInfo, bitrate: voiceChannel.bitrate, userLimit: voiceChannel.userLimit, rtcRegion: voiceChannel.rtcRegion, }; } return baseInfo; }); if (!result.success) { return { content: [{ type: 'text', text: result.error }], isError: true }; } return { content: [{ type: 'text', text: JSON.stringify(result.data, null, 2) }] }; } ); // Create a new channel server.tool( 'create_channel', 'Create a new channel in a Discord server', { guildId: z.string().describe('The ID of the server (guild)'), name: z.string().describe('Name of the new channel'), type: z.enum(['text', 'voice', 'category', 'announcement', 'forum', 'stage']).describe('Type of channel'), parentId: z.string().optional().describe('ID of the parent category'), topic: z.string().optional().describe('Channel topic (text channels only)'), nsfw: z.boolean().optional().describe('Whether the channel is NSFW'), bitrate: z.number().optional().describe('Bitrate for voice channels'), userLimit: z.number().optional().describe('User limit for voice channels'), rateLimitPerUser: z.number().optional().describe('Slowmode in seconds'), position: z.number().optional().describe('Position of the channel'), reason: z.string().optional().describe('Reason for creating the channel'), }, async ({ guildId, name, type, parentId, topic, nsfw, bitrate, userLimit, rateLimitPerUser, position, reason }) => { const result = await withErrorHandling(async () => { const client = await getDiscordClient(); const guild = await client.guilds.fetch(guildId); const channelOptions: Record<string, unknown> = { name, type: channelTypeMap[type], parent: parentId, topic, nsfw, bitrate, userLimit, rateLimitPerUser, position, reason, }; // Remove undefined values Object.keys(channelOptions).forEach((key) => { if (channelOptions[key] === undefined) delete channelOptions[key]; }); const newChannel = await guild.channels.create(channelOptions as any); return { id: newChannel.id, name: newChannel.name, type: ChannelType[newChannel.type], message: 'Channel created' }; }); if (!result.success) { return { content: [{ type: 'text', text: result.error }], isError: true }; } return { content: [{ type: 'text', text: JSON.stringify(result.data, null, 2) }] }; } ); // Delete a channel server.tool( 'delete_channel', 'Delete a channel from a Discord server', { guildId: z.string().describe('The ID of the server (guild)'), channelId: z.string().describe('The ID of the channel to delete'), reason: z.string().optional().describe('Reason for deleting the channel'), }, async ({ guildId, channelId, reason }) => { const result = await withErrorHandling(async () => { const client = await getDiscordClient(); const guild = await client.guilds.fetch(guildId); const channel = await guild.channels.fetch(channelId); if (!channel) throw new Error('Channel not found'); const channelName = channel.name; await channel.delete(reason); return { channelId, channelName, message: 'Channel deleted successfully' }; }); if (!result.success) { return { content: [{ type: 'text', text: result.error }], isError: true }; } return { content: [{ type: 'text', text: JSON.stringify(result.data, null, 2) }] }; } ); // Modify channel settings server.tool( 'modify_channel', 'Modify channel settings (name, topic, permissions, position, etc.)', { guildId: z.string().describe('The ID of the server (guild)'), channelId: z.string().describe('The ID of the channel to modify'), name: z.string().optional().describe('New channel name'), topic: z.string().optional().describe('New channel topic'), nsfw: z.boolean().optional().describe('Whether the channel is NSFW'), parentId: z.string().optional().describe('New parent category ID'), position: z.number().optional().describe('New channel position'), rateLimitPerUser: z.number().optional().describe('New slowmode in seconds'), bitrate: z.number().optional().describe('New bitrate (voice channels)'), userLimit: z.number().optional().describe('New user limit (voice channels)'), reason: z.string().optional().describe('Reason for the modification'), }, async ({ guildId, channelId, name, topic, nsfw, parentId, position, rateLimitPerUser, bitrate, userLimit, reason }) => { const result = await withErrorHandling(async () => { const client = await getDiscordClient(); const guild = await client.guilds.fetch(guildId); const channel = await guild.channels.fetch(channelId); if (!channel) throw new Error('Channel not found'); const updateData: Record<string, unknown> = {}; if (name !== undefined) updateData.name = name; if (topic !== undefined) updateData.topic = topic; if (nsfw !== undefined) updateData.nsfw = nsfw; if (parentId !== undefined) updateData.parent = parentId; if (position !== undefined) updateData.position = position; if (rateLimitPerUser !== undefined) updateData.rateLimitPerUser = rateLimitPerUser; if (bitrate !== undefined) updateData.bitrate = bitrate; if (userLimit !== undefined) updateData.userLimit = userLimit; if (reason !== undefined) updateData.reason = reason; const updatedChannel = await channel.edit(updateData); return { id: updatedChannel.id, name: updatedChannel.name, type: ChannelType[updatedChannel.type], message: 'Channel updated successfully', }; }); if (!result.success) { return { content: [{ type: 'text', text: result.error }], isError: true }; } return { content: [{ type: 'text', text: JSON.stringify(result.data, null, 2) }] }; } ); }

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/scarecr0w12/discord-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server