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:
Garfield
2026-05-05 22:01:21 -04:00
parent 385f91de4d
commit e1e7d88c8a
6 changed files with 724 additions and 0 deletions

View File

@@ -703,6 +703,214 @@ export function getManifest(serverUrl: string, authEnabled: boolean) {
examples: [{ chat_id: '@mychannel', account: 'default' }],
},
// ── Discord tools ──────────────────────────────────────────────────────
{
name: 'discord_get_me',
category: 'discord',
description: 'Get information about the Discord bot',
when_to_use:
'User asks about the Discord bot, wants to verify it is connected, or needs the bot username.',
input_schema: {
type: 'object',
properties: {
account: { type: 'string', description: 'Which Discord account to use (default: "default")' },
},
},
returns: {
type: 'object',
properties: {
id: { type: 'string', description: 'Bot user ID' },
username: { type: 'string' },
bot: { type: 'boolean' },
},
},
examples: [{ account: 'default' }],
},
{
name: 'discord_get_guilds',
category: 'discord',
description: 'List Discord servers the bot is in',
when_to_use:
'User wants to know which Discord servers are available or needs a server ID.',
input_schema: {
type: 'object',
properties: {
account: { type: 'string', description: 'Which Discord account to use (default: "default")' },
},
},
returns: {
type: 'array',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Guild ID' },
name: { type: 'string', description: 'Server name' },
},
},
},
examples: [{ account: 'default' }],
},
{
name: 'discord_get_channels',
category: 'discord',
description: 'List channels in a Discord server',
when_to_use:
'User needs to find a channel ID to send a message to.',
input_schema: {
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")' },
},
},
returns: {
type: 'array',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Channel ID' },
name: { type: 'string' },
type: { type: 'number', description: 'Channel type code' },
},
},
},
examples: [{ guild_id: '1234567890123456789', account: 'default' }],
},
{
name: 'discord_send_message',
category: 'discord',
description: 'Send a message to a Discord channel',
when_to_use:
'User wants to post a message in a Discord server channel.',
input_schema: {
type: 'object',
required: ['channel_id', 'content'],
properties: {
channel_id: { type: 'string', description: 'Discord channel ID' },
content: { type: 'string', description: 'Message content (max 2000 chars)' },
account: { type: 'string', description: 'Which Discord account to use (default: "default")' },
},
},
returns: {
type: 'object',
properties: {
id: { type: 'string', description: 'Message ID' },
channel_id: { type: 'string' },
},
},
examples: [{ channel_id: '1234567890123456789', content: 'Hello Discord!', account: 'default' }],
},
{
name: 'discord_get_messages',
category: 'discord',
description: 'Get recent messages from a Discord channel',
when_to_use:
'User wants to read recent chat history from a Discord channel.',
input_schema: {
type: 'object',
required: ['channel_id'],
properties: {
channel_id: { type: 'string', description: 'Discord channel ID' },
limit: { type: 'number', description: 'Max messages (default: 10, max: 100)' },
account: { type: 'string', description: 'Which Discord account to use (default: "default")' },
},
},
returns: {
type: 'array',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Message ID' },
content: { type: 'string' },
author: { type: 'object', properties: { username: { type: 'string' }, id: { type: 'string' } } },
timestamp: { type: 'string', format: 'date-time' },
},
},
},
examples: [{ channel_id: '1234567890123456789', limit: 10, account: 'default' }],
},
// ── Instagram tools ────────────────────────────────────────────────────
{
name: 'instagram_get_profile',
category: 'instagram',
description: 'Get Instagram Business/Creator account profile',
when_to_use:
'User asks about their Instagram stats, followers, or account details.',
input_schema: {
type: 'object',
properties: {
account: { type: 'string', description: 'Which Instagram account to use (default: "default")' },
},
},
returns: {
type: 'object',
properties: {
id: { type: 'string' },
username: { type: 'string' },
name: { type: 'string' },
followers_count: { type: 'number' },
follows_count: { type: 'number' },
media_count: { type: 'number' },
},
},
examples: [{ account: 'default' }],
},
{
name: 'instagram_get_media',
category: 'instagram',
description: 'Get recent posts from Instagram',
when_to_use:
'User wants to see their recent Instagram content.',
input_schema: {
type: 'object',
properties: {
limit: { type: 'number', description: 'Max posts (default: 10)' },
account: { type: 'string', description: 'Which Instagram account to use (default: "default")' },
},
},
returns: {
type: 'array',
items: {
type: 'object',
properties: {
id: { type: 'string' },
caption: { type: 'string' },
media_type: { type: 'string' },
media_url: { type: 'string' },
permalink: { type: 'string' },
timestamp: { type: 'string' },
},
},
},
examples: [{ limit: 5, account: 'default' }],
},
{
name: 'instagram_create_post',
category: 'instagram',
description: 'Create a post on Instagram',
when_to_use:
'User wants to publish an image to their Instagram Business/Creator account.',
input_schema: {
type: 'object',
required: ['image_url'],
properties: {
image_url: { type: 'string', description: 'Publicly accessible image URL' },
caption: { type: 'string', description: 'Post caption' },
account: { type: 'string', description: 'Which Instagram account to use (default: "default")' },
},
},
returns: {
type: 'object',
properties: {
success: { type: 'boolean' },
media_id: { type: 'string' },
},
},
examples: [{ image_url: 'https://example.com/photo.jpg', caption: 'New post!', account: 'default' }],
},
// ── Obsidian tools ──────────────────────────────────────────────────────
{
name: 'obsidian_search_notes',
@@ -874,6 +1082,14 @@ export function getManifest(serverUrl: string, authEnabled: boolean) {
description: 'Telegram messaging via Bot API',
icon: '✈️',
},
discord: {
description: 'Discord server messaging via Bot API',
icon: '🎮',
},
instagram: {
description: 'Instagram Business/Creator account via Graph API',
icon: '📸',
},
},
};
}