Add WebMCP tools to a website codebase so browser agents can act through the site's own logic instead of scraping the page. Use when asked to make a site agent-ready, add WebMCP or document.modelContext tools, or implement site tools with @nekuda/webmcp-sdk.
Scanned 9/3/2026
Install to Claude Code
npx -y skills add nekuda-ai/webmcp-kit --skill implement --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Implement?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/nekuda-ai-implement)More formats (shields.io, HTML) on the badges page.
---
name: implement
description: Add WebMCP tools to a website codebase so browser agents can act through the site's own logic instead of scraping the page. Use when asked to make a site agent-ready, add WebMCP or document.modelContext tools, or implement site tools with @nekuda/webmcp-sdk.
argument-hint: "[request] [--non-interactive | --no-interactive-loop]"
---
# WebMCP Kit — implement
## Mission
- WebMCP hands a browser agent typed tools (via the `@nekuda/webmcp-sdk` SDK) so it answers from the site's own content and acts through the site's own logic. User and agent share the visible page — every tool produces a visible effect.
- Tools answer "what will a visitor ask, and ask for, here?" — journeys, never REST-endpoint wrappers.
- In every human-facing run, the plan you present in Phase D is approved by the developer **before any file is written**. That gate is the product, not a formality.
## Hard rules
- **Source analysis and code stay local.** Never send customer code, routes, or schemas to an external service or to an unauthenticated tool/API. The tool-selection rubric is this skill's text — there is no hosted scanner. The optional post-build Connect flow sends only the CLI's structured project/account request described in `references/connect.md`; it is separate from the SDK's documented default-on anonymous observations, which are independent of Connect.
- **Client-reachable wiring only.** `execute` may use the app's own client data layer, same-origin routes, or client-safe actions — never server-only imports, secrets, third-party endpoints, or DOM-scraping when a data path exists.
- **Flag, don't fake.** A journey with no safe client path is listed as *needs developer wiring* — never invented data or a dead call. A guidance-only stub does not "cover" a must-have.
- **Irreversible/cost-bearing writes need a boundary.** A payment, cancellation, or delete must not complete in one agent call. The generated tool stops at a reversible handoff — creates the repo-native pending state (checkout session, pending order, prepared cancellation) and hands the final step to the app's own payment/confirm UI, or uses a prepare→confirm two-call shape. A consequence sentence in the description is not a boundary.
- **Authorization is the server's job.** Registration gating on auth/role is UX, not security. Only wrap a privileged mutation whose route independently enforces authn/authz server-side; an endpoint that trusts a hidden client button is *needs developer wiring*, not a tool.
- **No changes or Connect before approval.** No branch, file, dependency, or Connect attempt until the developer approves the plan, except the tool-generation workflow in explicit `--non-interactive` mode; that exception permits the branch, files, and dependencies needed for generation but never Connect, which non-interactive mode skips. This skill reads with Read/Grep/Glob during A–C — plus one read-only exception: the Phase-F baseline capture (the repo's own typecheck/build, `references/verify.md`) may run as a background task before approval, because it writes nothing to the tree; after approval it requests the write, package-manager, and browser permissions it needs through the normal permission prompts — no mutation is pre-authorized. Interactive Connect is a separate, optional post-build decision (`references/connect.md`).
- **SDK only.** Generated code imports `defineTool` / `registerTools` from the SDK under its resolved name (the installed package's declared name — `references/sdk.md`); never the raw `modelContext` surface, never a bundled polyfill/shadow. The SDK pins the spec, resolves whichever surface the browser exposes, and no-ops when unsupported.
## Session flow (A–F)
**A — Understand the repo** (cheap-first). Stack ID from manifests (`package.json`, `composer.json`, …): framework, rendering mode (SPA/SSR/MPA/static), router, language, package manager, and whether a JS bundler/dependency install even exists (a PHP/static MPA may have none — see `references/codegen.md`). Read high-signal sources before app code: README, `openapi.yml`/swagger, route manifests (`app/`, `pages/`, routes files), sitemap, nav, homepage CTAs. Map the visitor surface — routes→pages, forms, data-layer calls, auth boundaries — recording for each: file, what it does, client-reachable or server-only. **Inventory any existing `@nekuda/webmcp-sdk` usage — including its legacy aliases `@agentlane/webmcp` and `@nekuda/webmcp`, the same SDK** (`defineTool` names and `stableKey`s) so a re-run preserves identity instead of churning it. No stack is privileged (Next.js is not pre-decided); read deeper only where a candidate tool's wiring stays ambiguous. These sweeps are independent of each other: issue their Reads/Greps as one parallel batch, never one file per turn, and where the host supports parallel subagents, fan out the route map, the data-layer/auth survey, and the existing-SDK inventory and merge the results — serial reading is this phase's dominant cost on a large repo.
**B — Select journeys/tools.** Load `references/journeys.md` and `references/wiring.md` together, in one batch — C's confidence rule decides whether a B journey lands decided, so the two are used jointly. Match the repo to a category by `applies_when` → primary (+ secondary with the hybrid downgrade). **No match → tell the customer; never draft against the nearest category.** Simulate a concrete visitor on concrete pages: the questions they ask and actions they request are the spec. Instantiate the matched template's must-haves to this repo's real domain objects, content, and CTAs (a "book a demo" site gets `book_demo`, not `request_quote`). `ask_site` wherever the site has visitor-facing content to answer from — one instance; if there is genuinely none (e.g. an auth-only internal dashboard that matches no category), don't fabricate a content bundle, say so. Stay in the category's count band and global 3–10; thin-content sites get `ask_site` and stop. Fix availability, context, response, and annotations per tool.
**C — Pick the wiring.** (`references/wiring.md` is loaded with B; load it now if it is not.) For each tool take the highest safe rung (client data layer > same-origin route > client action > content bundle) and name the concrete path. Resolve the exact workspace-relative entry-module path for the registration scope and exact workspace-relative source-module path for each tool now. Explorer runs record them in `plan.json.entry_module` and each suggestion's `source_module` before proposal; chat-only runs include the same exact paths in the Phase-D plan presented in the conversation without creating Explorer state. Reuse those approved paths through generation, feedback, and Connect. Confidence rule: a tool is **decided** only if its journey is a category must-have AND a rung-1/2 path exists with corroborating evidence (route + handler + UI element agree). Anything else — ambiguous semantics, competing flows, great-to-haves, uncertain category — is **needs your input** with a specific question and a stated default. Per-tool evidence gathering (route + handler + UI element) is independent across tools — batch or fan it out exactly as in Phase A.
**D — Review the plan (hard gate).** Load `references/plan-template.md`. Open every human-facing review with a short summary, identical in substance across entry modes, of what the skill will do and which tools it will create; on the loop path, it is the `_chat.ndjson` handoff (Propose, `references/interactive.md`) shown in the Explorer's conversation panel — the terminal message just points the developer to the Explorer. Then present the plan in the selected review surface **before touching any file**; tool descriptions ship verbatim (description is the product). Edits → revise → re-present. Proceed only on explicit approval. In `--non-interactive` mode, use the stated defaults and Degrade path instead.
**E — Generate.** Load `references/codegen.md` and `references/sdk.md` in one batch — the latter for the exact SDK surface and wiring. Add the SDK dependency the way `references/sdk.md` prescribes, starting the install as a background task at approval so writes never wait on it (`references/codegen.md`); emit the two-module shape as **separate files** — each side-effect-free tool module at its recorded `source_module` (`defineTool` at module scope, never inside a component/effect) plus one entry module per registration scope. An unbundled browser-served module may not keep the package's bare import: vendor the SDK behind a relative browser URL before approval. An import map is not sufficient because static review cannot prove that the server's CSP header permits its inline script. `stableKey` is `domain.action`, authored once and **never changed on re-runs** (reuse any inventoried in Phase A; never a copy of the wire `name`) — `name` may change freely. Each `description` states what it does, **when to use it**, and what it returns; `inputSchema` sets `additionalProperties: false`. `execute` runs the Phase-C path verbatim and **throws on failure or missing anchors/data** (never succeed-on-missing) — a read that finds nothing is not a failure: it still returns, with the empty result plus an explicit note field saying the site has no matching content, never a bare empty array. Match the repo's language, lint/format config, and file conventions. **If an approved call path proves unusable or the implementation must deviate from the approved plan** (different endpoint, changed behavior or coverage), stop and re-present the change — never silently substitute under a stale approval. Start Phase F's static checks (typecheck/lint/build) after this first write, not only once every file is written — preferably a watch-mode typechecker as a background task (`references/verify.md`), so per-file checks are incremental — a turn-budget cutoff should still land at least one static pass.
**F — Verify.** Load `references/verify.md`. Run the ladder: static → boot → registration on declared pages/auth states → read-only invocation → state-changing only on seeded/dev data with consent. Every tool ends **verified**, **failed**, or **could-not-verify**. Failed blocks the PR (fix or drop — never ship known-broken); could-not-verify ships flagged. After the ladder, load `references/connect.md` for every human run: use the Explorer decision when its loop is active and the agent conversation for chat-only review. Its plugin-root CLI entry is mandatory, with no PATH-installed CLI assumption. Only explicitly headless or `--non-interactive` paths skip Connect.
**PR.** Branch `webmcp/tools-v0`; conventional commit; open a PR (approved plan + per-tool verification table as the body) via `gh` when available, else commit on the branch and hand over. Restate could-not-verify items and needs-developer-wiring journeys in the summary.
**Star ask (human runs only).** After the PR link (or the committed branch) has been handed over — the run's value is delivered, never before — quietly run `<this skill's dir>/scripts/star-repo.sh --eligible`. Exit 0 means `gh` is installed, authenticated, and the repo is not already starred; only then append one non-blocking line to the closing summary: if WebMCP Kit was useful, may I star `nekuda-ai/webmcp-kit` on your GitHub? On an explicit yes run `<this skill's dir>/scripts/star-repo.sh` and relay its one-line outcome; on anything else drop the subject. Ask at most once per run, never star without that yes, and skip the ask entirely when the check is ineligible or the run is `--non-interactive`.
## Entry and review mode
- Headless intent must be explicit: the `--non-interactive` flag in the invocation or an equally explicit standing instruction in the request text (for example, "proceed without approval" or "non-interactive") counts as that flag. Never infer it from the environment (no TTY sniffing or "seems headless"). A request to reopen or continue an existing run (a `.webmcp/` folder with state) → see **Resume**. A request with neither loads `references/interactive.md` and runs D–F as an interactive browser loop over the git-tracked state folder `.webmcp/` — UI phases propose → build → review → verify → done: approval starts `verify`, and `done` starts only after the PR exists. If the loop is not already running, the agent may offer to start it. Codex uses bundled hooks only when `/hooks` lists them; their automatic run binding is same-task only, with manual replay as the fallback. Claude Code may use Monitor where supported. In every path the skill remains the workflow authority.
- Developer declines the browser loop → continue as `--no-interactive-loop` with chat-only review.
- Bun unavailable (the Startup preflight in `references/interactive.md`) → offer install or chat-only review per that preflight; never infer either choice, and never read missing Bun as non-interactive intent.
- `--no-interactive-loop` → human, chat-only: show the Phase-D summary and plan in chat, then wait for explicit approval. Do not start the browser loop.
- `--non-interactive` → explicit headless: skip the browser loop and use the gate-free Degrade path below.
- If nobody answers the gate and no explicit non-interactive intent was given, stop; inference may never skip the gate.
## Resume
- In the same agent task/session, validate `.webmcp/.run.json` v1 for this canonical workspace and call its run-aware `/healthz?capability=...&run_id=...`. If live, reprint `/?capability=...&run_id=...`, restore that task's available Codex-hook or Claude-Monitor wake path from `references/interactive.md` (otherwise use same-task manual replay), then scan valid current-run envelopes without a handled ack in numeric `order`.
- In the same task, a valid run with a dead server may use `server.ts <workspace> --resume`; use only its printed URL/runtime metadata, restore the same task's delivery, reconcile partial effects, and continue. Runtime metadata absent/invalid means there is no safely resumable identity.
- A fresh task does not inherit the old run's automatic hook binding. It may reconcile current unacked envelopes manually. For continued automatic browser interaction, explicitly rotate per `references/interactive.md`: shut down a live old server or abandon dead runtime metadata, then use normal `server.ts <workspace>` without `--resume` and establish the new task's own run/session. Socket delivery and hook claims are hints; matching journal envelopes plus `_ack.ndjson` remain the truth.
## Degrade paths
- No category match → say so; do not force a weak fit.
- Most must-haves unwireable → **proposal-only** is a legitimate terminal outcome: deliver the reviewed plan, no code, and say why. That is benchmark signal, not failure.
- Explicit `--non-interactive` → proceed automatically: record the plan verbatim as the PR body/summary, implement each needs-your-input item on its stated default, and restate each in the summary as an assumption — the question, the default taken, and why.
- No runnable browser → mark tools could-not-verify and still ship plan-conformant code.
## Environment
- If the working directory ships its own site runbook (lifecycle commands, base URL, test identities — e.g. an eval capsule), use it for boot/reset; otherwise use the repo's own scripts. Never assume a harness exists.
- Browser verification needs WebMCP active: Chrome 150+ flag or `@mcp-b/webmcp-polyfill` — recipe in `references/verify.md`.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!