diff --git a/README.md b/README.md index 7cfcaca..79aa9e0 100644 --- a/README.md +++ b/README.md @@ -1,198 +1,229 @@ -# webmcpify — the WebMCP agent skill +

webmcpify — the WebMCP agent skill

+ +

+ + + webmcpify — make any web app agent-ready, verifiably. The WebMCP agent skill for existing web apps. + +

+ +

+ Latest release + Checks + MIT license + WebMCP: document.modelContext +

+ +

+ Website · + Docs · + Install · + Demo · + Changelog +

+ +**webmcpify** is an agent skill that makes an **existing** web app callable by browser +AI agents through [WebMCP](https://webmachinelearning.github.io/webmcp/) — +`document.modelContext`, the proposed standard incubated in the W3C Web Machine +Learning Community Group and in Chrome origin trial. Your coding agent inventories +the app, proposes a tool manifest for your approval, integrates the tools with a +tiny vendored runtime, and **proves each one works in real Chrome**. Unrelated code +stays untouched — from a static landing page to a multi-tenant SaaS. -**Make any web app agent-ready — verifiably.** - -🌐 **[webmcpify.at](https://webmcpify.at)** — the site itself is webmcpified: open it with a WebMCP-enabled agent and call its tools. - -webmcpify is a WebMCP agent skill for **curated core coverage or route-by-route -parity**. It integrates [WebMCP](https://webmachinelearning.github.io/webmcp/) -(`document.modelContext` — a proposed web standard incubated in the W3C Web Machine -Learning Community Group, currently in Chrome origin trial) into an **existing** -web application — from a static landing page to a large multi-tenant SaaS — end to end: - -``` -DETECT ─▶ INVENTORY ─▶ [you approve the tool manifest] ─▶ INTEGRATE ─▶ VERIFY ─▶ HEAL ─▶ AUDIT - loop loop loop loop +```sh +npx skills add TueJon/webmcpify # once +/webmcpify # in your app's repo, inside your coding agent ``` -Your coding agent investigates the codebase, asks whether you want a curated set of -high-value actions or an auditable per-route interaction census, then proposes a -**tool manifest** with names, schemas, examples, coverage reasons, and a read-only/ -mutating classification. After your approval it integrates the tools, **exercises -each one in a real browser**, and heals failures—while keeping unrelated logic and -UI untouched. - -## See native Chrome verification - -**[Watch the uncut 63-second runtime demo](proof/artifacts/webmcpify-proof-480p.mp4)** — -a prepared local fixture passes a real approval click, registers one client-only -tool, then exercises native `document.modelContext.getTools()` / `executeTool()` -verification, a visible UI change, invalid-input handling, and cleanup. - -The runtime registration and browser assertions are real. The phase labels are -advanced by a deterministic script for legibility; the recording does not execute -the skill's inventory, integration, or audit phases. The [`proof/`](proof/README.md) -pack includes the runnable fixture, prepared before/after example manifests, an -illustrative integration patch, and artifact checksums. Reproduce the native-browser -checks with `npm run proof:verify`. - -## Why - -Browser AI agents (Gemini in Chrome, extensions, assistive tech) are learning to -call structured page tools instead of scraping the DOM. WebMCP is the emerging -standard for that, co-authored by Google and Microsoft engineers, in origin trial -since Chrome 149. Making an app agent-ready by hand means reading a spec that is -still moving (the API surface has changed repeatedly during the trial), learning tool-design -conventions, and building a verification setup — webmcpify packages all of that -into one command for your coding agent. +> [!TIP] +> **New in [v0.6.0](https://github.com/TueJon/webmcpify/releases/tag/v0.6.0):** +> evidence-aware resume — changed app files, contracts or browsers invalidate the +> verification they affect — plus scoped browser access and independent checks for +> every mutation. + +## How it works + +

+ + + Pipeline: detect, inventory, you approve the tool manifest, integrate, verify in real Chrome, heal failures with capped retries, audit. Every phase reads and writes .webmcpify/manifest.json. + +

+ +- **One human checkpoint.** You approve the tool manifest: names, schemas, examples, + coverage reasons, and a read-only or mutating class per tool. After that the agent + only comes back for what it genuinely can't resolve — an app that won't start, or a + tool that still fails after its capped heal attempts. +- **Loops over persisted state.** Every phase reads and writes + `.webmcpify/manifest.json`, so a run resumes across sessions, context windows and + even different agents. Recorded evidence tells it which checks are still valid. +- **Proof, not promises.** Each tool is enumerated and executed through Chrome's + native `getTools()` / `executeTool()`, asserting on the tool result **and** the + resulting UI state. + +## What your agent adds to your app + +From the [reproducible proof fixture](proof/README.md). First, the manifest entry +you approve at the gate (abridged): + +```jsonc +{ + "id": "set_release_filter", + "mutating": "client", // browser state only — no server write + "inputSchema": { + "type": "object", + "properties": { "category": { "type": "string", "enum": ["all", "feature", "fix"] } }, + "required": ["category"], + "additionalProperties": false + }, + "source": ["proof/demo/app.js:applyFilter"], // the UI's existing code path + "examples": { "valid": { "category": "fix" }, "invalid": { "category": "private" } }, + "expect": { "result": "2 release notes visible", + "ui": "only the two synthetic fix notes remain visible" }, + "cleanup": "execute the same UI path with category=all" +} +``` -## Install (one command) +Then the integration: a registration that calls the code path the UI already uses, +through the vendored runtime. + +```js +import { createToolScope } from './webmcpify.js'; // vendored, MIT, ~290 lines +import { applyFilter } from './app.js'; // existing UI logic, unchanged + +createToolScope('proof-release-notes', [{ + name: 'set_release_filter', + description: 'Filters the visible synthetic release notes by category ' + + "using the page's existing filter path.", + inputSchema: schema, // the approved schema above + annotations: { readOnlyHint: false, untrustedContentHint: false, consequentialHint: false }, + execute: ({ category }) => { + if (!schema.properties.category.enum.includes(category)) { + return 'ERROR: category must be one of all, feature, or fix.'; + } + return `${applyFilter(category)} release notes visible for ${category}.`; + }, +}]); // feature-detected: a safe no-op in browsers without WebMCP +``` -**Any agent** — Claude Code, Codex, Cursor, opencode, Copilot, and [70+ more](https://github.com/vercel-labs/skills): +## See it run -```sh -npx skills add TueJon/webmcpify -``` +

