A comprehensive demonstration of the Web Model Context Protocol (WebMCP), a W3C draft specification that enables web pages to expose tools for AI agents to discover and invoke.
WebMCP brings the Model Context Protocol (MCP) to web browsers, allowing:
- Web pages as MCP servers: Expose JavaScript-based tools that AI agents can call
- Tool discovery: Agents can list available tools and their schemas
- Secure invocation: Tools are invoked with validated inputs per JSON Schema
- Real-time updates: Pages can notify agents when tools change
A complete implementation of the draft spec:
navigator.modelContext- The ModelContextContainer interface- Tool registration with JSON Schema validation
- JSON-RPC 2.0 message handling
- Event-based tool list change notifications
15+ tools showcasing different capabilities:
| Category | Tools |
|---|---|
| Math | calculate, convert_units |
| DOM | query_page, get_page_info, extract_text, click_element, fill_input, scroll_page |
| Storage | get_storage, set_storage |
| App | manage_todo, manage_cart, set_theme, show_notification |
| Network | fetch_data |
A simulated AI agent that:
- Parses natural language requests
- Selects appropriate tools
- Invokes tools with proper arguments
- Displays results to the user
# Install dependencies
npm install
# Start development server
npm run devVisit http://localhost:3000 to see the demo.
Try these prompts:
- "Calculate 15% tip on $85"
- "Convert 100 km to miles"
- "Add 'Buy groceries' to my todo list"
- "Add headphones to my cart for $99"
- "Show me all headings on this page"
- "Switch to dark mode"
Open browser console and use:
// List all tools
window.webmcp.listTools();
// Call a tool directly
await window.webmcp.callTool('calculate', { expression: '2 + 2' });
// Call page query
await window.webmcp.callTool('query_page', { selector: 'button', limit: 5 });The polyfill supports standard MCP JSON-RPC messages:
// Initialize
await navigator.modelContext.handleMessage({
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: {},
});
// List tools
await navigator.modelContext.handleMessage({
jsonrpc: '2.0',
id: 2,
method: 'tools/list',
params: {},
});
// Call a tool
await navigator.modelContext.handleMessage({
jsonrpc: '2.0',
id: 3,
method: 'tools/call',
params: {
name: 'calculate',
arguments: { expression: '10 * 5' },
},
});┌─────────────────────────────────────────────────────────────┐
│ Web Browser │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────┐ ┌────────────────────────────────┐ │
│ │ AI Agent │ │ Web Page │ │
│ │ (Extension/ │◄──►│ navigator.modelContext │ │
│ │ External) │ │ ┌──────────────────────────┐ │ │
│ │ │ │ │ ModelContextContainer │ │ │
│ │ - Discover │ │ │ ├── Tool: calculate │ │ │
│ │ - Invoke │ │ │ ├── Tool: query_page │ │ │
│ │ - Process │ │ │ ├── Tool: manage_todo │ │ │
│ └─────────────────┘ │ │ └── ... │ │ │
│ │ └──────────────────────────┘ │ │
│ └────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
navigator.modelContext.registerTool({
name: 'my_custom_tool',
title: 'My Custom Tool',
description: 'Does something amazing',
inputSchema: {
type: 'object',
properties: {
param1: { type: 'string', description: 'First parameter' },
param2: { type: 'number', description: 'Second parameter' },
},
required: ['param1'],
},
outputSchema: {
type: 'object',
properties: {
result: { type: 'string' },
},
},
handler: async ({ param1, param2 }) => {
// Your tool logic here
return { result: `Processed: ${param1}` };
},
});This demo implements the draft WebMCP specification and follows the Model Context Protocol for tool definitions and invocations.
- ✅
navigator.modelContexton SecureContext - ✅ Tool registration with JSON Schema
- ✅ JSON-RPC 2.0 message format
- ✅
tools/listandtools/callmethods - ✅ Tool change notifications
- ✅ Error handling per spec
WebMCP requires a secure context (HTTPS or localhost). The polyfill works in all modern browsers:
- Chrome 80+
- Firefox 75+
- Safari 13.1+
- Edge 80+
MIT