const SCHEMA_VERSION = '1.0.0';

export function getOpenApiSpec(serverUrl: string) {
  return {
    openapi: '3.1.0',
    info: {
      title: 'Hermes',
      description: 'Personal AI tools: Obsidian vault (create, read, update, search notes) and email operations across multiple accounts.',
      version: '1.0.0',
    },
    servers: [{ url: serverUrl }],
    security: [{ bearerAuth: [] }],
    components: {
      schemas: {},
      securitySchemes: {
        bearerAuth: { type: 'http', scheme: 'bearer' },
      },
    },
    paths: {
      '/api/obsidian/search': {
        get: {
          operationId: 'obsidian_search_notes',
          summary: 'Search Obsidian notes',
          description: 'Full-text search across the vault by content, title, or tags. Returns matching note paths, excerpts, and metadata.',
          parameters: [
            { name: 'query', in: 'query', required: true, schema: { type: 'string' }, description: 'Text to search for in note content or title' },
            { name: 'limit', in: 'query', schema: { type: 'integer', default: 10 }, description: 'Maximum number of results to return' },
            { name: 'path_filter', in: 'query', schema: { type: 'string' }, description: 'Only return notes whose path contains this string (e.g. "Daily Notes" or "SquareMCP")' },
            { name: 'tags', in: 'query', schema: { type: 'string' }, description: 'Comma-separated list of tags all results must have' },
          ],
          responses: {
            '200': {
              description: 'Matching notes',
              content: {
                'application/json': {
                  schema: {
                    type: 'array',
                    items: {
                      type: 'object',
                      properties: {
                        path: { type: 'string', description: 'Relative vault path — use this as-is in other calls' },
                        title: { type: 'string' },
                        excerpt: { type: 'string', description: 'Matched text excerpt (~200 chars)' },
                        tags: { type: 'array', items: { type: 'string' } },
                        modified_date: { type: 'string', format: 'date-time' },
                      },
                    },
                  },
                },
              },
            },
          },
        },
      },
      '/api/obsidian/note': {
        get: {
          operationId: 'obsidian_read_note',
          summary: 'Read an Obsidian note',
          description: 'Retrieve the full markdown content of a specific note by its vault path.',
          parameters: [
            { name: 'path', in: 'query', required: true, schema: { type: 'string' }, description: 'Relative vault path (e.g. "CMG Project/SoFi First Principles Readout for CMG and AIO.md")' },
          ],
          responses: {
            '200': {
              description: 'Full note',
              content: {
                'application/json': {
                  schema: {
                    type: 'object',
                    properties: {
                      path: { type: 'string' },
                      title: { type: 'string' },
                      content: { type: 'string', description: 'Full markdown content' },
                      tags: { type: 'array', items: { type: 'string' } },
                      links: { type: 'array', items: { type: 'string' }, description: 'Internal [[wiki-links]] found in note' },
                      modified_date: { type: 'string', format: 'date-time' },
                    },
                  },
                },
              },
            },
            '404': { description: 'Note not found' },
          },
        },
        put: {
          operationId: 'obsidian_update_note',
          summary: 'Overwrite an Obsidian note',
          description: 'Replace the entire content of a note with new markdown. Creates the note if it does not exist. Use this for rewrites or structural edits; use the append endpoint for adding content.',
          requestBody: {
            required: true,
            content: {
              'application/json': {
                schema: {
                  type: 'object',
                  required: ['path', 'content'],
                  properties: {
                    path: { type: 'string', description: 'Relative vault path' },
                    content: { type: 'string', description: 'Full markdown content — replaces existing content entirely' },
                  },
                },
              },
            },
          },
          responses: {
            '200': {
              description: 'Note written',
              content: {
                'application/json': {
                  schema: {
                    type: 'object',
                    properties: {
                      success: { type: 'boolean' },
                      path: { type: 'string' },
                      bytes_written: { type: 'integer' },
                    },
                  },
                },
              },
            },
          },
        },
      },
      '/api/obsidian/note/append': {
        post: {
          operationId: 'obsidian_append_to_note',
          summary: 'Append to an Obsidian note',
          description: 'Add markdown content to the end of a note, optionally under an H2 section header. Creates the note if it does not exist.',
          requestBody: {
            required: true,
            content: {
              'application/json': {
                schema: {
                  type: 'object',
                  required: ['path', 'content'],
                  properties: {
                    path: { type: 'string', description: 'Relative vault path (e.g. "Daily Notes/2026-04-28.md")' },
                    content: { type: 'string', description: 'Markdown content to append' },
                    header: { type: 'string', description: 'Optional H2 section header inserted before the content' },
                    create_if_missing: { type: 'boolean', default: true, description: 'Create the note if it does not exist' },
                  },
                },
              },
            },
          },
          responses: {
            '200': {
              description: 'Content appended',
              content: {
                'application/json': {
                  schema: {
                    type: 'object',
                    properties: {
                      success: { type: 'boolean' },
                      path: { type: 'string' },
                      bytes_written: { type: 'integer' },
                    },
                  },
                },
              },
            },
          },
        },
      },
      '/api/obsidian/sync': {
        get: {
          operationId: 'obsidian_sync_status',
          summary: 'Check vault sync status',
          description: 'Returns Syncthing sync state and vault statistics.',
          responses: {
            '200': {
              description: 'Sync status',
              content: {
                'application/json': {
                  schema: {
                    type: 'object',
                    properties: {
                      status: { type: 'string', description: 'Syncthing state (idle, syncing, error, etc.)' },
                      last_sync: { type: 'string', format: 'date-time', nullable: true },
                      vault_size: { type: 'integer', description: 'Total vault size in bytes' },
                      pending_changes: { type: 'integer', description: 'Files awaiting sync' },
                    },
                  },
                },
              },
            },
          },
        },
      },

      // ── Email ───────────────────────────────────────────────────
      '/api/email/profile': {
        get: {
          operationId: 'get_profile',
          summary: 'Get email account profile',
          parameters: [
            { name: 'account', in: 'query', schema: { type: 'string' }, description: 'Mailbox account (yahoo, fetcherpay, garfield, sales, leads, founder, gmail)' },
          ],
          responses: { '200': { description: 'Profile info' } },
        },
      },
      '/api/email/search': {
        get: {
          operationId: 'search_messages',
          summary: 'Search email messages',
          parameters: [
            { name: 'q', in: 'query', required: true, schema: { type: 'string' } },
            { name: 'maxResults', in: 'query', schema: { type: 'integer', default: 20 } },
            { name: 'account', in: 'query', schema: { type: 'string' } },
            { name: 'folder', in: 'query', schema: { type: 'string' } },
          ],
          responses: { '200': { description: 'Search results' } },
        },
      },
      '/api/email/read': {
        get: {
          operationId: 'read_message',
          summary: 'Read email by UID',
          parameters: [
            { name: 'uid', in: 'query', required: true, schema: { type: 'integer' } },
            { name: 'account', in: 'query', schema: { type: 'string' } },
            { name: 'folder', in: 'query', schema: { type: 'string' } },
          ],
          responses: { '200': { description: 'Message body' } },
        },
      },
      '/api/email/send': {
        post: {
          operationId: 'send_email',
          summary: 'Send email',
          requestBody: {
            required: true,
            content: {
              'application/json': {
                schema: {
                  type: 'object',
                  required: ['to', 'subject', 'body'],
                  properties: {
                    to: { type: 'string' },
                    subject: { type: 'string' },
                    body: { type: 'string' },
                    account: { type: 'string' },
                  },
                },
              },
            },
          },
          responses: { '200': { description: 'Email sent' } },
        },
      },

      // ── WhatsApp ────────────────────────────────────────────────
      '/api/whatsapp/send': {
        post: {
          operationId: 'whatsapp_send_message',
          summary: 'Send WhatsApp message',
          requestBody: {
            required: true,
            content: {
              'application/json': {
                schema: {
                  type: 'object',
                  required: ['to', 'message'],
                  properties: {
                    to: { type: 'string', description: 'Phone number in international format' },
                    message: { type: 'string' },
                    account: { type: 'string' },
                  },
                },
              },
            },
          },
          responses: { '200': { description: 'Message sent' } },
        },
      },
      '/api/whatsapp/template': {
        post: {
          operationId: 'whatsapp_send_template',
          summary: 'Send WhatsApp template',
          requestBody: {
            required: true,
            content: {
              'application/json': {
                schema: {
                  type: 'object',
                  required: ['to', 'template_name'],
                  properties: {
                    to: { type: 'string' },
                    template_name: { type: 'string' },
                    language: { type: 'string' },
                    components: { type: 'array', items: { type: 'object' } },
                    account: { type: 'string' },
                  },
                },
              },
            },
          },
          responses: { '200': { description: 'Template sent' } },
        },
      },
      '/api/whatsapp/templates': {
        get: {
          operationId: 'whatsapp_list_templates',
          summary: 'List WhatsApp templates',
          parameters: [
            { name: 'account', in: 'query', schema: { type: 'string' } },
          ],
          responses: { '200': { description: 'Template list' } },
        },
      },

      // ── LinkedIn ────────────────────────────────────────────────
      '/api/linkedin/profile': {
        get: {
          operationId: 'linkedin_get_profile',
          summary: 'Get LinkedIn profile',
          parameters: [
            { name: 'account', in: 'query', schema: { type: 'string' } },
          ],
          responses: { '200': { description: 'Profile info' } },
        },
      },
      '/api/linkedin/post': {
        post: {
          operationId: 'linkedin_create_post',
          summary: 'Create LinkedIn post',
          requestBody: {
            required: true,
            content: {
              'application/json': {
                schema: {
                  type: 'object',
                  required: ['text'],
                  properties: {
                    text: { type: 'string' },
                    visibility: { type: 'string', enum: ['PUBLIC', 'CONNECTIONS'] },
                    account: { type: 'string' },
                  },
                },
              },
            },
          },
          responses: { '200': { description: 'Post created' } },
        },
      },

      // ── Telegram ────────────────────────────────────────────────
      '/api/telegram/message': {
        post: {
          operationId: 'telegram_send_message',
          summary: 'Send Telegram message',
          requestBody: {
            required: true,
            content: {
              'application/json': {
                schema: {
                  type: 'object',
                  required: ['chat_id', 'text'],
                  properties: {
                    chat_id: { type: 'string' },
                    text: { type: 'string' },
                    parse_mode: { type: 'string' },
                    account: { type: 'string' },
                  },
                },
              },
            },
          },
          responses: { '200': { description: 'Message sent' } },
        },
      },
      '/api/telegram/updates': {
        get: {
          operationId: 'telegram_get_updates',
          summary: 'Get Telegram updates',
          parameters: [
            { name: 'limit', in: 'query', schema: { type: 'integer' } },
            { name: 'account', in: 'query', schema: { type: 'string' } },
          ],
          responses: { '200': { description: 'Updates list' } },
        },
      },

      // ── Discord ─────────────────────────────────────────────────
      '/api/discord/guilds': {
        get: {
          operationId: 'discord_get_guilds',
          summary: 'List Discord servers',
          parameters: [
            { name: 'account', in: 'query', schema: { type: 'string' } },
          ],
          responses: { '200': { description: 'Guild list' } },
        },
      },
      '/api/discord/message': {
        post: {
          operationId: 'discord_send_message',
          summary: 'Send Discord message',
          requestBody: {
            required: true,
            content: {
              'application/json': {
                schema: {
                  type: 'object',
                  required: ['channel_id', 'content'],
                  properties: {
                    channel_id: { type: 'string' },
                    content: { type: 'string' },
                    account: { type: 'string' },
                  },
                },
              },
            },
          },
          responses: { '200': { description: 'Message sent' } },
        },
      },
      '/api/discord/messages': {
        get: {
          operationId: 'discord_get_messages',
          summary: 'Get Discord messages',
          parameters: [
            { name: 'channel_id', in: 'query', required: true, schema: { type: 'string' } },
            { name: 'limit', in: 'query', schema: { type: 'integer' } },
            { name: 'account', in: 'query', schema: { type: 'string' } },
          ],
          responses: { '200': { description: 'Message list' } },
        },
      },

      // ── Instagram ───────────────────────────────────────────────
      '/api/instagram/profile': {
        get: {
          operationId: 'instagram_get_profile',
          summary: 'Get Instagram profile',
          parameters: [
            { name: 'account', in: 'query', schema: { type: 'string' } },
          ],
          responses: { '200': { description: 'Profile info' } },
        },
      },
      '/api/instagram/media': {
        get: {
          operationId: 'instagram_get_media',
          summary: 'Get Instagram media',
          parameters: [
            { name: 'limit', in: 'query', schema: { type: 'integer' } },
            { name: 'account', in: 'query', schema: { type: 'string' } },
          ],
          responses: { '200': { description: 'Media list' } },
        },
      },
      '/api/instagram/post': {
        post: {
          operationId: 'instagram_create_post',
          summary: 'Create Instagram post',
          requestBody: {
            required: true,
            content: {
              'application/json': {
                schema: {
                  type: 'object',
                  required: ['image_url'],
                  properties: {
                    image_url: { type: 'string' },
                    caption: { type: 'string' },
                    account: { type: 'string' },
                  },
                },
              },
            },
          },
          responses: { '200': { description: 'Post created' } },
        },
      },

      // ── Twitter/X ───────────────────────────────────────────────
      '/api/twitter/search': {
        get: {
          operationId: 'twitter_search_tweets',
          summary: 'Search tweets',
          parameters: [
            { name: 'query', in: 'query', required: true, schema: { type: 'string' } },
            { name: 'max_results', in: 'query', schema: { type: 'integer' } },
            { name: 'account', in: 'query', schema: { type: 'string' } },
          ],
          responses: { '200': { description: 'Tweet list' } },
        },
      },
      '/api/twitter/user': {
        get: {
          operationId: 'twitter_get_user_profile',
          summary: 'Get Twitter user profile',
          parameters: [
            { name: 'username', in: 'query', required: true, schema: { type: 'string' } },
            { name: 'account', in: 'query', schema: { type: 'string' } },
          ],
          responses: { '200': { description: 'User profile' } },
        },
      },
      '/api/twitter/tweets': {
        get: {
          operationId: 'twitter_get_user_tweets',
          summary: 'Get user tweets',
          parameters: [
            { name: 'username', in: 'query', required: true, schema: { type: 'string' } },
            { name: 'max_results', in: 'query', schema: { type: 'integer' } },
            { name: 'account', in: 'query', schema: { type: 'string' } },
          ],
          responses: { '200': { description: 'Tweet list' } },
        },
      },
    },
  };
}

