WebMCP at the edge.
A Cloudflare Worker that equips any website with WebMCP from a single TOML config. Browser-native agents see your site's tools automatically. Desktop MCP clients pair through a dedicated page.
Get started Source on GitHubHow it works
The Worker sits in front of your domain. On every request it does one of two things:
- If the request matches a Worker-owned path (manifest,
/mcplanding for GET and HEAD,/_webmcp/exec/*,/_webmcp/health,/llms.txt,/robots.txt,/.well-known/agents.mdand its 301 aliases,/.well-known/api-catalog,/.well-known/agent-skills/site/SKILL.mdand its case-variant aliases,/.well-known/agent-skills/index.json,/.well-known/ard.jsonand its 301 alias/.well-known/ai-catalog.json), handle it directly. - Otherwise proxy the request to origin. Two modifications happen on the way back to the visitor:
- HTTP
Linkheader added on every proxied response - HTML, PDF, image, JSON, anything. One entry per discovery surface:rel="webmcp"to the manifest,rel="api-catalog"to the RFC 9727 catalog,rel="ard"to the ARD manifest,rel="agent-skills"to the SKILL.md,rel="describedby"to llms.txt. An agent doing aHEADrequest finds them all without parsing a body. - On HTML responses only (status 200,
text/html, UTF-8, path not excluded), HTMLRewriter injects matching<link>tags into<head>(rel="webmcp",rel="api-catalog",rel="ard",rel="agent-skills", andrel="describedby"andrel="alternate"to llms.txt) and a<script src="https://<request host>/_webmcp/bootstrap.<hash>.js" defer integrity="sha384-..." crossorigin="anonymous">before</body>that auto-registers the tools viadocument.modelContext(falling back to the deprecatednavigator.modelContext). Non-HTML responses pass through unchanged in their body. - If a
[[forms]]block matches the current path, declarative WebMCP attributes (toolname,tooldescription,toolparamdescription,toolautosubmit) are stamped onto matching forms in the HTML response.
- HTTP
What you get
Manifest
Static tool catalogue at /.well-known/webmcp (/.well-known/webmcp.json 301s here).
Auto-registration
Site-wide document.modelContext.registerTool (falling back to navigator.modelContext) for browser-native agents.
Discovery
HTTP Link header and matching <link> tags on every page, advertising the manifest (rel="webmcp"), API catalog (rel="api-catalog"), Agent Skill (rel="agent-skills"), and ARD manifest (rel="ard").
Landing page
/mcp lists the site's tools and registers them in browsers with WebMCP. With the fallback widget on, it walks desktop MCP clients through pairing with a local bridge.
llms.txt + robots.txt
Augmented with WebMCP discovery hints, idempotently merged.
AGENTS.md
Auto-published at /.well-known/agents.md with 301 aliases for /AGENTS.md and /agents.md.
API catalog
RFC 9727 Linkset at /.well-known/api-catalog pointing at the WebMCP manifest. Merges with origin's catalog if present.
Agent Skill + Discovery
SKILL.md at /.well-known/agent-skills/site/SKILL.md with auto-generated tool list and publisher hints. Wrapped by an index at /.well-known/agent-skills/index.json with a SHA-256 digest per the Cloudflare Agent Skills Discovery RFC v0.2.0 so spec-aware agents verify integrity before parsing.
ARD manifest
Agentic Resource Discovery (ARD v0.91) manifest at /.well-known/ard.json listing the site's Agent Skill so ARD registries can index it. The old path /.well-known/ai-catalog.json answers with a 301 to it. Publisher half only. Advertised via a robots.txt Agentmap directive, rel="ard", and llms.txt.
Form injection
Stamp toolname / tooldescription / toolparamdescription onto existing forms at the edge from a [[forms]] TOML block.
Five executors
sitemap_filter, rss_feed, dom_extract, http_json, http_get.
Every surface can be switched off
Each card above is a single boolean in your [features] block. Disagree with a convention or do not want to publish it? Flip it off and the route disappears, the link advertisement drops out, and no fingerprint is left. For example llms.txt is widely debated; if you would rather not serve it set llms_txt = false and cf-webmcp stops claiming the path. Same applies to agents.md, the API catalog, the Agent Skill, the ARD manifest, the 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. Two are off by default and need opting in: the ARD manifest (ai_catalog; ARD is a proposal) and the fallback widget (fallback_widget; it needs the widget in R2 and a bridge program on the visitor's computer).
Two minutes to deploy
git clone https://github.com/basgr/cf-webmcp
cd cf-webmcp
cp templates/wordpress.toml webmcp.toml
cp wrangler.example.toml wrangler.toml
# edit webmcp.toml + wrangler.toml
npm install
npm run build
wrangler deploy
Three templates ship: default, wordpress, woocommerce. All three turn on the fallback widget, which needs an R2 bucket and the widget uploaded before wrangler deploy. See Install for the commands.