@extension.dev/mcp 3.17.0 → 4.0.8

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.
@@ -0,0 +1,20 @@
1
+ export declare class CDPConnection {
2
+ private ws;
3
+ private messageId;
4
+ private eventListeners;
5
+ private pendingRequests;
6
+ private consoleMessages;
7
+ connect(wsUrl: string): Promise<void>;
8
+ disconnect(): void;
9
+ private handleMessage;
10
+ private rejectAllPending;
11
+ sendCommand(method: string, params?: Record<string, unknown>, sessionId?: string): Promise<unknown>;
12
+ getConsoleMessages(): Array<{
13
+ level: string;
14
+ text: string;
15
+ source: string;
16
+ timestamp: number;
17
+ }>;
18
+ getConsoleSummary(): Record<string, unknown>;
19
+ protected onEvent(handler: (msg: Record<string, unknown>) => void): () => void;
20
+ }
@@ -0,0 +1,5 @@
1
+ export declare const PAGE_HTML_SCRIPT = "(() => {\n try {\n const doctype = document.doctype;\n const dt = doctype\n ? '<!DOCTYPE ' + doctype.name\n + (doctype.publicId ? ' PUBLIC \"' + doctype.publicId + '\"' : '')\n + (doctype.systemId ? ' \"' + doctype.systemId + '\"' : '')\n + '>'\n : '';\n // Include shadow DOM content from extension roots\n const roots = Array.from(document.querySelectorAll(\n '#extension-root,[data-extension-root]:not([data-extension-root=\"extension-js-devtools\"])'\n ));\n if (roots.length) {\n const clone = document.documentElement.cloneNode(true);\n const clonedRoots = Array.from(clone.querySelectorAll(\n '#extension-root,[data-extension-root]:not([data-extension-root=\"extension-js-devtools\"])'\n ));\n const s = new XMLSerializer();\n for (let i = 0; i < Math.min(roots.length, clonedRoots.length); i++) {\n const sr = roots[i].shadowRoot;\n if (!sr) continue;\n try {\n const shadow = Array.from(sr.childNodes).map(n => {\n try { return s.serializeToString(n); } catch { return ''; }\n }).join('');\n if (shadow) clonedRoots[i].innerHTML = shadow;\n } catch {}\n }\n return dt + '\\n' + clone.outerHTML;\n }\n return dt + '\\n' + document.documentElement.outerHTML;\n } catch (e) { return ''; }\n })()";
2
+ export declare const PAGE_META_SCRIPT = "(() => {\n try {\n return {\n title: document.title,\n url: location.href,\n readyState: document.readyState,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio\n },\n frameCount: window.frames.length,\n scriptCount: document.querySelectorAll('script').length,\n styleCount: document.querySelectorAll('style,link[rel=\"stylesheet\"]').length\n };\n } catch { return {}; }\n })()";
3
+ export declare const EXTENSION_ROOT_META_SCRIPT = "(() => {\n try {\n const readGeneration = (node) => {\n const raw = node.getAttribute && node.getAttribute('data-extjs-reinject-generation');\n const parsed = Number(raw);\n return Number.isFinite(parsed) ? parsed : undefined;\n };\n const normalize = (node) => ({\n tag: node.tagName ? String(node.tagName).toLowerCase() : 'unknown',\n id: node.id || undefined,\n key: node.getAttribute ? node.getAttribute('data-extjs-reinject-key') || undefined : undefined,\n generation: readGeneration(node),\n status: node.getAttribute ? node.getAttribute('data-extjs-reinject-status') || undefined : undefined\n });\n const roots = Array.from(\n document.querySelectorAll('#extension-root,[data-extension-root]:not([data-extension-root=\"extension-js-devtools\"])')\n ).slice(0, 10).map(normalize);\n const markers = Array.from(\n document.querySelectorAll('[data-extjs-reinject-marker=\"true\"]')\n ).slice(0, 10).map(normalize);\n if (!roots.length && !markers.length) return null;\n const generations = [...roots, ...markers]\n .map(e => e.generation)\n .filter(g => typeof g === 'number');\n return {\n rootCount: roots.length,\n markerCount: markers.length,\n latestGeneration: generations.length ? Math.max(...generations) : 0,\n roots,\n markers\n };\n } catch { return null; }\n })()";
4
+ export declare function probeSelectorsScript(selectors: string[]): string;
5
+ export declare function domSnapshotScript(maxNodes: number): string;
@@ -1,14 +1,5 @@
1
- export declare class CDPClient {
2
- private ws;
3
- private messageId;
4
- private eventListeners;
5
- private pendingRequests;
6
- private consoleMessages;
7
- connect(wsUrl: string): Promise<void>;
8
- disconnect(): void;
9
- private handleMessage;
10
- private rejectAllPending;
11
- sendCommand(method: string, params?: Record<string, unknown>, sessionId?: string): Promise<unknown>;
1
+ import { CDPConnection } from "./cdp-connection";
2
+ export declare class CDPClient extends CDPConnection {
12
3
  static discoverBrowserWsUrl(port: number, host?: string): Promise<string>;
13
4
  static discoverTargets(port: number, host?: string): Promise<Array<{
14
5
  id: string;
@@ -37,12 +28,4 @@ export declare class CDPClient {
37
28
  }>>;
38
29
  getDomSnapshot(sessionId: string, maxNodes?: number): Promise<Array<Record<string, unknown>>>;
39
30
  getExtensionRootMeta(sessionId: string): Promise<Record<string, unknown> | null>;
40
- getConsoleMessages(): Array<{
41
- level: string;
42
- text: string;
43
- source: string;
44
- timestamp: number;
45
- }>;
46
- getConsoleSummary(): Record<string, unknown>;
47
- private onEvent;
48
31
  }
@@ -1,4 +1,4 @@
1
- import { type ChildProcess } from "node:child_process";
1
+ import type { ChildProcess } from "node:child_process";
2
2
  export interface CliResult {
3
3
  code: number | null;
4
4
  stdout: string;
@@ -0,0 +1,6 @@
1
+ export declare const CONTROL_ENVELOPE_VERSION = 1;
2
+ export declare const CONTROL_WS_PATH = "/extjs-control";
3
+ export declare const DEFAULT_LIMIT = 200;
4
+ export declare const DEFAULT_FOLLOW_MS = 4000;
5
+ export declare const MIN_FOLLOW_MS = 500;
6
+ export declare const MAX_FOLLOW_MS = 15000;
@@ -0,0 +1,14 @@
1
+ export interface LogsArgs {
2
+ projectPath: string;
3
+ browser?: string;
4
+ level?: string;
5
+ context?: string[] | string;
6
+ signalsOnly?: boolean;
7
+ since?: number;
8
+ url?: string;
9
+ tab?: number;
10
+ follow?: boolean;
11
+ followMs?: number;
12
+ limit?: number;
13
+ }
14
+ export declare function makeFilter(args: LogsArgs): (event: any) => boolean;
@@ -0,0 +1,65 @@
1
+ export declare const schema: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {
7
+ projectPath: {
8
+ type: string;
9
+ description: string;
10
+ };
11
+ browser: {
12
+ type: string;
13
+ default: string;
14
+ description: string;
15
+ };
16
+ level: {
17
+ type: string;
18
+ enum: string[];
19
+ default: string;
20
+ description: string;
21
+ };
22
+ context: {
23
+ type: string;
24
+ items: {
25
+ type: string;
26
+ enum: string[];
27
+ };
28
+ description: string;
29
+ };
30
+ signalsOnly: {
31
+ type: string;
32
+ default: boolean;
33
+ description: string;
34
+ };
35
+ since: {
36
+ type: string;
37
+ description: string;
38
+ };
39
+ url: {
40
+ type: string;
41
+ description: string;
42
+ };
43
+ tab: {
44
+ type: string;
45
+ description: string;
46
+ };
47
+ follow: {
48
+ type: string;
49
+ default: boolean;
50
+ description: string;
51
+ };
52
+ followMs: {
53
+ type: string;
54
+ default: number;
55
+ description: string;
56
+ };
57
+ limit: {
58
+ type: string;
59
+ default: number;
60
+ description: string;
61
+ };
62
+ };
63
+ required: string[];
64
+ };
65
+ };
@@ -1,80 +1,3 @@
1
- export declare const schema: {
2
- name: string;
3
- description: string;
4
- inputSchema: {
5
- type: "object";
6
- properties: {
7
- projectPath: {
8
- type: string;
9
- description: string;
10
- };
11
- browser: {
12
- type: string;
13
- default: string;
14
- description: string;
15
- };
16
- level: {
17
- type: string;
18
- enum: string[];
19
- default: string;
20
- description: string;
21
- };
22
- context: {
23
- type: string;
24
- items: {
25
- type: string;
26
- enum: string[];
27
- };
28
- description: string;
29
- };
30
- signalsOnly: {
31
- type: string;
32
- default: boolean;
33
- description: string;
34
- };
35
- since: {
36
- type: string;
37
- description: string;
38
- };
39
- url: {
40
- type: string;
41
- description: string;
42
- };
43
- tab: {
44
- type: string;
45
- description: string;
46
- };
47
- follow: {
48
- type: string;
49
- default: boolean;
50
- description: string;
51
- };
52
- followMs: {
53
- type: string;
54
- default: number;
55
- description: string;
56
- };
57
- limit: {
58
- type: string;
59
- default: number;
60
- description: string;
61
- };
62
- };
63
- required: string[];
64
- };
65
- };
66
- interface LogsArgs {
67
- projectPath: string;
68
- browser?: string;
69
- level?: string;
70
- context?: string[] | string;
71
- signalsOnly?: boolean;
72
- since?: number;
73
- url?: string;
74
- tab?: number;
75
- follow?: boolean;
76
- followMs?: number;
77
- limit?: number;
78
- }
1
+ import { type LogsArgs } from "./logs-filter";
2
+ export { schema } from "./logs-schema";
79
3
  export declare function handler(args: LogsArgs): Promise<string>;
80
- export {};
@@ -26,6 +26,21 @@ export declare const schema: {
26
26
  };
27
27
  /** Resolve the access token: EXTENSION_DEV_TOKEN env first, then the login creds file. */
28
28
  export declare function resolveToken(): string;
29
+ /**
30
+ * Validate the platform base URL BEFORE we attach a bearer token to a request to
31
+ * it. SECURITY: the `api` arg / EXTENSION_DEV_API_URL is operator-supplied, but a
32
+ * hostile value (e.g. via prompt-injection in the client) could redirect the
33
+ * token to an attacker. The access token must never leave over plaintext or go to
34
+ * an arbitrary scheme, so we require https -- allowing http only for localhost
35
+ * dev. Returns the normalized base (no trailing slash) or an error message.
36
+ */
37
+ export declare function safeApiBase(raw: string): {
38
+ ok: true;
39
+ base: string;
40
+ } | {
41
+ ok: false;
42
+ message: string;
43
+ };
29
44
  export declare function handler(args: {
30
45
  projectPath: string;
31
46
  ttlHours?: number;
@@ -0,0 +1,50 @@
1
+ export declare const schema: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {
7
+ buildId: {
8
+ type: string;
9
+ description: string;
10
+ };
11
+ channel: {
12
+ type: string;
13
+ description: string;
14
+ };
15
+ sourceChannel: {
16
+ type: string;
17
+ description: string;
18
+ };
19
+ browsers: {
20
+ type: string;
21
+ items: {
22
+ type: string;
23
+ };
24
+ description: string;
25
+ };
26
+ version: {
27
+ type: string;
28
+ description: string;
29
+ };
30
+ releaseNotes: {
31
+ type: string;
32
+ description: string;
33
+ };
34
+ api: {
35
+ type: string;
36
+ description: string;
37
+ };
38
+ };
39
+ required: string[];
40
+ };
41
+ };
42
+ export declare function handler(args: {
43
+ buildId: string;
44
+ channel: string;
45
+ sourceChannel?: string;
46
+ browsers?: string[];
47
+ version?: string;
48
+ releaseNotes?: string;
49
+ api?: string;
50
+ }): Promise<string>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@extension.dev/mcp",
3
3
  "type": "module",
4
- "version": "3.17.0",
4
+ "version": "4.0.8",
5
5
  "description": "MCP server that lets AI agents build, run, inspect, and publish browser extensions. 26 tools for scaffolding, live DOM inspection, log streaming, and store-ready builds across Chrome, Edge, and Firefox.",
6
6
  "license": "MIT",
7
7
  "author": {
@@ -20,7 +20,6 @@
20
20
  "engines": {
21
21
  "node": ">=20.18"
22
22
  },
23
- "packageManager": "pnpm@10.19.0",
24
23
  "exports": {
25
24
  ".": {
26
25
  "types": "./dist/module.d.ts",
@@ -40,15 +39,6 @@
40
39
  "CHANGELOG.md",
41
40
  "LICENSE"
42
41
  ],
43
- "scripts": {
44
- "clean": "rm -rf dist",
45
- "watch": "rslib build --watch",
46
- "compile": "rslib build",
47
- "build": "pnpm run compile",
48
- "start": "node bin/extension-mcp.js",
49
- "test": "vitest run",
50
- "prepublishOnly": "pnpm run test && pnpm run compile"
51
- },
52
42
  "publishConfig": {
53
43
  "access": "public",
54
44
  "registry": "https://registry.npmjs.org"
@@ -73,9 +63,11 @@
73
63
  ],
74
64
  "dependencies": {
75
65
  "@modelcontextprotocol/sdk": "^1.12.1",
76
- "extension-create": "^3.13.5",
77
- "extension-develop": "^3.13.5",
78
- "extension-install": "^3.13.5",
66
+ "browser-extension-manifest-fields": "^2.2.9",
67
+ "cross-spawn": "^7.0.6",
68
+ "extension-create": "^4.0.8",
69
+ "extension-develop": "^4.0.8",
70
+ "extension-install": "^4.0.8",
79
71
  "ws": "^8.20.0"
80
72
  },
81
73
  "devDependencies": {
@@ -84,5 +76,13 @@
84
76
  "@types/ws": "^8.18.1",
85
77
  "typescript": "6.0.2",
86
78
  "vitest": "^4.1.3"
79
+ },
80
+ "scripts": {
81
+ "clean": "rm -rf dist",
82
+ "watch": "rslib build --watch",
83
+ "compile": "rslib build",
84
+ "build": "pnpm run compile",
85
+ "start": "node bin/extension-mcp.js",
86
+ "test": "vitest run"
87
87
  }
88
- }
88
+ }