Platform tools
The eleven platform tools connect an agent to extension.dev: login, workspace and project creation, workspace and build reads, rebuilds, a shareable preview, publishing, release promotion and store submission. Reach for them when the agent should hand a build to someone else or move it toward a store. The platform is in private alpha.
Quick start
claude mcp add extension-dev -- npx @extension.dev/mcp --features=local,platform
npx @extension.dev/mcp login --project <workspace>/<project>The first line turns the platform group on. The second prints a code and a URL: approve the code at extension.dev/device, and the project-scoped token is stored on this machine for at most 7 days.
How it works
The local tools need nothing. The platform tools read EXTENSION_DEV_TOKEN, a workspace or project access token, from the environment, or use the stored device login.
Login
extension_auth with action: "login" and project: "<workspace>/<project>" returns a user code and a URL. You approve the code at extension.dev/device. No GitHub token reaches the machine. The token is project scoped, stored locally, never returned to the agent, and lives at most 7 days.
Login names a project that already exists, but the login call does not check the name. A code is always minted, so nobody can use the endpoint to probe which private projects exist. The check happens at approval, where you are signed in and your own access is known. A code nobody approves expires.
If the project does not exist yet, import a repository or a template at extension.dev/new, then log in again.
The same flow runs headless as extension-mcp login, extension-mcp whoami, extension-mcp logout and extension-mcp release promote. CI re-mints from the console's Access tokens page, or sets EXTENSION_DEV_TOKEN. Add --project <workspace>/<project> to the server's arguments so that server only ever acts on that project.
Several projects under one approval
extension_project_create takes projects, a list of { project, repo } entries in one workspace, in place of project and repo. One approval page lists every name, each project is created by its own request, and each one's 7-day token is stored as that project's login.
extension_auth with action: "login" takes projects, a list of <workspace>/<project> names of existing projects, and stores one token per project. That is also how logins that expire together are renewed. Pass workspace with projects: "*" instead to sign in to every project the workspace has, at most 20; see Use the platform from your agent.
Both lists hold one workspace and 1 to 20 names, each by its exact slug (lowercase letters and digits joined by single dashes, at most 48 characters), none twice. A create list is capped at 10, the platform's limit per approving account per hour, and a longer list is refused rather than split. While projects remain, the answer is status: "creating" with the same deviceCode to call again, always with one row per project, so a refusal on one never hides the others. A server pinned with --project refuses a list that names any other project.
Share a build in progress
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, and the bytes run in an isolated sandbox origin or not at all. The link also serves the build as a zip, so it hands over the built code.
The link lives for the workspace plan's share window, 30 days on Free and 365 on Pro. The answer carries its exact expiresAt and a revokeUrl. A revoke is permanent. Every share is appended to .extension.dev/shared-previews.json in the project, and the server adds that folder to .gitignore. Without share, the tool returns a local-only deep link and uploads nothing.
extension_shares lists every link the token has shared, live and dead, with each previewUrl and revokeUrl. It revokes one by artifactId or any of its URLs, and with projectPath it reconciles against the project's own record (remoteOnly, localOnly) without rewriting it.
Publish is not submit
extension_publish answers with the project's build page on its workspace host: the canonical public page for a public project, or a time-limited ?share= link (1 to 168 hours) for a private one. It uploads nothing and never changes the project's visibility. The revocable preview link above is the other verb: it uploads the local build (Share an unpublished build for review).
extension_submit sends a released build into a store's review queue (Chrome Web Store, Edge Add-ons, Firefox AMO and the App Store for Safari) through extension.dev, which holds your store credentials and dispatches from your project's mirror CI. Credentials are never tool arguments. A real submission is not reversible from the tool, and only Chrome accepts a cancel. It defaults to a dry run, and dryRun: false needs the workspace owner's token. Read the dry run before you let an agent submit.
Safari submission needs a paid plan. A free workspace that names safari is refused, and the refusal covers the whole call: submit the other three stores with safari left out of browsers.
extension_release_promote moves a release channel to a tested build, headless, from CI or an agent session. 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.
Reference
| Tool | What it does | Needs |
|---|---|---|
extension_auth | Logs this machine in, reports the login, or clears it | A person approving the code |
extension_workspace_create | Creates a workspace without the console | A person approving the code |
extension_project_create | Creates 1 to 10 projects under one approval | A person approving the code |
extension_preview_web | Previews the build in the emulator; share: true uploads it and mints a link | Login for share: true; up to 2,000 files and about 64MB of text, roughly 48MB of images, fonts or wasm |
extension_shares | Lists and revokes shared links | Login; a revoke waits for approval by default |
extension_publish | Returns the project's build page URL; ttlHours 1 to 168 for a private project | Login |
extension_release_promote | Points a release channel at a build | A login approved by an owner; every promote waits for an owner's approval |
extension_release_status | Reads channels, submissions and store health | Login |
extension_workspace | Reads the workspace's plan, projects, usage and a project's settings | Login of any project in the workspace |
extension_builds | Reads builds and their logs, rebuilds, changes build settings, adds a channel | Login; a settings change waits for an owner's approval |
extension_submit | Dispatches a store submission; dry run by default | Login; dryRun: false needs the owner's token and waits for an owner's approval |
When it fails
- A platform tool returns an auth error: the stored login lives at most 7 days. Log in again with
extension_auth, or setEXTENSION_DEV_TOKEN. - The device page says the project does not exist: login mints a code for any name, and the check happens at approval. Create the project at extension.dev/new, then log in again.
- The tool is not listed: the server started without the platform group. Add
--features=local,platformto its arguments. - A share upload is refused as too large: the cap is 2,000 files and about 64MB of text. Trim bundled assets, or build without large source maps.
- A create list is refused: it named more than 10 projects, two workspaces, a slug twice, or a project outside the server's
--projectpin. Fix the list, because the server never splits it. - A submit naming
safariis refused on a free workspace: the refusal covers the whole call. Dropsafarifrombrowsers, or move the workspace to a paid plan.
Next
- MCP server: install, the two groups and the session gates
- Server flags and telemetry:
--features,--no-ship,--projectand the approvals - Use the platform from your agent: what a login reads and does, and which acts wait for an owner
- Access tokens and Publish from the CLI