Expand description
Server-side toolkit for WebMCP, the W3C Community Group proposal that lets a
web page register tools an in-browser AI agent can call through
document.modelContext (registerTool, getTools, executeTool).
WebMCP is not the server-to-server Model Context Protocol (MCP): MCP servers
(for example with rmcp) are called by desktop or CLI agents, while WebMCP
tools live in a browser tab and run with the signed-in user’s session. This
crate covers the server half of WebMCP and is framework-agnostic:
Tool::newvalidates a definition at boot: name 1–128 of[A-Za-z0-9_.-], WebMCP annotationsread_only/untrusted_content/consequential/debugging, a strict JSON Schema subset, a same-origin endpoint, GET only when read-only.Registryselects the tools each page exposes;Manifest::to_script_tagrenders them as a script-safe<script type="application/json">element.RUNTIME_JSis the shared browser runtime (zero dependencies). It registers the manifest’s tools and, when an agent calls one, calls the tool’s endpoint with the user’s session cookies and CSRF token, without following redirects and without retries. Serve it and reference it withruntime_script_tag.form_attrsandparam_attrrender the declarative form attributes.- Origin trial helpers, plus
OriginTrialLayerbehind thetowerfeature.
Endpoints keep authorization, CSRF checks and input validation; annotations are hints, not security controls. The same manifest format and runtime ship in the Ruby (reference), Go and Django packages. Spec baseline: WebMCP Draft CG Report 2026-10-02.
use serde_json::json;
use webmcp::{Endpoint, Manifest, ScriptTagOptions, Tool, ToolDef, Transport};
let mut definition = ToolDef::new("list_tasks", "List my tasks.",
json!({"type": "object"}), Endpoint::new("/api/tasks", "GET"));
definition.annotations.insert("read_only".into(), true);
let tool = Tool::new(definition)?;
let manifest = Manifest::build(&[&tool], Transport::default())?;
let html = manifest.to_script_tag(&ScriptTagOptions::default());
assert!(html.contains("data-webmcp-autostart"));With tower, OriginTrialLayer fills only missing response headers.
The axum feature enables Tower support for this documentation-only example;
the application supplies its own axum dependency:
use axum::{routing::get, Router};
use webmcp::OriginTrialLayer;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let app: Router = Router::new().route("/", get(|| async { "ok" }))
.layer(OriginTrialLayer::new("YOUR_TOKEN")?.warn_on_oac_opt_out(true));
Ok(())
}Structs§
- Csrf
- CSRF token location, read by the browser runtime on each invocation.
- Definition
Error - Invalid tool, schema, transport, registry, or form metadata.
- Endpoint
- An explicit browser-to-server endpoint projection, validated by
Tool::new. - Manifest
- An immutable manifest containing only the tools passed to
Manifest::build. - Registry
- A boot-time registry. Selection is explicit; registration alone exposes nothing.
- Script
TagOptions - Script tag options. Autostart marking is enabled by default.
- Tool
- An owned, immutable, validated browser tool. Construction never registers it.
- ToolDef
- Mutable input to
Tool::new; not itself a validated or exposed tool. - Transport
- Explicit transport configuration. Rust supplies no implicit CSRF defaults.
Constants§
- ORIGIN_
TRIAL_ HEADER - The HTTP response header used for an Origin Trial token.
- RUNTIME_
JS - The byte-for-byte copy of the shared browser runtime.
- RUNTIME_
SHA256 - SHA-256 of the shipped runtime (also pinned in
conformance/RUNTIME.sha256).
Functions§
- apply_
origin_ trial - The plain header-list helper when the optional
httpfeature is disabled. Fill a missing Origin-Trial header in a framework-independent header list. Matching is case-insensitive, existing empty values are preserved, and an empty token is a no-op. - apply_
origin_ trial_ headers - The plain header-list helper when the optional
httpfeature is disabled. Fill a missing Origin-Trial header in a framework-independent header list. Matching is case-insensitive, existing empty values are preserved, and an empty token is a no-op. - form_
attrs - Render escaped, normative declarative form attributes.
- origin_
trial_ header - Build the original 0.0.1 header pair without validating or changing the token.
- origin_
trial_ meta_ tag - Render an escaped Origin Trial meta tag, or an empty string for an empty token.
- param_
attr - Render an escaped
toolparamdescriptionattribute, even for pre-escaped input. - runtime_
script_ tag - Render an external module script tag with an optional escaped CSP nonce.
Serve
RUNTIME_JSatsrcusing your framework’s asset pipeline.
Type Aliases§
- Error
- An error in a tool definition or declarative form’s metadata.