@extension.dev/mcp 6.3.0 → 6.5.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.
Files changed (33) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +105 -18
  4. package/README.md +15 -2
  5. package/bin/extension-mcp.js +1 -0
  6. package/dist/module.js +3942 -2053
  7. package/dist/src/lib/artifacts-api.d.ts +56 -0
  8. package/dist/src/lib/carrier.d.ts +0 -57
  9. package/dist/src/lib/credentials.d.ts +0 -9
  10. package/dist/src/lib/device-flow.d.ts +0 -6
  11. package/dist/src/lib/github-device.d.ts +0 -9
  12. package/dist/src/lib/guest-load-oracle.d.ts +0 -10
  13. package/dist/src/lib/login-flow.d.ts +0 -36
  14. package/dist/src/lib/preview-upload.d.ts +33 -0
  15. package/dist/src/lib/project-ignore.d.ts +10 -0
  16. package/dist/src/lib/publish.d.ts +0 -10
  17. package/dist/src/lib/registry-access.d.ts +3 -19
  18. package/dist/src/lib/registry.d.ts +0 -65
  19. package/dist/src/lib/share-record.d.ts +33 -0
  20. package/dist/src/lib/vendor/chrome-theme/chrome-theme-color-math.d.ts +84 -0
  21. package/dist/src/lib/vendor/chrome-theme/chrome-theme-reference.d.ts +270 -0
  22. package/dist/src/lib/vendor/chrome-theme/chrome-theme-resolve.d.ts +52 -0
  23. package/dist/src/tools/open.d.ts +1 -0
  24. package/dist/src/tools/preview-web.d.ts +76 -0
  25. package/dist/src/tools/shares.d.ts +51 -0
  26. package/dist/src/tools/stop.d.ts +0 -1
  27. package/dist/src/tools/store-status.d.ts +0 -9
  28. package/dist/src/tools/theme-verify.d.ts +22 -0
  29. package/extensions/live-preview/chromium/action/index.js +9 -1
  30. package/extensions/live-preview/chromium/background/service_worker.js +10 -2
  31. package/extensions/live-preview/chromium/manifest.json +1 -0
  32. package/package.json +2 -2
  33. package/server.json +3 -3
@@ -10,7 +10,7 @@
10
10
  "name": "extension-mcp",
11
11
  "source": "./",
