1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! 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::new`] validates a definition at boot: name 1–128 of `[A-Za-z0-9_.-]`,
//! WebMCP annotations `read_only`/`untrusted_content`/`consequential`/`debugging`,
//! a strict JSON Schema subset, a same-origin endpoint, GET only when read-only.
//! - [`Registry`] selects the tools each page exposes; [`Manifest::to_script_tag`]
//! renders them as a script-safe `<script type="application/json">` element.
//! - [`RUNTIME_JS`] is 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 with [`runtime_script_tag`].
//! - [`form_attrs`] and [`param_attr`] render the declarative form attributes.
//! - Origin trial helpers, plus `OriginTrialLayer` behind the `tower` feature.
//!
//! 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"));
//! # Ok::<(), webmcp::DefinitionError>(())
//! ```
//!
//! 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:
//!
//! ```ignore
//! 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));
//! # let _ = app;
//! Ok(())
//! }
//! ```
pub use ;
pub use ;
pub use *;
/// An error in a tool definition or declarative form's metadata.
pub type Error = DefinitionError;
/// The byte-for-byte copy of the shared browser runtime.
pub const RUNTIME_JS: &str = include_str!;
/// SHA-256 of the shipped runtime (also pinned in `conformance/RUNTIME.sha256`).
pub const RUNTIME_SHA256: &str = "287200d4ef89e16ccd0f0bbb035d9b484c3a761503f3df40f8f1cf5f3baae452";
pub
/// Render escaped, normative declarative form attributes.
///
/// Metadata must be trusted literals: HTML escaping does not stop prompt injection.
/// Render an escaped `toolparamdescription` attribute, even for pre-escaped input.
/// Render an external module script tag with an optional escaped CSP nonce.
/// Serve [`RUNTIME_JS`] at `src` using your framework's asset pipeline.
pub