Skip to main content
Glama

Discord Agent MCP

by aj-geddes
emojis.ts11.4 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { DiscordClientManager } from "../discord/client.js"; import { Logger } from "../utils/logger.js"; import { z } from "zod"; import { PermissionDeniedError, InvalidInputError } from "../errors/discord.js"; import { validateGuildAccess } from "../utils/guild-validation.js"; import { PermissionFlagsBits } from "discord.js"; export function registerEmojiTools( server: McpServer, discordManager: DiscordClientManager, logger: Logger, ) { // List Guild Emojis Tool server.registerTool( "list_guild_emojis", { title: "List Guild Emojis", description: "Get all custom emojis for a guild", inputSchema: { guildId: z.string().describe("Guild ID"), }, outputSchema: { success: z.boolean(), emojis: z .array( z.object({ id: z.string(), name: z.string(), animated: z.boolean(), available: z.boolean(), managed: z.boolean(), requireColons: z.boolean(), roles: z.array(z.string()).optional(), creator: z .object({ id: z.string(), username: z.string(), discriminator: z.string(), }) .optional(), }), ) .optional(), count: z.number().optional(), error: z.string().optional(), }, }, async ({ guildId }) => { try { const client = discordManager.getClient(); const guild = await validateGuildAccess(client, guildId); // Fetch all emojis const emojis = await guild.emojis.fetch(); const emojiList = emojis.map((emoji) => ({ id: emoji.id, name: emoji.name || "unknown", animated: emoji.animated || false, available: emoji.available !== false, managed: emoji.managed || false, requireColons: emoji.requiresColons || false, roles: emoji.roles?.cache.map((r) => r.id) || [], creator: emoji.author ? { id: emoji.author.id, username: emoji.author.username, discriminator: emoji.author.discriminator, } : undefined, })); const output = { success: true, emojis: emojiList, count: emojiList.length, }; logger.info("Listed guild emojis", { guildId, count: emojiList.length }); return { content: [ { type: "text" as const, text: `Found ${emojiList.length} custom emojis in guild ${guild.name}`, }, ], structuredContent: output, }; } catch (error: any) { logger.error("Failed to list guild emojis", { error: error.message, guildId, }); return { content: [ { type: "text" as const, text: `Error: ${error.message}`, }, ], structuredContent: { success: false, error: error.message, }, }; } }, ); // Create Emoji Tool server.registerTool( "create_emoji", { title: "Create Guild Emoji", description: "Upload a custom emoji to the guild from base64 image data or file path", inputSchema: { guildId: z.string().describe("Guild ID"), name: z .string() .min(2) .max(32) .regex(/^\w+$/) .describe("Emoji name (2-32 alphanumeric characters and underscores)"), image: z .string() .describe( "Base64 encoded image data (data:image/png;base64,...) or file path", ), roles: z .array(z.string()) .optional() .describe("Array of role IDs that can use this emoji"), reason: z.string().optional().describe("Audit log reason"), }, outputSchema: { success: z.boolean(), emoji: z .object({ id: z.string(), name: z.string(), animated: z.boolean(), url: z.string(), }) .optional(), error: z.string().optional(), }, }, async ({ guildId, name, image, roles, reason }) => { try { const client = discordManager.getClient(); const guild = await validateGuildAccess(client, guildId); // Check permissions const botMember = await guild.members.fetch(client.user!.id); if ( !botMember.permissions.has(PermissionFlagsBits.ManageGuildExpressions) ) { throw new PermissionDeniedError( "ManageGuildExpressions", guildId, ); } // Validate image format if (!image.startsWith("data:image/") && !image.startsWith("/")) { throw new InvalidInputError( "image", "Must be base64 data URI or absolute file path", ); } // Create emoji const emoji = await guild.emojis.create({ attachment: image, name: name, roles: roles || [], reason: reason, }); const output = { success: true, emoji: { id: emoji.id, name: emoji.name || name, animated: emoji.animated || false, url: emoji.imageURL() || "", }, }; logger.info("Created emoji", { guildId, emojiId: emoji.id, name, }); return { content: [ { type: "text" as const, text: `Created emoji :${emoji.name}: in ${guild.name}`, }, ], structuredContent: output, }; } catch (error: any) { logger.error("Failed to create emoji", { error: error.message, guildId, name, }); return { content: [ { type: "text" as const, text: `Error: ${error.message}`, }, ], structuredContent: { success: false, error: error.message, }, }; } }, ); // Modify Emoji Tool server.registerTool( "modify_emoji", { title: "Modify Guild Emoji", description: "Update an existing custom emoji's name or role restrictions", inputSchema: { guildId: z.string().describe("Guild ID"), emojiId: z.string().describe("Emoji ID to modify"), name: z .string() .min(2) .max(32) .regex(/^\w+$/) .optional() .describe("New emoji name"), roles: z .array(z.string()) .optional() .describe("New array of role IDs (replaces existing)"), reason: z.string().optional().describe("Audit log reason"), }, outputSchema: { success: z.boolean(), emoji: z .object({ id: z.string(), name: z.string(), roles: z.array(z.string()), }) .optional(), error: z.string().optional(), }, }, async ({ guildId, emojiId, name, roles, reason }) => { try { const client = discordManager.getClient(); const guild = await validateGuildAccess(client, guildId); // Check permissions const botMember = await guild.members.fetch(client.user!.id); if ( !botMember.permissions.has(PermissionFlagsBits.ManageGuildExpressions) ) { throw new PermissionDeniedError( "ManageGuildExpressions", guildId, ); } // Fetch emoji const emoji = await guild.emojis.fetch(emojiId); if (!emoji) { throw new InvalidInputError("emojiId", "Emoji not found"); } // Update emoji const updated = await emoji.edit({ name: name, roles: roles, reason: reason, }); const output = { success: true, emoji: { id: updated.id, name: updated.name || "", roles: updated.roles?.cache.map((r) => r.id) || [], }, }; logger.info("Modified emoji", { guildId, emojiId, }); return { content: [ { type: "text" as const, text: `Updated emoji :${updated.name}: in ${guild.name}`, }, ], structuredContent: output, }; } catch (error: any) { logger.error("Failed to modify emoji", { error: error.message, guildId, emojiId, }); return { content: [ { type: "text" as const, text: `Error: ${error.message}`, }, ], structuredContent: { success: false, error: error.message, }, }; } }, ); // Delete Emoji Tool server.registerTool( "delete_emoji", { title: "Delete Guild Emoji", description: "Delete a custom emoji from the guild", inputSchema: { guildId: z.string().describe("Guild ID"), emojiId: z.string().describe("Emoji ID to delete"), reason: z.string().optional().describe("Audit log reason"), }, outputSchema: { success: z.boolean(), emojiId: z.string().optional(), error: z.string().optional(), }, }, async ({ guildId, emojiId, reason }) => { try { const client = discordManager.getClient(); const guild = await validateGuildAccess(client, guildId); // Check permissions const botMember = await guild.members.fetch(client.user!.id); if ( !botMember.permissions.has(PermissionFlagsBits.ManageGuildExpressions) ) { throw new PermissionDeniedError( "ManageGuildExpressions", guildId, ); } // Fetch emoji const emoji = await guild.emojis.fetch(emojiId); if (!emoji) { throw new InvalidInputError("emojiId", "Emoji not found"); } const emojiName = emoji.name; // Delete emoji await emoji.delete(reason); const output = { success: true, emojiId: emojiId, }; logger.info("Deleted emoji", { guildId, emojiId, }); return { content: [ { type: "text" as const, text: `Deleted emoji :${emojiName}: from ${guild.name}`, }, ], structuredContent: output, }; } catch (error: any) { logger.error("Failed to delete emoji", { error: error.message, guildId, emojiId, }); return { content: [ { type: "text" as const, text: `Error: ${error.message}`, }, ], structuredContent: { success: false, error: error.message, }, }; } }, ); }

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/aj-geddes/discord-agent-mcp'

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