diff --git a/README.de.md b/README.de.md index 328d056..d41bfe5 100644 --- a/README.de.md +++ b/README.de.md @@ -60,6 +60,68 @@ AIPex ist die Antwort. Installieren Sie die Erweiterung, bringen Sie Ihren eigen --- +## Verwendung mit KI-Coding-Agenten (MCP) + +AIPex unterstützt jetzt das [Model Context Protocol (MCP)](https://modelcontextprotocol.io), sodass KI-Agenten wie Cursor, Claude Code und VS Code Copilot Ihren Browser direkt steuern können. + +``` +AI Agent ──stdio──▶ aipex-mcp-bridge ──WebSocket──▶ AIPex Extension ──▶ Browser +``` + +### Schritt 1: Agenten konfigurieren + +**Cursor** (`.cursor/mcp.json`) · **Claude Desktop** (`claude_desktop_config.json`) · **Windsurf** (`mcp_config.json`): + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +**Claude Code**: + +```bash +claude mcp add aipex-browser -- npx -y aipex-mcp-bridge +``` + +**VS Code Copilot** (`.vscode/mcp.json`): + +```json +{ + "servers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +### Schritt 2: Erweiterung verbinden + +1. Chrome öffnen → AIPex-Symbol → **Optionen** +2. WebSocket-URL auf `ws://localhost:9223` setzen +3. Auf **Verbinden** klicken + +Ihr Agent verfügt jetzt über 30+ Browser-Automatisierungstools via MCP. Siehe [mcp-bridge/README.md](mcp-bridge/README.md) für erweiterte Optionen. + +--- + +## Skill + +AIPex liefert ein **`aipex-browser`**-Skill — ein sofort einsatzbereites Skill-Paket für Agenten, die das Skill-Protokoll unterstützen (wie [Claude Code](https://claude.ai/code) und [OpenClaw](https://openclaw.dev)-kompatible Runtimes). + +Das Skill enthält eine Werkzeugstrategie, vollständige Parameterschemata für alle 30+ Browser-Tools und gängige Automatisierungsmuster — sodass der Agent den Browser sofort effizient steuern kann. + +Siehe [`skill/SKILL.md`](skill/SKILL.md) für die vollständige Definition. + +--- + ## Demos ### "Ich habe 100 Tabs offen. Hilfe." diff --git a/README.es.md b/README.es.md index d8eab4d..21b3005 100644 --- a/README.es.md +++ b/README.es.md @@ -60,6 +60,68 @@ AIPex es la respuesta. Instala la extensión, trae tu propia clave API y automat --- +## Uso con agentes de IA (MCP) + +AIPex ahora soporta el [Model Context Protocol (MCP)](https://modelcontextprotocol.io), permitiendo que agentes de IA como Cursor, Claude Code y VS Code Copilot controlen tu navegador directamente. + +``` +AI Agent ──stdio──▶ aipex-mcp-bridge ──WebSocket──▶ AIPex Extension ──▶ Browser +``` + +### Paso 1: Configura tu agente + +**Cursor** (`.cursor/mcp.json`) · **Claude Desktop** (`claude_desktop_config.json`) · **Windsurf** (`mcp_config.json`): + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +**Claude Code**: + +```bash +claude mcp add aipex-browser -- npx -y aipex-mcp-bridge +``` + +**VS Code Copilot** (`.vscode/mcp.json`): + +```json +{ + "servers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +### Paso 2: Conecta la extensión + +1. Abre Chrome → icono de AIPex → **Opciones** +2. Establece la URL de WebSocket en `ws://localhost:9223` +3. Haz clic en **Conectar** + +Tu agente ahora tiene 30+ herramientas de automatización de navegador disponibles via MCP. Ver [mcp-bridge/README.md](mcp-bridge/README.md) para opciones avanzadas. + +--- + +## Skill + +AIPex incluye un skill **`aipex-browser`** — un paquete listo para usar para agentes que soporten el protocolo de skill (como [Claude Code](https://claude.ai/code) y runtimes compatibles con [OpenClaw](https://openclaw.dev)). + +El skill incluye estrategia de uso de herramientas, esquemas completos de parámetros para las 30+ herramientas de navegador y patrones de automatización comunes — permitiendo al agente controlar el navegador eficazmente sin exploración previa. + +Ver [`skill/SKILL.md`](skill/SKILL.md) para la definición completa. + +--- + ## Demos ### "Tengo 100 pestañas abiertas. Ayuda." diff --git a/README.fr.md b/README.fr.md index 5d22153..db6dd61 100644 --- a/README.fr.md +++ b/README.fr.md @@ -60,6 +60,68 @@ AIPex est la réponse. Installez l'extension, apportez votre propre clé API et --- +## Utilisation avec des agents IA (MCP) + +AIPex prend désormais en charge le [Model Context Protocol (MCP)](https://modelcontextprotocol.io), permettant aux agents IA comme Cursor, Claude Code et VS Code Copilot de contrôler votre navigateur directement. + +``` +AI Agent ──stdio──▶ aipex-mcp-bridge ──WebSocket──▶ AIPex Extension ──▶ Browser +``` + +### Étape 1 : Configurer votre agent + +**Cursor** (`.cursor/mcp.json`) · **Claude Desktop** (`claude_desktop_config.json`) · **Windsurf** (`mcp_config.json`) : + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +**Claude Code** : + +```bash +claude mcp add aipex-browser -- npx -y aipex-mcp-bridge +``` + +**VS Code Copilot** (`.vscode/mcp.json`) : + +```json +{ + "servers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +### Étape 2 : Connecter l'extension + +1. Ouvrez Chrome → icône AIPex → **Options** +2. Définissez l'URL WebSocket sur `ws://localhost:9223` +3. Cliquez sur **Connecter** + +Votre agent dispose maintenant de 30+ outils d'automatisation de navigateur via MCP. Voir [mcp-bridge/README.md](mcp-bridge/README.md) pour les options avancées. + +--- + +## Skill + +AIPex fournit un skill **`aipex-browser`** — un package prêt à l'emploi pour les agents supportant le protocole de skill (comme [Claude Code](https://claude.ai/code) et les runtimes compatibles [OpenClaw](https://openclaw.dev)). + +Le skill intègre une stratégie d'utilisation des outils, les schémas complets des paramètres des 30+ outils de navigateur et des patterns d'automatisation courants — permettant à l'agent de contrôler le navigateur efficacement sans exploration préalable. + +Voir [`skill/SKILL.md`](skill/SKILL.md) pour la définition complète. + +--- + ## Démos ### "J'ai 100 onglets ouverts. À l'aide." diff --git a/README.ja.md b/README.ja.md index ca16488..e5c0ba5 100644 --- a/README.ja.md +++ b/README.ja.md @@ -60,6 +60,68 @@ AIPexがその答えです。拡張機能をインストールし、独自のAPI --- +## AIエージェントとの連携(MCP) + +AIPexは[Model Context Protocol(MCP)](https://modelcontextprotocol.io)をサポートし、Cursor・Claude Code・VS Code CopilotなどのAIエージェントがブラウザを直接操作できるようになりました。 + +``` +AI Agent ──stdio──▶ aipex-mcp-bridge ──WebSocket──▶ AIPex Extension ──▶ Browser +``` + +### ステップ1:エージェントを設定する + +**Cursor** (`.cursor/mcp.json`) · **Claude Desktop** (`claude_desktop_config.json`) · **Windsurf** (`mcp_config.json`): + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +**Claude Code**: + +```bash +claude mcp add aipex-browser -- npx -y aipex-mcp-bridge +``` + +**VS Code Copilot** (`.vscode/mcp.json`): + +```json +{ + "servers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +### ステップ2:拡張機能を接続する + +1. Chrome → AIPexアイコン → **オプション**を開く +2. WebSocket URLを `ws://localhost:9223` に設定 +3. **接続**をクリック + +これでエージェントはMCP経由で30以上のブラウザ自動化ツールを使用できます。詳細は [mcp-bridge/README.md](mcp-bridge/README.md) を参照してください。 + +--- + +## スキル(Skill) + +AIPexは**`aipex-browser`**スキルを提供します。[Claude Code](https://claude.ai/code)や[OpenClaw](https://openclaw.dev)互換ランタイムなど、スキルプロトコルに対応したエージェントがすぐに使えるブラウザ自動化スキルパッケージです。 + +スキルには、ツール使用戦略・30以上のブラウザツールの完全なパラメータスキーマ・よく使われるパターンが含まれており、エージェントが試行錯誤なしにブラウザを効率よく操作できます。 + +詳細は [`skill/SKILL.md`](skill/SKILL.md) をご参照ください。 + +--- + ## デモ ### "100個のタブが開いています。助けて。" diff --git a/README.ko.md b/README.ko.md index cfee7f6..4f4fc6c 100644 --- a/README.ko.md +++ b/README.ko.md @@ -60,6 +60,68 @@ AIPex가 그 대답입니다. 확장 프로그램을 설치하고, 자신의 API --- +## AI 에이전트와 연동 (MCP) + +AIPex는 이제 [Model Context Protocol(MCP)](https://modelcontextprotocol.io)을 지원하여 Cursor, Claude Code, VS Code Copilot 등 AI 에이전트가 브라우저를 직접 제어할 수 있습니다. + +``` +AI Agent ──stdio──▶ aipex-mcp-bridge ──WebSocket──▶ AIPex Extension ──▶ Browser +``` + +### 1단계: 에이전트 설정 + +**Cursor** (`.cursor/mcp.json`) · **Claude Desktop** (`claude_desktop_config.json`) · **Windsurf** (`mcp_config.json`): + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +**Claude Code**: + +```bash +claude mcp add aipex-browser -- npx -y aipex-mcp-bridge +``` + +**VS Code Copilot** (`.vscode/mcp.json`): + +```json +{ + "servers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +### 2단계: 확장 프로그램 연결 + +1. Chrome → AIPex 아이콘 → **옵션** 열기 +2. WebSocket URL을 `ws://localhost:9223`으로 설정 +3. **연결** 클릭 + +이제 에이전트는 MCP를 통해 30개 이상의 브라우저 자동화 도구를 사용할 수 있습니다. 자세한 설정은 [mcp-bridge/README.md](mcp-bridge/README.md)를 참고하세요. + +--- + +## 스킬 (Skill) + +AIPex는 **`aipex-browser`** 스킬을 제공합니다. [Claude Code](https://claude.ai/code) 및 [OpenClaw](https://openclaw.dev) 호환 런타임 등 스킬 프로토콜을 지원하는 에이전트가 바로 사용할 수 있는 브라우저 자동화 스킬 패키지입니다. + +스킬에는 도구 사용 전략, 30개 이상의 브라우저 도구 파라미터 스키마, 자주 쓰이는 자동화 패턴이 포함되어 있어 에이전트가 시행착오 없이 효율적으로 브라우저를 제어할 수 있습니다. + +자세한 내용은 [`skill/SKILL.md`](skill/SKILL.md)를 참고하세요. + +--- + ## 데모 ### "탭이 100개 열려 있습니다. 도와주세요." diff --git a/README.md b/README.md index 5775fc1..a0a91ad 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,68 @@ AIPex is the answer. Install the extension, bring your own API key, and automate --- +## Use with AI Coding Agents (MCP) + +AIPex now supports the [Model Context Protocol (MCP)](https://modelcontextprotocol.io), giving AI coding agents like Cursor, Claude Code, and VS Code Copilot direct control over your browser. + +``` +AI Agent ──stdio──▶ aipex-mcp-bridge ──WebSocket──▶ AIPex Extension ──▶ Browser +``` + +### Step 1: Configure your agent + +**Cursor** (`.cursor/mcp.json`) · **Claude Desktop** (`claude_desktop_config.json`) · **Windsurf** (`mcp_config.json`): + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +**Claude Code**: + +```bash +claude mcp add aipex-browser -- npx -y aipex-mcp-bridge +``` + +**VS Code Copilot** (`.vscode/mcp.json`): + +```json +{ + "servers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +### Step 2: Connect the extension + +1. Open Chrome → AIPex icon → **Options** +2. Set WebSocket URL to `ws://localhost:9223` +3. Click **Connect** + +Your agent now has 30+ browser automation tools available via MCP. See [mcp-bridge/README.md](mcp-bridge/README.md) for advanced options. + +--- + +## Skill + +AIPex ships an **`aipex-browser`** skill — a ready-to-use skill package for agents that support the skill protocol (such as [Claude Code](https://claude.ai/code) and [OpenClaw](https://openclaw.dev)-compatible runtimes). + +The skill bundles tool usage strategy, complete parameter schemas for all 30+ browser tools, and common automation patterns — so an agent can control the browser effectively without discovering tools from scratch. + +See [`skill/SKILL.md`](skill/SKILL.md) for the full skill definition. + +--- + ## Demos ### "I have 100 tabs open. Help." @@ -102,9 +164,9 @@ https://github.com/user-attachments/assets/ba454715-c759-41df-bf87-e835f76be365 - Integration - - [ ] Cursor + - [x] Cursor - - [ ] Claude Code + - [x] Claude Code - Skills diff --git a/README.pt.md b/README.pt.md index 39cdaa0..5012767 100644 --- a/README.pt.md +++ b/README.pt.md @@ -60,6 +60,68 @@ AIPex é a resposta. Instale a extensão, traga sua própria chave de API e auto --- +## Uso com Agentes de IA (MCP) + +AIPex agora suporta o [Model Context Protocol (MCP)](https://modelcontextprotocol.io), permitindo que agentes de IA como Cursor, Claude Code e VS Code Copilot controlem seu navegador diretamente. + +``` +AI Agent ──stdio──▶ aipex-mcp-bridge ──WebSocket──▶ AIPex Extension ──▶ Browser +``` + +### Passo 1: Configurar seu agente + +**Cursor** (`.cursor/mcp.json`) · **Claude Desktop** (`claude_desktop_config.json`) · **Windsurf** (`mcp_config.json`): + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +**Claude Code**: + +```bash +claude mcp add aipex-browser -- npx -y aipex-mcp-bridge +``` + +**VS Code Copilot** (`.vscode/mcp.json`): + +```json +{ + "servers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +### Passo 2: Conectar a extensão + +1. Abra o Chrome → ícone AIPex → **Opções** +2. Defina a URL WebSocket como `ws://localhost:9223` +3. Clique em **Conectar** + +Seu agente agora tem 30+ ferramentas de automação de navegador disponíveis via MCP. Veja [mcp-bridge/README.md](mcp-bridge/README.md) para opções avançadas. + +--- + +## Skill + +AIPex fornece um skill **`aipex-browser`** — um pacote pronto para uso para agentes que suportam o protocolo de skill (como [Claude Code](https://claude.ai/code) e runtimes compatíveis com [OpenClaw](https://openclaw.dev)). + +O skill inclui estratégia de uso de ferramentas, esquemas completos de parâmetros para as 30+ ferramentas de navegador e padrões comuns de automação — permitindo ao agente controlar o navegador eficientemente sem exploração prévia. + +Veja [`skill/SKILL.md`](skill/SKILL.md) para a definição completa. + +--- + ## Demos ### "Tenho 100 abas abertas. Socorro." diff --git a/README.ru.md b/README.ru.md index 0c6b465..25d209c 100644 --- a/README.ru.md +++ b/README.ru.md @@ -60,6 +60,68 @@ AIPex — это ответ. Установите расширение, введ --- +## Использование с ИИ-агентами (MCP) + +AIPex теперь поддерживает [Model Context Protocol (MCP)](https://modelcontextprotocol.io), позволяя ИИ-агентам, таким как Cursor, Claude Code и VS Code Copilot, напрямую управлять вашим браузером. + +``` +AI Agent ──stdio──▶ aipex-mcp-bridge ──WebSocket──▶ AIPex Extension ──▶ Browser +``` + +### Шаг 1: Настройка агента + +**Cursor** (`.cursor/mcp.json`) · **Claude Desktop** (`claude_desktop_config.json`) · **Windsurf** (`mcp_config.json`): + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +**Claude Code**: + +```bash +claude mcp add aipex-browser -- npx -y aipex-mcp-bridge +``` + +**VS Code Copilot** (`.vscode/mcp.json`): + +```json +{ + "servers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +### Шаг 2: Подключение расширения + +1. Откройте Chrome → иконка AIPex → **Настройки** +2. Установите WebSocket URL: `ws://localhost:9223` +3. Нажмите **Подключить** + +Ваш агент теперь имеет доступ к 30+ инструментам автоматизации браузера через MCP. См. [mcp-bridge/README.md](mcp-bridge/README.md) для расширенных настроек. + +--- + +## Skill + +AIPex предоставляет skill **`aipex-browser`** — готовый к использованию пакет для агентов, поддерживающих протокол skill (таких как [Claude Code](https://claude.ai/code) и среды выполнения, совместимые с [OpenClaw](https://openclaw.dev)). + +Skill включает стратегию использования инструментов, полные схемы параметров для 30+ инструментов управления браузером и типовые паттерны автоматизации — агент может сразу эффективно управлять браузером без предварительного изучения. + +Подробнее см. [`skill/SKILL.md`](skill/SKILL.md). + +--- + ## Демонстрации ### "У меня открыто 100 вкладок. Помогите." diff --git a/README.zh-CN.md b/README.zh-CN.md index 4529434..a244658 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -59,6 +59,68 @@ AIPex 就是答案。安装扩展,输入你自己的 API Key,然后直接开 --- +## 与 AI 编程助手集成(MCP) + +AIPex 现已支持 [模型上下文协议(MCP)](https://modelcontextprotocol.io),让 Cursor、Claude Code、VS Code Copilot 等 AI 助手能够直接控制你的浏览器。 + +``` +AI Agent ──stdio──▶ aipex-mcp-bridge ──WebSocket──▶ AIPex Extension ──▶ Browser +``` + +### 第一步:配置你的 AI 工具 + +**Cursor** (`.cursor/mcp.json`) · **Claude Desktop** (`claude_desktop_config.json`) · **Windsurf** (`mcp_config.json`): + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +**Claude Code**: + +```bash +claude mcp add aipex-browser -- npx -y aipex-mcp-bridge +``` + +**VS Code Copilot** (`.vscode/mcp.json`): + +```json +{ + "servers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +### 第二步:连接扩展程序 + +1. 打开 Chrome → 点击 AIPex 图标 → **选项** +2. 将 WebSocket URL 设置为 `ws://localhost:9223` +3. 点击 **连接** + +你的 AI 助手现在可以通过 MCP 使用 30+ 个浏览器自动化工具。更多配置详见 [mcp-bridge/README.md](mcp-bridge/README.md)。 + +--- + +## Skill + +AIPex 提供了一个 **`aipex-browser`** skill —— 供支持 skill 协议的 agent(如 [Claude Code](https://claude.ai/code) 及兼容 [OpenClaw](https://openclaw.dev) 的运行时)使用的即开即用自动化技能包。 + +该 skill 内置了工具使用策略、所有 30+ 浏览器工具的完整参数 schema,以及常用自动化模式,让 agent 无需自行摸索即可高效控制浏览器。 + +详见 [`skill/SKILL.md`](skill/SKILL.md)。 + +--- + ## 演示 ### "我开了100个标签页,救命" diff --git a/mcp-bridge/README.md b/mcp-bridge/README.md new file mode 100644 index 0000000..fe32a00 --- /dev/null +++ b/mcp-bridge/README.md @@ -0,0 +1,119 @@ +# aipex-mcp-bridge + +MCP bridge that connects AI agents to the [AIPex](https://aipex.ai) browser extension via WebSocket. + +Works with **any** MCP client that supports stdio transport — Cursor, Claude Desktop, Claude Code, VS Code Copilot, Windsurf, Zed, and more. + +## How it works + +``` +AI Agent (MCP client) ──stdio──▶ aipex-mcp-bridge ──WebSocket──▶ AIPex Chrome Extension +``` + +The bridge starts a WebSocket server on `localhost:9223` (configurable) and communicates with your AI agent over stdio using the MCP protocol. The AIPex extension connects to the WebSocket server to expose browser control tools. + +## Quick start + +### 1. Configure your AI agent + +Add the following to your agent's MCP configuration: + +**Cursor** (`.cursor/mcp.json`): + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +**Claude Desktop** (`claude_desktop_config.json`): + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +**Claude Code**: + +```bash +claude mcp add aipex-browser -- npx -y aipex-mcp-bridge +``` + +**VS Code Copilot** (`.vscode/mcp.json`): + +```json +{ + "servers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +**Windsurf** (`mcp_config.json`): + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +### 2. Connect AIPex extension + +1. Open Chrome → AIPex extension → Options page +2. Set WebSocket URL to `ws://localhost:9223` +3. Click **Connect** + +Your AI agent can now control the browser through AIPex. + +## Options + +``` +npx aipex-mcp-bridge [--port ] +``` + +| Option | Default | Description | +| ----------------- | ------- | ---------------------------------- | +| `--port ` | `9223` | WebSocket port for AIPex extension | +| `--help`, `-h` | | Show help message | +| `--version`, `-v` | | Show version | + +### Custom port example + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge", "--port", "8080"] + } + } +} +``` + +## Requirements + +- Node.js >= 18 +- AIPex Chrome extension installed + +## License + +MIT diff --git a/mcp-bridge/package.json b/mcp-bridge/package.json new file mode 100644 index 0000000..ddc1571 --- /dev/null +++ b/mcp-bridge/package.json @@ -0,0 +1,47 @@ +{ + "name": "aipex-mcp-bridge", + "version": "1.0.0", + "description": "MCP bridge that connects AI agents (Cursor, Claude, VS Code Copilot, etc.) to the AIPex browser extension via WebSocket", + "type": "module", + "bin": { + "aipex-mcp-bridge": "./dist/bridge.js" + }, + "files": [ + "dist", + "README.md" + ], + "scripts": { + "build": "tsup", + "dev": "tsx src/bridge.ts" + }, + "dependencies": { + "ws": "^8.18.0" + }, + "devDependencies": { + "@types/ws": "^8.5.13", + "@types/node": "^22.0.0", + "tsup": "^8.0.0", + "tsx": "^4.21.0", + "typescript": "^5.3.0" + }, + "keywords": [ + "mcp", + "model-context-protocol", + "aipex", + "browser", + "cursor", + "claude", + "copilot", + "websocket", + "bridge" + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/AIPexStudio/aipex-whole.git", + "directory": "aipex/mcp-bridge" + }, + "engines": { + "node": ">=18.0.0" + } +} diff --git a/mcp-bridge/pnpm-lock.yaml b/mcp-bridge/pnpm-lock.yaml new file mode 100644 index 0000000..043776c --- /dev/null +++ b/mcp-bridge/pnpm-lock.yaml @@ -0,0 +1,969 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + ws: + specifier: ^8.18.0 + version: 8.19.0 + devDependencies: + '@types/node': + specifier: ^22.0.0 + version: 22.19.13 + '@types/ws': + specifier: ^8.5.13 + version: 8.18.1 + tsup: + specifier: ^8.0.0 + version: 8.5.1(tsx@4.21.0)(typescript@5.9.3) + tsx: + specifier: ^4.21.0 + version: 4.21.0 + typescript: + specifier: ^5.3.0 + version: 5.9.3 + +packages: + + '@esbuild/aix-ppc64@0.27.3': + resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.3': + resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.3': + resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.3': + resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.3': + resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.3': + resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.3': + resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.3': + resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.3': + resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.3': + resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.3': + resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.3': + resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.3': + resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.3': + resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.3': + resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.3': + resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.3': + resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.3': + resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.3': + resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.3': + resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.3': + resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.3': + resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.3': + resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.3': + resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.3': + resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.3': + resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@rollup/rollup-android-arm-eabi@4.59.0': + resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.59.0': + resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.59.0': + resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.59.0': + resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.59.0': + resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.59.0': + resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.59.0': + resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.59.0': + resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.59.0': + resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.59.0': + resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.59.0': + resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.59.0': + resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.59.0': + resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.59.0': + resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.59.0': + resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.59.0': + resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.59.0': + resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.59.0': + resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.59.0': + resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.59.0': + resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.59.0': + resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} + cpu: [x64] + os: [win32] + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/node@22.19.13': + resolution: {integrity: sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw==} + + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + bundle-require@5.1.0: + resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: '>=0.18' + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + esbuild@0.27.3: + resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} + engines: {node: '>=18'} + hasBin: true + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fix-dts-default-cjs-exports@1.0.1: + resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + get-tsconfig@4.13.6: + resolution: {integrity: sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==} + + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + load-tsconfig@0.2.5: + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + mlly@1.8.0: + resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} + peerDependencies: + jiti: '>=1.21.0' + postcss: '>=8.0.9' + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + yaml: + optional: true + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + rollup@4.59.0: + resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} + + sucrase@3.35.1: + resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + tsup@8.5.1: + resolution: {integrity: sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + '@microsoft/api-extractor': ^7.36.0 + '@swc/core': ^1 + postcss: ^8.4.12 + typescript: '>=4.5.0' + peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + '@swc/core': + optional: true + postcss: + optional: true + typescript: + optional: true + + tsx@4.21.0: + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} + engines: {node: '>=18.0.0'} + hasBin: true + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.6.3: + resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + ws@8.19.0: + resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + +snapshots: + + '@esbuild/aix-ppc64@0.27.3': + optional: true + + '@esbuild/android-arm64@0.27.3': + optional: true + + '@esbuild/android-arm@0.27.3': + optional: true + + '@esbuild/android-x64@0.27.3': + optional: true + + '@esbuild/darwin-arm64@0.27.3': + optional: true + + '@esbuild/darwin-x64@0.27.3': + optional: true + + '@esbuild/freebsd-arm64@0.27.3': + optional: true + + '@esbuild/freebsd-x64@0.27.3': + optional: true + + '@esbuild/linux-arm64@0.27.3': + optional: true + + '@esbuild/linux-arm@0.27.3': + optional: true + + '@esbuild/linux-ia32@0.27.3': + optional: true + + '@esbuild/linux-loong64@0.27.3': + optional: true + + '@esbuild/linux-mips64el@0.27.3': + optional: true + + '@esbuild/linux-ppc64@0.27.3': + optional: true + + '@esbuild/linux-riscv64@0.27.3': + optional: true + + '@esbuild/linux-s390x@0.27.3': + optional: true + + '@esbuild/linux-x64@0.27.3': + optional: true + + '@esbuild/netbsd-arm64@0.27.3': + optional: true + + '@esbuild/netbsd-x64@0.27.3': + optional: true + + '@esbuild/openbsd-arm64@0.27.3': + optional: true + + '@esbuild/openbsd-x64@0.27.3': + optional: true + + '@esbuild/openharmony-arm64@0.27.3': + optional: true + + '@esbuild/sunos-x64@0.27.3': + optional: true + + '@esbuild/win32-arm64@0.27.3': + optional: true + + '@esbuild/win32-ia32@0.27.3': + optional: true + + '@esbuild/win32-x64@0.27.3': + optional: true + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@rollup/rollup-android-arm-eabi@4.59.0': + optional: true + + '@rollup/rollup-android-arm64@4.59.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.59.0': + optional: true + + '@rollup/rollup-darwin-x64@4.59.0': + optional: true + + '@rollup/rollup-freebsd-arm64@4.59.0': + optional: true + + '@rollup/rollup-freebsd-x64@4.59.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.59.0': + optional: true + + '@rollup/rollup-openbsd-x64@4.59.0': + optional: true + + '@rollup/rollup-openharmony-arm64@4.59.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.59.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.59.0': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.59.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.59.0': + optional: true + + '@types/estree@1.0.8': {} + + '@types/node@22.19.13': + dependencies: + undici-types: 6.21.0 + + '@types/ws@8.18.1': + dependencies: + '@types/node': 22.19.13 + + acorn@8.16.0: {} + + any-promise@1.3.0: {} + + bundle-require@5.1.0(esbuild@0.27.3): + dependencies: + esbuild: 0.27.3 + load-tsconfig: 0.2.5 + + cac@6.7.14: {} + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + commander@4.1.1: {} + + confbox@0.1.8: {} + + consola@3.4.2: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + esbuild@0.27.3: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.3 + '@esbuild/android-arm': 0.27.3 + '@esbuild/android-arm64': 0.27.3 + '@esbuild/android-x64': 0.27.3 + '@esbuild/darwin-arm64': 0.27.3 + '@esbuild/darwin-x64': 0.27.3 + '@esbuild/freebsd-arm64': 0.27.3 + '@esbuild/freebsd-x64': 0.27.3 + '@esbuild/linux-arm': 0.27.3 + '@esbuild/linux-arm64': 0.27.3 + '@esbuild/linux-ia32': 0.27.3 + '@esbuild/linux-loong64': 0.27.3 + '@esbuild/linux-mips64el': 0.27.3 + '@esbuild/linux-ppc64': 0.27.3 + '@esbuild/linux-riscv64': 0.27.3 + '@esbuild/linux-s390x': 0.27.3 + '@esbuild/linux-x64': 0.27.3 + '@esbuild/netbsd-arm64': 0.27.3 + '@esbuild/netbsd-x64': 0.27.3 + '@esbuild/openbsd-arm64': 0.27.3 + '@esbuild/openbsd-x64': 0.27.3 + '@esbuild/openharmony-arm64': 0.27.3 + '@esbuild/sunos-x64': 0.27.3 + '@esbuild/win32-arm64': 0.27.3 + '@esbuild/win32-ia32': 0.27.3 + '@esbuild/win32-x64': 0.27.3 + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + fix-dts-default-cjs-exports@1.0.1: + dependencies: + magic-string: 0.30.21 + mlly: 1.8.0 + rollup: 4.59.0 + + fsevents@2.3.3: + optional: true + + get-tsconfig@4.13.6: + dependencies: + resolve-pkg-maps: 1.0.0 + + joycon@3.1.1: {} + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + load-tsconfig@0.2.5: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + mlly@1.8.0: + dependencies: + acorn: 8.16.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.3 + + ms@2.1.3: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + object-assign@4.1.1: {} + + pathe@2.0.3: {} + + picocolors@1.1.1: {} + + picomatch@4.0.3: {} + + pirates@4.0.7: {} + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.0 + pathe: 2.0.3 + + postcss-load-config@6.0.1(tsx@4.21.0): + dependencies: + lilconfig: 3.1.3 + optionalDependencies: + tsx: 4.21.0 + + readdirp@4.1.2: {} + + resolve-from@5.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + rollup@4.59.0: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.59.0 + '@rollup/rollup-android-arm64': 4.59.0 + '@rollup/rollup-darwin-arm64': 4.59.0 + '@rollup/rollup-darwin-x64': 4.59.0 + '@rollup/rollup-freebsd-arm64': 4.59.0 + '@rollup/rollup-freebsd-x64': 4.59.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.59.0 + '@rollup/rollup-linux-arm-musleabihf': 4.59.0 + '@rollup/rollup-linux-arm64-gnu': 4.59.0 + '@rollup/rollup-linux-arm64-musl': 4.59.0 + '@rollup/rollup-linux-loong64-gnu': 4.59.0 + '@rollup/rollup-linux-loong64-musl': 4.59.0 + '@rollup/rollup-linux-ppc64-gnu': 4.59.0 + '@rollup/rollup-linux-ppc64-musl': 4.59.0 + '@rollup/rollup-linux-riscv64-gnu': 4.59.0 + '@rollup/rollup-linux-riscv64-musl': 4.59.0 + '@rollup/rollup-linux-s390x-gnu': 4.59.0 + '@rollup/rollup-linux-x64-gnu': 4.59.0 + '@rollup/rollup-linux-x64-musl': 4.59.0 + '@rollup/rollup-openbsd-x64': 4.59.0 + '@rollup/rollup-openharmony-arm64': 4.59.0 + '@rollup/rollup-win32-arm64-msvc': 4.59.0 + '@rollup/rollup-win32-ia32-msvc': 4.59.0 + '@rollup/rollup-win32-x64-gnu': 4.59.0 + '@rollup/rollup-win32-x64-msvc': 4.59.0 + fsevents: 2.3.3 + + source-map@0.7.6: {} + + sucrase@3.35.1: + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + commander: 4.1.1 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.7 + tinyglobby: 0.2.15 + ts-interface-checker: 0.1.13 + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + tinyexec@0.3.2: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + tree-kill@1.2.2: {} + + ts-interface-checker@0.1.13: {} + + tsup@8.5.1(tsx@4.21.0)(typescript@5.9.3): + dependencies: + bundle-require: 5.1.0(esbuild@0.27.3) + cac: 6.7.14 + chokidar: 4.0.3 + consola: 3.4.2 + debug: 4.4.3 + esbuild: 0.27.3 + fix-dts-default-cjs-exports: 1.0.1 + joycon: 3.1.1 + picocolors: 1.1.1 + postcss-load-config: 6.0.1(tsx@4.21.0) + resolve-from: 5.0.0 + rollup: 4.59.0 + source-map: 0.7.6 + sucrase: 3.35.1 + tinyexec: 0.3.2 + tinyglobby: 0.2.15 + tree-kill: 1.2.2 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - jiti + - supports-color + - tsx + - yaml + + tsx@4.21.0: + dependencies: + esbuild: 0.27.3 + get-tsconfig: 4.13.6 + optionalDependencies: + fsevents: 2.3.3 + + typescript@5.9.3: {} + + ufo@1.6.3: {} + + undici-types@6.21.0: {} + + ws@8.19.0: {} diff --git a/mcp-bridge/src/bridge.ts b/mcp-bridge/src/bridge.ts new file mode 100644 index 0000000..2a40da1 --- /dev/null +++ b/mcp-bridge/src/bridge.ts @@ -0,0 +1,351 @@ +/** + * AIPex MCP Bridge + * + * A stdio MCP server that bridges AI agents to the AIPex Chrome extension via WebSocket. + * + * Agent (MCP client) ──stdio──▶ this bridge ──WebSocket──▶ AIPex extension (MCP server) + * + * Usage: + * npx aipex-mcp-bridge [--port 9223] + * + * Works with any MCP client that supports stdio transport: + * - Cursor, Claude Desktop, Claude Code, VS Code Copilot, Windsurf, Zed, etc. + */ + +import { createServer } from "node:http" +import { createInterface } from "node:readline" +import { WebSocket, WebSocketServer } from "ws" + +// ── CLI args ──────────────────────────────────────────────────────────────── + +const cliArgs = process.argv.slice(2) + +if (cliArgs.includes("--help") || cliArgs.includes("-h")) { + process.stderr.write(` +AIPex MCP Bridge — connect AI agents to AIPex browser extension + +Usage: + npx aipex-mcp-bridge [--port ] + +Options: + --port WebSocket port for AIPex extension (default: 9223) + --help, -h Show this help message + --version, -v Show version + +After starting, open AIPex extension Options and connect to: + ws://localhost: +`) + process.exit(0) +} + +if (cliArgs.includes("--version") || cliArgs.includes("-v")) { + process.stderr.write("aipex-mcp-bridge 1.0.0\n") + process.exit(0) +} + +const portIdx = cliArgs.indexOf("--port") +const WS_PORT = portIdx !== -1 ? parseInt(cliArgs[portIdx + 1], 10) : 9223 + +if (isNaN(WS_PORT) || WS_PORT < 1 || WS_PORT > 65535) { + process.stderr.write(`Invalid port number. Must be between 1 and 65535.\n`) + process.exit(1) +} + +// ── Logging (stderr only — stdout is reserved for MCP protocol) ───────────── + +function log(msg: string) { + process.stderr.write(`[aipex-bridge] ${msg}\n`) +} + +// ── JSON-RPC types ────────────────────────────────────────────────────────── + +interface JSONRPCRequest { + jsonrpc: "2.0" + id: number | string | null + method: string + params?: unknown +} + +interface JSONRPCResponse { + jsonrpc: "2.0" + id: number | string | null + result?: unknown + error?: { code: number; message: string } +} + +type JSONRPCMessage = JSONRPCRequest | JSONRPCResponse + +interface McpTool { + name: string + description?: string + inputSchema?: unknown +} + +// ── AIPex WebSocket connection state ──────────────────────────────────────── + +let aipexSocket: WebSocket | null = null +let aipexReady = false +let cachedTools: McpTool[] = [] + +let nextAipexId = 1 +const aipexPending = new Map< + number | string, + { resolve: (v: unknown) => void; reject: (e: Error) => void } +>() + +// ── Respond to MCP client (stdout, JSON-RPC 2.0) ─────────────────────────── + +function respond(id: number | string | null, result: unknown) { + const msg: JSONRPCResponse = { jsonrpc: "2.0", id, result } + process.stdout.write(JSON.stringify(msg) + "\n") +} + +function respondError( + id: number | string | null, + code: number, + message: string +) { + const msg: JSONRPCResponse = { jsonrpc: "2.0", id, error: { code, message } } + process.stdout.write(JSON.stringify(msg) + "\n") +} + +// ── Send requests to AIPex (WebSocket) ────────────────────────────────────── + +function sendToAipex(method: string, params: unknown = {}): Promise { + if (!aipexSocket || aipexSocket.readyState !== WebSocket.OPEN) { + return Promise.reject(new Error("AIPex extension not connected")) + } + const id = nextAipexId++ + const msg = { jsonrpc: "2.0", id, method, params } + aipexSocket.send(JSON.stringify(msg)) + return new Promise((resolve, reject) => { + aipexPending.set(id, { resolve, reject }) + }) +} + +// ── Handle messages from AIPex ────────────────────────────────────────────── + +function handleAipexMessage(raw: string) { + let msg: JSONRPCMessage + try { + msg = JSON.parse(raw) + } catch { + log(`Failed to parse AIPex message: ${raw.slice(0, 100)}`) + return + } + + if ("result" in msg || "error" in msg) { + const res = msg as JSONRPCResponse + const p = aipexPending.get(res.id!) + if (p) { + aipexPending.delete(res.id!) + if (res.error) { + p.reject(new Error(res.error.message)) + } else { + p.resolve(res.result) + } + } + } +} + +// ── MCP handshake (runs automatically when AIPex connects) ────────────────── + +async function doAipexHandshake(socket: WebSocket) { + log("Starting MCP handshake with AIPex...") + + const initResult = (await sendToAipex("initialize", { + protocolVersion: "2024-11-05", + capabilities: {}, + clientInfo: { name: "aipex-mcp-bridge", version: "1.0.0" } + })) as Record + + const serverInfo = initResult?.serverInfo as + | Record + | undefined + log(`AIPex server: ${serverInfo?.name ?? "?"} v${serverInfo?.version ?? "?"}`) + + socket.send( + JSON.stringify({ jsonrpc: "2.0", method: "notifications/initialized" }) + ) + + const toolsResult = (await sendToAipex("tools/list")) as Record< + string, + unknown + > + cachedTools = (toolsResult?.tools as McpTool[]) ?? [] + aipexReady = true + + log(`Handshake complete. ${cachedTools.length} tools available.`) +} + +// ── Handle MCP requests from the agent (stdin) ────────────────────────────── + +async function handleAgentRequest(req: JSONRPCRequest) { + const { id, method, params } = req + + if (method === "initialize") { + respond(id, { + protocolVersion: "2024-11-05", + capabilities: { tools: {} }, + serverInfo: { name: "aipex-mcp-bridge", version: "1.0.0" } + }) + return + } + + if (method === "notifications/initialized") { + return + } + + if (method === "tools/list") { + if (aipexReady && cachedTools.length > 0) { + respond(id, { tools: cachedTools }) + } else { + respond(id, { + tools: [ + { + name: "check_aipex_connection", + description: [ + "AIPex extension is not connected. To enable browser control:", + `1. Open Chrome → AIPex extension → Options page`, + `2. Set WebSocket URL to: ws://localhost:${WS_PORT}`, + `3. Click Connect`, + `Then reload this MCP server.` + ].join("\n"), + inputSchema: { type: "object", properties: {} } + } + ] + }) + } + return + } + + if (method === "tools/call") { + if ( + !aipexReady || + !aipexSocket || + aipexSocket.readyState !== WebSocket.OPEN + ) { + respondError( + id, + -32000, + `AIPex extension not connected. Open AIPex Options and connect to ws://localhost:${WS_PORT}` + ) + return + } + try { + const result = await sendToAipex( + "tools/call", + params as Record + ) + respond(id, result) + } catch (e) { + respondError(id, -32000, e instanceof Error ? e.message : String(e)) + } + return + } + + if (method === "ping") { + if (aipexReady && aipexSocket?.readyState === WebSocket.OPEN) { + try { + const result = await sendToAipex("ping") + respond(id, result) + } catch { + respond(id, {}) + } + } else { + respond(id, {}) + } + return + } + + respondError(id, -32601, `Method not found: ${method}`) +} + +// ── Read MCP requests from stdin ──────────────────────────────────────────── + +const stdinRl = createInterface({ input: process.stdin }) + +stdinRl.on("line", (line) => { + const trimmed = line.trim() + if (!trimmed) return + + let req: JSONRPCRequest + try { + req = JSON.parse(trimmed) + } catch { + log(`Failed to parse stdin: ${trimmed.slice(0, 100)}`) + return + } + + handleAgentRequest(req).catch((e) => { + log(`Error handling request: ${e instanceof Error ? e.message : String(e)}`) + if (req.id != null) { + respondError(req.id, -32603, "Internal error") + } + }) +}) + +stdinRl.on("close", () => { + log("stdin closed, shutting down") + process.exit(0) +}) + +// ── WebSocket server (waits for AIPex extension to connect) ───────────────── + +const httpServer = createServer() +const wss = new WebSocketServer({ server: httpServer }) + +wss.on("connection", (socket, req) => { + const addr = req.socket.remoteAddress ?? "unknown" + + if (aipexSocket && aipexSocket.readyState === WebSocket.OPEN) { + log(`New connection from ${addr}, closing previous`) + aipexSocket.close() + } + + aipexSocket = socket + aipexReady = false + cachedTools = [] + log(`AIPex extension connected from ${addr}`) + + socket.on("message", (data) => { + handleAipexMessage(data.toString()) + }) + + socket.on("close", () => { + log("AIPex extension disconnected") + if (aipexSocket === socket) { + aipexSocket = null + aipexReady = false + cachedTools = [] + } + }) + + socket.on("error", (err) => { + log(`Socket error: ${err.message}`) + }) + + doAipexHandshake(socket).catch((err: Error) => { + log(`Handshake failed: ${err.message}`) + }) +}) + +wss.on("error", (err) => { + log(`WebSocket server error: ${err.message}`) +}) + +// ── Start ─────────────────────────────────────────────────────────────────── + +httpServer.listen(WS_PORT, () => { + log(`AIPex MCP Bridge started`) + log(`WebSocket server listening on ws://localhost:${WS_PORT}`) + log(`Waiting for AIPex extension to connect...`) + log(`Open AIPex Options → set URL to ws://localhost:${WS_PORT} → Connect`) +}) + +process.on("SIGINT", () => { + log("Shutting down...") + wss.close() + httpServer.close() + process.exit(0) +}) diff --git a/mcp-bridge/tsconfig.json b/mcp-bridge/tsconfig.json new file mode 100644 index 0000000..3cee636 --- /dev/null +++ b/mcp-bridge/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "outDir": "dist", + "rootDir": "src", + "declaration": false + }, + "include": ["src"] +} diff --git a/mcp-bridge/tsup.config.ts b/mcp-bridge/tsup.config.ts new file mode 100644 index 0000000..7ba1b6f --- /dev/null +++ b/mcp-bridge/tsup.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from "tsup" + +export default defineConfig({ + entry: ["src/bridge.ts"], + format: ["esm"], + target: "node18", + clean: true, + banner: { + js: "#!/usr/bin/env node" + } +}) diff --git a/skill/SKILL.md b/skill/SKILL.md new file mode 100644 index 0000000..a566db0 --- /dev/null +++ b/skill/SKILL.md @@ -0,0 +1,257 @@ +--- +name: aipex-browser +description: AI-powered browser automation using the AIPex Chrome Extension via MCP bridge. Use this skill when the agent needs to control a Chrome browser — navigating pages, clicking elements, filling forms, capturing screenshots, managing tabs, or downloading content — by connecting to the AIPex MCP bridge. +version: 1.0.0 +metadata: + openclaw: + requires: + bins: + - npx + emoji: "🌐" + homepage: https://aipex.ai + os: [macos, linux, windows] +--- + +# AIPex Browser Control + +AIPex is a Chrome extension that exposes 30+ browser automation tools over the Model Context Protocol (MCP). Once connected, the agent can control any Chrome tab using natural language — clicking, typing, navigating, capturing screenshots, downloading content, and more. + +**Architecture:** +``` +Agent (MCP client) ──stdio──▶ aipex-mcp-bridge ──WebSocket──▶ AIPex Chrome Extension ──▶ Browser APIs +``` + +--- + +## When to Use This Skill + +Use this skill when the user wants to: + +- Navigate to URLs, click links, fill forms, or interact with any web page +- Automate multi-step browser workflows +- Extract or download data from web pages +- Capture screenshots of browser tabs +- Manage multiple tabs across browser windows +- Perform browser-assisted testing (accessibility, UX, regression) + +--- + +## Prerequisites + +- **AIPex Chrome extension** installed (available on the Chrome Web Store or via developer build) +- **Node.js >= 18** installed on the local machine + +The user is assumed to have AIPex installed. The agent only needs to complete the two connection steps below. + +--- + +## Step 1: Register the MCP Server + +Add the following to the agent's MCP configuration. No manual installation is needed — `npx` downloads and runs `aipex-mcp-bridge` automatically. + +### Cursor (`.cursor/mcp.json`) + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +### Claude Desktop (`claude_desktop_config.json`) + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +### Claude Code (CLI) + +```bash +claude mcp add aipex-browser -- npx -y aipex-mcp-bridge +``` + +### VS Code Copilot (`.vscode/mcp.json`) + +```json +{ + "servers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +### Windsurf (`mcp_config.json`) + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge"] + } + } +} +``` + +### Custom port (optional) + +The bridge listens on `localhost:9223` by default. To use a different port: + +```json +{ + "mcpServers": { + "aipex-browser": { + "command": "npx", + "args": ["-y", "aipex-mcp-bridge", "--port", "9224"] + } + } +} +``` + +Then use `ws://localhost:9224` in Step 2. + +--- + +## Step 2: Connect the AIPex Extension to the Bridge + +After the MCP server is registered and running: + +1. Open Chrome and click the **AIPex** extension icon +2. Go to **Options** (or right-click the icon → "Extension options") +3. Find the **WebSocket Connection** section +4. Enter: `ws://localhost:9223` +5. Click **Connect** + +The bridge and extension will handshake, and all browser tools will become available to the agent. + +**Verifying the connection:** If only a single tool called `check_aipex_connection` is visible, the extension has not yet connected. Follow Step 2 again, then reload the MCP server in agent settings. + +--- + +## Tool Usage Strategy (IMPORTANT) + +Always follow this priority order to minimize token cost and latency: + +### Priority 1 — `search_elements` (always try first) + +Query the page's accessibility tree to find elements and get their UIDs. Fast, cheap, requires no screenshot. + +``` +search_elements(tabId, "{button,input,textarea,select,a}*") +``` + +### Priority 2 — UID-based interaction (preferred) + +Use UIDs returned by `search_elements` to interact directly: + +- `click(tabId, uid)` — click any element +- `fill_element_by_uid(tabId, uid, value)` — type into inputs +- `hover_element_by_uid(tabId, uid)` — reveal menus or tooltips + +### Priority 3 — `capture_screenshot` + `computer` (high-cost fallback only) + +Use only when `search_elements` fails after two different query attempts, or when pixel-level interaction is required (canvas, drag-and-drop, sliders). + +1. `capture_screenshot(sendToLLM=true)` — see the page +2. `computer(action, coordinate)` — click/type at pixel coordinates + +### Standard Workflow + +``` +get_all_tabs() + → search_elements(tabId, "") + → click(tabId, uid) OR fill_element_by_uid(tabId, uid, value) + → [capture_screenshot(sendToLLM=true) to verify if needed] +``` + +--- + +## Available Tool Categories + +| Category | Tools | Description | +|---|---|---| +| Tab Management | 8 tools | Open, close, switch, pin, group tabs | +| UI Interaction | 7 tools | Click, fill, hover, keyboard, coordinate-based | +| Page Content | 4 tools | Metadata, scroll, highlight elements/text | +| Screenshots | 2 tools | Capture visible tab or specific tab | +| Downloads | 3 tools | Save text as markdown, download images | +| Human Intervention | 4 tools | Request user input mid-automation | + +**Key tools by category:** + +| Category | Key Tools | +|---|---| +| Tab | `get_all_tabs`, `switch_to_tab`, `create_new_tab`, `close_tab` | +| UI | `search_elements`, `click`, `fill_element_by_uid`, `computer` | +| Page | `get_page_metadata`, `scroll_to_element`, `highlight_element` | +| Screenshot | `capture_screenshot`, `capture_tab_screenshot` | +| Download | `download_text_as_markdown`, `download_image` | +| Intervention | `request_intervention`, `list_interventions` | + +To load complete parameter schemas and examples for every tool: + +``` +read_skill_reference("aipex-browser", "references/tools-reference.md") +``` + +--- + +## Common Patterns + +### Navigate to a URL and click a button + +``` +create_new_tab("https://example.com") +→ search_elements(tabId, "*[Ss]ubmit*") +→ click(tabId, uid) +``` + +### Fill a login form + +``` +get_all_tabs() +→ search_elements(tabId, "{input,textbox}*") +→ fill_element_by_uid(tabId, emailUid, "user@example.com") +→ fill_element_by_uid(tabId, passwordUid, "secret") +→ search_elements(tabId, "*[Ll]ogin*") +→ click(tabId, uid) +``` + +### Extract page content to markdown + +``` +get_page_metadata() +→ download_text_as_markdown(content, "page-extract") +``` + +### Visual verification + +``` +capture_screenshot(sendToLLM=true) +``` + +--- + +## Troubleshooting + +| Symptom | Likely Cause | Fix | +|---|---|---| +| Only `check_aipex_connection` visible | Extension not connected to bridge | Open AIPex Options → set WebSocket URL → Connect | +| Port 9223 already in use | Port conflict on machine | Use `--port 9224` in MCP config and `ws://localhost:9224` in extension | +| `search_elements` returns 0 results | Page uses canvas or non-semantic HTML | Fall back to `capture_screenshot(sendToLLM=true)` + `computer` tool | +| Connection drops frequently | Service worker sleep cycle | AIPex uses keepalive pings; reconnect extension from Options if needed | +| Tools appear but calls time out | Bridge not receiving WebSocket messages | Restart bridge: reload MCP server in agent settings | diff --git a/skill/references/tools-reference.md b/skill/references/tools-reference.md new file mode 100644 index 0000000..bf9c597 --- /dev/null +++ b/skill/references/tools-reference.md @@ -0,0 +1,427 @@ +# AIPex Browser Tools Reference + +Complete parameter schemas and usage examples for all AIPex MCP tools exposed via `aipex-mcp-bridge`. + +--- + +## Tab Management + +### `get_all_tabs` + +Get all open tabs across all browser windows. + +**Parameters:** none + +**Returns:** Array of tab objects — `id`, `title`, `url`, `windowId`, `active`, `pinned` + +--- + +### `get_current_tab` + +Get the currently active tab. + +**Parameters:** none + +**Returns:** Tab object — `id`, `title`, `url`, `windowId` + +--- + +### `switch_to_tab` + +Switch browser focus to a specific tab. + +| Parameter | Type | Required | Description | +|---|---|---|---| +| `tabId` | number | yes | ID of the tab to switch to | + +--- + +### `create_new_tab` + +Open a new tab at the specified URL. + +| Parameter | Type | Required | Description | +|---|---|---|---| +| `url` | string | yes | URL to open | + +**Returns:** New tab object including its `id` + +--- + +### `get_tab_info` + +Get detailed info about a specific tab. + +| Parameter | Type | Required | Description | +|---|---|---|---| +| `tabId` | number | yes | ID of the tab | + +--- + +### `close_tab` + +Close a tab by ID. + +| Parameter | Type | Required | Description | +|---|---|---|---| +| `tabId` | number | yes | ID of the tab to close | + +--- + +### `organize_tabs` + +Use AI to automatically group all open tabs by topic or domain. + +**Parameters:** none + +--- + +### `ungroup_tabs` + +Remove all tab groups in the current window. + +**Parameters:** none + +--- + +## UI Interaction + +### `search_elements` ← **Use First** + +Search the page's accessibility tree using glob patterns. Returns matching elements with `uid` values for direct interaction. Fast and token-efficient — no screenshot needed. + +| Parameter | Type | Required | Default | Description | +|---|---|---|---|---| +| `tabId` | number | yes | — | ID of the tab to search | +| `query` | string | yes | — | Glob pattern (see below) | +| `contextLevels` | number | no | 1 | Lines of surrounding context to include | + +**Glob syntax quick reference:** + +| Pattern | Matches | +|---|---| +| `*` | Any sequence of characters | +| `?` | Exactly one character | +| `[abc]` | Any of those characters | +| `{a,b,c}` | Any of those alternatives | + +**Starter queries:** + +``` +{button,input,textarea,select,a}* — all interactive elements +{button,link,a}* — clickable elements only +*[Ss]ubmit*, *[Ss]ave*, *[Cc]onfirm* — action buttons +*[Ll]ogin*, *[Ss]ign* — auth elements +*[Ss]earch* — search inputs +{input,textbox,combobox}* — text inputs +``` + +**Returns:** Accessibility tree excerpt with `uid=` attributes on matched elements. Use those UIDs directly with `click`, `fill_element_by_uid`, and `hover_element_by_uid`. + +--- + +### `click` + +Click an element by UID. + +| Parameter | Type | Required | Default | Description | +|---|---|---|---|---| +| `tabId` | number | yes | — | ID of the tab | +| `uid` | string | yes | — | Element UID from `search_elements` | +| `dblClick` | boolean | no | false | Set to `true` for double-click | + +--- + +### `fill_element_by_uid` + +Type text into an input element by UID. + +| Parameter | Type | Required | Description | +|---|---|---|---| +| `tabId` | number | yes | ID of the tab | +| `uid` | string | yes | Element UID from `search_elements` | +| `value` | string | yes | Text to type into the element | + +--- + +### `fill_form` + +Fill multiple form fields at once. + +| Parameter | Type | Required | Description | +|---|---|---|---| +| `tabId` | number | yes | ID of the tab | +| `elements` | array | yes | Array of `{ uid, value }` objects | + +**Example:** + +```json +{ + "tabId": 42, + "elements": [ + { "uid": "input-email-3", "value": "user@example.com" }, + { "uid": "input-pass-4", "value": "password123" } + ] +} +``` + +--- + +### `get_editor_value` + +Read the full text content of a code editor (Monaco, CodeMirror, ACE) or textarea without truncation. Call before overwriting to avoid data loss. + +| Parameter | Type | Required | Description | +|---|---|---|---| +| `tabId` | number | yes | ID of the tab | +| `uid` | string | yes | UID of the editor element | + +--- + +### `hover_element_by_uid` + +Hover over an element to reveal tooltips, dropdown menus, or hover states. + +| Parameter | Type | Required | Description | +|---|---|---|---| +| `tabId` | number | yes | ID of the tab | +| `uid` | string | yes | Element UID from `search_elements` | + +--- + +### `computer` ← **High-Cost Fallback** + +Coordinate-based mouse and keyboard interaction. Use only when `search_elements` fails after two different query attempts, or when the task requires pixel-level interaction (canvas, drag-and-drop, custom sliders). + +**Prerequisite:** Call `capture_screenshot(sendToLLM=true)` first. Coordinates are pixel positions from the screenshot. + +| Parameter | Type | Required | Description | +|---|---|---|---| +| `action` | enum | yes | See action table below | +| `coordinate` | [x, y] | conditional | Pixel coords. Required for most actions. | +| `text` | string | conditional | Text to type or key name(s) to press | +| `start_coordinate` | [x, y] | conditional | Drag start position (for `left_click_drag`) | +| `scroll_direction` | enum | no | `up`, `down`, `left`, `right` | +| `scroll_amount` | number | no | Pixels to scroll | +| `tabId` | number | no | Tab ID (defaults to active tab) | +| `uid` | string | no | Element UID (for `scroll_to` action) | + +**Actions:** + +| Action | Description | +|---|---| +| `left_click` | Single left click at coordinate | +| `right_click` | Right-click (context menu) at coordinate | +| `double_click` | Double-click at coordinate | +| `triple_click` | Triple-click (select all in field) at coordinate | +| `hover` | Move mouse to coordinate without clicking | +| `type` | Type a text string at the current cursor position | +| `key` | Press a keyboard key or combination | +| `scroll` | Scroll at coordinate in given direction | +| `scroll_to` | Scroll a UID element into view | +| `left_click_drag` | Drag from `start_coordinate` to `coordinate` | + +**Common `key` values:** + +``` +"Enter" — submit / confirm +"Tab" — move focus forward +"shift+Tab" — move focus backward +"Escape" — close dialogs / cancel +"cmd+a" — select all (macOS) +"ctrl+a" — select all (Windows/Linux) +"Backspace" — delete character before cursor +"Delete" — delete character after cursor +"ArrowDown" — navigate list down +"ArrowUp" — navigate list up +"Space" — toggle checkbox / activate button +``` + +--- + +## Page Content + +### `get_page_metadata` + +Get page metadata from the active tab. + +**Parameters:** none + +**Returns:** `{ title, description, keywords, url, favicon }` + +--- + +### `scroll_to_element` + +Scroll a DOM element into view and center it in the viewport. + +| Parameter | Type | Required | Description | +|---|---|---|---| +| `selector` | string | yes | CSS selector of the element | + +--- + +### `highlight_element` + +Add a persistent visual highlight (drop shadow) to DOM elements. Useful for audit reports or before capturing screenshots. + +| Parameter | Type | Required | Default | Description | +|---|---|---|---|---| +| `selector` | string | yes | — | CSS selector | +| `color` | string | no | — | Shadow color, e.g. `"#00d4ff"` | +| `duration` | number | no | — | Duration in ms (`0` = permanent) | +| `intensity` | enum | no | `"normal"` | `"subtle"`, `"normal"`, or `"strong"` | +| `persist` | boolean | no | `true` | Keep highlight after page interaction | + +--- + +### `highlight_text_inline` + +Highlight specific words or phrases within text content on the page. + +| Parameter | Type | Required | Default | Description | +|---|---|---|---|---| +| `selector` | string | yes | — | CSS selector of container element(s) | +| `searchText` | string | yes | — | Text or phrase to highlight | +| `caseSensitive` | boolean | no | `false` | Case-sensitive match | +| `wholeWords` | boolean | no | `false` | Match whole words only | +| `highlightColor` | string | no | `"#DC143C"` | Text color | +| `backgroundColor` | string | no | `"transparent"` | Background color | +| `fontWeight` | string | no | `"bold"` | Font weight | +| `persist` | boolean | no | `true` | Keep highlight permanently | + +--- + +## Screenshots + +### `capture_screenshot` + +Capture the current visible area of the active tab. + +**When to use:** Only when `search_elements` cannot find the target after two query attempts, or when visual layout, images, charts, or canvas content must be analyzed. Adding `sendToLLM=true` increases token cost. + +| Parameter | Type | Required | Default | Description | +|---|---|---|---|---| +| `sendToLLM` | boolean | no | `false` | Send image to LLM for visual analysis. When `true`, enables the `computer` tool for coordinate-based follow-up actions. | + +--- + +### `capture_tab_screenshot` + +Capture a screenshot of a specific tab by ID. + +| Parameter | Type | Required | Default | Description | +|---|---|---|---|---| +| `tabId` | number | yes | — | ID of the tab to capture | +| `sendToLLM` | boolean | no | `false` | Send image to LLM. Use sparingly. | + +--- + +## Downloads + +### `download_text_as_markdown` + +Save text content as a `.md` file to the user's local filesystem. + +| Parameter | Type | Required | Default | Description | +|---|---|---|---|---| +| `text` | string | yes | — | Text content to save | +| `filename` | string | no | — | Filename without `.md` extension | +| `folderPath` | string | no | — | Optional subfolder path | +| `displayResults` | boolean | no | `true` | Show download confirmation | + +--- + +### `download_image` + +Download an image from base64 data to the local filesystem. + +| Parameter | Type | Required | Description | +|---|---|---|---| +| `imageData` | string | yes | Base64 image data URL (must start with `data:image/`) | +| `filename` | string | no | Filename without extension | +| `folderPath` | string | no | Optional subfolder path | + +--- + +### `download_chat_images` + +Download multiple images from chat messages to the local filesystem. + +| Parameter | Type | Required | Default | Description | +|---|---|---|---|---| +| `messages` | array | yes | — | Array of `{ id, parts: [{ type, imageData, imageTitle }] }` | +| `folderPrefix` | string | no | — | Folder name for organizing downloads | +| `filenamingStrategy` | enum | no | `"descriptive"` | `"descriptive"`, `"sequential"`, or `"timestamp"` | +| `displayResults` | boolean | no | `true` | Show download results | + +--- + +## Human Intervention + +Use these tools to pause automation and request user input when the agent cannot proceed autonomously (e.g., CAPTCHA, 2FA, ambiguous choices). + +### `list_interventions` + +List all available human intervention types. + +| Parameter | Type | Required | Description | +|---|---|---|---| +| `enabledOnly` | boolean | no | Return only enabled intervention types | + +--- + +### `get_intervention_info` + +Get detailed schema and examples for a specific intervention type. + +| Parameter | Type | Required | Description | +|---|---|---|---| +| `type` | string | yes | Intervention type (e.g. `"voice-input"`, `"user-selection"`, `"monitor-operation"`) | + +--- + +### `request_intervention` + +Pause automation and request human input. + +| Parameter | Type | Required | Default | Description | +|---|---|---|---|---| +| `type` | string | yes | — | Intervention type to request | +| `params` | any | no | — | Type-specific parameters | +| `timeout` | number | no | `300` | Timeout in seconds before auto-cancelling | +| `reason` | string | no | — | Explanation shown to the user | + +--- + +### `cancel_intervention` + +Cancel the currently active intervention request. + +| Parameter | Type | Required | Description | +|---|---|---|---| +| `id` | string | no | Intervention ID. If omitted, cancels the active intervention. | + +--- + +## Tool Selection Decision Tree + +``` +Need to interact with a page element? +│ +├── YES ──▶ search_elements(tabId, pattern) +│ │ +│ ├── Found UIDs? ──▶ YES ──▶ click / fill_element_by_uid / hover_element_by_uid +│ │ +│ └── No results after 2 different queries? +│ └──▶ capture_screenshot(sendToLLM=true) +│ └──▶ computer(action, coordinate) +│ +└── NO ──▶ What kind of task? + │ + ├── Tab operation ──▶ get_all_tabs / switch_to_tab / create_new_tab / close_tab + ├── Download content ──▶ download_text_as_markdown / download_image + ├── Visual capture ──▶ capture_screenshot / capture_tab_screenshot + ├── Page info ──▶ get_page_metadata / scroll_to_element + └── Need user input ──▶ request_intervention +```