webmcpify — GitHub Copilot skill: what it does, install
This skill turns a web app into WebMCP tools for AI agents, checks them in a real browser, and heals issues found during verification.
npx skills add github/awesome-copilot --skill webmcpifyWhat webmcpify does
webmcpify runs a web app through detection, inventory, manifest approval, integration, verification, healing, and audit. It maps user-facing actions to WebMCP tools so browser AI agents can use structured calls instead of guessing through the DOM. Progress is kept in .webmcpify/, with a manifest, report, and inventory shards.
The skill directory includes phase guides in references/ and vendorable code in templates/, including a runtime, ambient types, a JS variant, React JSX typings, and a verification spec. Registration uses document.modelContext, with a feature-detected fallback for the deprecated navigator.modelContext. The app should behave the same in browsers without WebMCP.
Use it when you control the web app and want its existing actions exposed to browser AI agents. Skip it for backend-only MCP servers, third-party sites, or generic SEO work. Server-mutating tools need explicit approval per tool.
What it helps with
- create a WebMCP tool manifest for a web app
- expose user-facing app actions to browser AI agents
- verify integrated tools in a real browser
- heal failures found by the verification loop
- keep unrelated code outside the diff
Example prompts for the agent
- `/webmcpify inventory` to map the app without code changes
- `/webmcpify integrate` to add approved tools
- `/webmcpify verify` to verify and heal integrated tools
How to install webmcpify
1Skills CLI (Vercel)
npx skills add github/awesome-copilot --skill webmcpify2GitHub CLI
gh skill install github/awesome-copilot webmcpify3Manually: put the files in place
.github/skills/webmcpify/SKILL.md1Skills CLI (Vercel)
npx skills add github/awesome-copilot --skill webmcpify -a claude-code2Manually: put the files in place
~/.claude/skills/webmcpify/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/webmcpify/
Manually: put the files in place
.agents/skills/webmcpify/SKILL.mdFor all projects use ~/.agents/skills/
Manually: put the files in place
.cursor/skills/webmcpify/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
Platform CLI
gemini skills install https://github.com/github/awesome-copilot --path skills/webmcpifyManually: put the files in place
.devin/skills/webmcpify/SKILL.mdThe legacy .windsurf/skills/ path still works
Claude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
From the same set554
The whole set →Similar
Questions about webmcpify
How do I install webmcpify in GitHub Copilot?
Run npx skills add github/awesome-copilot --skill webmcpify, then use .github/skills/webmcpify/SKILL.md.
What does webmcpify do?
It inventories a web app's user-facing actions, proposes a WebMCP manifest, integrates approved tools, and verifies them in a browser.
Will the app still work without WebMCP?
Yes. The skill requires feature detection so the app behaves identically in browsers without WebMCP. The supplied material describes WebMCP as an evolving Chrome origin-trial API.
Source text
SKILL.md · MIT
---
name: webmcpify
description: 'Make a web app agent-ready — propose a WebMCP tool manifest, integrate, verify in a real browser, heal; unrelated code stays untouched. Use for "webmcpify", "add WebMCP", or "expose app actions to AI agents".'
argument-hint: "[inventory|integrate|verify|status|full] [scope notes]"
license: MIT
metadata:
source: https://github.com/TueJon/webmcpify
---
# webmcpify — make any web app agent-ready, verifiably
You are running the webmcpify pipeline. It takes an existing web application and
exposes its user-facing functionality as [WebMCP](https://webmachinelearning.github.io/webmcp/)
tools (`document.modelContext` — a proposed web standard incubated in the W3C Web
Machine Learning Community Group, currently a Chrome origin trial), so browser AI
agents can operate the app through structured tool calls instead of guessing at the DOM.
```
DETECT ──▶ INVENTORY ──▶ [HUMAN GATE: manifest approval] ──▶ INTEGRATE ──▶ VERIFY ──▶ HEAL ──▶ AUDIT
▲ loop per-area batches on big apps ▲ loop ▲ loop ▲ loop
└── per area └── per manifest entry ──┘
```
Everything you need ships inside this skill directory: phase guides in
`references/`, and vendorable code in `templates/` (runtime, ambient types,
JS variant, React JSX typings, verification spec). Never assume files exist
outside the skill dir.
**Out of scope** (stop and say so): backend-only MCP servers (that's classic MCP,
not WebMCP), automating third-party sites you don't control, and generic SEO work.
## Invocation modes
The user may pass an argument (`/webmcpify <mode>` or plain words):
| Argument | Run | Stop at |
|---|---|---|
| *(none)* or `full` | all phases, resuming from current manifest state | done |
| `inventory` / `map` | DETECT + INVENTORY loops only — **zero code changes** | present the manifest table for review |
| `integrate` | INTEGRATE loop only (requires approved tools in the manifest) | integrated + built |
| `verify` | VERIFY + HEAL loops on integrated/verified tools | green/skipped report |
| `status` | read `.webmcpify/manifest.json` — **read-only** | report phase, per-status tool counts, and the recommended next command |
Any other text is scoping guidance (e.g. "only the checkout area", "read-only tools only").
## Ground rules (non-negotiable, enforce in every phase)
1. **Zero unrelated changes.** Every diff hunk you produce must trace to a manifest
entry or the recorded one-time setup. Never refactor, reformat, rename, or
"improve" anything else — note problems in the report instead. Files that were
already dirty at baseline (recorded in the manifest) are **untouchable**: never
modify or revert them.
2. **Read-only tools first.** Mutations are tri-state: `mutating: false`,
`"client"` (browser-local only: prefs, localStorage), or `"server"` (data
leaves the browser). Server-mutating tools require explicit **per-tool** human
approval recorded in the manifest; client-mutating tools may be approved as a
batch at the gate. Never expose destructive, irreversible, or payment actions
in a first integration.
3. **The server is the only trust boundary.** A tool's `execute()` may only call code
paths the UI already uses (same endpoints, same validation, same auth). Never
create new endpoints, never bypass existing checks, never put secrets in tools.
4. **Spec-shaped and dependency-free.** Register via `document.modelContext.registerTool()`
with AbortSignal lifecycle (feature-detect the deprecated `navigator.modelContext`
fallback). No third-party WebMCP runtime dependencies. Everything feature-detected:
the app behaves identically in browsers without WebMCP.
5. **Never `toolautosubmit` on state-changing forms** — neither `mutating: "client"`
nor `"server"`. Only on pure read forms (search, filter, availability).
6. **State lives in files, not in your context.** Read/write `.webmcpify/` constantly;
assume your context can be wiped between any two steps. Write the manifest
atomically (write `manifest.json.tmp`, then rename over `manifest.json`).
7. **Commits are opt-in.** Never commit unless the human chose a commit policy at
the gate (see below). Without git or without permission, leave changes in the
working tree and record progress in the manifest only.
## Fresh, authoritative guidance
WebMCP is an evolving origin-trial API — the surface has already changed during the
trial (testing API removed 2026-07; `navigator` → `document`). Before Phase 2, if
network is available, pull Google's current official guides rather than relying on
memory:
```sh
npx -y modern-web-guidance@latest retrieve "webmcp,agentic-forms,agentic-javascript-tools"
```
If offline, use `references/integrate.md` — but prefer the live guides when they conflict.
## The state protocol — `.webmcpify/` in the target repo
| File | Purpose |
|---|---|
| `manifest.json` | Single source of truth (schema below; atomic writes) |
| `areas/<id>.tools.json` | Sub-agent shard output during inventory fan-out (merged, then deleted) |
| `report.md` | Human-facing running report; finalized at the end |
**Resume rule:** if `manifest.json` exists, resume — recompute nothing already
recorded. **Merge leftover shards FIRST**: any existing `areas/<id>.tools.json`
files are merged into the manifest (mark those areas `inventoried`, delete the
shards) before redispatching any sub-agents. Then continue at `pipeline.phase`,
the first `pending` area, or the first tool whose status is not terminal.
Terminal statuses: `verified`, `skipped`, `rejected`.
**Phase transitions** (make the atomic manifest write the moment the condition holds):
- `detect → inventory`: `app` recorded, `baselineSha`/`baselineDirty` captured.
- `inventory → gate`: no area `pending`, completeness pass has run.
- `gate → integrate`: every `discovered` tool is `approved`/`rejected`, and
`commitPolicy` + `commitWebmcpifyDir` are set.
- `integrate → verify`: no `approved` tools remain (each `integrated` or terminal),
build green.
- `verify → heal`: verify loop visited every `integrated` tool and ≥1 is `failed`
(none failed → straight to `audit`).
- `heal → audit`: no tool `failed` and post-heal full re-verify passed.
- `audit → done`: every hunk mapped-or-flagged, `report.md` finalized.
Manifest schema (Webmcpify Manifest v3):
```jsonc
{
"webmcpify": 3,
"app": { "stack": "react-vite", "typescript": true, "entry": "src/main.tsx",
"baseUrl": "http://localhost:5173", "startCommand": "npm run dev",
"authFixtures": { // how verify OBTAINS each session
"member": { "obtain": "npm run seed:test-user, then sign in at /login",
"account": "[email protected]",
"env": ["TEST_MEMBER_PASSWORD"] } // env var NAMES only — never secret values
} },
"pipeline": {
"phase": "inventory", // detect|inventory|gate|integrate|verify|heal|audit|done — transition rules above
"setup": { // PATHS created/modified per one-time setup step ([] = not done yet)
"runtimeVendored": ["src/webmcp/webmcpify.ts", "src/webmcp/webmcp.d.ts"],
"harnessInstalled": [".webmcpify/webmcp.spec.ts"],
"originTrialNoted": ["README.md"]
},
"baselineSha": "abc1234", // HEAD at pipeline start; null if no git
"baselineDirty": ["src/wip.ts"], // paths dirty at start — untouchable (ground rule 1)
"commitPolicy": null, // set at the gate: "commit-per-batch" | "no-commit"
"commitWebmcpifyDir": null, // set at the gate: commit .webmcpify/ itself? true | false
"blockers": [] // e.g. "app won't start locally: needs $API_KEY" — surfaced at the gate
},
"areas": [
{ "id": "checkout", "paths": ["src/features/checkout/"], "status": "pending" } // pending|inventoried
],
"tools": [
{
"id": "create_ticket",
"area": "tickets",
"kind": "imperative", // imperative | declarative
"mutating": "server", // false | "client" (browser-local only: prefs, localStorage) | "server" (data leaves the browser)
"priority": 1, // 1 = expose first; 2/3 = later waves
"description": "Creates a new ticket in the currently open project.",
"inputSchema": { /* JSON Schema */ },
"annotations": { "readOnlyHint": false, "untrustedContentHint": false }, // verify asserts these on the enumerated tool
"source": ["src/features/tickets/NewTicket.tsx:42"], // the UI code path it wraps
"route": "/projects/demo/tickets", // where verify navigates
"auth": ["role:member"], // "none" | "session" | ["role:<name>", ...] — keys into app.authFixtures; verify runs once per listed role
"examples": { "valid": { "title": "Test ticket" }, "invalid": {} },
// invalid: null ONLY for readOnlyHint tools with no/empty params —
// verify then asserts dual-outcome: rejects OR resolves with no side effect
"expect": { "result": "created", "navigation": null, "ui": "new row appears in the ticket list" },
// exactly one of result|navigation: result = substring of the resolved string;
// navigation = destination URL/pattern when executeTool resolves null (it navigated)
"cleanup": "delete the created ticket via the UI's own delete path (test data only)", // required for mutating:"server", recommended for "client"
"status": "discovered", // discovered|approved|rejected*|integrated|verified*|failed|skipped* (* = terminal)
"approval": null, // server-mutating tools, once approved: { "note": "...", "at": "2026-07-12",
// "productionSideEffect": null } — set only when verification unavoidably
// causes a real production effect (see VERIFY: production side-effect policy)
"attempts": 0, // heal-fix cycles; the triggering verify failure is attempt 0
"batchCommit": null, // sha under commit-per-batch — lands in the manifest one commit LATER
"notes": ""
}
],
"log": [ "2026-07-12 inventory: area checkout done, 4 candidates" ]
}
```
**v2→v3 migration:** resuming a `"webmcpify": 2` manifest migrates in place on
first write — `auth` string → array; `setup` booleans → path arrays (`false` →
`[]`; `true` → recover paths from git/`log`, else `null` = done-but-unrecorded,
audit treats those files flag-only); `mutating: true` → `"server"`; add
`annotations` (defaults from the inventory table), `blockers: []`,
`commitWebmcpifyDir: null`, `expect.navigation: null`; then bump to 3.
## Phase 0 — DETECT
Identify stack, build + dev-server commands, TypeScript or not, auth model
(including how verify obtains each test session → `app.authFixtures`), test
setup, and how the app starts locally; record under `app`. Record the git baseline:
`pipeline.baselineSha` = current HEAD and `pipeline.baselineDirty` = `git status
--porcelain` paths (both `null`/`[]` without git). If the app cannot be started
locally, append the blocker to `pipeline.blockers` — integration may proceed, but
verification will be blocked and this must be surfaced at the gate. Details:
`references/inventory.md`.
## Phase 1 — INVENTORY (loop; scales to any size)
**Never map a large codebase in one pass.**
1. **Area map first (cheap, structural):** enumerate routes/views/feature modules
from the router config, pages directory, or navigation — without reading
implementation files. Write every area to `areas` with `"pending"`.
2. **Inventory loop — one area per iteration:** deep-read only that area's files;
draft a candidate tool per user action (conventions, tool-count budget, and
overlap rules: `references/inventory.md`) with ALL manifest fields filled,
including `route`, `auth`, `annotations`, `examples`, `expect`, and `cleanup`
(required for `mutating: "server"`, recommended for `"client"`) — the verify
phase runs from these fields alone. Append as `"discovered"`, mark the area
`"inventoried"`, write the manifest, repeat.
- **Sub-agent fan-out:** sub-agents never write `manifest.json`. Each writes only
its own `areas/<id>.tools.json` shard — schema
`{ "webmcpifyShard": 3, "area": "<id>", "tools": [ /* full v3 tool entries */ ] }`,
written atomically (tmp + rename). You (the coordinator) merge shards into
the manifest sequentially, then delete them; on resume, merge existing
shards FIRST before redispatching (Resume rule).
3. **Exit:** no `pending` areas remain, plus one completeness pass — walk the app's
navigation and ask "is any visible user action missing?"
## GATE — manifest approval (the one main checkpoint)
Present the manifest compactly (id, area, kind, mutating, priority, one-line
description) — per-area batches on large apps. Ask the human to decide, in one
exchange where possible:
1. Which tools are `approved` vs `rejected` (**`rejected` is terminal** — rejected
tools are excluded from every later phase and from exit conditions).
`mutating: "server"` tools need individual acknowledgment → record in
`approval`; `mutating: "client"` tools may be approved as a batch.
2. **Commit policy**: `commit-per-batch` (each integration batch committed,
revertable — recommended on a clean baseline) or `no-commit` (leave changes
uncommitted for the human to review/commit) → `pipeline.commitPolicy`. Also
whether `.webmcpify/` itself should be committed (recommended: yes — it
documents the integration) → `pipeline.commitWebmcpifyDir`.
3. Every entry in `pipeline.blockers` (e.g. app won't start). If verifying a tool
will unavoidably cause a real production side effect (e.g. a mailer with an
Origin-allow-listed endpoint), get that approved HERE and record it in the
tool's `approval.productionSideEffect` — see VERIFY.
Apply `references/security.md` to every mutating tool **before** presenting.
## Phase 2 — INTEGRATE (loop)
One-time setup first — record the created/modified file **paths** in
`pipeline.setup` (e.g. `runtimeVendored: ["src/webmcp/webmcpify.ts", ...]`):
vendor the runtime from this skill's `templates/` (`webmcpify.ts`, or
`webmcpify.js` for non-TS projects, plus `webmcp.d.ts` for TS and
`webmcp-jsx.d.ts` for React TSX — keep the full MIT header; see
`references/runtime.md`) and note the origin-trial/flag requirement in the target
README (`originTrialNoted`). Then loop:
1. Pick the next batch of `approved` tools — one area or ≤5 tools.
2. Implement per `references/integrate.md`: declarative attributes for standard
HTML forms (including framework-rendered and fetch-intercepted ones);
imperative registration via the vendored runtime for non-form or
controlled-state actions.
3. Build + typecheck; fix only what the batch broke.
4. Mark tools `"integrated"`, write the manifest. Under `commit-per-batch`:
require a **clean index** before staging (unrelated staged changes → stop and
surface); stage **only the batch's files by path** — never `git add -A`, `-u`,
`.`, or `commit -a`; commit `feat(webmcp): expose <ids> (webmcpify)`. The
commit sha lands in `batchCommit` on the **next** manifest write — one commit
later (the manifest can't contain its own commit's sha). Never amend a
previous batch commit.
5. Repeat until no `approved` tools remain.
## Phase 3 — VERIFY (loop)
Set up once from `templates/webmcp.spec.ts` per `references/verify.md` (real headed
Chrome; production `getTools()`/`executeTool()` surface with legacy fallback probe).
Then loop over every `integrated` tool, using its manifest `route`, `auth`,
`examples`, `expect`, and `annotations` fields:
- assert the tool is registered with the expected schema (enumerated `inputSchema`
is a *stringified* JSON Schema — parse before comparing) **and** the manifest
`annotations`;
- execute the valid example (mutating tools: dev/test data only, then run
`cleanup`) and one invalid example (`invalid: null` zero-param read tools:
dual-outcome assertion — see `references/verify.md`);
- assert on the returned result **and** the resulting UI state per `expect`
(a UI **delta**, or `expect.navigation` when execution resolves `null`).
Pass → `"verified"`. Fail → `"failed"` + failure note. Role-scoped tools: run the
loop once per role listed in `auth`, signing in via the matching
`app.authFixtures` entry.
**Production side-effect policy** — when a tool's verification unavoidably causes
a real production effect (e.g. an email actually sent), ALL THREE are required:
(1) the human approved it at the gate, recorded in `approval.productionSideEffect`;
(2) every test payload is marked `[webmcpify verification]`; (3) the effect is
listed in `report.md`. Without the recorded approval, don't execute the live
path — mark the tool `skipped` with a blocker note.
## Phase 4 — HEAL (loop)
While any tool is `"failed"`: diagnose via `references/heal.md`, fix **only** that
tool's integration — **implementation-only** fixes; if the fix would change the
approved contract (schema, description, `mutating` class, `annotations`,
`expect`), go back to the gate for re-approval instead of silently changing the
manifest. The triggering verify failure is attempt 0; increment `attempts` per
fix cycle and re-verify. At `attempts` = 3 → `"skipped"` with a clear blocker
note (an explicit escalation to the human, not a silent drop). Never widen the
diff or fake a pass. After healing, re-run verification once for **all** tools
with status `integrated` or `verified` (healing one tool can break another —
scope collisions).
**Exit:** every tool is `verified`, `skipped`, or `rejected`; build green.
## Final — AUDIT + report
1. **Diff audit (flag-only, never auto-revert):** collect the pipeline's changes —
`git diff <baselineSha>..HEAD` **plus the index and untracked files** under
`commit-per-batch`, or the working tree + index + untracked under `no-commit`.
Every hunk must map to a manifest entry or a recorded `pipeline.setup` path.
An unmapped hunk → **flag it in the report** with file/line and a suggested
disposition; never revert anything yourself. A hunk in a `baselineDirty` file
→ untouchable, flag only. Without a `baselineSha`, audit the files named in
manifest `source` fields and `pipeline.setup` paths (setup entries recorded as
`null` by the v2→v3 migration: fall back to flag-only for those files).
2. Finalize `.webmcpify/report.md`: tool coverage per area, skipped/rejected tools
with reasons, security notes (which mutating tools exist, what guards them,
any recorded production side effects), how to test manually (flag, DevTools
WebMCP pane, inspector extension), and every blocker that needs a human.
3. Tell the human: what's exposed, what's skipped and why, and how to try it.
## References (read on demand, not upfront)
- `references/inventory.md` — area mapping, naming/schema conventions, budgets/overlap
- `references/integrate.md` — declarative + imperative patterns per stack
- `references/runtime.md` — vendoring + wiring the `templates/` runtime
- `references/verify.md` — harness setup: flags, surfaces, Playwright/Puppeteer, evals
- `references/heal.md` — failure taxonomy → fixes
- `references/security.md` — the security checklist (apply before the gate and at audit)
© github · MIT · github/awesome-copilot