vite-plugin-aipanel 1.2.8 → 1.2.10

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 (58) hide show
  1. package/es/core/chrome-project.d.ts +15 -0
  2. package/es/core/chrome-project.mjs +13 -0
  3. package/es/core/mcp-chrome.d.ts +12 -8
  4. package/es/core/mcp-chrome.mjs +52 -10
  5. package/es/core/mcp-proxy.d.ts +21 -1
  6. package/es/core/mcp-proxy.mjs +83 -12
  7. package/es/core/mcp-tools.d.ts +51 -3
  8. package/es/core/mcp-tools.mjs +109 -659
  9. package/es/core/official-meta.d.ts +9 -0
  10. package/es/core/official-meta.mjs +62 -0
  11. package/es/core/official-tools.d.ts +7 -0
  12. package/es/core/official-tools.mjs +54 -0
  13. package/es/core/proxy-server.mjs +16 -13
  14. package/es/core/service.mjs +4 -5
  15. package/es/endpoints/context.mjs +2 -2
  16. package/es/endpoints/host-events.mjs +1 -2
  17. package/es/endpoints/index.d.ts +2 -2
  18. package/es/endpoints/index.mjs +2 -2
  19. package/es/endpoints/mcp.d.ts +2 -2
  20. package/es/endpoints/mcp.mjs +116 -87
  21. package/es/endpoints/sse.mjs +3 -3
  22. package/es/endpoints/vue-devtools.d.ts +5 -2
  23. package/es/endpoints/vue-devtools.mjs +3 -4
  24. package/es/index.mjs +29 -6
  25. package/lib/client.js +2380 -2369
  26. package/lib/core/chrome-project.cjs +36 -0
  27. package/lib/core/chrome-project.d.ts +15 -0
  28. package/lib/core/mcp-chrome.cjs +64 -10
  29. package/lib/core/mcp-chrome.d.ts +12 -8
  30. package/lib/core/mcp-proxy.cjs +87 -13
  31. package/lib/core/mcp-proxy.d.ts +21 -1
  32. package/lib/core/mcp-tools.cjs +124 -660
  33. package/lib/core/mcp-tools.d.ts +51 -3
  34. package/lib/core/official-meta.cjs +85 -0
  35. package/lib/core/official-meta.d.ts +9 -0
  36. package/lib/core/official-tools.cjs +70 -0
  37. package/lib/core/official-tools.d.ts +7 -0
  38. package/lib/core/proxy-server.cjs +16 -13
  39. package/lib/core/service.cjs +4 -5
  40. package/lib/endpoints/context.cjs +1 -1
  41. package/lib/endpoints/host-events.cjs +0 -1
  42. package/lib/endpoints/index.cjs +2 -2
  43. package/lib/endpoints/index.d.ts +2 -2
  44. package/lib/endpoints/mcp.cjs +114 -85
  45. package/lib/endpoints/mcp.d.ts +2 -2
  46. package/lib/endpoints/sse.cjs +2 -2
  47. package/lib/endpoints/vue-devtools.cjs +4 -5
  48. package/lib/endpoints/vue-devtools.d.ts +5 -2
  49. package/lib/index.cjs +29 -7
  50. package/package.json +10 -7
  51. package/es/utils/format-bridge.d.ts +0 -9
  52. package/es/utils/format-bridge.mjs +0 -80
  53. package/es/utils/system.d.ts +0 -3
  54. package/es/utils/system.mjs +0 -76
  55. package/lib/utils/format-bridge.cjs +0 -102
  56. package/lib/utils/format-bridge.d.ts +0 -9
  57. package/lib/utils/system.cjs +0 -110
  58. package/lib/utils/system.d.ts +0 -3
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 项目边界策略解析:在请求时把 chromeMcp.project 与 vite 自动 origins 合并为一份体。
3
+ * 所有边界判定(页面归属 / 导航目标 / 扩展页)均只读此解析结果,单一来源。
4
+ */
5
+ import type { ViteDevServer } from "vite";
6
+ import type { ChromeProjectOptions } from "@aipanel/core";
7
+ export interface ProjectScope {
8
+ /** 项目页 origins(自动,“项目页全局一个”分类 + vue-devtools 桥可用范围) */
9
+ origins: string[];
10
+ /** 可操作范围 = 项目页 ∪ allowOrigins:chrome 页面级 list/current/pageId 校验、navigate/new 目标用 */
11
+ operationsOrigins: string[];
12
+ /** 是否允许 chrome-extension:// 页面纳入可操作范围 */
13
+ includeExtensions: boolean;
14
+ }
15
+ export declare function resolveProjectScope(server: ViteDevServer, project?: ChromeProjectOptions): ProjectScope;
@@ -0,0 +1,13 @@
1
+ import { getProjectOrigins } from "./mcp-chrome.mjs";
2
+ function resolveProjectScope(server, project) {
3
+ const auto = getProjectOrigins(server);
4
+ const operationsOrigins = [.../* @__PURE__ */ new Set([...auto, ...project?.allowOrigins ?? []])];
5
+ return {
6
+ origins: auto,
7
+ operationsOrigins,
8
+ includeExtensions: project?.includeExtensionPages === true
9
+ };
10
+ }
11
+ export {
12
+ resolveProjectScope
13
+ };
@@ -7,8 +7,12 @@ import type { ViteDevServer } from "vite";
7
7
  import type { McpProxy } from "./mcp-proxy";
