Skip to main content
Glama
seerkong

Ego Automation MCP Server

by seerkong
README.md
# Ego Automation MCP App Demo

这是一个可运行的 MCP Apps demo:MCP App 是控制台 UI;MCP server 是唯一能启动 `ego-browser nodejs`、复用 task space/tab 并调用页面 bundle 的执行边界。

## 流程原理

```mermaid
sequenceDiagram
    participant Host as MCP Apps Host
    participant App as sandbox MCP App
    participant MCP as HTTP MCP Server
    participant Ego as ego-browser nodejs
    participant Page as 目标页面

    Host->>MCP: 连接 /mcp,列出 tools/resources
    MCP-->>Host: ego_open_session、ego_find_records、ui:// resource
    Host->>MCP: 读取 ui://ego-automation/console.html
    MCP-->>Host: mcp-app.html
    Host->>App: 在 sandbox iframe 渲染 AppBridge
    App->>MCP: tools/call ego_open_session(url)
    MCP->>Ego: spawn ego-browser nodejs
    Ego->>Ego: 创建 task space/tab
    Ego->>Ego: Page.addScriptToEvaluateOnNewDocument
    Ego->>Page: 导航到目标 URL
    Page-->>Ego: 页面加载并暴露 __egoSkill.ready
    Ego-->>MCP: session.id + tab/task 元数据
    MCP-->>App: 结构化会话结果
    App->>MCP: tools/call ego_find_records(sessionId, status)
    MCP->>Ego: 切回保存的 task space/tab
    Ego->>Page: 仅调用白名单 findRecords(args)
    Page-->>Ego: data-status 过滤结果
    Ego-->>MCP: JSON 结果
    MCP-->>App: count、records
```

具体链路如下:

1. Host 连接 `http://127.0.0.1:3001/mcp`,发现两个工具和 `ui://ego-automation/console.html` App resource。
2. Host 把 resource 放进 sandbox iframe;App 只能通过 `app.callServerTool()` 发起 MCP 工具调用,不能直接启动本地进程、读本地目录或控制 Ego。
3. 点击“打开 ego 会话”后,MCP server 调用 `EgoGateway.openSession()`。Gateway 启动 `ego-browser nodejs`,创建隔离 task space,注册 `Page.addScriptToEvaluateOnNewDocument` 预加载受控 bundle,再导航到输入的 URL。
4. Gateway 保存 `session.id`、task space 和 tab 标识。后续查询必须携带这个 `session.id`,因此查询会复用同一浏览器页面,而不是新开页面。
5. 点击“查询 pending records”后,server 只允许执行声明的 `findRecords` 操作。页面 bundle 读取带有 `data-status` 的 DOM 元素,按 `status: "pending"` 过滤并返回 JSON。
6. MCP server 将结果同时放入 `structuredContent` 和文本 envelope,App 解包后渲染到结果面板。

本地演示页面是 `http://127.0.0.1:3001/pending-records.html`,其中有两条 pending 记录和一条 done 记录;默认输入框已指向该页面。

## Run

```sh
cd /Users/kongweixian/ai/demo/ego-automation-mcp-app-demo
npm install
npm run build
npm start
```

- MCP endpoint: `http://127.0.0.1:3001/mcp`
- HTTP bundle: `http://127.0.0.1:3001/bundles/ego-skill-api.js`
- Pending records fixture: `http://127.0.0.1:3001/pending-records.html`
- Local end-to-end fixture: `http://127.0.0.1:3001/fixture.html`

用支持 MCP Apps 的 Host 调用 `ego_open_session` 会渲染控制台。App 内的按钮调用 `ego_find_records`;服务端只允许调用 bundle 的 `findRecords`,不会接受任意 JavaScript、shell 命令或文件路径。

## Local stdio entry

`node stdio.mjs` 通过 stdio 提供同一组 MCP tools 和 App resource。它会为 Ego 页面预加载单独启动一个自动分配端口的 `127.0.0.1` bundle 静态服务器;该入口不会发布 MCP HTTP endpoint。

## Codex MCP Apps Companion

Codex 当前把 MCP tools 提供给对话,但不原生渲染 MCP Apps resource。此项目提供独立的同源 Web host:`http://127.0.0.1:3001/codex-host.html`。它在 sandbox iframe 中加载 `ui://` resource,并以 MCP Apps `AppBridge` 把 App 的调用转发给同一个 MCP server;它不是 Codex 对话 UI 的替代品。

## HTTPS target pages

Gateway 启动时读取受控的 `bundles/ego-skill-api.js`,并把源码直接放进 `Page.addScriptToEvaluateOnNewDocument` 预加载脚本。因此 HTTPS 目标不会依赖从页面加载本地 HTTP bundle,也不会触发 mixed-content;返回的 `bundleUrl` 仍用于展示和外部部署场景。

如果把 bundle 改为远程加载,请把构建产物放到受控 HTTPS origin,并设置:

```sh
PUBLIC_BASE_URL=https://mcp.example.com \\
EGO_BUNDLE_URL=https://assets.example.com/ego-skill-api.v0.1.0.js \\
npm start
```

bundle 必须使用版本化的受控 URL,不能使用不受信任或可变的 `latest.js`。

## Boundaries

`mcp-app.html` 是 sandbox iframe 中的 UI,不能读写本机目录或启动 ego。文件系统、process 和 ego 操作都留在 `server.mjs` / `lib/ego-gateway.mjs`;App 只经 `app.callServerTool()` 调用语义化 MCP 工具。

Maintenance

ActivitySlowing
ResponsivenessNo issues