@extension.dev/mcp 10.4.3 → 10.8.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +118 -0
- package/README.md +42 -1
- package/dist/module.js +7204 -5423
- package/dist/src/lib/approval-gate.d.ts +27 -0
- package/dist/src/lib/artifacts-api.d.ts +3 -0
- package/dist/src/lib/cdp-page-scripts.d.ts +1 -0
- package/dist/src/lib/cdp.d.ts +9 -0
- package/dist/src/lib/device-flow.d.ts +18 -0
- package/dist/src/lib/envelope.d.ts +1 -1
- package/dist/src/lib/funnel-telemetry.d.ts +24 -0
- package/dist/src/lib/match-patterns.d.ts +3 -0
- package/dist/src/lib/origins.d.ts +2 -0
- package/dist/src/lib/platform-hold.d.ts +21 -0
- package/dist/src/lib/preview-upload.d.ts +2 -0
- package/dist/src/lib/project-manifest.d.ts +18 -0
- package/dist/src/lib/publish.d.ts +2 -0
- package/dist/src/lib/registry.d.ts +11 -7
- package/dist/src/lib/share-cors-probe.d.ts +1 -0
- package/dist/src/lib/store-md.d.ts +11 -0
- package/dist/src/lib/template-artifact-source.d.ts +2 -1
- package/dist/src/lib/verdict.d.ts +63 -0
- package/dist/src/tools/assert.d.ts +90 -0
- package/dist/src/tools/doctor.d.ts +2 -1
- package/dist/src/tools/logs-filter.d.ts +2 -2
- package/dist/src/tools/logs.d.ts +3 -0
- package/dist/src/tools/open.d.ts +4 -0
- package/dist/src/tools/project-create.d.ts +65 -0
- package/dist/src/tools/release-promote.d.ts +5 -0
- package/dist/src/tools/shares.d.ts +5 -0
- package/dist/src/tools/submit.d.ts +5 -0
- package/package.json +3 -3
- 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 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.
|
|
13
|
+
"version": "10.8.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 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.
|
|
4
|
+
"version": "10.8.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cezar Augusto",
|
|
7
7
|
"email": "hello@extension.dev",
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,123 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 10.8.0
|
|
4
|
+
|
|
5
|
+
Some MCP actions change what a public channel serves or hand something to a
|
|
6
|
+
store, and none of those can be taken back in place. The client now carries
|
|
7
|
+
an approval gate for exactly those actions, so a human can stand between an
|
|
8
|
+
agent's proposal and the write when the platform asks for one.
|
|
9
|
+
|
|
10
|
+
- `extension_submit`, `extension_release_promote` and the destructive
|
|
11
|
+
`extension_shares` actions accept an `approvalId`. When the platform's
|
|
12
|
+
approval gate is on, the first call answers `approval-required` with an
|
|
13
|
+
approval id and a URL a human approves at extension.dev; the same call
|
|
14
|
+
repeated with that id performs the action. Rejections and pending
|
|
15
|
+
approvals answer as themselves, never as a bare error.
|
|
16
|
+
- Approvals are bound to an action fingerprint, so an approval for one
|
|
17
|
+
promote cannot be replayed on another.
|
|
18
|
+
- The gate is off unless the platform enables it; every existing flow is
|
|
19
|
+
unchanged by default.
|
|
20
|
+
|
|
21
|
+
## 10.7.0
|
|
22
|
+
|
|
23
|
+
The published client had no idea the platform could be held, so on the five
|
|
24
|
+
lanes that run on our machines a reader met either a bare status code or an
|
|
25
|
+
honest refusal that then sent them to a page answering 503. That is what
|
|
26
|
+
makes someone conclude the product is broken.
|
|
27
|
+
|
|
28
|
+
- A held lane now answers one shape on `extension_publish`,
|
|
29
|
+
`extension_release_promote`, `extension_submit`,
|
|
30
|
+
`extension_project_create`, `extension_shares`, `extension_preview_web`
|
|
31
|
+
and the registry reads behind `extension_release_status`: status
|
|
32
|
+
`platform-held`, `error.platformCode` set to `PLATFORM_NOT_OPEN`, and a
|
|
33
|
+
message carrying the condition, what still works, and a way back.
|
|
34
|
+
- What still works is the part that was missing. Creating, developing and
|
|
35
|
+
packaging an extension run on your own machine, they are free forever, and
|
|
36
|
+
the hold does not touch them, so `extension_create`, `extension_dev`,
|
|
37
|
+
`extension_build`, `extension_manifest_validate` and `extension_doctor`
|
|
38
|
+
are named in the refusal and repeated in `value.stillWorks`.
|
|
39
|
+
- A held refusal may not point at a held surface, so the only link it
|
|
40
|
+
carries is `templates.extension.dev`, the one surface that stays open,
|
|
41
|
+
and no refusal names a date.
|
|
42
|
+
- Registry reads no longer collapse a non-ok response to
|
|
43
|
+
`<url> returned <status>`. The body is read once and its message travels
|
|
44
|
+
with the result, so a refusal the platform wrote reaches the reader
|
|
45
|
+
instead of a number. A held read is answered without buying an access
|
|
46
|
+
grant first, because a shut lane is not an auth problem.
|
|
47
|
+
- The hold is recognised by the `code` field and the `x-extensiondev-hold`
|
|
48
|
+
header rather than by matching the sentence, so the wording can change on
|
|
49
|
+
the server without a client release.
|
|
50
|
+
|
|
51
|
+
## 10.6.1
|
|
52
|
+
|
|
53
|
+
Two reply strings pointed a stranger at surfaces the public hold keeps
|
|
54
|
+
dark, so the remedy they named was a dead end wearing an instruction.
|
|
55
|
+
|
|
56
|
+
- The closed-lane refusal in `extension_project_create` now relays the
|
|
57
|
+
server's own message verbatim whenever the server sends one, so the
|
|
58
|
+
platform decides what a caller reads there. The hardcoded console
|
|
59
|
+
pointer survives only as the fallback for a refusal that carries no
|
|
60
|
+
message field.
|
|
61
|
+
- `extension_release_status` no longer promises that publicUrl links
|
|
62
|
+
need no login today. They are the public build pages and open without
|
|
63
|
+
login once the project is publicly reachable, and the console Builds
|
|
64
|
+
page is described as the authoritative record rather than a view the
|
|
65
|
+
caller is promised to see render.
|
|
66
|
+
|
|
67
|
+
## 10.6.0
|
|
68
|
+
|
|
69
|
+
The server covered every stage of the lifecycle except the one an agent
|
|
70
|
+
needs most. It could read anything, so every expectation had to be
|
|
71
|
+
hand-rolled as a string of JavaScript over a blob, which is the guessing
|
|
72
|
+
the paired skill exists to prevent.
|
|
73
|
+
|
|
74
|
+
- `extension_assert` is the test stage: a list of expectations in, one
|
|
75
|
+
verdict each out. Five checks ship, `background-worker-booted`,
|
|
76
|
+
`surface-rendered`, `content-script-injected`, `storage-key-present`
|
|
77
|
+
and `console-errors-empty`, and the run is a pass only when every one
|
|
78
|
+
of them passed.
|
|
79
|
+
- A check that the platform cannot cover comes back `inconclusive`, never
|
|
80
|
+
a pass and never a red against the extension, and carries a `settledBy`
|
|
81
|
+
naming the evidence that would answer it. A content script's execution
|
|
82
|
+
is not observable from outside its isolated world, so a declared
|
|
83
|
+
`content_scripts` match is inconclusive rather than a pass; an absent
|
|
84
|
+
MV3 worker target is inconclusive because Chrome delists an idle one;
|
|
85
|
+
zero errors over a session that never wrote a log line is inconclusive
|
|
86
|
+
because zero errors and zero events are the same number; a read the
|
|
87
|
+
platform refuses, such as `chrome.storage` without `allowControl`, is
|
|
88
|
+
inconclusive because nothing was learned about the extension.
|
|
89
|
+
- The verdict document is a port of the preview lane's own contract, with
|
|
90
|
+
its own contract name and check registry so the two can never be
|
|
91
|
+
confused, and each check names the preview check it is the
|
|
92
|
+
live-browser counterpart of. A contract test pins the outcome
|
|
93
|
+
vocabulary, the check and document shapes, and the aggregation rule
|
|
94
|
+
against that package's own code whenever a monorepo checkout is
|
|
95
|
+
reachable, the way the STORE.md corpus pins its parser.
|
|
96
|
+
- The manifest candidate list, which `extension_open` held three copies
|
|
97
|
+
of, moves to one reader that every caller shares.
|
|
98
|
+
|
|
99
|
+
## 10.5.0
|
|
100
|
+
|
|
101
|
+
`extension_submit`'s STORE.md advisory and the platform parser that feeds
|
|
102
|
+
AMO and Partner Center disagreed, and the disagreement ran in the
|
|
103
|
+
dangerous direction: the advisory stayed silent about notes the
|
|
104
|
+
submission would never carry.
|
|
105
|
+
|
|
106
|
+
- The hand-rolled section and field probing in `extension_submit` is
|
|
107
|
+
replaced by `src/lib/store-md.ts`, an exact port of the parser the
|
|
108
|
+
submission runs. Headings the platform ignores, such as
|
|
109
|
+
`### AMO reviewer notes` or a Firefox-naming Edge section, now raise
|
|
110
|
+
the warning they always should have.
|
|
111
|
+
- A contract corpus of 14 STORE.md fixtures and a pin generated from the
|
|
112
|
+
platform parser hold the two implementations together: the pin carries
|
|
113
|
+
the upstream file's sha256 and its answer for every fixture, and the
|
|
114
|
+
suite replays both parsers over the corpus whenever the upstream
|
|
115
|
+
checkout is reachable. Neither side can move alone.
|
|
116
|
+
- When the notes are found, the advisory now names the file it read and
|
|
117
|
+
says the submission reads STORE.md from the source repository at the
|
|
118
|
+
built commit, so an uncommitted edit is never mistaken for a
|
|
119
|
+
submission that carries it.
|
|
120
|
+
|
|
3
121
|
## 10.4.3
|
|
4
122
|
|
|
5
123
|
Four truths an agent reads got sharper. A share recorded twice is one
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
# @extension.dev/mcp [![Version][npm-version-image]][npm-version-url] [![Downloads][npm-downloads-image]][npm-downloads-url] [![Discord][discord-image]][discord-url]
|
|
9
9
|
|
|
10
|
-
> Give your AI agent hands for browser extension development.
|
|
10
|
+
> Give your AI agent hands for browser extension development. 30 MCP tools that scaffold, run, inspect, debug, and publish cross-browser extensions.
|
|
11
11
|
|
|
12
12
|
<img alt="Logo" align="right" src="https://media.extension.land/brand/extension-dev/logo-dock.png" width="20.7%" />
|
|
13
13
|
|
|
@@ -117,12 +117,14 @@ cp node_modules/@extension.dev/mcp/claude/commands/*.md ~/my-extension/.claude/c
|
|
|
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 |
|
|
120
|
+
| test | `extension_assert` | State expectations about a running extension and get one verdict each: pass, fail, or inconclusive |
|
|
120
121
|
| act | `extension_eval` | Evaluate in a context (needs `allowEval: true` on `extension_dev`) |
|
|
121
122
|
| act | `extension_storage` | Read/write `chrome.storage` |
|
|
122
123
|
| act | `extension_reload` | Reload extension or tab |
|
|
123
124
|
| act | `extension_open` | Open a surface / trigger `action`, `command` |
|
|
124
125
|
| browsers | `extension_browsers` | Detect, list, install, and uninstall browsers |
|
|
125
126
|
| platform | `extension_auth` | Device login at extension.dev, plus login status and logout |
|
|
127
|
+
| platform | `extension_project_create` | Create the extension.dev project for a built extension, headless, via device approval |
|
|
126
128
|
| platform | `extension_preview_web` | Render a build in the web emulator, and share it as a link |
|
|
127
129
|
| platform | `extension_shares` | List every link you have shared, and revoke one permanently |
|
|
128
130
|
| platform | `extension_publish` | Publish a shareable preview to extension.dev |
|
|
@@ -132,6 +134,45 @@ cp node_modules/@extension.dev/mcp/claude/commands/*.md ~/my-extension/.claude/c
|
|
|
132
134
|
|
|
133
135
|
Browser-launching tools (`dev`, `start`) 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.
|
|
134
136
|
|
|
137
|
+
## Asserting instead of guessing
|
|
138
|
+
|
|
139
|
+
Every other tool here hands back a reading: a DOM, a log window, an evaluated
|
|
140
|
+
expression. Turning a reading into "the popup works" was left to the agent, as
|
|
141
|
+
a string of JavaScript it wrote on the spot, which is the guesswork the paired
|
|
142
|
+
skill exists to prevent. `extension_assert` states the expectation and returns
|
|
143
|
+
the verdict.
|
|
144
|
+
|
|
145
|
+
```jsonc
|
|
146
|
+
{
|
|
147
|
+
"projectPath": "/path/to/extension",
|
|
148
|
+
"expect": [
|
|
149
|
+
{ "assert": "background-worker-booted" },
|
|
150
|
+
{ "assert": "surface-rendered", "surface": "popup", "selector": "[data-testid=root]" },
|
|
151
|
+
{ "assert": "storage-key-present", "key": "settings", "area": "local" },
|
|
152
|
+
{ "assert": "console-errors-empty", "context": ["background", "popup"] },
|
|
153
|
+
{ "assert": "content-script-injected", "url": "https://shop.example/cart" }
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Each check comes back as `pass`, `fail` or `inconclusive`, and the run is a
|
|
159
|
+
pass only when every check passed. `inconclusive` is the part that matters: it
|
|
160
|
+
means this platform cannot cover the question today, and the check carries a
|
|
161
|
+
`settledBy` naming the evidence that would answer it. A content script's
|
|
162
|
+
execution is not observable from outside its isolated world, so
|
|
163
|
+
`content-script-injected` passes only on a line the script itself wrote and is
|
|
164
|
+
inconclusive over a declared match, never a pass. "No console errors" over a
|
|
165
|
+
session that never built is inconclusive too, because zero errors and zero
|
|
166
|
+
events are the same number. A read the platform refuses, such as
|
|
167
|
+
`chrome.storage` on a session started without `allowControl`, is inconclusive
|
|
168
|
+
rather than a failure: nothing was learned about the extension.
|
|
169
|
+
|
|
170
|
+
The verdict document is the same grammar the preview lane's CI verdict uses
|
|
171
|
+
(`@extension.dev/preview-verdict`), with its own contract name and its own
|
|
172
|
+
check registry, so a document from one lane can never be mistaken for the
|
|
173
|
+
other's. Each check here names the preview check it is the live-browser
|
|
174
|
+
counterpart of, and a contract test holds the two grammars together.
|
|
175
|
+
|
|
135
176
|
## Sharing a build in progress
|
|
136
177
|
|
|
137
178
|
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. Those bytes run in an isolated sandbox origin or they do not run at all: preview refuses a shared build rather than serving it in its own renderer. Sharing needs auth (`extension_auth` or `EXTENSION_DEV_TOKEN`), the link lives 30 days, and `DELETE`ing the returned `revokeUrl` with the same token kills it early. Re-sharing an unchanged build returns that same link rather than a second one, and only a revoked link is replaced by a different one, because revocation is permanent: the address is burned and never resolves again. That makes `revokeUrl` the handle to the link you just made, so every share is also appended to `.extension.dev/shared-previews.json` in the project (gitignored) so it survives losing the tool output. The upload holds up to 2,000 files and about 64MB of text, or roughly 48MB when the build is mostly images, fonts or wasm, which travel base64-encoded. Without `share`, the tool returns a local-only deep link and uploads nothing.
|