8
8
  /** 从 Vite 服务器解析的所有 URL 中提取项目 origin 列表 */
9
9
  export declare function getProjectOrigins(server: ViteDevServer): string[];
10
- /** 判断页面 URL 是否属于项目的某个 origin */
10
+ /** 判断页面 URL 是否命中某个范围条目(allowOrigins 三种写法,见模块注释) */
11
+ export declare function isOriginEntryMatch(url: string, entry: string): boolean;
12
+ /** 判断页面 URL 是否命中某组范围条目(可为精确 origin / 通配符 / 正则) */
11
13
  export declare function isProjectPage(url: string, origins: string[]): boolean;
14
+ /** 判断页面 URL 是否属于可操作范围(范围条目,或启用时的扩展页) */
15
+ export declare function isPageAllowed(url: string, origins: string[], includeExtensions: boolean): boolean;
12
16
  export interface PageInfo {
13
17
  pageId: number;
14
18
  url: string;
@@ -28,18 +32,18 @@ type PageIdResult = {
28
32
  error: string;
29
33
  };
30
34
  /**
31
- * 校验 pageId 是否属于项目页面
35
+ * 校验 pageId 是否属于可操作范围(项目页 ∪ allowOrigins)
32
36
  *
33
- * 调用 list_pages → 过滤项目页面 → 检查 pageId 是否在范围内。
37
+ * 调用 list_pages → 过滤允许页面 → 检查 pageId 是否在范围内。
34
38
  * 供 MCP 代理层和 Vue DevTools 端点共用。
35
39
  */
36
- export declare function validatePageId(mcp: McpProxy, pageId: number, projectOrigins: string[]): Promise<{
40
+ export declare function validatePageId(mcp: McpProxy, pageId: number, operationsOrigins: string[], includeExtensions?: boolean): Promise<{
37
41
  valid: true;
38
- projectPages: PageInfo[];
42
+ allowedPages: PageInfo[];
39
43
  } | {
40
44
  valid: false;
41
45
  error: string;
42
- projectPages: PageInfo[];
46
+ allowedPages: PageInfo[];
43
47
  }>;
44
48
  /**
45
49
  * 通过 MCP 解析当前页面对应的 Chrome DevTools pageId
@@ -50,7 +54,7 @@ export declare function validatePageId(mcp: McpProxy, pageId: number, projectOri
50
54
  *
51
55
  * 失败时返回具体原因,由调用方透传给 Agent。
52
56
  */
53
- export declare function resolveChromePageId(mcp: McpProxy | undefined, url: string, title: string, projectOrigins: string[], sessionId?: string, pages?: PageInfo[],
54
- /** Chrome 当前选中的 pageId(调用方传入,避免过滤后丢失非项目页面信息) */
57
+ export declare function resolveChromePageId(mcp: McpProxy | undefined, url: string, title: string, operationsOrigins: string[], sessionId?: string, pages?: PageInfo[],
58
+ /** Chrome 当前选中的 pageId(调用方传入,避免过滤后丢失范围外页面信息) */
55
59
  chromeSelectedPageId?: number): Promise<PageIdResult>;
56
60
  export {};
@@ -1,3 +1,4 @@
1
+ import picomatch from "picomatch";
1
2
  import { createLogger } from "@aipanel/core/node";
2
3
  const log = createLogger("McpChrome");
3
4
  function getProjectOrigins(server) {
@@ -7,8 +8,45 @@ function getProjectOrigins(server) {
7
8
  log.debug("project origins", { origins });
8
9
  return origins;
9
10
  }
11
+ const entryMatcherCache = /* @__PURE__ */ new Map();
12
+ function parseRegexEntry(entry) {
13
+ if (!entry.startsWith("/")) return void 0;
14
+ const lastSlash = entry.lastIndexOf("/");
15
+ if (lastSlash <= 0) return void 0;
16
+ const source = entry.slice(1, lastSlash);
17
+ const flags = entry.slice(lastSlash + 1);
18
+ if (!/^[a-z]*$/.test(flags)) return void 0;
19
+ try {
20
+ return { kind: "regex", re: new RegExp(source, flags) };
21
+ } catch {
22
+ return void 0;
23
+ }
24
+ }
25
+ function compileEntryMatcher(entry) {
26
+ const cached = entryMatcherCache.get(entry);
27
+ if (cached) return cached;
28
+ let compiled = { kind: "prefix" };
29
+ const regexMatcher = parseRegexEntry(entry);
30
+ if (regexMatcher) {
31
+ compiled = regexMatcher;
32
+ } else if (picomatch.scan(entry).isGlob) {
33
+ compiled = { kind: "glob", match: picomatch(entry) };
34
+ }
35
+ entryMatcherCache.set(entry, compiled);
36
+ return compiled;
37
+ }
38
+ function isOriginEntryMatch(url, entry) {
39
+ const matcher = compileEntryMatcher(entry);
40
+ if (matcher.kind === "regex") return matcher.re.test(url);
41
+ if (matcher.kind === "glob") return matcher.match(url);
42
+ return url.startsWith(entry);
43
+ }
10
44
  function isProjectPage(url, origins) {
11
- return origins.some((origin) => url.startsWith(origin));
45
+ return origins.some((entry) => isOriginEntryMatch(url, entry));
46
+ }
47
+ function isPageAllowed(url, origins, includeExtensions) {
48
+ if (origins.some((entry) => isOriginEntryMatch(url, entry))) return true;
49
+ return includeExtensions && url.startsWith("chrome-extension://");
12
50
  }
13
51
  function parseListPages(text) {
14
52
  const pages = [];
@@ -39,29 +77,31 @@ function extractEvalValue(text) {
39
77
  return jsonStr.trim();
40
78
  }
41
79
  }
42
- async function validatePageId(mcp, pageId, projectOrigins) {
80
+ async function validatePageId(mcp, pageId, operationsOrigins, includeExtensions = false) {
43
81
  const listResult = await mcp.callChromeDevTool("list_pages", {});
44
82
  if (listResult?.error || !listResult?.result) {
45
83
  return {
46
84
  valid: false,
47
85
  error: listResult?.error?.message ?? "\u65E0\u6CD5\u83B7\u53D6 Chrome \u9875\u9762\u5217\u8868\uFF0C\u8BF7\u786E\u8BA4 Chrome DevTools \u5DF2\u8FDE\u63A5",
48
- projectPages: []
86
+ allowedPages: []
49
87
  };
50
88
  }
51
89
  const text = listResult?.result?.content?.[0]?.text;
52
90
  const allPages = text ? parseListPages(text) : [];
53
- const projectPages = allPages.filter((p) => isProjectPage(p.url, projectOrigins));
54
- const isValid = projectPages.some((p) => p.pageId === pageId);
91
+ const allowedPages = allPages.filter(
92
+ (p) => isPageAllowed(p.url, operationsOrigins, includeExtensions)
93
+ );
94
+ const isValid = allowedPages.some((p) => p.pageId === pageId);
55
95
  if (!isValid) {
56
96
  return {
57
97
  valid: false,
58
- error: `pageId ${pageId} \u65E0\u6548\u6216\u975E\u9879\u76EE\u9875\u9762\uFF0C\u8BF7\u83B7\u53D6\u6709\u6548\u9875\u9762 ID`,
59
- projectPages
98
+ error: `pageId ${pageId} \u4E0D\u5728\u53EF\u64CD\u4F5C\u8303\u56F4\uFF08\u9879\u76EE\u9875\u6216 allowOrigins \u767D\u540D\u5355\u9875\uFF09\uFF0C\u8BF7\u5148\u7528 list_pages \u83B7\u53D6\u6709\u6548\u9875\u9762 ID`,
99
+ allowedPages
60
100
  };
61
101
  }
62
- return { valid: true, projectPages };
102
+ return { valid: true, allowedPages };
63
103
  }
64
- async function resolveChromePageId(mcp, url, title, projectOrigins, sessionId, pages, chromeSelectedPageId) {
104
+ async function resolveChromePageId(mcp, url, title, operationsOrigins, sessionId, pages, chromeSelectedPageId) {
65
105
  if (!mcp || !mcp.isRunning) {
66
106
  const reason = !mcp ? "MCP \u6A21\u5757\u672A\u521D\u59CB\u5316" : "Chrome DevTools MCP \u8FDB\u7A0B\u672A\u542F\u52A8";
67
107
  log.debug(`resolveChromePageId: ${reason}`);
@@ -79,7 +119,7 @@ async function resolveChromePageId(mcp, url, title, projectOrigins, sessionId, p
79
119
  }
80
120
  const allPages = parseListPages(text);
81
121
  chromeSelectedPageId = allPages.find((p) => p.selected)?.pageId;
82
- pages = allPages.filter((p) => isProjectPage(p.url, projectOrigins));
122
+ pages = allPages.filter((p) => isProjectPage(p.url, operationsOrigins));
83
123
  }
84
124
  log.debug("resolveChromePageId: list_pages result", {
85
125
  pages: pages.map((p) => ({ id: p.pageId, url: p.url, title: p.title.substring(0, 40) })),
@@ -126,6 +166,8 @@ async function resolveChromePageId(mcp, url, title, projectOrigins, sessionId, p
126
166
  export {
127
167
  extractEvalValue,
128
168
  getProjectOrigins,
169
+ isOriginEntryMatch,
170
+ isPageAllowed,
129
171
  isProjectPage,
130
172
  parseListPages,
131
173
  resolveChromePageId,
@@ -1,5 +1,25 @@
1
+ /** chrome-devtools-mcp 的核心受保护参数(用户不可覆盖;始终最后注入确保生效) */
2
+ export declare const CORE_MCP_ARGS: readonly ["--auto-connect", "--no-usage-statistics", "--no-performance-crux", "--no-page-id-routing", "--allow-unrestricted-paths"];
3
+ /** 过滤用户透传参数:剔除与核心受保护 flag 冲突的项,其余原样保留 */
4
+ export type McpArgDropKind = "protected" | "managed";
5
+ export interface McpArgDrop {
6
+ arg: string;
7
+ kind: McpArgDropKind;
8
+ }
9
+ /** 分类用户透传参数:保留可透传项,列出被剔除项及原因 */
10
+ export declare function classifyUserMcpArgs(userArgs: readonly string[]): {
11
+ kept: string[];
12
+ dropped: McpArgDrop[];
13
+ };
14
+ /** 过滤用户透传参数:剔除与核心受保护/策略接管 flag 冲突的项 */
15
+ export declare function filterUserMcpArgs(userArgs: readonly string[]): string[];
1
16
  export interface McpProxyOptions {
2
- args?: string[];
17
+ /** 用户透传的额外 CLI 参数(追加;与核心受保护项冲突的会被剔除) */
18
+ userArgs?: string[];
19
+ /** 策略控制的内部注入参数(不经用户过滤,在用户参数之后、核心参数之前注入) */
20
+ managedArgs?: string[];
21
+ /** 用户透传的额外环境变量(合并到 process.env 之上) */
22
+ env?: Record<string, string>;
3
23
  idleTimeout?: number;
4
24
  }
5
25
  export declare class McpProxy {
@@ -17,13 +17,76 @@ var __privateWrapper = (obj, member, setter, getter) => ({
17
17
  return __privateGet(obj, member, getter);
18
18
  }
19
19
  });
20
- var _proc, _rl, _messageId, _internalIdBase, _pending, _args, _startPromise, _lastExit, _stderrTail, _idleTimer, _idleTimeout, _McpProxy_instances, doStart_fn, formatNotAvailable_fn, resetIdleTimer_fn;
20
+ var _proc, _rl, _messageId, _internalIdBase, _pending, _args, _env, _startPromise, _lastExit, _stderrTail, _idleTimer, _idleTimeout, _McpProxy_instances, doStart_fn, formatNotAvailable_fn, resetIdleTimer_fn;
21
21
  import { spawn } from "node:child_process";
22
22
  import { createInterface } from "node:readline";
23
23
  import crypto from "node:crypto";
24
24
  import path from "node:path";
25
25
  import { createLogger, createPackageRequire, resolvePackageDir } from "@aipanel/core/node";
26
26
  const log = createLogger("McpProxy");
27
+ const CORE_MCP_ARGS = [
28
+ "--auto-connect",
29
+ "--no-usage-statistics",
30
+ "--no-performance-crux",
31
+ // chrome-devtools-mcp >=1.8.0 默认开启 pageIdRouting(要求每个页面级工具都传 pageId)。
32
+ // 代理层已自行校验 pageId 并用 select_page 选中目标页面后再转发,故显式关闭,
33
+ // 避免底层工具 schema 强制必填 pageId 导致转发时的参数校验失败。
34
+ "--no-page-id-routing",
35
+ // 客户端未协商 roots,官方默认把文件工具限制在 OS 临时目录;
36
+ // 为保持 upload_file “不限制项目目录”的设计,显式允许任意路径
37
+ // (工具层仍受白名单 + pageId 归属约束)。
38
+ "--allow-unrestricted-paths"
39
+ ];
40
+ const PROTECTED_FLAGS = /* @__PURE__ */ new Set([
41
+ "auto-connect",
42
+ "usage-statistics",
43
+ "performance-crux",
44
+ "page-id-routing"
45
+ ]);
46
+ const MANAGED_FLAGS = /* @__PURE__ */ new Set([
47
+ "slim",
48
+ "category-extensions",
49
+ "category-pwa",
50
+ "category-experimental-third-party",
51
+ "category-experimental-webmcp",
52
+ "category-performance",
53
+ "category-network",
54
+ "category-emulation",
55
+ "experimental-vision",
56
+ "experimental-interop-tools",
57
+ "experimental-memory",
58
+ "experimental-screencast",
59
+ "experimental-structured-content",
60
+ "experimental-include-all-pages",
61
+ "allow-unrestricted-paths"
62
+ ]);
63
+ function canonicalFlagName(arg) {
64
+ let flag = arg.trim();
65
+ if (!flag.startsWith("-")) return null;
66
+ flag = flag.replace(/^--?/, "").split("=")[0] ?? "";
67
+ if (flag.startsWith("no-")) flag = flag.slice(3);
68
+ return flag || null;
69
+ }
70
+ function classifyUserMcpArgs(userArgs) {
71
+ const kept = [];
72
+ const dropped = [];
73
+ for (const arg of userArgs) {
74
+ const name = canonicalFlagName(arg);
75
+ if (name === null) {
76
+ kept.push(arg);
77
+ } else if (PROTECTED_FLAGS.has(name)) {
78
+ dropped.push({ arg, kind: "protected" });
79
+ } else if (MANAGED_FLAGS.has(name)) {
80
+ dropped.push({ arg, kind: "managed" });
81
+ } else {
82
+ kept.push(arg);
83
+ }
84
+ }
85
+ return { kept, dropped };
86
+ }
87
+ function filterUserMcpArgs(userArgs) {
88
+ return classifyUserMcpArgs(userArgs).kept;
89
+ }
27
90
  function resolveChromeDevToolsMcpBin() {
28
91
  const pluginDir = resolvePackageDir("vite-plugin-aipanel");
29
92
  const require2 = createPackageRequire(pluginDir);
@@ -43,6 +106,7 @@ class McpProxy {
43
106
  __privateAdd(this, _internalIdBase, 1e6);
44
107
  __privateAdd(this, _pending, /* @__PURE__ */ new Map());
45
108
  __privateAdd(this, _args);
109
+ __privateAdd(this, _env);
46
110
  __privateAdd(this, _startPromise, null);
47
111
  /** 最近一次进程退出信息,用于生成精确错误(无退出记录时为 null) */
48
112
  __privateAdd(this, _lastExit, null);
@@ -51,15 +115,17 @@ class McpProxy {
51
115
  __privateAdd(this, _idleTimer, null);
52
116
  __privateAdd(this, _idleTimeout);
53
117
  __publicField(this, "sessionId");
54
- __privateSet(this, _args, options.args ?? [
55
- "--auto-connect",
56
- "--no-usage-statistics",
57
- "--no-performance-crux",
58
- // chrome-devtools-mcp >=1.8.0 默认开启 pageIdRouting(要求每个页面级工具都传 pageId)。
59
- // 代理层已自行校验 pageId 并用 select_page 选中目标页面后再转发,故显式关闭,
60
- // 避免底层工具 schema 强制必填 pageId 导致转发时的参数校验失败。
61
- "--no-page-id-routing"
62
- ]);
118
+ const userArgs = options.userArgs ?? [];
119
+ const { kept, dropped } = classifyUserMcpArgs(userArgs);
120
+ if (dropped.length > 0) {
121
+ log.warn(
122
+ "chrome MCP \u7528\u6237\u53C2\u6570\u4E0E\u53D7\u4FDD\u62A4/\u7B56\u7565\u63A5\u7BA1 flag \u51B2\u7A81\uFF0C\u5DF2\u5FFD\u7565\uFF1B\u8BF7\u7528 chromeMcp.project \u914D\u7F6E\u5BF9\u5E94\u884C\u4E3A",
123
+ { dropped }
124
+ );
125
+ }
126
+ const managedArgs = options.managedArgs ?? [];
127
+ __privateSet(this, _args, [...kept, ...managedArgs, ...CORE_MCP_ARGS]);
128
+ __privateSet(this, _env, options.env);
63
129
  __privateSet(this, _idleTimeout, options.idleTimeout ?? 0);
64
130
  this.sessionId = crypto.randomUUID();
65
131
  }
@@ -153,6 +219,7 @@ _messageId = new WeakMap();
153
219
  _internalIdBase = new WeakMap();
154
220
  _pending = new WeakMap();
155
221
  _args = new WeakMap();
222
+ _env = new WeakMap();
156
223
  _startPromise = new WeakMap();
157
224
  _lastExit = new WeakMap();
158
225
  _stderrTail = new WeakMap();
@@ -166,7 +233,8 @@ doStart_fn = async function() {
166
233
  __privateSet(this, _lastExit, null);
167
234
  __privateSet(this, _stderrTail, []);
168
235
  __privateSet(this, _proc, spawn(process.execPath, [binPath, ...__privateGet(this, _args)], {
169
- stdio: ["pipe", "pipe", "pipe"]
236
+ stdio: ["pipe", "pipe", "pipe"],
237
+ env: { ...process.env, ...__privateGet(this, _env) }
170
238
  }));
171
239
  log.debug("Using local chrome-devtools-mcp");
172
240
  } catch {
@@ -255,5 +323,8 @@ resetIdleTimer_fn = function() {
255
323
  }, __privateGet(this, _idleTimeout)));
256
324
  };
257
325
  export {
258
- McpProxy
326
+ CORE_MCP_ARGS,
327
+ McpProxy,
328
+ classifyUserMcpArgs,
329
+ filterUserMcpArgs
259
330
  };
@@ -1,8 +1,13 @@
1
1
  /**
2
- * 自定义 DevTools 工具定义
3
- * 所有工具(除 chrome-devtools_list_pages)必须传入 pageId 参数,
4
- * 代理层校验 pageId 是否为项目页面后方可调用 chrome-devtools-mcp
2
+ * Chrome DevTools 工具层的项目维度元数据与自定义工具。
3
+ *
4
+ * 模型可见的 chrome-devtools_* 工具 = 官方 chrome-devtools-mcp 工具的白名单子集
5
+ * (schema/描述运行时同步自官方 tools/list,见 official-tools.ts)+ 本项目自定义工具。
6
+ * 工具层限制(白名单、必填 pageId、仅项目页)由本文件 + endpoints/mcp.ts 的 tools/call 共同执行。
5
7
  */
8
+ /** 模型可见名前缀:官方短名 → chrome-devtools_<name> */
9
+ export declare const MCP_PREFIX = "chrome-devtools_";
10
+ export declare function displayToolName(short: string): string;
6
11
  export interface CustomTool {
7
12
  name: string;
8
13
  description: string;
@@ -12,4 +17,47 @@ export interface CustomTool {
12
17
  required?: string[];
13
18
  };
14
19
  }
20
+ /**
21
+ * 默认暴露的官方页面级工具 = 元数据规则推导(pageScoped && 无条件 && 分类安全),
22
+ * 具体由 officialDefaultShorts() 给出。
23
+ * 以下为 meta 无法从 pageScoped 推断、需要“按页面上下文使用/列表/新建”的产品全局特例(短名)。
24
+ */
25
+ export declare const OFFICIAL_GLOBAL_POLICY: readonly ["evaluate_script", "list_console_messages", "list_pages", "new_page"];
26
+ export type OfficialToolShortName = string;
27
+ /** 不需要 pageId 的官方工具(无目标页,由调用层特别处理) */
28
+ export declare const OFFICIAL_NO_PAGE_TOOLS: ReadonlySet<string>;
29
+ /** 目标页参数:pageId 必须在可操作范围(项目页或 allowOrigins 白名单页)内 */
30
+ export declare const PAGE_ID_PROP: {
31
+ readonly pageId: {
32
+ readonly type: "number";
33
+ readonly description: "The ID of a page within the operation scope (project pages or chromeMcp.project.allowOrigins pages) to operate on";
34
+ };
35
+ };
36
+ /** 往官方 schema 上统一追加必填 pageId(保持工具层项目限制) */
37
+ export declare function withPageIdSchema(schema: CustomTool["inputSchema"]): CustomTool["inputSchema"];
38
+ /**
39
+ * 追加到官方描述末尾的项目维度说明(英文,按工具特例)。
40
+ * 只填“调用层真正实现的语义与官方不一样”的工具,
41
+ * 避免描述过度承诺(如 navigate_page 目标 URL 未被调用层限制,不填“必须在项目内”)。
42
+ * 其余页面级工具的项目边界由必填 pageId 参数说明表达(PAGE_ID_PROP)。
43
+ */
44
+ export declare const PROJECT_DESCRIPTION_NOTES: Record<string, string>;
45
+ /** 自定义工具(官方无对应,工具层本地实现) */
15
46
  export declare const CUSTOM_TOOLS: CustomTool[];
47
+ /** 官方声明了条件、且属于可开启范围的工具(由官方元数据派生,无手写) */
48
+ export declare function isOfficialExtraTool(short: string): boolean;
49
+ /** 由官方 conditions 推导所需 flag(experimentalX → --experimental-x,与官方 CLI 一致) */
50
+ export declare function extraToolFlag(short: string): string | undefined;
51
+ /** 可开启的二级工具名单(用于验证与提示) */
52
+ export declare function officialExtraCandidates(): string[];
53
+ /**
54
+ * 默认暴露的官方工具集:
55
+ * 页面级(pageScoped && 无 conditions && 分类安全)由官方元数据规则推导 + 全局特例 GLOBAL_POLICY。
56
+ */
57
+ export declare function officialDefaultShorts(): string[];
58
+ /** 配置工具面范围(默认为纯白名单) */
59
+ export declare function configureToolScope(extra?: readonly string[], deny?: readonly string[], warn?: (msg: string) => void): void;
60
+ /** 当前生效的官方白名单(短名,含 extra 减 deny) */
61
+ export declare function currentOfficialShorts(): string[];
62
+ /** tools/call 白名单守卫(含 current_page 与动态 extra/deny) */
63
+ export declare function isAllowedToolName(name: string): boolean;