cf-webmcp
A Cloudflare Worker that sits in front of a website and equips it with WebMCP. One TOML file in, every WebMCP-aware browser sees the site's tools out.
Not affiliated with Cloudflare. The
cf-prefix only reflects that the project runs exclusively on Cloudflare primitives - this is not an official Cloudflare product.
What it does
For each request, the Worker does one of two things:
1. Handle a Worker-owned path directly.
| Path | What lives there |
|---|---|
/.well-known/webmcp (+ /.well-known/webmcp.json 301 alias) |
Tool-catalogue manifest, machine-readable JSON |
/.well-known/api-catalog |
RFC 9727 Linkset (RFC 9264) pointing at the manifest |
/.well-known/ai-catalog.json |
ARD publisher catalog (v0.9 draft) listing the site's Agent Skill; default OFF |
/.well-known/agents.md (+ /AGENTS.md, /agents.md 301 aliases) |
AGENTS.md augmentation block for acting agents |
/.well-known/agent-skills/<slug>/SKILL.md (+ case-variant 301 aliases) |
Anthropic-format Agent Skill, auto-generated from [[tools]] plus publisher hints |
/.well-known/agent-skills/index.json |
Cloudflare Agent Skills Discovery RFC v0.2.0 index with build-time SHA-256 digest |
/llms.txt |
Origin's llms.txt with a WebMCP block merged in |
/robots.txt |
Origin's robots.txt with Disallow: /_webmcp/ merged in |
/mcp |
Landing page: native-API, desktop-pairing, or disabled state |
/_webmcp/exec/<tool> |
Tool execution endpoint (POST) |
/_webmcp/bootstrap.<hash>.js |
In-page tool registration script |
/_webmcp/widget.<hash>.js |
Optional desktop-bridge widget |
/_webmcp/health |
Operational health endpoint |
2. Otherwise, proxy to origin and modify the response on the way back.
- HTTP
Linkheader added to every proxied response (HTML, PDF, image, JSON, anything). One entry per discovery surface:rel="webmcp"to the manifest,rel="api-catalog"to the catalog,rel="agent-skills"to the SKILL.md. An agent doing aHEADrequest finds all three without parsing a body. - On HTML responses only (status 200,
text/html, UTF-8, path not in[injection].exclude_paths), HTMLRewriter injects:- matching
<link>tags into<head>(rel="webmcp",rel="api-catalog",rel="agent-skills"), - one
<script src="/_webmcp/bootstrap.<hash>.js" defer>before</body>that auto-registers the tools via the WebMCP runtime (document.modelContext, falling back to the deprecatednavigator.modelContext), skipping any tool name already declared on the page as a<form toolname>so a name is never registered twice, - W3C declarative form attributes (
toolname,tooldescription,toolparamdescription,toolautosubmit) stamped onto matching<form>elements when a[[forms]]block matches the current path.
- matching
Non-HTML responses (PDFs, images, JSON, CSS, JS, etc.) pass through with their body unchanged but with the Link header added.
The tool catalogue lives in one TOML file. Five server-side executor types (sitemap_filter, rss_feed, dom_extract, http_json, http_get) cover the imperative tool path; [[forms]] blocks cover the declarative-form path. Three deploy templates ship: default, wordpress, woocommerce (Store API).
Discovery surfaces
cf-webmcp publishes the same tool catalogue through multiple complementary surfaces, all driven from the single TOML:
/.well-known/webmcp(manifest, machine-readable)<link rel="webmcp">injected into every HTML pageLink: rel="webmcp"HTTP header on every response/llms.txtaugmented with a WebMCP block (idempotent merge with origin's file). Also advertised in theLinkheader and as<link rel="describedby" type="text/markdown">via the IANA-registered RFC 8288 relation, so generic agent-aware scanners that only recognise standard rels find a description of the site./robots.txtaugmented withDisallow: /_webmcp/(idempotent merge)/.well-known/agents.mdfor acting agents, with/AGENTS.mdand/agents.md301-redirecting to it/.well-known/api-catalog(RFC 9727) Linkset entry pointing at the WebMCP manifest. Also advertised in theLinkheader and as<link rel="api-catalog">on every response./.well-known/agent-skills/<slug>/SKILL.mdAnthropic-format Agent Skill with auto-generated tool list + publisher-written hints. Also advertised viarel="agent-skills"in theLinkheader and as a<link>tag./.well-known/agent-skills/index.json(Cloudflare Agent Skills Discovery RFC v0.2.0) wraps the SKILL.md in a spec-compliant index with a build-time SHA-256 digest for integrity verification.links.agent_skills_indexfield added to the manifest./.well-known/ai-catalog.json(ARD v0.9 draft) publisher catalog with one entry derived from the Agent Skill. Default OFF (spec not yet stable). Advertised viarobots.txtAgentmap directive,rel="ai-catalog"Link header and link tag, and llms.txt when enabled. Publisher half only: no registry REST API, no signing, no DNS discovery. Seedocs/ai-catalog.md./mcplanding page that branches at runtime between native, pair, and disabled states
Plus five executor types (sitemap_filter, rss_feed, dom_extract, http_json, http_get) for the imperative tool path, and a [[forms]] block for the declarative form path.
[!NOTE] Every surface above is opt-in. Each one maps to a single boolean in your
[features]block. If you disagree with a convention or do not want to publish it, flip the flag off and the route disappears, the link advertisement drops out, and no fingerprint is left.llms.txtis the most widely-debated example: setllms_txt = falseand cf-webmcp stops claiming the path entirely. Same applies toagents.md,api-catalog,agent-skills,fallback_widget, form-attribute injection, and the in-page<script>bootstrap. Defaults are "on" because cf-webmcp's value is publishing discovery surfaces; opting out is one TOML edit away. Seedocs/scope.mdfor what is in and out of scope at the project level.
Quick start
git clone https://github.com/basgr/cf-webmcp
cd cf-webmcp
cp templates/default.toml webmcp.toml
cp wrangler.example.toml wrangler.toml
# edit webmcp.toml: set [site], [origin], and tool URLs
# edit wrangler.toml: set the route for your domain
npm install
npm run build
wrangler deploy
Validation
You can verify a cf-webmcp deployment with a tool that does not know anything about your TOML or config - it only sees the rendered page. Lighthouse 13.3.0 ships an agentic-browsing audit category that does exactly this.
Running it against the demo's /forms page (Chrome Canary 150.x, verified 28 Aug 2026, WebMCP flag on) returns a perfect category score:
agent-accessibility-tree- passwebmcp-registered-tools- finds all 3 imperative tools from the injected bootstrap plus both declarative form tools (the cf-webmcp-stamped form and a hand-stamped control)webmcp-form-coverage- not applicable (every form on the page is already annotated)webmcp-schema-validity- pass (generatedinputSchemablocks validate)llms-txt- pass
A third-party auditor seeing only the HTTP response confirms both the auto-injected and the manually-stamped tools, which is the same vantage point external agent-readiness checkers use.
Documentation
Full reference docs live in docs/:
Getting started
- Deployment - full-proxy vs route-only modes, wrangler config, Bot Management bypass.
- Local testing -
wrangler devagainst the bundledtemplates/example-site/fixture. - Browser support - enabling the WebMCP flag in Chrome and verifying it.
Configuration
- Customisation - overriding the
/mcplanding template, placeholders, runtime state branching. - Form injection - the
[[forms]]block, declarativetoolname/tooldescription/toolparamdescription/toolautosubmitattribute stamping. - AGENTS.md -
/.well-known/agents.mdpublication + 301 aliases. - API catalog (RFC 9727) - the
/.well-known/api-catalogLinkset. - ARD ai-catalog - the
/.well-known/ai-catalog.jsonARD publisher catalog (default OFF). - Agent Skills - the
/.well-known/agent-skills/<slug>/SKILL.mdpublication.
Operations
- Costs - Workers, R2, and cache pricing under typical traffic.
- Privacy - what's logged, what's stripped from origin fetches, GDPR posture.
- Upgrade -
schema_versionpolicy, tool-name immutability, breaking-change procedure. - Limitations - SPA story, multi-language sites, service workers, other known edges.
Project
- Scope - what cf-webmcp is and is not. Read this before opening a feature request.
- Security model - tool descriptions are not a security boundary; what cf-webmcp does and does not defend against.
Acknowledgements
- Suganthan Mohanadasan, "WebMCP: I Made My Website AI Agent Ready" - the implementation guide that informed the publisher-side discovery patterns.
- jasonjmcghee/WebMCP - the fallback widget that bridges desktop MCP clients to WebMCP sites.
- webmachinelearning/webmcp - the W3C draft.
- specification.website (Joost de Valk) - independent worked-example reference for agent-ready websites; converges on the same
/.well-known/agent-skills/index.json, RFC 9727api-catalog,rel="describedby"for llms.txt, andrel="agent-skills"conventions that cf-webmcp ships. - Chudi Nnorukam, "A Developer's Guide to WebMCP" - hands-on WebMCP shipping guide; informed the extensionless
/.well-known/webmcppath and the bootstrap's runtime-compat work (host detection acrossnavigator/document.modelContextand the MCP{ content: [...] }tool-result shape), and independently measured ~0% WebMCP adoption across 111k domains.
License
MIT. See LICENSE.
No comments yet
Be the first to share your take.