@extension.dev/mcp 9.0.0 → 10.1.0

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.
@@ -9,8 +9,8 @@
9
9
  {
10
10
  "name": "extension-mcp",
11
11
  "source": "./",
12
- "description": "MCP tools for browser extension development: scaffold from 60+ templates, run the dev server with HMR, inspect the live DOM and logs, and publish store-ready builds for Chrome, Edge, and Firefox.",
13
- "version": "9.0.0",
12
+ "description": "MCP tools for browser extension development: scaffold from 50+ templates, run the dev server with HMR, inspect the live DOM and logs, and publish store-ready builds for Chrome, Edge, and Firefox.",
13
+ "version": "10.1.0",
14
14
  "category": "development",
15
15
  "author": {
16
16
  "name": "Cezar Augusto"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "extension-mcp",
3
- "description": "MCP tools for browser extension development: scaffold from 60+ templates, run the dev server with HMR, inspect the live DOM and logs, and publish store-ready builds for Chrome, Edge, and Firefox. Ships /extension, /extension-add, /extension-debug, and /extension-publish commands.",
4
- "version": "9.0.0",
3
+ "description": "MCP tools for browser extension development: scaffold from 50+ templates, run the dev server with HMR, inspect the live DOM and logs, and publish store-ready builds for Chrome, Edge, and Firefox. Ships /extension, /extension-add, /extension-debug, and /extension-publish commands.",
4
+ "version": "10.1.0",
5
5
  "author": {
6
6
  "name": "Cezar Augusto",
7
7
  "email": "hello@extension.dev",
package/CHANGELOG.md CHANGED
@@ -1,5 +1,112 @@
1
1
  # Changelog
2
2
 
3
+ ## 10.1.0
4
+
5
+ A six-lens audit of the whole surface (auth, platform, run, see, act and
6
+ build, plumbing) followed by a fix pass over everything it confirmed. 33
7
+ fixes, the ones you would notice first:
8
+
9
+ - A failed spawn of the dev CLI (npx missing from PATH) no longer crashes
10
+ the whole MCP server; it fails that one call with guidance.
11
+ - `extension_wait` now ignores ready contracts stamped before the current
12
+ session, so a leftover file from a crashed run can no longer report the
13
+ previous session's compile error as yours.
14
+ - `extension_create` never deletes a directory it did not create: the
15
+ transient-failure cleanup used to wipe pre-existing directories, including
16
+ their `.git`, when scaffolding into one.
17
+ - `extension_submit` dry runs are platform-primary: a platform-reported
18
+ preflight failure can no longer be overwritten by locally computed store
19
+ health, and token-only CI callers no longer fail the dry run for lacking a
20
+ local credentials file. The tool also gained a `projectPath` input so the
21
+ STORE.md advisory check reads the project, not the server's cwd.
22
+ - `manifest.json` with `world: "MAIN"` no longer fails Firefox validation:
23
+ Firefox has supported the MAIN world since 128. The rule is now a
24
+ strict_min_version advisory.
25
+ - Device login reports hard server errors as errors, on both the tool and
26
+ the CLI paths, instead of authorization-pending or a bogus timeout; the
27
+ login flow now enforces the same cleartext-http refusal as every other
28
+ token-bearing path, validates the returned project scope before storing
29
+ credentials, and the CLI prints the one-click approval link.
30
+ - `extension_publish` with a pinned buildSha no longer fills the response
31
+ with a different build's metadata when the pin is not in the local index.
32
+ - `extension_shares` no longer labels your own expired shares as "not owned
33
+ by this token" when listing with `status: "live"`, and revocation is only
34
+ reported permanent when the platform confirmed it.
35
+ - `extension_logs` accepts the `newtab`, `history`, and `bookmarks`
36
+ contexts, `level: "off"` silences console output instead of returning all
37
+ of it, and a stream error mid-follow returns what was collected instead
38
+ of discarding it.
39
+ - `extension_stop` and session bookkeeping survive an MCP restart: session
40
+ markers are cleaned when a session exits on its own, single-project stop
41
+ consults the same on-disk markers as `all: true`, orphan reaping escapes
42
+ regex metachars in project paths and only kills plausible session
43
+ processes, and a replaced session can no longer unregister its successor.
44
+ - `extension_open` trusts the live browser over the computed id hash when
45
+ they disagree (symlinked dist paths), so it no longer navigates to a
46
+ nonexistent extension id and no longer reports a successfully opened
47
+ surface as a failure.
48
+ - Offline first runs work: the bundled template catalog snapshot is now the
49
+ fallback when the network and cache are both unavailable, a corrupted
50
+ cache file heals instead of erroring, and a shapeless 200 response is no
51
+ longer cached for an hour.
52
+ - `extension-mcp --help`, `--version`, and unknown commands now answer
53
+ instead of silently starting a stdio server.
54
+ - The release pipeline bumps the version before building, so the published
55
+ bundle reports the version it ships as, with an assertion gating publish
56
+ on it and on the type declarations existing.
57
+ - Docs and drop-ins caught up with the code: template count corrected to
58
+ 50+, the AI template slugs are `ai-claude` and `ai-chatgpt`, Firefox
59
+ support noted for `extension_list_extensions` and Safari for
60
+ `extension_submit`, and the `extension_dom_snapshot` description names
61
+ which subpaths need the debug port.
62
+
63
+ ## 10.0.0
64
+
65
+ Every tool now returns the same frame. Before this, 28 tools hand-built 142
66
+ different JSON shapes: `ok` appeared on 71 of them, `error` on 67, `hint` on 60,
67
+ `message` on 49, `status` on 46, and five more keys carried the same meaning
68
+ under different names. An agent could not tell success from failure without
69
+ knowing which tool it had called.
70
+
71
+ The frame is schema 1, the same one the Extension.js CLI emits under
72
+ `--output json`:
73
+
74
+ ```json
75
+ {
76
+ "schema": 1,
77
+ "ok": false,
78
+ "command": "extension_dev",
79
+ "status": "compile-failed",
80
+ "value": null,
81
+ "error": { "code": "E_FIRST_COMPILE", "message": "…" },
82
+ "hint": "…",
83
+ "warnings": []
84
+ }
85
+ ```
86
+
87
+ `command` names the tool. `status` is a kebab-case word from that tool's own
88
+ vocabulary. `error.code` is stable and worth branching on; `error.message` is
89
+ free copy and is not. The payload moved under `value`, and every advisory note
90
+ that used to have its own key is now an entry in `warnings`.
91
+
92
+ **Breaking.** Every payload key moved one level down. `build.success` is now
93
+ `ok`, `doctor.healthy` is now `ok`, `manifest_validate.valid` is now
94
+ `value.valid`, and `wait` gained the `ok` it never had. The ready contract's own
95
+ `command` is carried as `value.sessionCommand`, because the envelope claims that
96
+ key. `authorization_pending` became `authorization-pending`, with the old
97
+ spelling echoed as `value.legacyStatus` for one minor.
98
+
99
+ `extension_dev` and `extension_start` also stopped reading the dev server's
100
+ prose to decide whether the first compile failed. They poll its `ready.json`
101
+ contract instead, which splits a locked profile out of a dead browser and
102
+ returns the compile errors as a list. The output scrape survives only as a
103
+ fallback for a project whose own CLI predates the contract, is confined to one
104
+ `@deprecated` module, and says so in `warnings` whenever it is used. The choice
105
+ is a capability probe, never a version check: a project-local `extension` binary
106
+ wins over this package's pin, so the version is not knowable in advance. The
107
+ contract's own error stamps are read whatever the engine's age, so a locked
108
+ profile is named as one the moment the engine records it.
109
+
3
110
  ## 9.0.0
4
111
 
5
112
  Every client pays for this server's tool list at the start of every session,
package/README.md CHANGED
@@ -25,7 +25,7 @@ Extensions fail silently: content scripts that never inject, panels that never o
25
25
 
26
26
  These tools give agents eyes on the live browser, so they debug from evidence instead of guessing:
27
27
 
28
- - **Scaffold** from the 60+ template catalog behind [templates.extension.dev](https://templates.extension.dev), or add a popup, sidebar, or content script to an existing project
28
+ - **Scaffold** from the 50+ template catalog behind [templates.extension.dev](https://templates.extension.dev), or add a popup, sidebar, or content script to an existing project
29
29
  - **Run** the dev server with HMR in Chrome, Edge, Firefox, Brave, Opera, Vivaldi, Yandex, Waterfox, LibreWolf, or any Chromium- or Gecko-based binary, plus Safari on macOS (no HMR yet), no build config
30
30
  - **See** the live DOM, unified logs from every extension context, `chrome.storage` contents, and the loaded-extension list
31
31
  - **Act**: evaluate code in any context, trigger the action button and commands, reload the extension, replay events
@@ -102,7 +102,7 @@ cp node_modules/@extension.dev/mcp/claude/commands/*.md ~/my-extension/.claude/c
102
102
  | Tier | Tool | Description |
103
103
  | ---- | ---- | ----------- |
104
104
  | build | `extension_create` | Scaffold from a template |
105
- | build | `extension_templates` | Browse 60+ templates (`list`) and read one's source (`source`) |
105
+ | build | `extension_templates` | Browse 50+ templates (`list`) and read one's source (`source`) |
106
106
  | build | `extension_add_feature` | Add sidebar/popup/content script |
107
107
  | build | `extension_build` | Build for production |
108
108
  | run | `extension_dev` | Dev server with HMR |
@@ -112,8 +112,8 @@ cp node_modules/@extension.dev/mcp/claude/commands/*.md ~/my-extension/.claude/c
112
112
  | see | `extension_manifest_validate` | Cross-browser manifest validation |
113
113
  | see | `extension_analyze` | Static analysis of the built extension on disk |
114
114
  | see | `extension_inspect` | Deep live inspection of a running extension (closed shadow roots, probes) |
115
- | see | `extension_dom_snapshot` | Shallow DOM snapshot of a chosen tab or extension surface, CDP-free |
116
- | see | `extension_list_extensions` | List loaded extensions (Chromium) |
115
+ | see | `extension_dom_snapshot` | Shallow DOM snapshot of a chosen tab or extension surface over the agent bridge |
116
+ | see | `extension_list_extensions` | List loaded extensions (Chromium and Firefox) |
117
117
  | see | `extension_logs` | Stream logs from every context |
118
118
  | see | `extension_doctor` | Diagnose the dev session leg by leg (ready contract, ports, token, executor, browser) |
119
119
  | see | `extension_theme_verify` | Verify a Chrome theme manifest against the colors Chrome actually paints |
@@ -142,7 +142,7 @@ That is a different job from shipping. Use `share` for the build you are holding
142
142
 
143
143
  ## From preview to store
144
144
 
145
- The platform tools connect agents to [extension.dev](https://extension.dev): `extension_auth` runs extension.dev's own device flow (you approve the code at [extension.dev/device](https://extension.dev/device), and GitHub is federated server-side, so no GitHub token ever reaches your machine) and stores a project-scoped token locally (never returned to the agent), `extension_publish` turns a build your project has already published into a shareable URL, and `extension_release_promote` promotes a tested build to a release channel from CI or an agent session, no browser required. `extension_submit` submits a built extension to the Chrome Web Store, Edge Add-ons, and Firefox AMO through extension.dev, which holds your store credentials and dispatches the release from your project's mirror CI, it defaults to a dry run and store credentials are never tool arguments. The two verbs are not interchangeable: `extension_publish` pushes to the extension.dev platform, `extension_submit` sends the build into a store's review queue, which is irreversible. After a real submission, `extension_release_status` reads the recorded outcome, per-store credential health, and review state from the project's public registry, so agents and CI can answer "was it approved?" without a console visit. Access tokens live at most 7 days; CI pipelines re-mint them from the console's Access tokens page.
145
+ The platform tools connect agents to [extension.dev](https://extension.dev): `extension_auth` runs extension.dev's own device flow (you approve the code at [extension.dev/device](https://extension.dev/device), and GitHub is federated server-side, so no GitHub token ever reaches your machine) and stores a project-scoped token locally (never returned to the agent), `extension_publish` turns a build your project has already published into a shareable URL, and `extension_release_promote` promotes a tested build to a release channel from CI or an agent session, no browser required. `extension_submit` submits a built extension to the Chrome Web Store, Edge Add-ons, Firefox AMO, and the App Store for Safari through extension.dev, which holds your store credentials and dispatches the release from your project's mirror CI, it defaults to a dry run and store credentials are never tool arguments. The two verbs are not interchangeable: `extension_publish` pushes to the extension.dev platform, `extension_submit` sends the build into a store's review queue, which is irreversible. After a real submission, `extension_release_status` reads the recorded outcome, per-store credential health, and review state from the project's public registry, so agents and CI can answer "was it approved?" without a console visit. Access tokens live at most 7 days; CI pipelines re-mint them from the console's Access tokens page.
146
146
 
147
147
  ## The extension.dev stack
148
148
 
@@ -7,17 +7,39 @@
7
7
  // ╚═╝ ╚═╝ ╚═════╝╚═╝
8
8
  // Apache License 2.0 (c) 2026 Cezar Augusto and the extension.dev collaborators
9
9
 
10
+ import {createRequire} from 'node:module'
10
11
  import {startServer, runCli} from '../dist/module.js'
11
12
 
13
+ const require = createRequire(import.meta.url)
14
+ const {version} = require('../package.json')
15
+
16
+ const usage = `@extension.dev/mcp ${version}
17
+
18
+ Usage:
19
+ extension-mcp Start the MCP server on stdio
20
+ extension-mcp login [flags] Device login at extension.dev
21
+ extension-mcp logout Remove the stored credentials
22
+ extension-mcp whoami Show the stored identity
23
+ extension-mcp release [...] Headless release commands
24
+ extension-mcp --version Print the version
25
+ `
26
+
12
27
  const [, , cmd, ...rest] = process.argv
13
28
 
14
- if (cmd && ['login', 'logout', 'whoami', 'release'].includes(cmd)) {
29
+ if (cmd === undefined) {
30
+ startServer()
31
+ } else if (['login', 'logout', 'whoami', 'release'].includes(cmd)) {
15
32
  runCli(cmd, rest)
16
33
  .then((code) => process.exit(code))
17
34
  .catch((err) => {
18
35
  process.stderr.write(`${err?.message || String(err)}\n`)
19
36
  process.exit(1)
20
37
  })
38
+ } else if (['--version', '-v'].includes(cmd)) {
39
+ process.stdout.write(`${version}\n`)
40
+ } else if (['--help', '-h', 'help'].includes(cmd)) {
41
+ process.stdout.write(usage)
21
42
  } else {
22
- startServer()
43
+ process.stderr.write(`Unknown command "${cmd}"\n\n${usage}`)
44
+ process.exit(1)
23
45
  }
@@ -7,7 +7,7 @@ This document explains how the three Claude integration layers (the template, th
7
7
  ```
8
8
  examples repo (GitHub)
9
9
  │
10
- ├── examples/<slug>/ 60+ extension templates
10
+ ├── examples/<slug>/ 50+ extension templates
11
11
  │ ├── src/manifest.json Source of truth per template
12
12
  │ ├── template.meta.json Curated metadata (tags, difficulty, useCases, AI fields)
13
13
  │ └── ...
package/claude/CLAUDE.md CHANGED
@@ -11,7 +11,7 @@ You are working on a browser extension project built with the [extension.dev](ht
11
11
 
12
12
  ## Template catalog
13
13
 
14
- The extension.dev platform ships 60+ templates in the [examples](https://github.com/extension-js/examples) repo. The canonical registry is `templates-meta.json` published as a GitHub release asset and committed to the repo.
14
+ The extension.dev platform ships 50+ templates in the [examples](https://github.com/extension-js/examples) repo. The canonical registry is `templates-meta.json` published as a GitHub release asset and committed to the repo.
15
15
 
16
16
  **How templates work:**
17
17
 
@@ -24,8 +24,8 @@ The extension.dev platform ships 60+ templates in the [examples](https://github.
24
24
  | Surface | Vanilla | React | Vue | Svelte | AI |
25
25
  | -------------- | ------------ | ---------------- | ------------- | ---------------- | ---------------- |
26
26
  | Content script | `content` | `content-react` | `content-vue` | `content-svelte` | n/a |
27
- | Sidebar | `sidebar` | `sidebar-shadcn` | n/a |, | `sidebar-claude` |
28
- | Action popup | `action` | n/a |, | n/a | `action-chatgpt` |
27
+ | Sidebar | `sidebar` | `sidebar-shadcn` | n/a | n/a | `ai-claude` |
28
+ | Action popup | `action` | n/a | n/a | n/a | `ai-chatgpt` |
29
29
  | New tab | `new` | `new-react` | `new-vue` | `new-svelte` | n/a |
30
30
  | Full framework | `javascript` | `react` | `vue` | `svelte` | n/a |
31
31
 
@@ -34,7 +34,7 @@ The extension.dev platform ships 60+ templates in the [examples](https://github.
34
34
  1. Match the user's desired surface (sidebar, content script, popup, etc.)
35
35
  2. Match their framework preference
36
36
  3. Prefer `featured: true` templates for common use cases
37
- 4. For AI-powered extensions, start from `sidebar-claude` or `action-chatgpt`
37
+ 4. For AI-powered extensions, start from `ai-claude` or `ai-chatgpt`
38
38
 
39
39
  **To browse all available templates:**
40
40
 
@@ -146,7 +146,7 @@ export default {
146
146
 
147
147
  ## Important gotchas
148
148
 
149
- 1. **world: "MAIN" is Chromium-only.** If your content script uses `"world": "MAIN"`, prefix it with `chromium:` and provide a Firefox fallback or skip.
149
+ 1. **world: "MAIN" needs Firefox 128+.** Chromium and current Firefox both support it; only when targeting Firefox older than 128 prefix it with `chromium:` and provide a fallback.
150
150
  2. **Side panels vs sidebar actions.** Chromium uses `side_panel` + `sidePanel` permission. Firefox uses `sidebar_action` (no permission needed).
151
151
  3. **Service workers vs background scripts.** Chromium uses `service_worker` (single file). Firefox uses `scripts` (array).
152
152
  4. **Environment variables.** Use `EXTENSION_PUBLIC_*` prefix for variables accessible in extension code. `import.meta.env.EXTENSION_PUBLIC_BROWSER` gives the current browser.
@@ -49,7 +49,9 @@ if (isFirefoxLike) {
49
49
 
50
50
  ## Content scripts with world: "MAIN"
51
51
 
52
- `world: "MAIN"` only works on Chromium. Must be prefixed:
52
+ `world: "MAIN"` works on Chromium and on Firefox 128 or newer. Only when
53
+ supporting Firefox older than 128, prefix it so those versions fall back to
54
+ the isolated world:
53
55
 
54
56
  ```json
55
57
  {
@@ -63,7 +65,7 @@ if (isFirefoxLike) {
63
65
  }
64
66
  ```
65
67
 
66
- Firefox will ignore the `chromium:world` field and run in the default isolated world.
68
+ Older Firefox ignores the `chromium:world` field and runs in the default isolated world.
67
69
 
68
70
  ## API differences
69
71
 
@@ -19,7 +19,7 @@ This file contains structured metadata for every template: surfaces, framework,
19
19
  **How `extension create` resolves templates today:**
20
20
 
21
21
  ```
22
- User: npx extension create my-ext --template=sidebar-claude
22
+ User: npx extension create my-ext --template=ai-claude
23
23
  │
24
24
  ▼
25
25
  programs/create/steps/import-external-template.ts
@@ -64,7 +64,7 @@ These map directly to existing programmatic APIs and provide immediate value.
64
64
  "template": {
65
65
  "type": "string",
66
66
  "default": "typescript",
67
- "description": "Template slug from the extension.dev template catalog (e.g. 'react', 'sidebar-claude', 'content-vue'). Use extension_templates to discover options."
67
+ "description": "Template slug from the extension.dev template catalog (e.g. 'react', 'ai-claude', 'content-vue'). Use extension_templates to discover options."
68
68
  },
69
69
  "install": {
70
70
  "type": "boolean",
@@ -154,7 +154,7 @@ These map directly to existing programmatic APIs and provide immediate value.
154
154
  ```json
155
155
  {
156
156
  "name": "extension_build",
157
- "description": "Build a browser extension for production. Outputs to dist/<browser>/. Optionally creates .zip for store submission.",
157
+ "description": "Build a browser extension for production. The output lands in dist/<browser>/. Pass zip:true to also package a .zip for store submission. The build refuses a manifest with build-blocking errors unless you pass skipValidation:true, because such a manifest yields a broken bundle the bundler itself never flags.",
158
158
  "inputSchema": {
159
159
  "type": "object",
160
160
  "properties": {
@@ -345,7 +345,7 @@ These combine extension.dev knowledge with the examples repo to make Claude _sma
345
345
  "properties": {
346
346
  "slug": {
347
347
  "type": "string",
348
- "description": "Template slug (e.g. 'sidebar-claude', 'content-react')"
348
+ "description": "Template slug (e.g. 'ai-claude', 'content-react')"
349
349
  },
350
350
  "files": {
351
351
  "type": "array",
@@ -610,22 +610,34 @@ The `similarTemplates` field lists templates from the catalog with similar surfa
610
610
  }
611
611
  ```
612
612
 
613
- **Returns:** The `ready.json` contract:
613
+ **Returns:** The schema-1 envelope, carrying the `ready.json` contract under `value`:
614
614
 
615
615
  ```json
616
616
  {
617
+ "schema": 1,
618
+ "ok": true,
619
+ "command": "extension_wait",
617
620
  "status": "ready",
618
- "command": "dev",
619
- "browser": "chrome",
620
- "port": 8080,
621
- "pid": 12345,
622
- "distPath": "/path/to/dist/chrome",
623
- "manifestPath": "/path/to/dist/chrome/manifest.json",
624
- "compiledAt": "2026-04-14T10:30:00.000Z",
625
- "startedAt": "2026-04-14T10:29:55.000Z"
621
+ "value": {
622
+ "compiled": true,
623
+ "browserAttached": true,
624
+ "sessionCommand": "dev",
625
+ "browser": "chrome",
626
+ "port": 8080,
627
+ "pid": 12345,
628
+ "distPath": "/path/to/dist/chrome",
629
+ "manifestPath": "/path/to/dist/chrome/manifest.json",
630
+ "compiledAt": "2026-04-14T10:30:00.000Z",
631
+ "startedAt": "2026-04-14T10:29:55.000Z"
632
+ },
633
+ "error": null,
634
+ "warnings": []
626
635
  }
627
636
  ```
628
637
 
638
+ The envelope's `command` names the tool, so the ready contract's own `command`
639
+ is carried as `value.sessionCommand`.
640
+
629
641
  **Why this matters for MCP:** When Claude starts a dev session via `extension_dev`, it needs to know when the extension is actually loaded and ready before calling `extension_inspect`. This tool provides that gate.
630
642
 
631
643
  ---
@@ -880,7 +892,7 @@ const CURATED_ALLOWED_KEYS = [
880
892
  ];
881
893
  ```
882
894
 
883
- **Example for `sidebar-claude/template.meta.json`:**
895
+ **Example for `ai-claude/template.meta.json`:**
884
896
 
885
897
  ```json
886
898
  {
@@ -930,7 +942,7 @@ These fields enable `extension_templates` to match user intent ("I want to build
930
942
  5. Extract browser detection into `extensionDetectBrowsers()` in `programs/extension`
931
943
  6. Extract wait mode into `extensionWait()` in `programs/extension`
932
944
  7. Add AI metadata fields to `CURATED_ALLOWED_KEYS` in `generate-templates-meta.mjs`
933
- 8. Populate `template.meta.json` with AI fields for key templates (sidebar-claude, action-chatgpt, sidebar-transformers-js)
945
+ 8. Populate `template.meta.json` with AI fields for key templates (ai-claude, ai-chatgpt, sidebar-transformers-js)
934
946
 
935
947
  ### Phase 2: MCP Server package
936
948