@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.
Files changed (2) hide show
  1. package/dist/index.js +160 -10
  2. 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 StepSchema = z4.object({
216
- kind: z4.literal("tool"),
217
- tool: z4.string(),
218
- args: z4.unknown()
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: StepSchema
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, ...toolArgs } = args;
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 v = coordinator.validateCall({ session_id, kind: "runJS", unsafe: true });
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: { kind: "js", source }
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: { kind: "tool", tool: params.step.tool, args: params.step.args }
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.65",
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",