@mallocfeng/chromedev 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -147
- package/package.json +2 -2
- package/skills/chromedev/SKILL.md +57 -11
- package/skills/chromedev/scripts/http_mcp_call.mjs +20 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ http://127.0.0.1:8787/mcp
|
|
|
13
13
|
整个流程只有两步:
|
|
14
14
|
|
|
15
15
|
1. 在 Chrome 中开启远程调试
|
|
16
|
-
2. 安装并启动 `chromedev`
|
|
16
|
+
2. 用 npm 安装并启动 `chromedev`
|
|
17
17
|
|
|
18
18
|
### 1. 在 Chrome 中开启远程调试
|
|
19
19
|
|
|
@@ -32,25 +32,19 @@ http://127.0.0.1:8787/mcp
|
|
|
32
32
|
|
|
33
33
|
### 2. 安装并启动服务
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
安装:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
38
|
npm install -g @mallocfeng/chromedev
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
启动:
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
44
|
chromedev run
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
node ./bin/chromedev.mjs run
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
成功后会看到:
|
|
47
|
+
成功后会看到类似输出:
|
|
54
48
|
|
|
55
49
|
```text
|
|
56
50
|
chromedev started in background (pid 12345)
|
|
@@ -59,47 +53,9 @@ endpoint: http://127.0.0.1:8787/mcp
|
|
|
59
53
|
|
|
60
54
|
这表示服务已经在后台运行,其他 AI 或程序现在可以访问 `http://127.0.0.1:8787/mcp`。
|
|
61
55
|
|
|
62
|
-
## npm 安装
|
|
63
|
-
|
|
64
|
-
推荐安装方式:
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
npm install -g @mallocfeng/chromedev
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
安装完成后可直接使用:
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
chromedev run
|
|
74
|
-
chromedev status
|
|
75
|
-
chromedev stop
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
如果你不想全局安装,也可以临时执行:
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
npx @mallocfeng/chromedev run
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
如果用户把这个 GitHub 仓库地址直接发给 AI,AI 应该按下面的步骤理解和执行:
|
|
85
|
-
|
|
86
|
-
1. 先安装命令行工具:
|
|
87
|
-
|
|
88
|
-
```bash
|
|
89
|
-
npm install -g @mallocfeng/chromedev
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
2. 然后启动服务:
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
chromedev run
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
3. 如果还需要安装 OpenClaw skill,再从 GitHub 下载项目源码,并把 `skills/chromedev` 拷贝到 OpenClaw 的 `skills` 目录。
|
|
99
|
-
|
|
100
56
|
## 常用命令
|
|
101
57
|
|
|
102
|
-
|
|
58
|
+
启动:
|
|
103
59
|
|
|
104
60
|
```bash
|
|
105
61
|
chromedev run
|
|
@@ -111,16 +67,16 @@ chromedev run
|
|
|
111
67
|
chromedev run --foreground
|
|
112
68
|
```
|
|
113
69
|
|
|
114
|
-
|
|
70
|
+
停止:
|
|
115
71
|
|
|
116
72
|
```bash
|
|
117
|
-
chromedev
|
|
73
|
+
chromedev stop
|
|
118
74
|
```
|
|
119
75
|
|
|
120
|
-
|
|
76
|
+
查看状态:
|
|
121
77
|
|
|
122
78
|
```bash
|
|
123
|
-
chromedev
|
|
79
|
+
chromedev status
|
|
124
80
|
```
|
|
125
81
|
|
|
126
82
|
查看日志路径:
|
|
@@ -129,21 +85,15 @@ chromedev stop
|
|
|
129
85
|
chromedev logs
|
|
130
86
|
```
|
|
131
87
|
|
|
132
|
-
如果你是在源码目录里本地运行,把 `chromedev` 换成:
|
|
133
|
-
|
|
134
|
-
```bash
|
|
135
|
-
node ./bin/chromedev.mjs
|
|
136
|
-
```
|
|
137
|
-
|
|
138
88
|
## 如何验证服务正常
|
|
139
89
|
|
|
140
|
-
|
|
90
|
+
查看状态:
|
|
141
91
|
|
|
142
92
|
```bash
|
|
143
93
|
chromedev status
|
|
144
94
|
```
|
|
145
95
|
|
|
146
|
-
|
|
96
|
+
检查端点:
|
|
147
97
|
|
|
148
98
|
```bash
|
|
149
99
|
curl -i http://127.0.0.1:8787/mcp
|
|
@@ -151,81 +101,30 @@ curl -i http://127.0.0.1:8787/mcp
|
|
|
151
101
|
|
|
152
102
|
如果返回 `400 Bad Request` 且内容类似 `No sessionId`,这是正常的,说明 MCP 端点已经存在。
|
|
153
103
|
|
|
154
|
-
## 命令行访问网页示例
|
|
155
|
-
|
|
156
|
-
列出当前页面:
|
|
157
|
-
|
|
158
|
-
```bash
|
|
159
|
-
node /Volumes/MacMiniDisk/project/chromeDev/skills/chromedev/scripts/http_mcp_call.mjs list_pages
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
打开 `163.com`:
|
|
163
|
-
|
|
164
|
-
```bash
|
|
165
|
-
node /Volumes/MacMiniDisk/project/chromeDev/skills/chromedev/scripts/http_mcp_call.mjs new_page '{"url":"https://www.163.com/","timeout":30000}'
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
读取当前页面快照:
|
|
169
|
-
|
|
170
|
-
```bash
|
|
171
|
-
node /Volumes/MacMiniDisk/project/chromeDev/skills/chromedev/scripts/http_mcp_call.mjs take_snapshot
|
|
172
|
-
```
|
|
173
|
-
|
|
174
104
|
## 在 OpenClaw 中安装 skill
|
|
175
105
|
|
|
176
|
-
|
|
106
|
+
这个仓库包含一份 skill:
|
|
177
107
|
|
|
178
108
|
```text
|
|
179
109
|
skills/chromedev
|
|
180
110
|
```
|
|
181
111
|
|
|
182
|
-
|
|
112
|
+
安装方法:
|
|
183
113
|
|
|
184
|
-
1.
|
|
185
|
-
2. 下载项目源码,或者直接 clone:
|
|
114
|
+
1. 从 GitHub 下载项目源码:
|
|
186
115
|
|
|
187
116
|
```bash
|
|
188
117
|
git clone https://github.com/mallocfeng/chromeDev.git
|
|
189
118
|
```
|
|
190
119
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
chromeDev/skills/chromedev
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
如果用户把 GitHub 地址直接发给 AI,AI 可以按这套指令执行:
|
|
198
|
-
|
|
199
|
-
```bash
|
|
200
|
-
git clone https://github.com/mallocfeng/chromeDev.git
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
然后取出:
|
|
204
|
-
|
|
205
|
-
```text
|
|
206
|
-
chromeDev/skills/chromedev
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
再把它复制到 OpenClaw 的 `skills` 目录下。
|
|
210
|
-
|
|
211
|
-
安装到 OpenClaw 的方法很简单:
|
|
212
|
-
|
|
213
|
-
1. 把项目目录中的 `skills/chromedev` 目录拷贝到你 OpenClaw 工作目录的 `skills` 文件夹下。
|
|
214
|
-
2. 如果你不清楚这个文件夹在哪里,可以先直接问 OpenClaw,它会告诉你当前 agent 工作目录在哪里。
|
|
215
|
-
3. 拷贝进去以后,运行:
|
|
120
|
+
2. 把其中的 `skills/chromedev` 目录拷贝到 OpenClaw 当前 agent 工作目录下的 `skills` 文件夹。
|
|
121
|
+
3. 如果你不知道 OpenClaw 的工作目录在哪里,直接先问 OpenClaw。
|
|
122
|
+
4. 拷贝完成后执行:
|
|
216
123
|
|
|
217
124
|
```bash
|
|
218
125
|
openclaw gateway restart
|
|
219
126
|
```
|
|
220
127
|
|
|
221
|
-
完成后就可以在 OpenClaw 里调用这个 skill。
|
|
222
|
-
|
|
223
|
-
给 AI 的可执行描述可以直接写成这样:
|
|
224
|
-
|
|
225
|
-
```text
|
|
226
|
-
从 https://github.com/mallocfeng/chromeDev 下载项目,把其中的 skills/chromedev 目录拷贝到当前 OpenClaw agent 工作目录下的 skills 文件夹,然后执行 openclaw gateway restart。
|
|
227
|
-
```
|
|
228
|
-
|
|
229
128
|
目录结构应该像这样:
|
|
230
129
|
|
|
231
130
|
```text
|
|
@@ -239,7 +138,7 @@ openclaw gateway restart
|
|
|
239
138
|
|
|
240
139
|
## 在 OpenClaw 中使用
|
|
241
140
|
|
|
242
|
-
|
|
141
|
+
可以直接这样输入:
|
|
243
142
|
|
|
244
143
|
```text
|
|
245
144
|
/chromedev 调用这个 skills 访问当前打开的纽约时报标签文章,并摘要
|
|
@@ -251,28 +150,11 @@ openclaw gateway restart
|
|
|
251
150
|
调用 chromedev 这个 skills,访问纽约时报,并且摘要新闻
|
|
252
151
|
```
|
|
253
152
|
|
|
254
|
-
这个 skill 会通过本地 `ChromeDev` MCP 服务访问你当前打开的 Chrome,并读取网页内容。
|
|
255
|
-
|
|
256
153
|
注意:
|
|
257
154
|
|
|
258
|
-
-
|
|
259
|
-
-
|
|
260
|
-
-
|
|
261
|
-
|
|
262
|
-
## 日志与运行文件
|
|
263
|
-
|
|
264
|
-
默认文件位置:
|
|
265
|
-
|
|
266
|
-
- `~/.chromedev/run/chromedev.pid`
|
|
267
|
-
- `~/.chromedev/run/chromedev.out.log`
|
|
268
|
-
- `~/.chromedev/run/chromedev.err.log`
|
|
269
|
-
|
|
270
|
-
直接查看日志:
|
|
271
|
-
|
|
272
|
-
```bash
|
|
273
|
-
tail -f ~/.chromedev/run/chromedev.out.log
|
|
274
|
-
tail -f ~/.chromedev/run/chromedev.err.log
|
|
275
|
-
```
|
|
155
|
+
- skill 只负责告诉 AI 怎么调用本地 ChromeDev 服务
|
|
156
|
+
- 真正提供浏览器访问能力的,是你本机运行中的 `chromedev run`
|
|
157
|
+
- 使用 skill 前,先确认本地服务已经启动
|
|
276
158
|
|
|
277
159
|
## 默认配置
|
|
278
160
|
|
|
@@ -293,6 +175,21 @@ MCP_REQUEST_TIMEOUT=30000
|
|
|
293
175
|
MCP_PORT=8788 chromedev run
|
|
294
176
|
```
|
|
295
177
|
|
|
178
|
+
## 日志位置
|
|
179
|
+
|
|
180
|
+
默认文件位置:
|
|
181
|
+
|
|
182
|
+
- `~/.chromedev/run/chromedev.pid`
|
|
183
|
+
- `~/.chromedev/run/chromedev.out.log`
|
|
184
|
+
- `~/.chromedev/run/chromedev.err.log`
|
|
185
|
+
|
|
186
|
+
查看日志:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
tail -f ~/.chromedev/run/chromedev.out.log
|
|
190
|
+
tail -f ~/.chromedev/run/chromedev.err.log
|
|
191
|
+
```
|
|
192
|
+
|
|
296
193
|
## 常见问题
|
|
297
194
|
|
|
298
195
|
### 1. `EADDRINUSE: address already in use 127.0.0.1:8787`
|
|
@@ -321,14 +218,6 @@ MCP_PORT=8788 chromedev run
|
|
|
321
218
|
3. 远程调试是否已经启用
|
|
322
219
|
4. Chrome 是否弹出了授权确认框但还没有点
|
|
323
220
|
|
|
324
|
-
### 3. 第一次连接会卡几秒
|
|
325
|
-
|
|
326
|
-
通常是正常的,可能是:
|
|
327
|
-
|
|
328
|
-
- Chrome 正在等待授权确认
|
|
329
|
-
- `autoConnect` 正在连接浏览器
|
|
330
|
-
- 页面本身还在加载
|
|
331
|
-
|
|
332
221
|
## 安全说明
|
|
333
222
|
|
|
334
223
|
- 服务只应监听本地地址 `127.0.0.1`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mallocfeng/chromedev",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI that exposes chrome-devtools-mcp as a local background service connected to your live Chrome browser.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"LICENSE"
|
|
34
34
|
],
|
|
35
35
|
"bin": {
|
|
36
|
-
"chromedev": "
|
|
36
|
+
"chromedev": "bin/chromedev.mjs"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"start": "node ./server/chrome-mcp-daemon.mjs",
|
|
@@ -8,6 +8,7 @@ description: Use this skill when you need to access or control a live Chrome bro
|
|
|
8
8
|
Use this skill when the user wants browser-backed data from real web pages through the local `chrome-devtools-mcp` middleware running at `http://127.0.0.1:8787/mcp`.
|
|
9
9
|
|
|
10
10
|
This skill is for cases where rendered browser state matters: JavaScript-heavy sites, login state in the user's Chrome, interaction flows, screenshots, DOM snapshots, or page data that should come from the live browser instead of plain HTTP fetches.
|
|
11
|
+
The primary behavior is simple: if the user gives a URL, open it and return the page content. If the page is a list page, return the list content in order.
|
|
11
12
|
|
|
12
13
|
## Preconditions
|
|
13
14
|
|
|
@@ -29,9 +30,28 @@ A response like `400 Bad Request` with `No sessionId` means the endpoint exists
|
|
|
29
30
|
2. Connect to `http://127.0.0.1:8787/mcp`.
|
|
30
31
|
3. Use MCP browser tools to open or select a page.
|
|
31
32
|
4. Prefer `take_snapshot` or `evaluate_script` for structured extraction.
|
|
32
|
-
5. Use `wait_for` when
|
|
33
|
+
5. Use `wait_for` only when the page is still loading and you know a stable piece of text or UI state to wait for.
|
|
33
34
|
6. Return the extracted data, not raw protocol noise.
|
|
34
35
|
|
|
36
|
+
## How To Interpret Requests
|
|
37
|
+
|
|
38
|
+
When the user gives a URL, treat it as a request to read the page and return its content:
|
|
39
|
+
|
|
40
|
+
1. Open the target URL with `new_page`.
|
|
41
|
+
2. Immediately call `list_pages` and select the page whose URL matches the target URL, or whose title clearly matches the target site.
|
|
42
|
+
3. If multiple tabs match, choose the most recently opened matching tab.
|
|
43
|
+
4. Only use `wait_for` if the page is still visibly loading and you know a stable text or selector to wait on.
|
|
44
|
+
5. Use `take_snapshot` or `evaluate_script` to read the selected page.
|
|
45
|
+
6. Return the page content faithfully and concisely. Do not add a summary unless the user explicitly asks for one.
|
|
46
|
+
|
|
47
|
+
Examples:
|
|
48
|
+
|
|
49
|
+
- "访问 163.com" means open `https://www.163.com/` and return the visible page content.
|
|
50
|
+
- "给我这个网页内容" means read the current page and return the content as-is.
|
|
51
|
+
- "访问纽约时报并读取文章" means open the NYTimes page or the specified article and return the article/page content.
|
|
52
|
+
- "读取这个 list 页面" means return the visible list items in order, including titles, text, and links when available.
|
|
53
|
+
- "读取 list" means extract the list structure, not a summary of the topic.
|
|
54
|
+
|
|
35
55
|
## Preferred tool order
|
|
36
56
|
|
|
37
57
|
- `list_pages`: inspect current browser pages before changing state.
|
|
@@ -46,9 +66,11 @@ A response like `400 Bad Request` with `No sessionId` means the endpoint exists
|
|
|
46
66
|
|
|
47
67
|
This skill includes a reusable script:
|
|
48
68
|
|
|
49
|
-
- [`scripts/http_mcp_call.mjs`](
|
|
69
|
+
- [`scripts/http_mcp_call.mjs`](scripts/http_mcp_call.mjs)
|
|
50
70
|
|
|
51
71
|
It connects to the local HTTP MCP endpoint and calls one tool.
|
|
72
|
+
Use the copy that lives inside `skills/chromedev` so the skill always runs the version bundled with the current workspace.
|
|
73
|
+
If `list_pages` reports that the selected page has been closed, the script creates a blank page and retries once so the tab list can be returned.
|
|
52
74
|
|
|
53
75
|
If `@modelcontextprotocol/sdk` is missing in the current workspace, install it in that workspace first:
|
|
54
76
|
|
|
@@ -61,52 +83,70 @@ npm install @modelcontextprotocol/sdk
|
|
|
61
83
|
List current pages:
|
|
62
84
|
|
|
63
85
|
```bash
|
|
64
|
-
node
|
|
86
|
+
node skills/chromedev/scripts/http_mcp_call.mjs list_pages
|
|
65
87
|
```
|
|
66
88
|
|
|
67
89
|
Open `163.com`:
|
|
68
90
|
|
|
69
91
|
```bash
|
|
70
|
-
node
|
|
92
|
+
node skills/chromedev/scripts/http_mcp_call.mjs new_page '{"url":"https://www.163.com/","timeout":30000}'
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Select the matching page before reading:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
node skills/chromedev/scripts/http_mcp_call.mjs list_pages
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Then choose the tab whose URL matches `https://www.163.com/` before calling `take_snapshot` or `evaluate_script`.
|
|
102
|
+
|
|
103
|
+
Read the current 163.com page:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
node skills/chromedev/scripts/http_mcp_call.mjs take_snapshot
|
|
71
107
|
```
|
|
72
108
|
|
|
73
109
|
Get the current page snapshot:
|
|
74
110
|
|
|
75
111
|
```bash
|
|
76
|
-
node
|
|
112
|
+
node skills/chromedev/scripts/http_mcp_call.mjs take_snapshot
|
|
77
113
|
```
|
|
78
114
|
|
|
79
115
|
Extract page title and URL:
|
|
80
116
|
|
|
81
117
|
```bash
|
|
82
|
-
node
|
|
118
|
+
node skills/chromedev/scripts/http_mcp_call.mjs evaluate_script '{"function":"() => ({ title: document.title, url: location.href })"}'
|
|
83
119
|
```
|
|
84
120
|
|
|
85
121
|
Wait for specific text:
|
|
86
122
|
|
|
87
123
|
```bash
|
|
88
|
-
node
|
|
124
|
+
node skills/chromedev/scripts/http_mcp_call.mjs wait_for '{"text":["网易","163"],"timeout":30000}'
|
|
89
125
|
```
|
|
90
126
|
|
|
127
|
+
If `list_pages` returns `The selected page has been closed`, just run it again. The bundled script will open `about:blank` and retry automatically.
|
|
128
|
+
|
|
91
129
|
## Extraction guidance
|
|
92
130
|
|
|
93
|
-
- Use `take_snapshot` for readable page
|
|
131
|
+
- Use `take_snapshot` for readable page content and page structure.
|
|
94
132
|
- Use `evaluate_script` for precise fields, arrays, links, prices, tables, or JSON-shaped output.
|
|
95
|
-
- Use `wait_for`
|
|
133
|
+
- Use `wait_for` only if the page is still loading and you know a reliable text or selector to wait on.
|
|
96
134
|
- Use `list_network_requests` and `get_network_request` only when DOM extraction is insufficient.
|
|
135
|
+
- For list pages, preserve order and return the item text or link target for each visible entry.
|
|
136
|
+
- For article pages, return the article text and visible metadata, not a recap unless asked.
|
|
97
137
|
|
|
98
138
|
## Example patterns
|
|
99
139
|
|
|
100
140
|
For article text:
|
|
101
141
|
|
|
102
142
|
```bash
|
|
103
|
-
node
|
|
143
|
+
node skills/chromedev/scripts/http_mcp_call.mjs evaluate_script '{"function":"() => ({ title: document.title, text: document.body.innerText.slice(0, 4000) })"}'
|
|
104
144
|
```
|
|
105
145
|
|
|
106
146
|
For links on the page:
|
|
107
147
|
|
|
108
148
|
```bash
|
|
109
|
-
node
|
|
149
|
+
node skills/chromedev/scripts/http_mcp_call.mjs evaluate_script '{"function":"() => Array.from(document.querySelectorAll(\"a\")).slice(0,50).map(a => ({ text: (a.innerText || a.textContent || \"\").trim(), href: a.href })).filter(x => x.href)"}'
|
|
110
150
|
```
|
|
111
151
|
|
|
112
152
|
## Operational notes
|
|
@@ -115,3 +155,9 @@ node /Volumes/MacMiniDisk/project/chromeDev/skills/chromedev/scripts/http_mcp_ca
|
|
|
115
155
|
- If a tool call hangs near connection start, assume Chrome may be waiting for the authorization dialog.
|
|
116
156
|
- Prefer returning concise extracted data over full raw snapshots unless the user asked for raw output.
|
|
117
157
|
- Do not expose the local MCP endpoint outside `127.0.0.1`.
|
|
158
|
+
- Prefer the bundled `skills/chromedev/scripts/http_mcp_call.mjs` over ad hoc absolute paths so the current workspace copy is always used.
|
|
159
|
+
- For URL-reading tasks, return the page content faithfully and concisely. Do not summarize unless explicitly requested.
|
|
160
|
+
- For list pages, return the list items faithfully and in order.
|
|
161
|
+
- Never assume the currently selected tab is the one you just opened. Always re-check `list_pages` and target the matching URL or title before reading.
|
|
162
|
+
- Prefer `take_snapshot` for the first pass and `evaluate_script` only when the user wants exact fields or raw text.
|
|
163
|
+
- Treat `wait_for` as optional. Use it only if a page is visibly still loading and you know a reliable text or selector to wait on.
|
|
@@ -47,13 +47,32 @@ async function main() {
|
|
|
47
47
|
|
|
48
48
|
try {
|
|
49
49
|
await client.connect(transport)
|
|
50
|
-
const result = await client
|
|
50
|
+
const result = await callWithRecovery(client, toolName, args)
|
|
51
51
|
console.log(JSON.stringify(result, null, 2))
|
|
52
52
|
} finally {
|
|
53
53
|
await transport.close().catch(() => {})
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
async function callWithRecovery(client, toolName, args) {
|
|
58
|
+
const result = await client.callTool({ name: toolName, arguments: args })
|
|
59
|
+
|
|
60
|
+
if (toolName === 'list_pages' && isClosedPageError(result)) {
|
|
61
|
+
await client.callTool({
|
|
62
|
+
name: 'new_page',
|
|
63
|
+
arguments: { url: 'about:blank', timeout: 30000 },
|
|
64
|
+
})
|
|
65
|
+
return client.callTool({ name: toolName, arguments: args })
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return result
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function isClosedPageError(result) {
|
|
72
|
+
const text = result?.content?.find?.((item) => item?.type === 'text')?.text || ''
|
|
73
|
+
return Boolean(result?.isError && text.includes('selected page has been closed'))
|
|
74
|
+
}
|
|
75
|
+
|
|
57
76
|
function printUsage() {
|
|
58
77
|
console.error('Usage: http_mcp_call.mjs <tool_name> [json_args]')
|
|
59
78
|
console.error("Example: http_mcp_call.mjs new_page '{\"url\":\"https://www.163.com/\",\"timeout\":30000}'")
|