<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Edge MCP Agent 2]]></title><description><![CDATA[<p dir="auto"></p><div class="card col-md-9 col-lg-6 position-relative link-preview p-0">



<a href="https://github.com/Raven777777/EMA2" title="GitHub - Raven777777/EMA2: 通过「Edge 扩展 + 单进程 Rust 中继」让 AI 助手直接控制你的**真实 Edge 浏览器**： 读取任意网页、操作标签页、点击元素、执行 JS，并**带真实登录态**。">
<img src="https://opengraph.githubassets.com/ef13156308168f0d9ead0c1a907e0520e24d03d1e976b4fc3ab59f9fc295d4b2/Raven777777/EMA2" class="card-img-top not-responsive" style="max-height:15rem" alt="Link Preview Image" />
</a>



<div class="card-body">
<h5 class="card-title">
<a class="text-decoration-none" href="https://github.com/Raven777777/EMA2">
GitHub - Raven777777/EMA2: 通过「Edge 扩展 + 单进程 Rust 中继」让 AI 助手直接控制你的**真实 Edge 浏览器**： 读取任意网页、操作标签页、点击元素、执行 JS，并**带真实登录态**。
</a>
</h5>
<p class="card-text line-clamp-3">通过「Edge 扩展 + 单进程 Rust 中继」让 AI 助手直接控制你的**真实 Edge 浏览器**： 读取任意网页、操作标签页、点击元素、执行 JS，并**带真实登录态**。 - Raven777777/EMA2</p>
</div>
<a href="https://github.com/Raven777777/EMA2" class="card-footer text-body-secondary small d-flex gap-2 align-items-center lh-2">



<img src="https://github.githubassets.com/favicons/favicon.svg" alt="favicon" class="not-responsive overflow-hiddden" style="max-width:21px;max-height:21px" />



<p class="d-inline-block text-truncate mb-0">GitHub <span class="text-secondary">(github.com)</span></p>
</a>
</div><p></p>
<h1>EMA2 — Edge MCP Agent 2 (Rust)</h1>
<p dir="auto">通过「Edge 扩展 + 单进程 Rust 中继」让 AI 助手直接控制你的<strong>真实 Edge 浏览器</strong>：<br />
读取任意网页、操作标签页、点击元素、执行 JS，并<strong>带真实登录态</strong>。</p>
<pre><code>AI 客户端 ──MCP over HTTP──&gt; ema2.exe (单进程) ──WebSocket──&gt; Edge 扩展 ──&gt; 真实浏览器
(opencode / Claude ...)   http://127.0.0.1:8765/mcp       ws://127.0.0.1:8765/
</code></pre>
<h2>特性</h2>
<ul>
<li><strong>单进程、单 exe（约 1.5 MB）</strong>：Rust 实现，一个常驻进程同时承担 MCP 服务与浏览器桥接</li>
<li><strong>MCP over HTTP</strong>：标准 Streamable HTTP + legacy SSE 双传输，opencode <code>type: remote</code> 直连</li>
<li><strong>控制真实浏览器</strong>：真实指纹、真实登录态，无头检测失效，不依赖 CDP 调试端口</li>
<li><strong>18 个工具</strong>：读页面 / 读标签页 / 列标签页 / 新建关闭 / 导航 / 点击 / 执行 JS，以及等待、截图、表单和页面交互工具</li>
<li><strong>MV3 保活</strong>：定时 ping，防止 Edge 扩展 service worker 闲置回收断连</li>
<li><strong>安全</strong>：只绑定 <code>127.0.0.1</code></li>
</ul>
<h2>目录结构</h2>
<pre><code>EMA2/
├── bin/ema2.exe                 # release 构建的单 exe（直接分发）
├── rust/                        # Rust 源码（cargo 工程）
│   └── src/
│       ├── main.rs              # 子命令：run / status
│       ├── config.rs            # 端口/保活（env 覆盖）
│       ├── http.rs              # axum：/mcp + /sse + /messages + /status + WS
│       ├── mcp.rs               # MCP 协议处理
│       ├── relay.rs             # 扩展 WS 连接 + 保活
│       ├── state.rs             # 共享状态（扩展连接/待响应映射）
│       └── tools.rs             # 18 个工具定义
├── extension/                   # Edge 浏览器扩展 (MV3)
├── scripts/
│   ├── setup.cmd                # cargo build --release → bin/
│   ├── start-bridge.cmd         # 启动常驻中继（隐藏后台）
│   └── stop-bridge.cmd          # 停止中继
├── examples/
│   ├── opencode.json.example    # opencode remote MCP 配置
├── docs/ARCHITECTURE.md
├── README.md
└── LICENSE
</code></pre>
<h2>快速开始</h2>
<h3>前置要求</h3>
<ul>
<li><strong>Microsoft Edge</strong>（新版）</li>
<li><strong>Rust 工具链</strong>（仅构建和测试需要；运行只需 <code>bin/ema2.exe</code>）</li>
</ul>
<h3>1. 启动中继</h3>
<pre><code class="language-bash">scripts\start-bridge.cmd     # 或直接运行 bin\ema2.exe run
</code></pre>
<h3>2. 加载扩展</h3>
<ol>
<li>Edge 打开 <code>edge://extensions/</code></li>
<li>打开右上角「开发人员模式」</li>
<li>「加载解压缩的扩展」→ 选择 <code>extension/</code> 目录</li>
<li>确认扩展已启用：<code>bin\ema2.exe status</code> 显示 <code>"extension_connected": true</code></li>
</ol>
<h3>3. 配置 AI 客户端</h3>
<p dir="auto"><strong>opencode</strong>（<code>~/.config/opencode/opencode.json</code>）：</p>
<pre><code class="language-json">{
  "mcp": {
    "edge-browser": {
      "type": "remote",
      "url": "http://127.0.0.1:8765/mcp",
      "enabled": true
    }
  }
}
</code></pre>
<p dir="auto"><strong>Claude Desktop</strong>（<code>%APPDATA%\Claude\claude_desktop_config.json</code>）：</p>
<pre><code class="language-json">{
  "mcpServers": {
    "edge-browser": {
      "url": "http://127.0.0.1:8765/mcp"
    }
  }
}
</code></pre>
<p dir="auto">然后重启 AI 客户端。</p>
<h2>工具列表</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>工具</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>edge_get_tabs</code></td>
<td>列出所有标签页（id/title/url/active）</td>
</tr>
<tr>
<td><code>edge_get_active_tab</code></td>
<td>当前标签页信息</td>
</tr>
<tr>
<td><code>edge_read_active_tab</code></td>
<td>提取当前标签页纯文本</td>
</tr>
<tr>
<td><code>edge_read_tab</code></td>
<td>按 tabId 提取指定标签页纯文本</td>
</tr>
<tr>
<td><code>edge_execute_js</code></td>
<td>在当前标签页执行任意 JS（chrome.debugger）</td>
</tr>
<tr>
<td><code>edge_click_element</code></td>
<td>按 CSS 选择器点击元素</td>
</tr>
<tr>
<td><code>edge_new_tab</code> / <code>edge_close_tab</code></td>
<td>新建 / 关闭标签页</td>
</tr>
<tr>
<td><code>edge_navigate</code></td>
<td>当前标签页跳转</td>
</tr>
<tr>
<td><code>edge_wait_for</code></td>
<td>等文本出现/消失或固定时长（默认超时 30s）</td>
</tr>
<tr>
<td><code>edge_take_screenshot</code></td>
<td>截图（保存 PNG 到输出目录，返回文件路径）</td>
</tr>
<tr>
<td><code>edge_console_messages</code></td>
<td>读取页面 console 日志</td>
</tr>
<tr>
<td><code>edge_network_requests</code></td>
<td>列出页面发起的网络请求（performance entries）</td>
</tr>
<tr>
<td><code>edge_type</code></td>
<td>向选择器元素输入文本（触发 input/change）</td>
</tr>
<tr>
<td><code>edge_press_key</code></td>
<td>在当前聚焦元素按键（Enter/Escape 等）</td>
</tr>
<tr>
<td><code>edge_fill_form</code></td>
<td>批量填充表单字段</td>
</tr>
<tr>
<td><code>edge_hover</code></td>
<td>悬停到指定元素</td>
</tr>
<tr>
<td><code>edge_scroll</code></td>
<td>页面滚动（默认一个视口高度）</td>
</tr>
</tbody>
</table>
<h2>配置（环境变量）</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>变量</th>
<th>默认</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>EDGE_MCP_PORT</code></td>
<td>8765</td>
<td>监听端口</td>
</tr>
<tr>
<td><code>EDGE_MCP_KEEPALIVE_MS</code></td>
<td>10000</td>
<td>MV3 保活 ping 间隔</td>
</tr>
<tr>
<td><code>EDGE_MCP_TOKEN</code></td>
<td>无</td>
<td>启用后 MCP HTTP 需 <code>Authorization: Bearer &lt;token&gt;</code>；扩展 WS 地址需追加 <code>?token=&lt;token&gt;</code></td>
</tr>
<tr>
<td><code>EDGE_MCP_OUTPUT_DIR</code></td>
<td><code>./output</code></td>
<td>截图输出目录</td>
</tr>
</tbody>
</table>
<h2>命令行</h2>
<pre><code class="language-bash">bin\ema2.exe run --port 8765    # 启动常驻中继
bin\ema2.exe status             # 健康检查（含扩展连接状态）
</code></pre>
<h2>HTTP MCP 调用示例</h2>
<p dir="auto">不依赖任何 SDK，任何语言用 HTTP POST 即可调用（这也是 opencode remote 接入的方式）：</p>
<pre><code class="language-bash"># 1. 握手
curl -X POST -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}' \
  http://127.0.0.1:8765/mcp

# 2. 工具列表
curl -X POST -H "Content-Type: application/json" -H "Mcp-Session-Id: &lt;session-id-from-step-1&gt;" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
  http://127.0.0.1:8765/mcp

# 3. 调用工具（打开新标签页 / 读取标签页文本）
curl -X POST -H "Content-Type: application/json" -H "Mcp-Session-Id: &lt;session-id-from-step-1&gt;" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"edge_new_tab","arguments":{"url":"https://www.bing.com"}}}' \
  http://127.0.0.1:8765/mcp
