feat: Discord + Instagram integrations
Discord Bot API
- New client: src/clients/discord.ts
- Tools: discord_get_me, discord_get_guilds, discord_get_channels, discord_send_message, discord_get_messages
- REST endpoints: GET /api/discord/me, /api/discord/guilds, /api/discord/channels, /api/discord/messages, POST /api/discord/message
- Multi-account env var: DISCORD_{ACCOUNT}_BOT_TOKEN
Instagram Graph API
- New client: src/clients/instagram.ts
- Tools: instagram_get_profile, instagram_get_media, instagram_create_post
- REST endpoints: GET /api/instagram/profile, /api/instagram/media, POST /api/instagram/post
- Multi-account env vars: INSTAGRAM_{ACCOUNT}_ACCESS_TOKEN, INSTAGRAM_{ACCOUNT}_BUSINESS_ACCOUNT_ID
Total tools: 32
This commit is contained in:
164
src/tools.ts
164
src/tools.ts
@@ -5,6 +5,8 @@ import { searchNotes, getNote, appendToNote, updateNote, getSyncStatus } from '.
|
||||
import { sendMessage, sendTemplate, getMessageStatus, listTemplates } from './clients/whatsapp.js';
|
||||
import { getProfile as getLinkedInProfile, createPost as createLinkedInPost, searchConnections, sendMessage as sendLinkedInMessage } from './clients/linkedin.js';
|
||||
import { getMe as getTelegramMe, sendMessage as sendTelegramMessage, sendPhoto as sendTelegramPhoto, getUpdates as getTelegramUpdates, getChat as getTelegramChat } from './clients/telegram.js';
|
||||
import { getMe as getDiscordMe, getGuilds, getChannels, sendMessage as sendDiscordMessage, getMessages as getDiscordMessages } from './clients/discord.js';
|
||||
import { getProfile as getInstagramProfile, getMedia as getInstagramMedia, createPost as createInstagramPost } from './clients/instagram.js';
|
||||
|
||||
const ACCOUNT_PARAM = {
|
||||
account: {
|
||||
@@ -353,6 +355,110 @@ export const tools: Tool[] = [
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ── Discord tools ────────────────────────────────────────────
|
||||
{
|
||||
name: 'discord_get_me',
|
||||
description:
|
||||
'Get information about the Discord bot. Use to verify the bot is connected and get its username.',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
account: { type: 'string', description: 'Which Discord account to use (default: "default")' },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'discord_get_guilds',
|
||||
description:
|
||||
'List Discord servers (guilds) the bot is a member of. Use to find server IDs for sending messages.',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
account: { type: 'string', description: 'Which Discord account to use (default: "default")' },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'discord_get_channels',
|
||||
description:
|
||||
'List channels in a Discord server. Use to find channel IDs for sending messages.',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
required: ['guild_id'],
|
||||
properties: {
|
||||
guild_id: { type: 'string', description: 'Discord server (guild) ID' },
|
||||
account: { type: 'string', description: 'Which Discord account to use (default: "default")' },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'discord_send_message',
|
||||
description:
|
||||
'Send a message to a Discord channel. Use when the user wants to post in a Discord server.',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
required: ['channel_id', 'content'],
|
||||
properties: {
|
||||
channel_id: { type: 'string', description: 'Discord channel ID' },
|
||||
content: { type: 'string', description: 'Message content (up to 2000 chars)' },
|
||||
account: { type: 'string', description: 'Which Discord account to use (default: "default")' },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'discord_get_messages',
|
||||
description:
|
||||
'Get recent messages from a Discord channel. Use to read chat history.',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
required: ['channel_id'],
|
||||
properties: {
|
||||
channel_id: { type: 'string', description: 'Discord channel ID' },
|
||||
limit: { type: 'number', description: 'Max messages to return (default: 10, max: 100)' },
|
||||
account: { type: 'string', description: 'Which Discord account to use (default: "default")' },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ── Instagram tools ──────────────────────────────────────────
|
||||
{
|
||||
name: 'instagram_get_profile',
|
||||
description:
|
||||
'Get Instagram Business/Creator account profile info. Use when the user asks about their Instagram stats, followers, or account details.',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
account: { type: 'string', description: 'Which Instagram account to use (default: "default")' },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'instagram_get_media',
|
||||
description:
|
||||
'Get recent posts from an Instagram Business/Creator account. Use when the user wants to see their recent content.',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
limit: { type: 'number', description: 'Max posts to return (default: 10)' },
|
||||
account: { type: 'string', description: 'Which Instagram account to use (default: "default")' },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'instagram_create_post',
|
||||
description:
|
||||
'Create a post on Instagram. [REQUIRES BUSINESS ACCOUNT] Only works with Instagram Business/Creator accounts connected to a Facebook Page.',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
required: ['image_url'],
|
||||
properties: {
|
||||
image_url: { type: 'string', description: 'Publicly accessible URL of the image to post' },
|
||||
caption: { type: 'string', description: 'Post caption text' },
|
||||
account: { type: 'string', description: 'Which Instagram account to use (default: "default")' },
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
function acct(args: Record<string, unknown>): Account {
|
||||
@@ -525,6 +631,64 @@ export async function handleToolCall(
|
||||
});
|
||||
break;
|
||||
|
||||
// ── Discord ─────────────────────────────────────────────────
|
||||
case 'discord_get_me':
|
||||
result = await getDiscordMe({
|
||||
account: args.account as string | undefined,
|
||||
});
|
||||
break;
|
||||
|
||||
case 'discord_get_guilds':
|
||||
result = await getGuilds({
|
||||
account: args.account as string | undefined,
|
||||
});
|
||||
break;
|
||||
|
||||
case 'discord_get_channels':
|
||||
result = await getChannels({
|
||||
guild_id: args.guild_id as string,
|
||||
account: args.account as string | undefined,
|
||||
});
|
||||
break;
|
||||
|
||||
case 'discord_send_message':
|
||||
result = await sendDiscordMessage({
|
||||
channel_id: args.channel_id as string,
|
||||
content: args.content as string,
|
||||
account: args.account as string | undefined,
|
||||
});
|
||||
break;
|
||||
|
||||
case 'discord_get_messages':
|
||||
result = await getDiscordMessages({
|
||||
channel_id: args.channel_id as string,
|
||||
limit: (args.limit as number) ?? 10,
|
||||
account: args.account as string | undefined,
|
||||
});
|
||||
break;
|
||||
|
||||
// ── Instagram ───────────────────────────────────────────────
|
||||
case 'instagram_get_profile':
|
||||
result = await getInstagramProfile({
|
||||
account: args.account as string | undefined,
|
||||
});
|
||||
break;
|
||||
|
||||
case 'instagram_get_media':
|
||||
result = await getInstagramMedia({
|
||||
limit: (args.limit as number) ?? 10,
|
||||
account: args.account as string | undefined,
|
||||
});
|
||||
break;
|
||||
|
||||
case 'instagram_create_post':
|
||||
result = await createInstagramPost({
|
||||
image_url: args.image_url as string,
|
||||
caption: args.caption as string | undefined,
|
||||
account: args.account as string | undefined,
|
||||
});
|
||||
break;
|
||||
|
||||
// Legacy Yahoo-prefixed names — keep working for any cached Claude sessions
|
||||
case 'yahoo_get_profile':
|
||||
result = await getProfile('yahoo');
|
||||
|
||||
Reference in New Issue
Block a user