@attson/atwebpilot-mcp 0.0.72 → 0.0.74
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 +15 -1
- package/dist/index.js +59 -10
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@ listen 端口的能力,所以方向只能如此。这也是配对页存在的
|
|
|
49
49
|
## 工具面
|
|
50
50
|
|
|
51
51
|
- 控制面 4 个:`list_tabs / open_session / close_session / get_quota`
|
|
52
|
-
- 发现 1 个:`browser_discoverTools` ——
|
|
52
|
+
- 发现 1 个:`browser_discoverTools` —— 已知工具时直接传 `enable: [...]`,已知分组时直接传 `enableGroups: ["export", ...]`;只有两者都未知时才不带参数读取目录。启用后会加入本进程的 `tools/list`(发送 `tools/list_changed`),并直接返回完整 schema。
|
|
53
53
|
- 执行面默认 **core 31 个** `browser_*`:浏览 / 采集 / 填表 / 导航 / 截图 闭环所需的工具。其余 20 个由 AI 按需 `discoverTools` 拉取,用户不用配置。
|
|
54
54
|
- 不暴露 `askUser`(MCP 会话没有人在侧边栏应答)和 `attachTab` / `detachTab`(目标 tab 已由 `open_session` 绑定)。
|
|
55
55
|
|
|
@@ -70,6 +70,20 @@ hover / uploadFile / scroll / waitFor`);`browser_storage` 也不会列出,
|
|
|
70
70
|
|
|
71
71
|
无法识别的值(包括已移除的 `parity`)按 `core` 处理,并往 stderr 打一条提示。
|
|
72
72
|
|
|
73
|
+
## 本地会话效率分析
|
|
74
|
+
|
|
75
|
+
在仓库根目录运行:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pnpm analyze:sessions
|
|
79
|
+
pnpm analyze:sessions -- --since 7d --clients claude --format json
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
分析器只读扫描 `~/.claude/projects` 与 `~/.codex/sessions` 中最近 30 天的
|
|
83
|
+
JSONL,识别真实 AtWebPilot 工具调用及重复验证、固定等待、重复截图、可批量填表等
|
|
84
|
+
模式。输出只包含聚合计数、参数字段名与不可逆指纹;不会输出或保存 prompt、参数值、
|
|
85
|
+
工具结果正文、凭证或绝对会话路径。使用 `--help` 查看目录覆盖等选项。
|
|
86
|
+
|
|
73
87
|
### 从 0.0.70 及更早版本迁移
|
|
74
88
|
|
|
75
89
|
| 旧 | 新 |
|
package/dist/index.js
CHANGED
|
@@ -895,7 +895,9 @@ var Coordinator = class {
|
|
|
895
895
|
return session;
|
|
896
896
|
}
|
|
897
897
|
closeSession(id) {
|
|
898
|
+
const session = this.sessions.get(id);
|
|
898
899
|
this.sessions.close(id);
|
|
900
|
+
if (session) this.notifySessionClosed(session);
|
|
899
901
|
}
|
|
900
902
|
// === Tool calls ===
|
|
901
903
|
validateCall(input) {
|
|
@@ -920,8 +922,22 @@ var Coordinator = class {
|
|
|
920
922
|
// === Periodic housekeeping ===
|
|
921
923
|
tick() {
|
|
922
924
|
const expired_sessions = this.sessions.tick();
|
|
925
|
+
for (const id of expired_sessions) {
|
|
926
|
+
const session = this.sessions.get(id);
|
|
927
|
+
if (session) this.notifySessionClosed(session);
|
|
928
|
+
}
|
|
923
929
|
return { expired_sessions };
|
|
924
930
|
}
|
|
931
|
+
notifySessionClosed(session) {
|
|
932
|
+
void this.hub.send(session.worker_id, {
|
|
933
|
+
type: "CLOSE_SESSION",
|
|
934
|
+
nonce: this.idGen.next("nonce"),
|
|
935
|
+
ts: this.clock.now(),
|
|
936
|
+
protocol_version: PROTOCOL_VERSION,
|
|
937
|
+
session_id: session.id
|
|
938
|
+
}).catch(() => {
|
|
939
|
+
});
|
|
940
|
+
}
|
|
925
941
|
};
|
|
926
942
|
|
|
927
943
|
// src/mcp-server.ts
|
|
@@ -1830,7 +1846,7 @@ var TOOL_DEFS = [
|
|
|
1830
1846
|
{
|
|
1831
1847
|
name: "resize",
|
|
1832
1848
|
description: "[FLOW] \u628A\u89C6\u53E3\u8C03\u6574\u5230\u6307\u5B9A\u5C3A\u5BF8\u3002main-world \u6863\u91CF\u53D6 outerWidth-innerWidth \u53CD\u63A8\u6D4F\u89C8\u5668\u8FB9\u6846\u540E\u6539\u7A97\u53E3\u5916\u6846\uFF0C\u89C6\u53E3\u7CBE\u786E\u4F46**\u7528\u6237\u7684\u7A97\u53E3\u4F1A\u771F\u7684\u53D8\u5927\u5C0F**\uFF1Bcdp \u6863\u7528 Emulation \u8986\u76D6\u8BBE\u5907\u5C3A\u5BF8\uFF0C\u4E0D\u52A8\u771F\u5B9E\u7A97\u53E3\u3002",
|
|
1833
|
-
mcp: { description: "Resize the viewport to width\xD7height." },
|
|
1849
|
+
mcp: { description: "Resize the viewport to width\xD7height and return the measured actualViewport plus verified status. Do not re-measure with runJS." },
|
|
1834
1850
|
input_schema: {
|
|
1835
1851
|
type: "object",
|
|
1836
1852
|
properties: {
|
|
@@ -2087,13 +2103,19 @@ function discoveryCatalog(all, advertised) {
|
|
|
2087
2103
|
}
|
|
2088
2104
|
|
|
2089
2105
|
// src/discover-tool.ts
|
|
2106
|
+
var DISCOVER_GROUPS = Object.keys(DISCOVERABLE_GROUPS);
|
|
2090
2107
|
var DISCOVER_TOOL = {
|
|
2091
2108
|
name: "browser_discoverTools",
|
|
2092
|
-
description: "The default tool list is the core set.
|
|
2109
|
+
description: "The default tool list is the core set. Enable known extras directly with enable=[names] or enableGroups=[groups]. Omit both only when you need the catalog. Groups: export, network, storage, browser-data, inspect, legacy-dom, form, tabs. Enabled tools join tools/list and the response includes their full schemas so you can call them immediately. Use this instead of rebuilding missing capabilities with runJS.",
|
|
2093
2110
|
inputSchema: {
|
|
2094
2111
|
type: "object",
|
|
2095
2112
|
properties: {
|
|
2096
|
-
enable: { type: "array", items: { type: "string" }, description: "Tool names from the catalog to advertise" }
|
|
2113
|
+
enable: { type: "array", items: { type: "string" }, description: "Tool names from the catalog to advertise" },
|
|
2114
|
+
enableGroups: {
|
|
2115
|
+
type: "array",
|
|
2116
|
+
items: { type: "string", enum: DISCOVER_GROUPS },
|
|
2117
|
+
description: "Known groups to advertise directly, without a catalog round trip"
|
|
2118
|
+
}
|
|
2097
2119
|
},
|
|
2098
2120
|
additionalProperties: false
|
|
2099
2121
|
}
|
|
@@ -2104,23 +2126,36 @@ function isRunnable(t, supported) {
|
|
|
2104
2126
|
function handleDiscover(input) {
|
|
2105
2127
|
const { all, advertised, args, supported } = input;
|
|
2106
2128
|
const byName = new Map(all.map((t) => [t.name, t]));
|
|
2107
|
-
const
|
|
2108
|
-
if (!
|
|
2129
|
+
const hasSelection = Array.isArray(args.enable) || Array.isArray(args.enableGroups);
|
|
2130
|
+
if (!hasSelection) {
|
|
2109
2131
|
const runnable = all.filter((t) => isRunnable(t, supported));
|
|
2110
2132
|
return { catalog: discoveryCatalog(runnable, advertised), changed: false };
|
|
2111
2133
|
}
|
|
2134
|
+
const explicit = Array.isArray(args.enable) ? args.enable.map(String) : [];
|
|
2135
|
+
const groups = Array.isArray(args.enableGroups) ? args.enableGroups.map(String) : [];
|
|
2136
|
+
const unknownGroups = groups.filter((group) => !DISCOVER_GROUPS.includes(group));
|
|
2137
|
+
const grouped = groups.flatMap(
|
|
2138
|
+
(group) => DISCOVERABLE_GROUPS[group] ?? []
|
|
2139
|
+
);
|
|
2140
|
+
const requestedByName = /* @__PURE__ */ new Map();
|
|
2141
|
+
for (const raw of explicit) {
|
|
2142
|
+
const name = raw.startsWith("browser_") ? raw : `browser_${raw}`;
|
|
2143
|
+
requestedByName.set(name, raw);
|
|
2144
|
+
}
|
|
2145
|
+
for (const name of grouped) {
|
|
2146
|
+
if (!requestedByName.has(name)) requestedByName.set(name, name);
|
|
2147
|
+
}
|
|
2112
2148
|
const enabled = [];
|
|
2113
2149
|
const unknown = [];
|
|
2114
2150
|
const unsupported = [];
|
|
2115
|
-
for (const
|
|
2116
|
-
const name = raw.startsWith("browser_") ? raw : `browser_${raw}`;
|
|
2151
|
+
for (const [name, reportAs] of requestedByName) {
|
|
2117
2152
|
const t = byName.get(name);
|
|
2118
2153
|
if (!t) {
|
|
2119
|
-
unknown.push(
|
|
2154
|
+
unknown.push(reportAs);
|
|
2120
2155
|
continue;
|
|
2121
2156
|
}
|
|
2122
2157
|
if (!isRunnable(t, supported)) {
|
|
2123
|
-
unsupported.push(
|
|
2158
|
+
unsupported.push(reportAs);
|
|
2124
2159
|
continue;
|
|
2125
2160
|
}
|
|
2126
2161
|
if (advertised.has(name)) continue;
|
|
@@ -2130,6 +2165,7 @@ function handleDiscover(input) {
|
|
|
2130
2165
|
return {
|
|
2131
2166
|
enabled,
|
|
2132
2167
|
...unknown.length ? { unknown } : {},
|
|
2168
|
+
...unknownGroups.length ? { unknownGroups } : {},
|
|
2133
2169
|
...unsupported.length ? { unsupported } : {},
|
|
2134
2170
|
changed: enabled.length > 0
|
|
2135
2171
|
};
|
|
@@ -2434,7 +2470,12 @@ function toolResult(gen, data) {
|
|
|
2434
2470
|
const d = data ?? {};
|
|
2435
2471
|
if (typeof d.data !== "string") return ok(data);
|
|
2436
2472
|
const mimeType = typeof d.media_type === "string" ? d.media_type : "image/png";
|
|
2437
|
-
|
|
2473
|
+
const { data: imageData, media_type: _mediaType, ...metadata } = d;
|
|
2474
|
+
const content = [{ type: "image", data: imageData, mimeType }];
|
|
2475
|
+
if (Object.keys(metadata).length > 0) {
|
|
2476
|
+
content.push({ type: "text", text: JSON.stringify(metadata) });
|
|
2477
|
+
}
|
|
2478
|
+
return { content };
|
|
2438
2479
|
}
|
|
2439
2480
|
var fail2 = (message) => ({ content: [{ type: "text", text: message }], isError: true });
|
|
2440
2481
|
async function dispatchCall(deps, name, args, onPairingRequired, state = DEFAULT_STATE, onListChanged) {
|
|
@@ -2986,6 +3027,7 @@ function processInfo(cwd = process.cwd()) {
|
|
|
2986
3027
|
|
|
2987
3028
|
// src/ensure-hub.ts
|
|
2988
3029
|
var DEFAULT_WORKER_WAIT_TIMEOUT_MS = 9e4;
|
|
3030
|
+
var SESSION_SWEEP_INTERVAL_MS = 3e4;
|
|
2989
3031
|
function createHubEnsurer(d) {
|
|
2990
3032
|
let bundle = null;
|
|
2991
3033
|
let inflight = null;
|
|
@@ -2994,6 +3036,7 @@ function createHubEnsurer(d) {
|
|
|
2994
3036
|
let opening = null;
|
|
2995
3037
|
let hubIsClosed = false;
|
|
2996
3038
|
let pendingDenial = false;
|
|
3039
|
+
let sessionSweepTimer = null;
|
|
2997
3040
|
let workerWait = null;
|
|
2998
3041
|
const info = d.processInfo ?? processInfo();
|
|
2999
3042
|
function connectedWorkerId(coordinator) {
|
|
@@ -3029,6 +3072,10 @@ function createHubEnsurer(d) {
|
|
|
3029
3072
|
}
|
|
3030
3073
|
function hubClosed() {
|
|
3031
3074
|
hubIsClosed = true;
|
|
3075
|
+
if (sessionSweepTimer) {
|
|
3076
|
+
clearInterval(sessionSweepTimer);
|
|
3077
|
+
sessionSweepTimer = null;
|
|
3078
|
+
}
|
|
3032
3079
|
if (workerWait) {
|
|
3033
3080
|
finishWorkerWait({ error: new Error("\u6D4F\u89C8\u5668\u914D\u5BF9\u670D\u52A1\u5DF2\u5173\u95ED\u3002") });
|
|
3034
3081
|
}
|
|
@@ -3057,6 +3104,8 @@ function createHubEnsurer(d) {
|
|
|
3057
3104
|
}
|
|
3058
3105
|
saveLastPort(port, d.identityDir);
|
|
3059
3106
|
const coordinator = new Coordinator({ hub, clock: d.clock, idGen: d.idGen });
|
|
3107
|
+
sessionSweepTimer = setInterval(() => coordinator.tick(), SESSION_SWEEP_INTERVAL_MS);
|
|
3108
|
+
sessionSweepTimer.unref?.();
|
|
3060
3109
|
installWire(hub, coordinator, d.clock, () => notifyWorkerReady(coordinator));
|
|
3061
3110
|
pairUrlValue = `http://127.0.0.1:${port}/pair`;
|
|
3062
3111
|
return { coordinator, hub, port };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@attson/atwebpilot-mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.74",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "MCP server for the atwebpilot browser extension - let Codex or Claude Code drive your browser.",
|
|
6
6
|
"homepage": "https://github.com/attson/atwebpilot#readme",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"typecheck": "tsc --noEmit",
|
|
28
28
|
"test": "vitest run",
|
|
29
29
|
"build": "tsup",
|
|
30
|
-
"start": "tsx src/index.ts"
|
|
30
|
+
"start": "tsx src/index.ts",
|
|
31
|
+
"analyze:sessions": "tsx src/session-analysis/cli.ts"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
33
34
|
"@modelcontextprotocol/sdk": "^1.0.0",
|