12
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": "6.3.0",
13
+ "version": "6.5.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
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": "6.3.0",
4
+ "version": "6.5.0",
5
5
  "author": {
6
6
  "name": "Cezar Augusto",
7
7
  "email": "hello@extension.dev",
package/CHANGELOG.md CHANGED
@@ -1,28 +1,115 @@
1
1
  # Changelog
2
2
 
3
- ## 6.4.0
3
+ ## 6.5.0
4
+
5
+ A link you shared is no longer only as findable as the response that created
6
+ it. The shares you have made are now listable, and revocable, from the tool
7
+ that made them.
8
+
9
+ ### Added
4
10
 
5
- A build on your machine can now become a link someone else can open.
11
+ - **`extension_shares` lists and revokes the links you have shared.**
12
+ `share:true` hands back a public link, an `expiresAt` and a `revokeUrl`, and
13
+ until now the only copy of that `revokeUrl` was the tool response and the
14
+ project's own `.extension.dev/shared-previews.json`. Neither could say what
15
+ was actually still live, and neither existed at all for a link shared from
16
+ another machine. `action:"list"` (the default) asks the platform for every
17
+ artifact the logged-in project owns and returns each one's `artifactId`,
18
+ name, version, live or dead state, `createdAt`, `expiresAt`, `revokedAt`,
19
+ size, and its `previewUrl`, `zipUrl` and `revokeUrl`. `previewUrl` and
20
+ `zipUrl` come back null for anything no longer live, because a revoked or
21
+ expired address resolves for nobody and echoing it back would invite passing
22
+ on a dead link; `revokeUrl` stays on every row.
23
+ - **`action:"revoke"` kills a link from where it was made.** It takes an
24
+ `artifactId` or, just as well, any URL of the share (`previewUrl`, `zipUrl`,
25
+ `viewUrl`, or `revokeUrl`), so the link you sent someone is enough to pull it
26
+ back without going to find a `curl` command. Revocation is permanent: the zip
27
+ is deleted and the id is burned, so a revoked link can never resolve again
28
+ and sharing the same build later mints a different one. The response says so
29
+ rather than reading like an undoable delete.
30
+ - **The platform's answer is reconciled with the project's record.** Pass
31
+ `projectPath` and every listed share is matched against
32
+ `.extension.dev/shared-previews.json`: a share the project recorded carries
33
+ its local `sharedAt`, `browser` and `distDir`, a share the platform knows
34
+ about but the project does not is flagged `remoteOnly` (shared from another
35
+ machine or another checkout), and a local record with no artifact behind it
36
+ is reported under `localOnly`. The tool only ever reads that file, never
37
+ rewrites it, so its append-only history stays intact.
38
+ - **A cut list is never passed off as the whole set.** When the platform
39
+ answers `truncated:true`, the response carries the count that came back
40
+ against the count that matched, says to raise `limit` or narrow with
41
+ `status:"live"`, and refuses to call a `localOnly` record dead, because a
42
+ share missing from a truncated list has not been shown to be gone.
6
43
 
7
44
  ### Changed
8
45
 
9
- - **`extension_preview_web` with `share:true` uploads the build you just
10
- made.** It used to route sharing through `extension_publish`, which takes no
11
- project path and uploads nothing: it flips a share link on whatever build the
12
- token's project last pushed from its own CI. So the link rendered a different
13
- build than the one on disk, and said so in a caveat. It now POSTs the resolved
14
- `dist/<browser>` to the platform's artifact store and returns a
46
+ - **A successful share now says where to find the link again.** The `share`
47
+ note and the `extension_preview_web` tool description both point at
48
+ `extension_shares`, at the moment the link exists and the question of how to
49
+ reach it later is about to come up.
50
+
51
+ ## 6.4.0
52
+
53
+ A build on your machine can now become a link someone else can open, and the
54
+ bundled Live Preview carrier finally allows the origin that opens it.
55
+
56
+ ### Added
57
+
58
+ - **`extension_preview_web` renders an in-progress build in the web emulator.**
59
+ It builds the project, points `preview.extension.dev` at `dist/<browser>` over
60
+ the dev-only `preview://build` scheme, and returns a deep link plus a
61
+ loadability check against the preview dev server. `surface:"inspect"` renders
62
+ in `inspect.extension.dev` instead, for fixture and forensic work. This tool
63
+ reaches npm for the first time in this release.
64
+ - **`share:true` uploads the build you just made.** It POSTs the resolved
65
+ `dist/<browser>` to the platform's artifact store and returns a public
15
66
  `preview.extension.dev` link that renders those exact bytes, for a recipient
16
- with no install, no sign-in, and no dev server. `share.serves` reports
17
- `uploaded-local-build`; the `requiredBackend` spec that described this as
18
- missing is gone because it is built.
19
- - `share` now returns `expiresAt` and `revokeUrl`. Shared builds expire, and
20
- `DELETE`ing `revokeUrl` with the same token kills the link immediately, which
21
- is the part a TTL alone cannot do when a link reaches the wrong person.
22
- - The `channel` argument is removed from `extension_preview_web`. It only ever
23
- selected which promoted CI build to render, and this tool no longer renders
24
- promoted builds. `extension_publish` and `extension_release_promote` are
25
- unchanged and remain the path for released, channel-scoped builds.
67
+ with no install, no sign-in, and no dev server. That link also serves the
68
+ whole build as a downloadable zip (`share.zipUrl`), so sharing it hands over
69
+ the built code. `share.serves` reports `uploaded-local-build`. Sharing needs a
70
+ token scoped to an existing extension.dev workspace and project
71
+ (`extension_login` or `EXTENSION_DEV_TOKEN`, valid up to 7 days), degrades to
72
+ a login hint when there is no token, and never fails the local preview.
73
+ `share` also returns `expiresAt` and `revokeUrl`: shared builds expire, and
74
+ `DELETE`ing `revokeUrl` with the same token kills the link for good, which is
75
+ the part a TTL alone cannot do when a link reaches the wrong person.
76
+ - **A shared link's revoke handle survives losing the tool output.** Revocation
77
+ is permanent and re-sharing mints a new artifact id, so `share.revokeUrl` is
78
+ the only handle that can ever pull a given link, and losing it used to mean
79
+ waiting out the 30-day TTL. Every successful share is now appended to
80
+ `.extension.dev/shared-previews.json` in the project, next to the carrier's
81
+ own project-local state and gitignored the same way: one entry per share with
82
+ `previewUrl`, `artifactId`, `revokeUrl`, `expiresAt`, `zipUrl` and the time it
83
+ was shared. The list is only ever appended to, an unreadable file is kept
84
+ aside instead of overwritten, a write that fails never fails the share, and
85
+ the returned `share.record` and note say where the handle went. If the entry
86
+ cannot be added to `.gitignore`, the response says so.
87
+ - **`extension_theme_verify` settles a Chrome theme manifest before it ships.**
88
+ It derives every color current Chrome would paint from the manifest with a
89
+ transcribed Chromium resolver and reports the divergence class of any problem:
90
+ D1 fabrication, D3 parity gap, D4 acceptance gap (keys Chrome silently
91
+ discards, such as dead legacy keys, incognito keys, unknown keys and
92
+ out-of-range values). The legs that need a real browser come back as
93
+ `needsAttended` with a pointer to the attended harnesses, never as passed.
94
+
95
+ ### Fixed
96
+
97
+ - **The bundled Live Preview carrier reaches `preview.extension.dev`.** This
98
+ package ships the carrier prebuilt and `extension_dev` materializes it into
99
+ the project's `./extensions`, so the carrier only changes when the package
100
+ does. Its `externally_connectable` allowlist had no web preview origin, so a
101
+ page on `preview.extension.dev` could not talk to the carrier at all. 6.3.0
102
+ shipped without the fix.
103
+ - The carrier popup requested `icons/icon.png` while the carrier build ships
104
+ `images/icon.png`, so the popup icon was broken.
105
+
106
+ ### Changed
107
+
108
+ - `extension_preview_web` takes no `channel` argument. It renders the build on
109
+ disk, not a promoted CI build. `extension_publish` and
110
+ `extension_release_promote` are unchanged and remain the path for released,
111
+ channel-scoped builds.
112
+ - The server advertises 35 tools, up from 33.
26
113
 
27
114
  ## 6.3.0
28
115
 
package/README.md CHANGED
@@ -5,9 +5,11 @@
5
5
  [discord-image]: https://img.shields.io/discord/1253608412890271755?label=Discord&logo=discord&style=flat&color=26FFB8
6
6
  [discord-url]: https://discord.gg/v9h2RgeTSN
7
7
 
8
+ <img alt="@extension.dev/mcp" src="https://media.extension.land/brand/repos/mcp/github-banner.png" />
9
+
8
10
  # @extension.dev/mcp [![Version][npm-version-image]][npm-version-url] [![Downloads][npm-downloads-image]][npm-downloads-url] [![Discord][discord-image]][discord-url]
9
11
 
10
- > Give your AI agent hands for browser extension development. 33 MCP tools that scaffold, run, inspect, debug, and publish cross-browser extensions.
12
+ > Give your AI agent hands for browser extension development. 35 MCP tools that scaffold, run, inspect, debug, and publish cross-browser extensions.
11
13
 
12
14
  <img alt="Logo" align="right" src="https://media.extension.land/brand/extension-dev/logo-dock.png" width="20.7%" />
13
15
 
@@ -118,6 +120,7 @@ cp node_modules/@extension.dev/mcp/claude/commands/*.md ~/my-extension/.claude/c
118
120
  | see | `extension_list_extensions` | List loaded extensions (Chromium) |
119
121
  | see | `extension_logs` | Stream logs from every context |
120
122
  | see | `extension_doctor` | Diagnose the dev session leg by leg (ready contract, ports, token, executor, browser) |
123
+ | see | `extension_theme_verify` | Verify a Chrome theme manifest against the colors Chrome actually paints |
121
124
  | act | `extension_eval` | Evaluate in a context (needs `allowEval: true` on `extension_dev`) |
122
125
  | act | `extension_storage` | Read/write `chrome.storage` |
123
126
  | act | `extension_reload` | Reload extension or tab |
@@ -129,15 +132,25 @@ cp node_modules/@extension.dev/mcp/claude/commands/*.md ~/my-extension/.claude/c
129
132
  | platform | `extension_login` | GitHub device-code login, stored token |
130
133
  | platform | `extension_whoami` | Show the stored login (never the token) |
131
134
  | platform | `extension_logout` | Remove stored credentials |
135
+ | platform | `extension_preview_web` | Render a build in the web emulator, and share it as a link |
136
+ | platform | `extension_shares` | List every link you have shared, and revoke one permanently |
132
137
  | platform | `extension_publish` | Publish a shareable preview to extension.dev |
133
138
  | platform | `extension_release_promote` | Promote a build to a release channel, headless |
134
139
  | platform | `extension_deploy` | Submit to the Chrome, Firefox, and Edge stores through extension.dev |
135
140
 
136
141
  Browser-launching tools (`dev`, `start`, `preview`) shell out to the `extension` CLI, the project's own `node_modules/.bin/extension` when present, otherwise `npx extension@<pinned>` at the version this package is verified against; everything else runs in-process.
137
142
 
143
+ ## Sharing a build in progress
144
+
145
+ An unpacked extension is unusually hard to hand to someone: the only way to look at a colleague's work-in-progress has been to take their zip and run untrusted code with real browser permissions on your own machine. `extension_preview_web` with `share: true` uploads the `dist/` it just built and returns a link that renders those exact bytes in the emulator. Whoever opens it installs nothing and signs in to nothing, which is what lets a designer, a PM, or a reviewer into the loop at all. Sharing needs auth (`extension_login` or `EXTENSION_DEV_TOKEN`), the link expires, and `DELETE`ing the returned `revokeUrl` with the same token kills it early. Revocation is permanent and re-sharing mints a new link, so that `revokeUrl` is the only handle to the link you just made; every share is also appended to `.extension.dev/shared-previews.json` in the project (gitignored) so it survives losing the tool output. Without `share`, the tool returns a local-only deep link and uploads nothing.
146
+
147
+ `extension_shares` is the other half of that: it lists every link the token has shared, live and dead, with the `previewUrl` and `revokeUrl` of each, and revokes one by `artifactId` or by pasting any of its URLs. Pass `projectPath` and it reconciles the platform's answer with the project's own record, so a link shared from another machine shows up as `remoteOnly` and a record with nothing behind it any more shows up under `localOnly`. It never rewrites the local file.
148
+
149
+ That is a different job from shipping. Use `share` for the build you are holding right now; use `extension_publish` and `extension_release_promote` below for builds your CI has released.
150
+
138
151
  ## From preview to store
139
152
 
140
- The platform tools connect agents to [extension.dev](https://extension.dev): `extension_login` runs a GitHub device-code flow and stores a project-scoped token locally (never returned to the agent), `extension_publish` turns a build into a shareable preview URL, and `extension_release_promote` promotes a tested build to a release channel from CI or an agent session, no browser required. `extension_deploy` 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. After a real submission, `extension_store_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.
153
+ The platform tools connect agents to [extension.dev](https://extension.dev): `extension_login` runs a GitHub device-code flow 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_deploy` 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. After a real submission, `extension_store_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.
141
154
 
142
155
  ## The extension.dev stack
143
156
 
@@ -6,6 +6,7 @@
6
6
  // ██║ ╚═╝ ██║╚██████╗██║
7
7
  // ╚═╝ ╚═╝ ╚═════╝╚═╝
8
8
  // Apache License 2.0 (c) 2026 Cezar Augusto and the extension.dev collaborators
9
+
9
10
  import {startServer, runCli} from '../dist/module.js'
10
11
 
11
12
  const [, , cmd, ...rest] = process.argv