@attson/atwebpilot-mcp 0.0.65 → 0.0.67
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/dist/index.js +160 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -212,11 +212,18 @@ var ChatSessionEventSchema = z3.discriminatedUnion("type", [
|
|
|
212
212
|
]);
|
|
213
213
|
|
|
214
214
|
// ../shared/src/protocol/messages.ts
|
|
215
|
-
var
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
215
|
+
var ProtocolStepSchema = z4.discriminatedUnion("kind", [
|
|
216
|
+
z4.object({
|
|
217
|
+
kind: z4.literal("tool"),
|
|
218
|
+
tool: z4.string(),
|
|
219
|
+
args: z4.unknown()
|
|
220
|
+
}),
|
|
221
|
+
z4.object({
|
|
222
|
+
kind: z4.literal("js"),
|
|
223
|
+
source: z4.string(),
|
|
224
|
+
timeoutMs: z4.number().int().positive().optional()
|
|
225
|
+
})
|
|
226
|
+
]);
|
|
220
227
|
var DerivedTabFields = {
|
|
221
228
|
/** true when the receiving connection owns this tab */
|
|
222
229
|
mine: z4.boolean().optional(),
|
|
@@ -330,7 +337,7 @@ var ExecSchema = z4.object({
|
|
|
330
337
|
req_id: z4.string(),
|
|
331
338
|
session_id: z4.string(),
|
|
332
339
|
tab_id: z4.string(),
|
|
333
|
-
step:
|
|
340
|
+
step: ProtocolStepSchema
|
|
334
341
|
});
|
|
335
342
|
var CloseSessionSchema = z4.object({
|
|
336
343
|
...EnvelopeFields,
|
|
@@ -687,6 +694,7 @@ function capabilityForTool(tool, opts) {
|
|
|
687
694
|
case "searchPageIndex":
|
|
688
695
|
case "readPageBlock":
|
|
689
696
|
case "extractPageFields":
|
|
697
|
+
case "inspectElement":
|
|
690
698
|
return "read:dom";
|
|
691
699
|
case "extractImages":
|
|
692
700
|
return "read:image";
|
|
@@ -998,6 +1006,25 @@ var TOOL_DEFS = [
|
|
|
998
1006
|
required: ["selector"]
|
|
999
1007
|
}
|
|
1000
1008
|
},
|
|
1009
|
+
{
|
|
1010
|
+
name: "inspectElement",
|
|
1011
|
+
description: "[FAST\xB7READ\xB7LAYOUT] \u8BFB\u53D6\u5143\u7D20\u7684\u8FD0\u884C\u65F6\u5E03\u5C40\u771F\u76F8\uFF1Acomputed style\u3001viewport/document rect\u3001\u53EF\u89C1\u6027\u3001\u7956\u5148\u94FE\u4E0E shadow root \u4FE1\u606F\u3002\n\u8C03\u8BD5 display/box-sizing/position/overflow/z-index\u3001\u5F39\u7A97\u6302\u8F7D\u70B9\u6216\u7236\u7EA7\u5E03\u5C40\u65F6\u4F18\u5148\u7528\u5B83\uFF0C\u4E0D\u8981\u4E3A\u8FD9\u4E9B\u53EA\u8BFB\u4FE1\u606F\u8C03\u7528 runJS\u3002",
|
|
1012
|
+
input_schema: {
|
|
1013
|
+
type: "object",
|
|
1014
|
+
properties: {
|
|
1015
|
+
selector: { type: "string", description: "CSS selector\uFF1B\u4E0E uid \u4E8C\u9009\u4E00" },
|
|
1016
|
+
uid: { type: "string", description: "takeSnapshot/findElements \u8FD4\u56DE\u7684 uid\uFF1B\u4E0E selector \u4E8C\u9009\u4E00" },
|
|
1017
|
+
ancestorDepth: { type: "integer", default: 5, minimum: 0, maximum: 10 },
|
|
1018
|
+
styleProperties: {
|
|
1019
|
+
type: "array",
|
|
1020
|
+
items: { type: "string" },
|
|
1021
|
+
maxItems: 50,
|
|
1022
|
+
description: "\u8981\u8BFB\u53D6\u7684 CSS \u5C5E\u6027\uFF1B\u7701\u7565\u65F6\u8FD4\u56DE\u5E38\u7528\u5E03\u5C40\u5C5E\u6027"
|
|
1023
|
+
},
|
|
1024
|
+
tabId: TAB_ID_FIELD
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
},
|
|
1001
1028
|
{
|
|
1002
1029
|
name: "extractText",
|
|
1003
1030
|
description: "[FAST\xB7TARGETED] \u63D0\u53D6\u9009\u62E9\u5668\u547D\u4E2D\u5143\u7D20\u7684\u6587\u672C\u3002single=true \u8FD4\u56DE\u5B57\u7B26\u4E32\uFF0C\u5426\u5219\u8FD4\u56DE\u6570\u7EC4\u3002\n\u53EA\u7528\u4E8E\u660E\u786E\u7684\u5C0F\u8303\u56F4 selector\uFF1B\u666E\u901A\u7F51\u9875\u7406\u89E3/\u5B57\u6BB5\u63D0\u53D6\u4E0D\u8981\u7528 extractText({selector:'body'})\uFF0C\u5148\u7528 createPageIndex + extractPageFields/searchPageIndex\u3002\n\n\u793A\u4F8B\uFF1A\n- \u63D0\u53D6\u6807\u9898\uFF1A{ selector: 'h1', single: true }\n- \u63D0\u53D6\u6240\u6709\u6BB5\u843D\uFF1A{ selector: 'article p' }",
|
|
@@ -1290,6 +1317,7 @@ var TOOL_DEFS = [
|
|
|
1290
1317
|
type: "object",
|
|
1291
1318
|
properties: {
|
|
1292
1319
|
source: { type: "string", description: "async function body" },
|
|
1320
|
+
timeoutMs: { type: "integer", minimum: 1, maximum: 25e3, default: 25e3 },
|
|
1293
1321
|
tabId: TAB_ID_FIELD
|
|
1294
1322
|
},
|
|
1295
1323
|
required: ["source"]
|
|
@@ -1856,6 +1884,114 @@ function readToolMode(env) {
|
|
|
1856
1884
|
return "full";
|
|
1857
1885
|
}
|
|
1858
1886
|
|
|
1887
|
+
// ../shared/src/static-scan.ts
|
|
1888
|
+
var RULES = [
|
|
1889
|
+
{
|
|
1890
|
+
rule: "uses-document-cookie",
|
|
1891
|
+
severity: "dangerous",
|
|
1892
|
+
message: "\u8BFB\u53D6/\u5199\u5165 cookie",
|
|
1893
|
+
pattern: /\bdocument\s*\.\s*cookie\b/g
|
|
1894
|
+
},
|
|
1895
|
+
{
|
|
1896
|
+
rule: "uses-eval",
|
|
1897
|
+
severity: "dangerous",
|
|
1898
|
+
message: "eval() \u6267\u884C\u52A8\u6001\u4EE3\u7801",
|
|
1899
|
+
pattern: /\beval\s*\(/g
|
|
1900
|
+
},
|
|
1901
|
+
{
|
|
1902
|
+
rule: "uses-new-function",
|
|
1903
|
+
severity: "dangerous",
|
|
1904
|
+
message: "new Function \u6267\u884C\u52A8\u6001\u4EE3\u7801",
|
|
1905
|
+
pattern: /\bnew\s+Function\s*\(/g
|
|
1906
|
+
},
|
|
1907
|
+
{
|
|
1908
|
+
rule: "uses-chrome-api",
|
|
1909
|
+
severity: "dangerous",
|
|
1910
|
+
message: "\u5C1D\u8BD5\u8BBF\u95EE\u6269\u5C55 API",
|
|
1911
|
+
pattern: /\b(chrome|browser)\s*\.\s*[a-zA-Z_$]/g
|
|
1912
|
+
},
|
|
1913
|
+
{
|
|
1914
|
+
rule: "uses-fetch",
|
|
1915
|
+
severity: "caution",
|
|
1916
|
+
message: "\u53D1\u8D77\u7F51\u7EDC\u8BF7\u6C42 (fetch)",
|
|
1917
|
+
pattern: /\bfetch\s*\(/g
|
|
1918
|
+
},
|
|
1919
|
+
{
|
|
1920
|
+
rule: "uses-xhr",
|
|
1921
|
+
severity: "caution",
|
|
1922
|
+
message: "\u53D1\u8D77\u7F51\u7EDC\u8BF7\u6C42 (XMLHttpRequest)",
|
|
1923
|
+
pattern: /\bnew\s+XMLHttpRequest\b|\bXMLHttpRequest\s*\(/g
|
|
1924
|
+
},
|
|
1925
|
+
{
|
|
1926
|
+
rule: "uses-send-beacon",
|
|
1927
|
+
severity: "caution",
|
|
1928
|
+
message: "navigator.sendBeacon",
|
|
1929
|
+
pattern: /navigator\s*\.\s*sendBeacon\b/g
|
|
1930
|
+
},
|
|
1931
|
+
{
|
|
1932
|
+
rule: "uses-storage",
|
|
1933
|
+
severity: "caution",
|
|
1934
|
+
message: "\u8BFB/\u5199 localStorage / sessionStorage",
|
|
1935
|
+
pattern: /\b(local|session)Storage\b/g
|
|
1936
|
+
},
|
|
1937
|
+
{
|
|
1938
|
+
rule: "uses-indexed-db",
|
|
1939
|
+
severity: "caution",
|
|
1940
|
+
message: "\u8BFB/\u5199 IndexedDB",
|
|
1941
|
+
pattern: /\bindexedDB\b/g
|
|
1942
|
+
},
|
|
1943
|
+
{
|
|
1944
|
+
rule: "uses-mutation-observer",
|
|
1945
|
+
severity: "info",
|
|
1946
|
+
message: "MutationObserver",
|
|
1947
|
+
pattern: /\bMutationObserver\b/g
|
|
1948
|
+
}
|
|
1949
|
+
];
|
|
1950
|
+
function runStaticScan(source) {
|
|
1951
|
+
const out = [];
|
|
1952
|
+
for (const r of RULES) {
|
|
1953
|
+
const matches = collectMatches(source, r.pattern);
|
|
1954
|
+
if (matches.length > 0) {
|
|
1955
|
+
out.push({
|
|
1956
|
+
rule: r.rule,
|
|
1957
|
+
severity: r.severity,
|
|
1958
|
+
message: r.message,
|
|
1959
|
+
matches
|
|
1960
|
+
});
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
return out;
|
|
1964
|
+
}
|
|
1965
|
+
function highestSeverity(findings) {
|
|
1966
|
+
if (findings.some((f) => f.severity === "dangerous")) return "dangerous";
|
|
1967
|
+
if (findings.some((f) => f.severity === "caution")) return "caution";
|
|
1968
|
+
return "info";
|
|
1969
|
+
}
|
|
1970
|
+
function collectMatches(source, pattern) {
|
|
1971
|
+
const re = new RegExp(pattern.source, pattern.flags.includes("g") ? pattern.flags : pattern.flags + "g");
|
|
1972
|
+
const out = [];
|
|
1973
|
+
let m;
|
|
1974
|
+
while ((m = re.exec(source)) !== null) {
|
|
1975
|
+
const { line, col } = locate(source, m.index);
|
|
1976
|
+
out.push({ line, col, text: m[0] });
|
|
1977
|
+
if (m.index === re.lastIndex) re.lastIndex++;
|
|
1978
|
+
}
|
|
1979
|
+
return out;
|
|
1980
|
+
}
|
|
1981
|
+
function locate(source, offset) {
|
|
1982
|
+
let line = 1;
|
|
1983
|
+
let col = 1;
|
|
1984
|
+
for (let i = 0; i < offset; i++) {
|
|
1985
|
+
if (source.charCodeAt(i) === 10) {
|
|
1986
|
+
line++;
|
|
1987
|
+
col = 1;
|
|
1988
|
+
} else {
|
|
1989
|
+
col++;
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
return { line, col };
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1859
1995
|
// src/handlers.ts
|
|
1860
1996
|
function singleWorkerId(c, pairUrl) {
|
|
1861
1997
|
const workers = c.workers.list();
|
|
@@ -1902,18 +2038,25 @@ async function handleBrowserTool(deps, gen, args) {
|
|
|
1902
2038
|
const session_id = String(args.session_id);
|
|
1903
2039
|
const session = coordinator.sessions.get(session_id);
|
|
1904
2040
|
if (!session) throw new Error(`session ${session_id} not found`);
|
|
1905
|
-
const { session_id: _omit, ...
|
|
2041
|
+
const { session_id: _omit, ...suppliedToolArgs } = args;
|
|
2042
|
+
const toolArgs = { ...suppliedToolArgs };
|
|
1906
2043
|
const tool = gen.builtinTool;
|
|
1907
2044
|
if (gen.stepKind === "js") {
|
|
1908
2045
|
const source = String(toolArgs.source ?? "");
|
|
1909
2046
|
if (!source) throw new Error("browser_runJS: source required");
|
|
1910
|
-
const
|
|
2047
|
+
const unsafe = highestSeverity(runStaticScan(source)) === "dangerous";
|
|
2048
|
+
const v = coordinator.validateCall({ session_id, kind: "runJS", unsafe });
|
|
1911
2049
|
if (!v.ok) throw new Error(`${v.error.code}: ${v.error.message}`);
|
|
1912
2050
|
coordinator.recordCall(session_id, v.dangerous);
|
|
2051
|
+
const requestedTimeout = toolArgs.timeoutMs;
|
|
1913
2052
|
const jsResult = await hub.exec(session.worker_id, {
|
|
1914
2053
|
session_id,
|
|
1915
2054
|
tab_id: session.tab_id,
|
|
1916
|
-
step: {
|
|
2055
|
+
step: {
|
|
2056
|
+
kind: "js",
|
|
2057
|
+
source,
|
|
2058
|
+
...typeof requestedTimeout === "number" && Number.isInteger(requestedTimeout) && requestedTimeout > 0 ? { timeoutMs: requestedTimeout } : {}
|
|
2059
|
+
}
|
|
1917
2060
|
});
|
|
1918
2061
|
if (!jsResult.ok) {
|
|
1919
2062
|
throw new Error(
|
|
@@ -1922,6 +2065,13 @@ async function handleBrowserTool(deps, gen, args) {
|
|
|
1922
2065
|
}
|
|
1923
2066
|
return jsResult.return ?? null;
|
|
1924
2067
|
}
|
|
2068
|
+
if (gen.builtinTool === "switchToTab" || gen.builtinTool === "closeTab") {
|
|
2069
|
+
const boundTabId = Number.parseInt(session.tab_id, 10);
|
|
2070
|
+
if (!Number.isFinite(boundTabId)) {
|
|
2071
|
+
throw new Error(`InvalidArgs: session tab_id "${session.tab_id}" is not numeric`);
|
|
2072
|
+
}
|
|
2073
|
+
toolArgs.tabId = boundTabId;
|
|
2074
|
+
}
|
|
1925
2075
|
const override = NON_BUILTIN_CAPABILITY[gen.builtinTool];
|
|
1926
2076
|
if (override) {
|
|
1927
2077
|
const v = coordinator.validateCall({ session_id, kind: "capability", capability: override });
|
|
@@ -2374,7 +2524,7 @@ var LoopbackWSHub = class {
|
|
|
2374
2524
|
req_id,
|
|
2375
2525
|
session_id: params.session_id,
|
|
2376
2526
|
tab_id: params.tab_id,
|
|
2377
|
-
step:
|
|
2527
|
+
step: params.step
|
|
2378
2528
|
});
|
|
2379
2529
|
if (this.byWorker.get(worker_id) !== socket) {
|
|
2380
2530
|
clearTimeout(timer);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@attson/atwebpilot-mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.67",
|
|
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",
|