import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
import { getDiscordClient } from '../utils/discord-client.js';
import { withErrorHandling } from '../utils/error-handler.js';
export function registerServerTools(server: McpServer): void {
// List servers (guilds) the bot has access to
server.tool(
'list_servers',
'List all Discord servers (guilds) the bot has access to',
{},
async () => {
const result = await withErrorHandling(async () => {
const client = await getDiscordClient();
const guilds = client.guilds.cache.map((guild) => ({
id: guild.id,
name: guild.name,
memberCount: guild.memberCount,
ownerId: guild.ownerId,
icon: guild.iconURL(),
}));
return guilds;
});
if (!result.success) {
return { content: [{ type: 'text', text: result.error }], isError: true };
}
return {
content: [
{
type: 'text',
text: JSON.stringify(result.data, null, 2),
},
],
};
}
);
// Get detailed server information
server.tool(
'get_server_info',
'Get detailed information about a specific 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);
// Fetch additional data
const channels = guild.channels.cache;
const roles = guild.roles.cache;
return {
id: guild.id,
name: guild.name,
description: guild.description,
memberCount: guild.memberCount,
ownerId: guild.ownerId,
createdAt: guild.createdAt.toISOString(),
icon: guild.iconURL(),
banner: guild.bannerURL(),
verificationLevel: guild.verificationLevel,
premiumTier: guild.premiumTier,
premiumSubscriptionCount: guild.premiumSubscriptionCount,
preferredLocale: guild.preferredLocale,
systemChannelId: guild.systemChannelId,
rulesChannelId: guild.rulesChannelId,
afkChannelId: guild.afkChannelId,
afkTimeout: guild.afkTimeout,
features: guild.features,
channelCount: channels.size,
roleCount: roles.size,
channels: channels.map((ch) => ({
id: ch.id,
name: ch.name,
type: ch.type,
})),
roles: roles.map((role) => ({
id: role.id,
name: role.name,
color: role.hexColor,
position: role.position,
})),
};
});
if (!result.success) {
return { content: [{ type: 'text', text: result.error }], isError: true };
}
return {
content: [
{
type: 'text',
text: JSON.stringify(result.data, null, 2),
},
],
};
}
);
// Modify server settings
server.tool(
'modify_server',
'Modify server settings (requires appropriate permissions)',
{
guildId: z.string().describe('The ID of the server (guild)'),
name: z.string().optional().describe('New server name'),
description: z.string().optional().describe('New server description'),
afkChannelId: z.string().optional().describe('ID of the AFK channel'),
afkTimeout: z.number().optional().describe('AFK timeout in seconds'),
systemChannelId: z.string().optional().describe('ID of the system channel'),
rulesChannelId: z.string().optional().describe('ID of the rules channel'),
reason: z.string().optional().describe('Reason for the modification'),
},
async ({ guildId, name, description, afkChannelId, afkTimeout, systemChannelId, rulesChannelId, reason }) => {
const result = await withErrorHandling(async () => {
const client = await getDiscordClient();
const guild = await client.guilds.fetch(guildId);
const updateData: Record<string, unknown> = {};
if (name !== undefined) updateData.name = name;
if (description !== undefined) updateData.description = description;
if (afkChannelId !== undefined) updateData.afkChannel = afkChannelId;
if (afkTimeout !== undefined) updateData.afkTimeout = afkTimeout;
if (systemChannelId !== undefined) updateData.systemChannel = systemChannelId;
if (rulesChannelId !== undefined) updateData.rulesChannel = rulesChannelId;
if (reason !== undefined) updateData.reason = reason;
const updatedGuild = await guild.edit(updateData);
return {
id: updatedGuild.id,
name: updatedGuild.name,
description: updatedGuild.description,
message: 'Server settings 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),
},
],
};
}
);
}