const ACCOUNT_PARAM_SCHEMA = {
  account: {
    type: 'string',
    enum: ['yahoo', 'fetcherpay', 'garfield', 'sales', 'leads', 'founder', 'gmail'],
    description:
      'Which mailbox to use: "yahoo" (gheron01@yahoo.com), "fetcherpay" (garfield.heron@fetcherpay.com), "garfield" (garfield@fetcherpay.com), "sales" (sales@fetcherpay.com), "leads" (leads@fetcherpay.com), "founder" (founder@fetcherpay.com), or "gmail" (Gmail account). Defaults to "yahoo".',
  },
};

export function getManifest(serverUrl: string, authEnabled: boolean) {
  return {
    schema_version: SCHEMA_VERSION,
    oauth_endpoints: {
      issuer: serverUrl,
      authorization_server_base: serverUrl,
      authorization: `${serverUrl}/oauth/authorize`,
      token: `${serverUrl}/oauth/token`,
      registration: `${serverUrl}/oauth/register`,
    },
    server: {
      name: 'hermes-mcp',
      version: '1.0.0',
      url: serverUrl,
      auth: authEnabled
        ? {
            type: 'apiKey',
            header: 'x-api-key',
            location: 'header',
            note: 'Also accepted as ?key= query parameter',
          }
        : { type: 'none' },
    },
    tools: [
      // ── Email tools ─────────────────────────────────────────────────────────
      {
        name: 'get_profile',
        category: 'email',
        description: 'Get the email account profile (email address and display name)',
        when_to_use:
          'User asks for their email address, display name, or account identity before sending or reading messages.',
        input_schema: {
          type: 'object',
          properties: { ...ACCOUNT_PARAM_SCHEMA },
        },
        returns: {
          type: 'object',
          properties: {
            email: { type: 'string', description: 'Full email address' },
            name: { type: 'string', description: 'Username portion of the email' },
            account: { type: 'string', description: 'Account alias used' },
          },
        },
        examples: [{ account: 'yahoo' }],
      },
      {
        name: 'search_messages',
        category: 'email',
        description: 'Search email messages by keyword, sender, or subject across the selected account',
        when_to_use:
          'User asks to find, look up, or search for emails, messages, or correspondence in Yahoo or FetcherPay mailboxes.',
        input_schema: {
          type: 'object',
          required: ['q'],
          properties: {
            q: {
              type: 'string',
              description: 'Search query — can be a keyword, from:email, or subject:text',
            },
            maxResults: {
              type: 'number',
              description: 'Maximum number of messages to return',
              default: 20,
            },
            ...ACCOUNT_PARAM_SCHEMA,
          },
        },
        returns: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              uid: { type: 'number' },
              messageId: { type: 'string' },
              subject: { type: 'string' },
              from: { type: 'string' },
              date: { type: 'string', format: 'date-time' },
              seen: { type: 'boolean' },
              size: { type: 'number' },
            },
          },
        },
        examples: [{ q: 'invoice', maxResults: 10, account: 'fetcherpay' }],
      },
      {
        name: 'read_message',
        category: 'email',
        description: 'Read a full email message including body text by its UID',
        when_to_use:
          'User asks to read, open, show, or summarize a specific email message identified by UID from search results.',
        input_schema: {
          type: 'object',
          required: ['uid'],
          properties: {
            uid: {
              type: 'number',
              description: 'Message UID returned by search_messages',
            },
            ...ACCOUNT_PARAM_SCHEMA,
          },
        },
        returns: {
          type: 'object',
          properties: {
            uid: { type: 'number' },
            messageId: { type: 'string' },
            subject: { type: 'string' },
            from: { type: 'string' },
            to: { type: 'string' },
            date: { type: 'string', format: 'date-time' },
            body: { type: 'string', description: 'Plain-text body (HTML stripped)' },
            seen: { type: 'boolean' },
          },
        },
        examples: [{ uid: 12345, account: 'yahoo' }],
      },
      {
        name: 'list_folders',
        category: 'email',
        description: 'List all email folders and mailboxes for the selected account',
        when_to_use:
          'User asks what folders exist, wants to know mailbox structure, or needs folder names for email organization.',
        input_schema: {
          type: 'object',
          properties: { ...ACCOUNT_PARAM_SCHEMA },
        },
        returns: {
          type: 'array',
          items: { type: 'string', description: 'Folder path (e.g. INBOX, Sent)' },
        },
        examples: [{ account: 'yahoo' }],
      },
      {
        name: 'create_draft',
        category: 'email',
        description: 'Create a draft email saved to the Drafts folder',
        when_to_use:
          'User wants to compose or save a draft email without sending it immediately.',
        input_schema: {
          type: 'object',
          required: ['to', 'subject', 'body'],
          properties: {
            to: { type: 'string', description: 'Recipient email address' },
            subject: { type: 'string', description: 'Email subject line' },
            body: { type: 'string', description: 'Email body in plain text' },
            ...ACCOUNT_PARAM_SCHEMA,
          },
        },
        returns: {
          type: 'string',
          description: 'Confirmation message indicating the draft was created',
        },
        examples: [
          {
            to: 'partner@example.com',
            subject: 'Meeting follow-up',
            body: 'Thanks for the call today.',
            account: 'fetcherpay',
          },
        ],
      },
      {
        name: 'send_email',
        category: 'email',
        description: 'Send an email immediately via SMTP',
        when_to_use:
          'User asks to send an email, message, or mail to someone right now.',
        input_schema: {
          type: 'object',
          required: ['to', 'subject', 'body'],
          properties: {
            to: { type: 'string', description: 'Recipient email address' },
            subject: { type: 'string', description: 'Email subject line' },
            body: { type: 'string', description: 'Email body in plain text' },
            ...ACCOUNT_PARAM_SCHEMA,
          },
        },
        returns: {
          type: 'string',
          description: 'SMTP message ID confirming the send',
        },
        examples: [
          {
            to: 'team@fetcherpay.com',
            subject: 'Weekly update',
            body: 'Here is the weekly summary.',
            account: 'garfield',
          },
        ],
      },

      // ── WhatsApp Business API tools ───────────────────────────────────────
      {
        name: 'whatsapp_send_message',
        category: 'whatsapp',
        description: 'Send a WhatsApp text message to a phone number',
        when_to_use:
          'User asks to send a WhatsApp message, text someone on WhatsApp, or notify via WhatsApp. Only works if the recipient has messaged you within the last 24 hours.',
        input_schema: {
          type: 'object',
          required: ['to', 'message'],
          properties: {
            to: { type: 'string', description: 'Recipient phone number in international format (e.g. +1234567890)' },
            message: { type: 'string', description: 'Message text to send' },
            account: { type: 'string', description: 'Which WhatsApp account to use (default: "default")' },
          },
        },
        returns: {
          type: 'object',
          properties: {
            success: { type: 'boolean' },
            message_id: { type: 'string', description: 'WhatsApp message ID' },
          },
        },
        examples: [{ to: '+1234567890', message: 'Hello from Hermes', account: 'default' }],
      },
      {
        name: 'whatsapp_send_template',
        category: 'whatsapp',
        description: 'Send an approved WhatsApp template message',
        when_to_use:
          'User wants to send a structured notification or alert via an approved WhatsApp template. Required when outside the 24-hour customer-service window.',
        input_schema: {
          type: 'object',
          required: ['to', 'template_name'],
          properties: {
            to: { type: 'string', description: 'Recipient phone number in international format' },
            template_name: { type: 'string', description: 'Name of the approved WhatsApp template' },
            language: { type: 'string', description: 'Template language code (default: "en")' },
            components: { type: 'array', items: { type: 'object' }, description: 'Template components (header, body, buttons) with parameters' },
            account: { type: 'string', description: 'Which WhatsApp account to use (default: "default")' },
          },
        },
        returns: {
          type: 'object',
          properties: {
            success: { type: 'boolean' },
            message_id: { type: 'string', description: 'WhatsApp message ID' },
          },
        },
        examples: [{ to: '+1234567890', template_name: 'hello_world', language: 'en', account: 'default' }],
      },
      {
        name: 'whatsapp_list_templates',
        category: 'whatsapp',
        description: 'List all approved WhatsApp message templates for the business account',
        when_to_use:
          'User asks what WhatsApp templates are available or wants to know which templates can be sent.',
        input_schema: {
          type: 'object',
          properties: {
            account: { type: 'string', description: 'Which WhatsApp account to use (default: "default")' },
          },
        },
        returns: {
          type: 'object',
          properties: {
            templates: {
              type: 'array',
              items: {
                type: 'object',
                properties: {
                  name: { type: 'string' },
                  language: { type: 'string' },
                  status: { type: 'string' },
                },
              },
            },
          },
        },
        examples: [{ account: 'default' }],
      },

      // ── LinkedIn tools ──────────────────────────────────────────────────────
      {
        name: 'linkedin_get_profile',
        category: 'linkedin',
        description: 'Get the LinkedIn profile of the authenticated user',
        when_to_use:
          'User asks about their LinkedIn profile, name, headline, or wants to verify which LinkedIn account is connected.',
        input_schema: {
          type: 'object',
          properties: {
            account: { type: 'string', description: 'Which LinkedIn account to use (default: "default")' },
          },
        },
        returns: {
          type: 'object',
          properties: {
            id: { type: 'string', description: 'LinkedIn person ID (OpenID sub)' },
            firstName: { type: 'string' },
            lastName: { type: 'string' },
            email: { type: 'string' },
            picture: { type: 'string', description: 'Profile photo URL' },
          },
        },
        examples: [{ account: 'default' }],
      },
      {
        name: 'linkedin_create_post',
        category: 'linkedin',
        description: 'Create a post on LinkedIn',
        when_to_use:
          'User wants to publish an update, share content, or post to their LinkedIn feed.',
        input_schema: {
          type: 'object',
          required: ['text'],
          properties: {
            text: { type: 'string', description: 'Post content text' },
            visibility: { type: 'string', enum: ['PUBLIC', 'CONNECTIONS'], description: 'PUBLIC (anyone) or CONNECTIONS (1st degree only)' },
            account: { type: 'string', description: 'Which LinkedIn account to use (default: "default")' },
          },
        },
        returns: {
          type: 'object',
          properties: {
            success: { type: 'boolean' },
            post_id: { type: 'string' },
            url: { type: 'string', description: 'Direct link to the post' },
          },
        },
        examples: [{ text: 'Excited to share our latest product update!', visibility: 'PUBLIC', account: 'default' }],
      },
      {
        name: 'linkedin_search_connections',
        category: 'linkedin',
        description: 'Search LinkedIn connections [REQUIRES PARTNERSHIP]',
        when_to_use:
          'User wants to search their LinkedIn network. NOTE: Requires LinkedIn Partnership Program — public API access was removed.',
        input_schema: {
          type: 'object',
          properties: {
            keywords: { type: 'string', description: 'Search keywords' },
            account: { type: 'string', description: 'Which LinkedIn account to use (default: "default")' },
          },
        },
        returns: {
          type: 'object',
          properties: {
            message: { type: 'string', description: 'Error or guidance message' },
          },
        },
        examples: [{ keywords: 'software engineer', account: 'default' }],
      },
      {
        name: 'linkedin_send_message',
        category: 'linkedin',
        description: 'Send a direct message on LinkedIn [REQUIRES PARTNERSHIP]',
        when_to_use:
          'User wants to send a LinkedIn DM. NOTE: Requires LinkedIn Partnership Program — messaging is not available through the public API.',
        input_schema: {
          type: 'object',
          required: ['recipient_id', 'message'],
          properties: {
            recipient_id: { type: 'string', description: 'LinkedIn person URN or ID' },
            message: { type: 'string', description: 'Message text' },
            account: { type: 'string', description: 'Which LinkedIn account to use (default: "default")' },
          },
        },
        returns: {
          type: 'object',
          properties: {
            message: { type: 'string', description: 'Error or guidance message' },
          },
        },
        examples: [{ recipient_id: 'urn:li:person:abc123', message: 'Hi, thanks for connecting!', account: 'default' }],
      },

      // ── Telegram tools ──────────────────────────────────────────────────────
      {
        name: 'telegram_get_me',
        category: 'telegram',
        description: 'Get information about the connected Telegram bot',
        when_to_use:
          'User asks about the Telegram bot, wants to verify it is connected, or needs the bot username.',
        input_schema: {
          type: 'object',
          properties: {
            account: { type: 'string', description: 'Which Telegram account to use (default: "default")' },
          },
        },
        returns: {
          type: 'object',
          properties: {
            id: { type: 'number', description: 'Bot user ID' },
            first_name: { type: 'string' },
            username: { type: 'string' },
            is_bot: { type: 'boolean' },
          },
        },
        examples: [{ account: 'default' }],
      },
      {
        name: 'telegram_send_message',
        category: 'telegram',
        description: 'Send a text message via Telegram bot',
        when_to_use:
          'User wants to send a Telegram message, DM someone, or notify a group or channel.',
        input_schema: {
          type: 'object',
          required: ['chat_id', 'text'],
          properties: {
            chat_id: { type: 'string', description: 'Chat ID, username (@username), or channel ID' },
            text: { type: 'string', description: 'Message text' },
            parse_mode: { type: 'string', enum: ['HTML', 'Markdown', 'MarkdownV2'], description: 'Message formatting mode' },
            account: { type: 'string', description: 'Which Telegram account to use (default: "default")' },
          },
        },
        returns: {
          type: 'object',
          properties: {
            message_id: { type: 'number' },
            chat_id: { type: 'string', description: 'Chat ID where the message was sent' },
          },
        },
        examples: [{ chat_id: '@mychannel', text: 'Hello from Hermes!', account: 'default' }],
      },
      {
        name: 'telegram_send_photo',
        category: 'telegram',
        description: 'Send a photo via Telegram bot',
        when_to_use:
          'User wants to share an image through Telegram.',
        input_schema: {
          type: 'object',
          required: ['chat_id', 'photo'],
          properties: {
            chat_id: { type: 'string', description: 'Chat ID, username (@username), or channel ID' },
            photo: { type: 'string', description: 'Photo URL or Telegram file_id' },
            caption: { type: 'string', description: 'Optional caption text' },
            account: { type: 'string', description: 'Which Telegram account to use (default: "default")' },
          },
        },
        returns: {
          type: 'object',
          properties: {
            message_id: { type: 'number' },
            chat_id: { type: 'string' },
          },
        },
        examples: [{ chat_id: '@mychannel', photo: 'https://example.com/image.jpg', caption: 'Check this out', account: 'default' }],
      },
      {
        name: 'telegram_get_updates',
        category: 'telegram',
        description: 'Get recent incoming messages for the Telegram bot',
        when_to_use:
          'User asks to check Telegram messages, read DMs, or see recent bot activity.',
        input_schema: {
          type: 'object',
          properties: {
            limit: { type: 'number', description: 'Max updates to return (default: 10)' },
            account: { type: 'string', description: 'Which Telegram account to use (default: "default")' },
          },
        },
        returns: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              update_id: { type: 'number' },
              message: {
                type: 'object',
                properties: {
                  message_id: { type: 'number' },
                  from: { type: 'object', properties: { id: { type: 'number' }, first_name: { type: 'string' }, username: { type: 'string' } } },
                  chat: { type: 'object', properties: { id: { type: 'number' }, type: { type: 'string' }, title: { type: 'string' } } },
                  date: { type: 'number' },
                  text: { type: 'string' },
                },
              },
            },
          },
        },
        examples: [{ limit: 5, account: 'default' }],
      },
      {
        name: 'telegram_get_chat',
        category: 'telegram',
        description: 'Get information about a Telegram chat or channel',
        when_to_use:
          'User wants to verify a Telegram chat exists or get its details before sending a message.',
        input_schema: {
          type: 'object',
          required: ['chat_id'],
          properties: {
            chat_id: { type: 'string', description: 'Chat ID, username (@username), or channel ID' },
            account: { type: 'string', description: 'Which Telegram account to use (default: "default")' },
          },
        },
        returns: {
          type: 'object',
          properties: {
            id: { type: 'number' },
            type: { type: 'string' },
            title: { type: 'string' },
            username: { type: 'string' },
            description: { type: 'string' },
            member_count: { type: 'number' },
          },
        },
        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' }],
      },

      // ── Twitter/X tools ────────────────────────────────────────────────────
      {
        name: 'twitter_search_tweets',
        category: 'twitter',
        description: 'Search recent tweets on Twitter/X',
        when_to_use:
          'User wants to find tweets about a topic, hashtag, keyword, or trend.',
        input_schema: {
          type: 'object',
          required: ['query'],
          properties: {
            query: { type: 'string', description: 'Search query (keyword, hashtag #xxx, from:username)' },
            max_results: { type: 'number', description: 'Max tweets (default: 10, max: 100)' },
            account: { type: 'string', description: 'Which Twitter account to use (default: "default")' },
          },
        },
        returns: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              id: { type: 'string', description: 'Tweet ID' },
              text: { type: 'string' },
              author_id: { type: 'string' },
              created_at: { type: 'string', format: 'date-time' },
            },
          },
        },
        examples: [{ query: '#AI', max_results: 10, account: 'default' }],
      },
      {
        name: 'twitter_get_user_profile',
        category: 'twitter',
        description: 'Get a Twitter/X user profile and stats',
        when_to_use:
          'User wants follower count, bio, or profile info for a specific Twitter account.',
        input_schema: {
          type: 'object',
          required: ['username'],
          properties: {
            username: { type: 'string', description: 'Twitter username without @' },
            account: { type: 'string', description: 'Which Twitter account to use (default: "default")' },
          },
        },
        returns: {
          type: 'object',
          properties: {
            id: { type: 'string' },
            name: { type: 'string' },
            username: { type: 'string' },
            description: { type: 'string' },
            followers_count: { type: 'number' },
            following_count: { type: 'number' },
            tweet_count: { type: 'number' },
          },
        },
        examples: [{ username: 'elonmusk', account: 'default' }],
      },
      {
        name: 'twitter_get_user_tweets',
        category: 'twitter',
        description: 'Get recent tweets from a specific user',
        when_to_use:
          'User wants to read someones recent tweets or timeline.',
        input_schema: {
          type: 'object',
          required: ['username'],
          properties: {
            username: { type: 'string', description: 'Twitter username without @' },
            max_results: { type: 'number', description: 'Max tweets (default: 10, max: 100)' },
            account: { type: 'string', description: 'Which Twitter account to use (default: "default")' },
          },
        },
        returns: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              id: { type: 'string' },
              text: { type: 'string' },
              created_at: { type: 'string', format: 'date-time' },
            },
          },
        },
        examples: [{ username: 'elonmusk', max_results: 5, account: 'default' }],
      },
      {
        name: 'twitter_create_tweet',
        category: 'twitter',
        description: 'Post a tweet [REQUIRES PAID TIER]',
        when_to_use:
          'User wants to post a tweet. NOTE: Free tier is read-only. Paid upgrade required.',
        input_schema: {
          type: 'object',
          required: ['text'],
          properties: {
            text: { type: 'string', description: 'Tweet text (max 280 chars)' },
            account: { type: 'string', description: 'Which Twitter account to use (default: "default")' },
          },
        },
        returns: {
          type: 'object',
          properties: {
            message: { type: 'string', description: 'Error or confirmation' },
          },
        },
        examples: [{ text: 'Hello from Hermes MCP!', account: 'default' }],
      },

      // ── Obsidian tools ──────────────────────────────────────────────────────
      {
        name: 'obsidian_search_notes',
        category: 'obsidian',
        description: 'Full-text search across the Obsidian vault by content, tags, or title',
        when_to_use:
          'User mentions "my notes", "in obsidian", "I wrote about", asks about personal knowledge, or references past notes.',
        input_schema: {
          type: 'object',
          required: ['query'],
          properties: {
            query: {
              type: 'string',
              description: 'Text to search for in note content or title',
            },
            tags: {
              type: 'array',
              items: { type: 'string' },
              description: 'Filter by Obsidian tags (all must match)',
            },
            limit: {
              type: 'number',
              description: 'Max results to return',
              default: 10,
            },
            path_filter: {
              type: 'string',
              description: 'Only return notes whose path contains this string (e.g. "Daily Notes")',
            },
          },
        },
        returns: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              path: { type: 'string', description: 'Relative file path in vault' },
              title: { type: 'string' },
              excerpt: { type: 'string', description: 'Matched text excerpt (~200 chars)' },
              tags: { type: 'array', items: { type: 'string' } },
              modified_date: { type: 'string', format: 'date-time' },
            },
          },
        },
        examples: [{ query: 'funding strategy', limit: 5 }],
      },
      {
        name: 'obsidian_read_note',
        category: 'obsidian',
        description: 'Retrieve the complete content of a specific Obsidian note by path or title',
        when_to_use:
          'User asks to read, open, show, or see a specific note by path or title.',
        input_schema: {
          type: 'object',
          required: ['path'],
          properties: {
            path: {
              type: 'string',
              description: 'File path relative to vault root (e.g. "Daily Notes/2026-04-15.md") or just the note title/filename',
            },
          },
        },
        returns: {
          type: 'object',
          properties: {
            path: { type: 'string' },
            title: { type: 'string' },
            content: { type: 'string', description: 'Full markdown content' },
            tags: { type: 'array', items: { type: 'string' } },
            links: {
              type: 'array',
              items: { type: 'string' },
              description: 'Internal wiki-style links extracted from content',
            },
            modified_date: { type: 'string', format: 'date-time' },
          },
        },
        examples: [{ path: 'Projects/FetcherPay.md' }],
      },
      {
        name: 'obsidian_append_to_note',
        category: 'obsidian',
        description: 'Append markdown content to any Obsidian note, creating it if missing',
        when_to_use:
          'User wants to log, save, journal, or add content to daily notes or specific vault files.',
        input_schema: {
          type: 'object',
          required: ['path', 'content'],
          properties: {
            path: {
              type: 'string',
              description: 'File path relative to vault root (e.g. "Daily Notes/2026-04-15.md")',
            },
            content: {
              type: 'string',
              description: 'Markdown content to append',
            },
            create_if_missing: {
              type: 'boolean',
              description: 'Create the note if it does not exist',
              default: true,
            },
            header: {
              type: 'string',
              description: 'Optional H2 section header to insert before the content',
            },
          },
        },
        returns: {
          type: 'object',
          properties: {
            success: { type: 'boolean' },
            path: { type: 'string' },
            bytes_written: { type: 'number' },
          },
        },
        examples: [
          {
            path: 'Daily Notes/2026-04-15.md',
            content: '- Met with investor at 2pm',
            header: 'Meetings',
          },
        ],
      },
      {
        name: 'obsidian_sync_status',
        category: 'obsidian',
        description: 'Check Syncthing sync status and vault statistics',
        when_to_use:
          'User asks if their vault is synced, up to date, or about device connectivity for Obsidian notes.',
        input_schema: {
          type: 'object',
          properties: {},
        },
        returns: {
          type: 'object',
          properties: {
            status: { type: 'string', description: 'Syncthing state (e.g. idle, syncing, error)' },
            last_sync: {
              type: ['string', 'null'],
              format: 'date-time',
              description: 'ISO timestamp of last state change',
            },
            vault_size: { type: 'number', description: 'Total bytes in vault' },
            pending_changes: { type: 'number', description: 'Files needing sync' },
          },
        },
        examples: [{}],
      },
    ],
    categories: {
      obsidian: {
        description: 'Personal knowledge management via Obsidian vault',
        icon: '📝',
      },
      email: {
        description: 'Email operations for Yahoo, FetcherPay, and Gmail accounts',
        icon: '📧',
      },
      whatsapp: {
        description: 'WhatsApp Business API messaging via Meta Cloud API',
        icon: '💬',
      },
      linkedin: {
        description: 'LinkedIn profile and posting via LinkedIn API',
        icon: '🔗',
      },
      telegram: {
        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: '📸',
      },
      twitter: {
        description: 'Twitter/X search and profile lookup (read-only on free tier)',
        icon: '🐦',
      },
    },
  };
}