</code></pre>
<p dir="auto">Node.js 示例（读取网页正文）：</p>
<pre><code class="language-js">// sessionId is the Mcp-Session-Id response header from initialize.
const res = await fetch('http://127.0.0.1:8765/mcp', {
  method: 'POST', headers: { 'Content-Type': 'application/json', 'Mcp-Session-Id': sessionId },
  body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/call',
    params: { name: 'edge_read_active_tab', arguments: {} } }),
});
const j = await res.json();
console.log(j.result.content[0].text);
</code></pre>
<h2>构建</h2>
<pre><code class="language-bash">scripts\setup.cmd     # 或 cd rust &amp;&amp; cargo build --release，产物复制到 bin/
</code></pre>
<p dir="auto">验证 Rust 服务和扩展脚本：</p>
<pre><code class="language-bash">cd rust
cargo test
cargo build --release
cd ..
node --check extension\background.js
</code></pre>
<p dir="auto"><code>cargo test</code> 当前用于验证项目可编译和测试入口；浏览器工具需要加载 Edge 扩展后才能进行端到端调用。</p>
<h2>天气查询脚本</h2>
<p dir="auto"><code>scripts/weather.js</code> 通过 EMA2 MCP 控制真实 Edge，在 Google 查询天气并读取结果，不直接调用天气 API。需要先启动中继并确保扩展已连接：</p>
<pre><code class="language-bash">node scripts/weather.js "Tokyo"
node scripts/weather.js "New York"
node scripts/weather.js "Shanghai" --json
</code></pre>
<p dir="auto">作为模块复用：</p>
<pre><code class="language-js">const { queryWeather } = require('./scripts/weather.js');
const weather = await queryWeather('Tokyo');
</code></pre>
<p dir="auto">可通过 <code>EMA2_MCP_URL</code> 和 <code>EDGE_MCP_TOKEN</code> 覆盖 MCP 地址和鉴权；浏览器控制请求超时为 30 秒。</p>
<h2>常见问题</h2>
<p dir="auto"><strong>扩展报 <code>ERR_CONNECTION_REFUSED</code></strong><br />
中继没在运行。先 <code>scripts\start-bridge.cmd</code>，扩展会自动重连（每 3s）。</p>
<p dir="auto"><strong><code>edge_execute_js</code> 报错</strong><br />
该工具走 <code>chrome.debugger</code>，attach 时 Edge 会短暂显示"正在调试"提示；不能在内置页面（edge:// 等）执行。若行为异常，到 <code>edge://extensions/</code> 刷新扩展。</p>
<p dir="auto"><strong>想换端口</strong><br />
环境变量 <code>EDGE_MCP_PORT</code>，或 <code>ema2.exe run --port &lt;n&gt;</code>；扩展侧通过 <code>chrome.storage.local</code> 设置 <code>wsUrl</code> 同步修改。</p>
<p dir="auto"><strong>重启电脑后中继没了</strong><br />
<code>scripts\start-bridge.cmd</code> 是手动常驻；如需开机自启，加入「启动」文件夹或任务计划。</p>
<h2>安全提示</h2>
<ul>
<li>中继只绑定 <code>127.0.0.1</code>，不要对外网暴露</li>
<li>扩展含 <code>debugger</code> + <code>&lt;all_urls&gt;</code> 权限，等价于完全控制浏览器，<strong>仅用于可信的本机环境</strong></li>
<li>用真实登录态做高频自动化时，遵守目标网站服务条款，账号风控依旧有效</li>
</ul>
<h2>MIT</h2>
]]></description><link>https://blog.clouldon.com/topic/28/edge-mcp-agent-2</link><generator>RSS for Node</generator><lastBuildDate>Mon, 24 Aug 2026 07:31:06 GMT</lastBuildDate><atom:link href="https://blog.clouldon.com/topic/28.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 05 Aug 2026 23:46:00 GMT</pubDate><ttl>60</ttl></channel></rss>