+ Watch the uncut 63-second runtime demo: approval click, native getTools and executeTool, UI change, invalid input, cleanup +

-**Claude Code** (as a plugin): +A prepared local fixture passes a real approval click, registers one client-only tool, +then exercises native `document.modelContext.getTools()` / `executeTool()`, a visible +UI change, invalid-input handling and cleanup. The runtime registration and browser +assertions are real; the phase labels are advanced by a script for legibility, so the +recording does not run the skill's inventory, integration or audit phases. Reproduce +the native checks with `npm run proof:verify`; the [`proof/`](proof/README.md) pack +holds the fixture, before/after manifests, an illustrative patch and checksums. -``` -/plugin marketplace add TueJon/webmcpify -/plugin install webmcpify@webmcpify -``` +## Install -**Manual**: copy [`skills/webmcpify/`](skills/webmcpify/) into your agent's skills -directory, or just tell your agent to follow -[`skills/webmcpify/SKILL.md`](skills/webmcpify/SKILL.md). +| Where | How | +|---|---| +| **Any agent** — Claude Code, Codex, Cursor, opencode, Copilot and [70+ more](https://github.com/vercel-labs/skills) | `npx skills add TueJon/webmcpify` | +| **Claude Code** plugin | `/plugin marketplace add TueJon/webmcpify` then `/plugin install webmcpify@webmcpify` | +| **Manual** | Copy [`skills/webmcpify/`](skills/webmcpify/) into your agent's skills directory, or tell your agent to follow [`SKILL.md`](skills/webmcpify/SKILL.md) | -The skill directory is self-contained — pipeline, phase guides, vendorable runtime, -and the verification template all ship inside it. +The skill directory is self-contained: pipeline, phase guides, vendorable runtime and +the verification template all ship inside it. ## Use -Open your agent in the target repo and pick your scope: - -``` -/webmcpify # full pipeline -/webmcpify inventory # just investigate + propose the tool manifest (zero code changes) -/webmcpify integrate # integrate the approved manifest -/webmcpify workbench # agent launches the temporary visual tool inspector -/webmcpify verify # verify + heal what's integrated -/webmcpify status # where are we? what's next? -/webmcpify full parity # census every interactive element on every authenticated route -``` +Open your agent in the target repo and pick a scope — or just say *"webmcpify this app"*. -(or in plain words: *"webmcpify this app"*, *"map what tools this app could expose"*) +| Command | What happens | Changes your code | +|---|---|---| +| `/webmcpify` | Full pipeline, resuming wherever the manifest says | After your approval | +| `/webmcpify inventory` | Investigate and propose the tool manifest | Never | +| `/webmcpify integrate` | Integrate the approved manifest in small batches | Yes | +| `/webmcpify workbench` | Agent launches a temporary visual tool inspector | No — development aid only | +| `/webmcpify verify` | Verify and heal what is integrated | Only to fix a failing tool | +| `/webmcpify status` | Where are we, what's next | Never (read-only) | +| `/webmcpify full parity` | Census every interactive element on every authenticated route | After your approval | -The pipeline has **one main checkpoint** — you approve the tool manifest (and, for -apps under git, choose whether integration batches are committed). Beyond that it -only comes back for things it genuinely can't resolve: an app that won't start, or -a tool that still fails after capped heal attempts. All state persists in -`.webmcpify/manifest.json`, so runs are **resumable** across sessions, context -windows, and even different agents. On resume, recorded app files, tool contracts, -runtime and browser inputs determine which verification evidence remains valid. -Changed or unknown dependencies require fresh checks; uncertain interrupted -mutations must be reconciled through a read path before retrying. These records -are skill-managed evidence, not an automatic dependency tracker or a WebMCP field. -See [re-verification](skills/webmcpify/references/reverify.md). +### Curated core or route-by-route parity -Verification uses a dedicated test context and approved origins, accounts and -fixtures. Official guidance is read directly; running an optional guidance package -requires an exact reviewed version and separate authorization. Mutation checks -compare the intended effect with an independent read path and an unchanged -neighbor or invariant. Optional model evals need approved data and explicit -run, time and spend limits; a smoke pass does not establish journey quality. +| | **Curated** | **Parity** | +|---|---|---| +| Goal | A usable toolset for the actions that matter | Auditable completeness | +| Output | Reviewed route → tool map for core actions | Per-route element census: every interaction maps to a tool or a written reason | +| Keeps it usable by | Priority waves, an overlap rule (no two tools match the same request), role/tenant coverage | Route-scoped registration; client-capacity gaps are reported, never guessed | -## Built to scale to large codebases +The agent asks you to choose before inventory — there is no silent default — and a +tool count alone is never called 100%. -Every phase is a **loop over persistent state**, not a one-shot pass: +## Guarantees -- **Inventory** maps the codebase into areas (routes/views/modules) first, then +| | Guarantee | How it's enforced | +|---|---|---| +| 🧩 | **Unrelated code stays untouched** | Every diff hunk traces to a manifest entry; a final audit checks against the recorded baseline commit; files already dirty at the start are never modified or reverted | +| 🔒 | **Read-only first** | Server mutations need your explicit per-tool approval; auth, signup, billing, payment and credential-returning tools stay excluded; irreversible deletes can only open the app's own confirmation UI | +| 🛡️ | **Your server stays the trust boundary** | Tools only call code paths your UI already uses — no new endpoints, no bypasses | +| 📦 | **Zero dependencies** | A small MIT runtime is vendored and feature-detected; the app behaves the same in browsers without WebMCP | +| 🚦 | **No ambiguous imperative results** | The runtime rejects accidental bare `null` / `undefined`; route-changing tools return a structured result before navigation and route-scope disposal | +| 🧪 | **Exercised, not assumed** | Every tool runs in real Chrome against the result and the UI state; mutations are confirmed through an independent read path with an unchanged neighbor; declarative forms get the real submit click | +| 📝 | **Crash-safe mutation checks** | A dependency-free host helper journals dispatches and cleanups, settles verified outcomes atomically, and serializes runners through an advisory-lock sidecar on Linux and macOS/FreeBSD | +| ♻️ | **Honest resume** | Changed files, contracts, runtimes or browsers invalidate the evidence they affect, unknown dependencies mean a full re-check, and interrupted mutations are reconciled before any retry ([re-verification](skills/webmcpify/references/reverify.md)) | +| 🔐 | **Scoped access** | A dedicated test context with approved origins, accounts and fixtures; official guidance is read directly, never executed as an unreviewed package | +| 🧭 | **Spec over scoreboard** | Checker findings are classified, not chased; the public discovery layer (`/.well-known/webmcp`) is a separate approval | + +
+Built to scale to large codebases + +- **Inventory** maps the codebase into areas (routes, views, modules) first, then deep-reads one area per iteration — a 500-file SaaS is processed area by area, - never in one context-busting sweep. Sub-agent fan-out writes per-area shard - files; a single coordinator merges them (no write races). -- **Coverage is explicit:** `curated` produces a reviewed route→tool map for core - actions; `parity` produces a per-route element census where every interaction is - mapped to a tool or a written reason. A tool count alone is never called 100%. -- **Tool budgets** keep curated SaaS toolsets usable: priority waves, an overlap rule - (no two tools matching the same request), and role/tenant coverage tracking. - Parity uses route-scoped registration and reports client-capacity gaps instead of - claiming an unmeasured universal per-page limit. -- **Integrate** works in small batches (one area or ≤5 tools), each independently - built and typechecked — committed per batch only if you opted in. -- **Verify/Heal** iterate per tool with attempt caps and honest escalation - instead of infinite loops; mutating tools get cleanup steps between retries. -- Interrupt at any point; the next run resumes from the manifest. Verification - evidence records app, contract and browser inputs; changed inputs trigger - bounded re-verification, while `status` remains read-only. - -## Guarantees + never in one context-busting sweep. Sub-agent fan-out writes per-area shard files; + a single coordinator merges them. +- **Integrate** works in batches of one area or at most five tools, each built and + typechecked — committed per batch only if you opted in. +- **Verify / Heal** iterate per tool with attempt caps and honest escalation; + mutating tools get cleanup steps between retries. +- **Interrupt anywhere.** The next run resumes from the manifest; `status` stays + read-only. + +
+ +
+Platform status and compatibility + +WebMCP is an **origin trial** (Chrome 149 onward; the stable milestone is an +estimate, not a commitment). Production exposure needs an +[origin-trial token](https://developer.chrome.com/origintrials/); local development +needs `chrome://flags/#enable-webmcp-testing`. The API has already changed during +the trial (testing API removed 2026-07; `navigator` → `document`) — webmcpify +isolates that churn in one vendored file, and its verification probes whether the +browser takes current object input or Chrome 150's legacy JSON-string input without +retrying real tools. Integration reads the official Chrome guides and the CG draft +directly. + +ChatGPT's separate, model- and account-gated client surface is documented as +[Site tools](skills/webmcpify/references/client.md), with dated availability facts +and a troubleshooting order. Release-by-release spec adaptations are in the +[changelog](CHANGELOG.md). -- **Unrelated logic and UI stay untouched** — every diff hunk traces to a manifest - entry; a final audit against the recorded baseline commit enforces it, and files - that were already dirty when the run started are never modified or reverted. -- **Read-only first** — server mutations require your explicit per-tool approval. - Auth, signup, billing, payment and credential-returning tools stay excluded; - irreversible delete actions can only open the app's existing confirmation UI. -- **Server stays the trust boundary** — tools only call code paths your UI already - uses; no new endpoints, no bypasses. -- **Spec-shaped, zero dependencies** — a small MIT runtime is vendored into your - repo (no npm dependency), everything feature-detected: your app is - **behaviorally unchanged** in browsers without WebMCP. -- **No ambiguous imperative results** — the runtime guards accidental bare - `null`/`undefined`, and route-changing tools return a structured result before - deferring navigation and route-scope disposal. -- **Exercised, not assumed** — every tool is enumerated and executed in real - Chrome, asserting on both the tool result and the resulting UI state, from - examples recorded in the manifest. That includes mutating declarative forms, - where Chrome pauses the execution until a real submit interaction — the - harness performs that submit click mid-execution instead of faking the pass. -- **Crash-safe mutation checks** — a dependency-free host helper journals every - mutating dispatch and cleanup before execution, atomically settles verified - outcomes, and serializes runners with a permanent advisory-lock sidecar on - Linux (`flock`) and macOS/FreeBSD (`lockf -k`). -- **Spec over scoreboard** — WebMCP checkers and inspector extensions grade pages - against a mix of spec features, conventions, and invented checks. webmcpify - classifies their findings instead of chasing them: it never emits - non-existent attributes or adds markup an app doesn't need to raise a score. - Optional off-page discovery (a `/.well-known/webmcp` manifest, `rel="webmcp"` - links) is a separately approved layer, because it publishes tool metadata - publicly — never part of a default integration. +
## What's in this repo | Path | Purpose | |---|---| -| [`skills/webmcpify/SKILL.md`](skills/webmcpify/SKILL.md) | The pipeline (what your agent follows) | -| [`skills/webmcpify/references/`](skills/webmcpify/references/) | Phase guides: inventory, integrate, Workbench, runtime, verify, heal, security, discovery | +| [`skills/webmcpify/SKILL.md`](skills/webmcpify/SKILL.md) | The pipeline your agent follows | +| [`skills/webmcpify/references/`](skills/webmcpify/references/) | Phase guides: inventory, integrate, Workbench, runtime, verify, re-verify, heal, security, discovery, client surfaces | | [`skills/webmcpify/templates/`](skills/webmcpify/templates/) | Vendorable runtime (TS + JS), durable mutation journal, temporary visual Workbench, ambient types, Playwright verification template, discovery manifest | - -## Status - -WebMCP itself is an **origin trial** (Chrome 149 →; the stable milestone is an -estimate, not a commitment): production exposure needs an -[origin-trial token](https://developer.chrome.com/origintrials/), local development -needs `chrome://flags/#enable-webmcp-testing`. The API surface has already changed -during the trial (testing API removed 2026-07; `navigator` → `document`) — webmcpify -isolates that churn in one vendored file, and its verification surfaces probe -whether the browser uses current object input or Chrome 150's legacy JSON-string -input without retrying real tools. It reads the official Chrome guides and CG draft directly at integration time. -The optional modern-web-guidance CLI requires a reviewed exact version and -separate approval before execution. - -Release-by-release spec adaptations are recorded in the [changelog](CHANGELOG.md). -ChatGPT's separate, model/account-gated client surface is documented as -[Site tools](skills/webmcpify/references/client.md), with dated availability facts -and a troubleshooting order. +| [`proof/`](proof/README.md) | Reproducible native-Chrome proof: fixture, manifests, recording, checksums | ## Related projects -- [webmcpify.at](https://webmcpify.at) — project website (itself agent-ready, in all three layers: imperative tools via the vendored runtime, a declarative install form, and a published `/.well-known/webmcp` manifest) +- [webmcpify.at](https://webmcpify.at) — the project website, itself agent-ready in all three layers: imperative tools via the vendored runtime, a declarative install form, and a published `/.well-known/webmcp` manifest - [webmachinelearning/webmcp](https://github.com/webmachinelearning/webmcp) — the spec draft (W3C WebML CG) -- [GoogleChromeLabs/webmcp-tools](https://github.com/GoogleChromeLabs/webmcp-tools) — Google's demos, types, and evals CLI (webmcpify follows these patterns) +- [GoogleChromeLabs/webmcp-tools](https://github.com/GoogleChromeLabs/webmcp-tools) — Google's demos, types and evals CLI (webmcpify follows these patterns) - [GoogleChrome/modern-web-guidance](https://github.com/GoogleChrome/modern-web-guidance) — official best-practice guides (optional CLI; exact version and execution approval required) - [Puppeteer WebMCP](https://pptr.dev/guides/webmcp) — experimental first-class WebMCP automation API (Chrome 151+ as documented 2026-08-29; alternative verify harness) -- [MCP-B / WebMCP-org](https://github.com/WebMCP-org/npm-packages) — WebMCP ecosystem: polyfill, extension, transports, and dev tooling (webmcpify vendors a minimal runtime instead of adding dependencies) +- [MCP-B / WebMCP-org](https://github.com/WebMCP-org/npm-packages) — polyfill, extension, transports and dev tooling (webmcpify vendors a minimal runtime instead of adding dependencies) ## License diff --git a/assets/readme/banner-dark.svg b/assets/readme/banner-dark.svg new file mode 100644 index 0000000..8cae808 --- /dev/null +++ b/assets/readme/banner-dark.svg @@ -0,0 +1,41 @@ + + webmcpify — the WebMCP agent skill + Make any web app agent-ready, verifiably: an agent calls typed tools that webmcpify registers in your existing app. + + + + + + + webmcpify + Make any web app agent-ready — verifiably. + The WebMCP agent skill for existing web apps: inventory, + approve, integrate, then verify every tool in real Chrome. + document.modelContextzero dependenciesMIT + + + + your-app.example + + search_products() + add_to_cart() + track_order() + + + + agent + tool calls + + + + + + VERIFIED ✓ + + diff --git a/assets/readme/banner-light.svg b/assets/readme/banner-light.svg new file mode 100644 index 0000000..9944e56 --- /dev/null +++ b/assets/readme/banner-light.svg @@ -0,0 +1,41 @@ + + webmcpify — the WebMCP agent skill + Make any web app agent-ready, verifiably: an agent calls typed tools that webmcpify registers in your existing app. + + + + + + + webmcpify + Make any web app agent-ready — verifiably. + The WebMCP agent skill for existing web apps: inventory, + approve, integrate, then verify every tool in real Chrome. + document.modelContextzero dependenciesMIT + + + + your-app.example + + search_products() + add_to_cart() + track_order() + + + + agent + tool calls + + + + + + VERIFIED ✓ + + diff --git a/assets/readme/build.mjs b/assets/readme/build.mjs new file mode 100644 index 0000000..f72020a --- /dev/null +++ b/assets/readme/build.mjs @@ -0,0 +1,155 @@ +// Generates the README artwork (banner + pipeline) in light and dark variants. +// Both variants share one layout; only the color tokens differ, so they cannot drift. +// Run: node assets/readme/build.mjs (tests/readme-art.test.mjs fails on stale output) +import { writeFileSync } from 'node:fs'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const here = dirname(fileURLToPath(import.meta.url)); + +export const themes = { + light: { + panel: '#f8f7fd', panelStroke: '#e4e2ee', ink: '#14121c', muted: '#555365', + hairline: '#d9d6e6', primary: '#653ec7', primaryInk: '#4c279f', tint: '#efebfd', + node: '#ffffff', gate: '#653ec7', onGate: '#ffffff', logoFill: '#f5f3fb', skeleton: '#c9c6d6', + }, + dark: { + panel: '#12111c', panelStroke: '#2c2a3b', ink: '#eeedf5', muted: '#a4a2b7', + hairline: '#3a3850', primary: '#a492fb', primaryInk: '#c3b6ff', tint: '#1d1930', + node: '#0d0c15', gate: '#7a58ea', onGate: '#ffffff', logoFill: '#1d1930', skeleton: '#3c3a4e', + }, +}; + +const SANS = "'Familjen Grotesk','Segoe UI',system-ui,-apple-system,'Helvetica Neue',Arial,sans-serif"; +const MONO = "'Spline Sans Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,'Liberation Mono',monospace"; + +const esc = (s) => s.replace(/&/g, '&').replace(//g, '>'); + +function styles(t) { + return ``; +} + +const arrowHead = (x, y, dir) => { + // Small filled triangle whose tip sits at (x, y). + const d = { right: `M${x} ${y} l-9 -4.5 v9 z`, down: `M${x} ${y} l-4.5 -9 h9 z`, left: `M${x} ${y} l9 -4.5 v9 z` }; + return ``; +}; + +export function banner(t) { + const chips = ['document.modelContext', 'zero dependencies', 'MIT']; + let x = 44; + const chipSvg = chips.map((label) => { + const w = Math.round(label.length * 7.7 + 26); + const out = `` + + `${esc(label)}`; + x += w + 10; + return out; + }).join(''); + const rows = [110, 156, 202]; + const tools = ['search_products()', 'add_to_cart()', 'track_order()']; + return ` + webmcpify — the WebMCP agent skill + Make any web app agent-ready, verifiably: an agent calls typed tools that webmcpify registers in your existing app. + ${styles(t)} + + + + + + webmcpify + Make any web app agent-ready — verifiably. + The WebMCP agent skill for existing web apps: inventory, + approve, integrate, then verify every tool in real Chrome. + ${chipSvg} + + + + your-app.example + + ${rows.map((y, i) => `` + + `${tools[i]}`).join('\n ')} + + + + agent + tool calls + ${arrowHead(836, 128, 'left')} + ${arrowHead(836, 174, 'left')} + ${arrowHead(836, 220, 'left')} + + + VERIFIED ✓ + + +`; +} + +const stages = [ + { name: 'DETECT', lines: ['stack, routes,', 'auth and state'] }, + { name: 'INVENTORY', lines: ['reads area by area,', 'proposes a tool', 'manifest'], loop: '↻ per area' }, + { name: 'YOU APPROVE', lines: ['names, schemas,', 'read-only or', 'mutating — per tool'], gate: true }, + { name: 'INTEGRATE', lines: ['vendored runtime,', 'built + typechecked'], loop: '↻ per batch' }, + { name: 'VERIFY', lines: ['real Chrome:', 'result + UI state'] }, + { name: 'HEAL', lines: ['fixes only that', 'tool, capped'] }, + { name: 'AUDIT', lines: ['every diff hunk', 'maps to the manifest'] }, +]; + +export function pipeline(t) { + const cx = (i) => 86 + i * 138; + const half = 58; + const top = 158; + const parts = []; + stages.forEach((s, i) => { + const x = cx(i); + parts.push(``); + parts.push(`${s.name}`); + s.lines.forEach((line, j) => parts.push(`${esc(line)}`)); + parts.push(``); + if (i < stages.length - 1) { + parts.push(`${arrowHead(cx(i + 1) - half - 2, 182, 'right')}`); + } + if (s.loop) { + parts.push(`${arrowHead(x - 34, 156, 'down')}`); + parts.push(`${s.loop}`); + } + if (s.gate) parts.push(`◆ human gate`); + }); + // VERIFY ⇄ HEAL: failed tools go to HEAL, then back to VERIFY until they pass or hit the cap. + const v = cx(4); const h = cx(5); + parts.push(`${arrowHead(v + 8, 156, 'down')}`); + parts.push(`↻ re-verify, capped`); + return ` + The webmcpify pipeline + Detect, inventory, human approval of the tool manifest, integrate, verify in real Chrome, heal failures with capped retries, audit. Every phase reads and writes .webmcpify/manifest.json. + ${styles(t)} + + FIG. 2 — THE PIPELINE + ↻ loops over persisted state + + ${parts.join('\n ')} + + + .webmcpify/manifest.json + single source of truth — every phase reads and writes it + ✓ resumes across sessions, context windows and agents + ✓ keeps verification evidence per tool + +`; +} + +export const outputs = { + 'banner-light.svg': () => banner(themes.light), + 'banner-dark.svg': () => banner(themes.dark), + 'pipeline-light.svg': () => pipeline(themes.light), + 'pipeline-dark.svg': () => pipeline(themes.dark), +}; + +if (process.argv[1] === fileURLToPath(import.meta.url)) { + for (const [name, render] of Object.entries(outputs)) writeFileSync(join(here, name), render()); +} diff --git a/assets/readme/demo-poster.webp b/assets/readme/demo-poster.webp new file mode 100644 index 0000000..ec90edb Binary files /dev/null and b/assets/readme/demo-poster.webp differ diff --git a/assets/readme/pipeline-dark.svg b/assets/readme/pipeline-dark.svg new file mode 100644 index 0000000..c1e084c --- /dev/null +++ b/assets/readme/pipeline-dark.svg @@ -0,0 +1,71 @@ + + The webmcpify pipeline + Detect, inventory, human approval of the tool manifest, integrate, verify in real Chrome, heal failures with capped retries, audit. Every phase reads and writes .webmcpify/manifest.json. + + + FIG. 2 — THE PIPELINE + ↻ loops over persisted state + + + DETECT + stack, routes, + auth and state + + + + INVENTORY + reads area by area, + proposes a tool + manifest + + + + ↻ per area + + YOU APPROVE + names, schemas, + read-only or + mutating — per tool + + + ◆ human gate + + INTEGRATE + vendored runtime, + built + typechecked + + + + ↻ per batch + + VERIFY + real Chrome: + result + UI state + + + + HEAL + fixes only that + tool, capped + + + + AUDIT + every diff hunk + maps to the manifest + + + ↻ re-verify, capped + + + .webmcpify/manifest.json + single source of truth — every phase reads and writes it + ✓ resumes across sessions, context windows and agents + ✓ keeps verification evidence per tool + diff --git a/assets/readme/pipeline-light.svg b/assets/readme/pipeline-light.svg new file mode 100644 index 0000000..86f42f1 --- /dev/null +++ b/assets/readme/pipeline-light.svg @@ -0,0 +1,71 @@ + + The webmcpify pipeline + Detect, inventory, human approval of the tool manifest, integrate, verify in real Chrome, heal failures with capped retries, audit. Every phase reads and writes .webmcpify/manifest.json. + + + FIG. 2 — THE PIPELINE + ↻ loops over persisted state + + + DETECT + stack, routes, + auth and state + + + + INVENTORY + reads area by area, + proposes a tool + manifest + + + + ↻ per area + + YOU APPROVE + names, schemas, + read-only or + mutating — per tool + + + ◆ human gate + + INTEGRATE + vendored runtime, + built + typechecked + + + + ↻ per batch + + VERIFY + real Chrome: + result + UI state + + + + HEAL + fixes only that + tool, capped + + + + AUDIT + every diff hunk + maps to the manifest + + + ↻ re-verify, capped + + + .webmcpify/manifest.json + single source of truth — every phase reads and writes it + ✓ resumes across sessions, context windows and agents + ✓ keeps verification evidence per tool + diff --git a/tests/readme-art.test.mjs b/tests/readme-art.test.mjs new file mode 100644 index 0000000..972ad7c --- /dev/null +++ b/tests/readme-art.test.mjs @@ -0,0 +1,22 @@ +import assert from 'node:assert/strict'; +import { readFileSync } from 'node:fs'; +import test from 'node:test'; +import { outputs } from '../assets/readme/build.mjs'; + +test('README artwork matches its generator (run node assets/readme/build.mjs)', () => { + for (const [name, render] of Object.entries(outputs)) { + const committed = readFileSync(new URL(`../assets/readme/${name}`, import.meta.url), 'utf8'); + assert.equal(committed, render(), `${name} is stale`); + } +}); + +test('README references only existing artwork and both theme variants', () => { + const readme = readFileSync(new URL('../README.md', import.meta.url), 'utf8'); + assert.match(readme, /]*>[^<]*WebMCP agent skill[^<]*<\/h1>/, + 'README must retain a semantic h1 containing the discoverability phrase'); + for (const base of ['banner', 'pipeline']) { + assert.match(readme, new RegExp(`assets/readme/${base}-dark\\.svg`)); + assert.match(readme, new RegExp(`assets/readme/${base}-light\\.svg`)); + } + readFileSync(new URL('../assets/readme/demo-poster.webp', import.meta.url)); +});