Astro integration that exposes your site content via WebMCP for AI agents. Make your Astro site AI-agent ready in one line of code.
WebMCP is a proposed web standard by Chrome that lets websites declare structured tools for AI agents. Instead of an agent visually interpreting each page element, the site explicitly declares what can be done — search articles, navigate to sections, get page metadata.
- Spec: https://webmachinelearning.github.io/webmcp/
- Chrome docs: https://developer.chrome.com/docs/ai/webmcp
- GitHub: https://github.com/webmachinelearning/webmcp
npm install @freshjuice/astro-webmcp// astro.config.mjs
import { defineConfig } from 'astro/config';
import webmcp from '@freshjuice/astro-webmcp';
export default defineConfig({
integrations: [webmcp()],
});All site content is automatically exposed via WebMCP.
webmcp({
// Filter which collections to expose (default: all)
collections: ['blog', 'docs'],
// Custom tools — expose your own domain-specific functionality
customTools: [
{
name: 'search_products',
description: 'Search the product catalog by name, category, or keyword.',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: 'Search term' },
},
required: ['query'],
},
executeBody: `return fetch('/api/search?q=' + encodeURIComponent(params.query))
.then(r => r.json())
.then(d => safeOutput(d));`,
annotations: { readOnlyHint: true, untrustedContentHint: true },
},
],
// Auto-register annotated <form> elements as WebMCP tools
formScanning: true,
// Search backend for search_content (default: 'manifest')
search: {
backend: 'pagefind', // 'manifest' | 'pagefind' | 'orama'
oramaIndexUrl: '/search-index.json', // required for 'orama'
pagefindBundlePath: '/pagefind/', // default for 'pagefind'
},
// Security options
security: {
exposedTo: [], // origins allowed cross-origin access (default: none)
maxOutputLength: 1500, // max chars per tool output (default: 1500)
sanitizeOutputs: true, // strip prompt injection patterns (default: true)
},
})| Option | Type | Default | Description |
|---|---|---|---|
collections |
string[] |
undefined (all) |
List of collections to include in the manifest |
customTools |
CustomTool[] |
[] |
Domain-specific tools to register alongside built-in ones |
formScanning |
boolean |
false |
Auto-register <form name="..." description="..."> elements as tools |
search.backend |
'manifest' | 'pagefind' | 'orama' |
'manifest' |
Search backend for search_content |
search.oramaIndexUrl |
string |
— | URL of pre-built Orama index (required for 'orama') |
search.pagefindBundlePath |
string |
'/pagefind/' |
Pagefind bundle path |
security.exposedTo |
string[] |
[] |
Origins allowed to access tools cross-origin |
security.maxOutputLength |
number |
1500 |
Character limit per tool output |
security.sanitizeOutputs |
boolean |
true |
Strip patterns that resemble prompt injection |
The customTools array lets you expose your own site-specific functionality. Each tool needs:
name— unique tool identifierdescription— natural language description for AI agentsinputSchema— JSON Schema for the tool's parametersexecuteBody— function body (runs in browser). ReceivesparamsandsafeOutput. Must return data or a Promise.annotations— optional security hints (readOnlyHint,untrustedContentHint)
search_content supports three backends, with automatic fallback to manifest search:
| Backend | Description | Requires |
|---|---|---|
manifest (default) |
Substring search on the generated manifest | Nothing — always works |
pagefind |
Full-text search via Pagefind | astro-pagefind or pagefind on the page |
orama |
Full-text search via Orama | @freshjuice/astro-search-plugin or similar, with oramaIndexUrl |
When formScanning: true, any <form> element with name and description attributes is auto-registered as a WebMCP tool:
<form name="search_products" description="Search product catalog by keyword">
<input name="query" type="text" required>
<button type="submit">Search</button>
</form>The integration builds the input schema from form fields and submits the form when the agent calls the tool. This implements the spec's declarative API — no JS required.
| Tool | Description |
|---|---|
search_content |
Search articles and pages by keyword (supports manifest, Pagefind, or Orama backends) |
list_sections |
List available content sections with item counts |
go_to |
Navigate to a specific page by slug (prompts user consent via requestUserInteraction) |
get_page_info |
Get current page metadata (title, description, headings, language, word count, canonical URL) |
| declarative forms | Any <form name="..." description="..."> when formScanning: true |
| your custom tools | Whatever you define via customTools |
┌──────────────────────────────────────────────────────────┐
│ BUILD TIME │
│ │
│ Astro pages ────→ Hook astro:build:done │
│ │ │
│ ▼ │
│ /_webmcp/manifest.json │
│ (titles, slugs, descriptions, │
│ tags, OG metadata, lang, word count) │
└──────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────┐
│ RUNTIME (Browser) │
│ │
│ Injected script (head-inline) │
│ │ │
│ ├─ fetch('/_webmcp/manifest.json') │
│ │ │
│ ├─ navigator.modelContext.provideContext() │
│ │ ├─ search_content (manifest/pagefind/orama) │
│ │ ├─ list_sections │
│ │ ├─ go_to (+ requestUserInteraction) │
│ │ ├─ get_page_info (enhanced metadata) │
│ │ └─ custom tools (user-defined) │
│ │ │
│ └─ scanDeclarativeForms() (if formScanning: true) │
└──────────────────────────────────────────────────────────┘
WebMCP is currently available in Chrome 149+ via one of two methods:
- Open
chrome://flags#webmcp-for-testing - Enable the flag
- Restart Chrome
For production sites (no flag required for visitors), register for a Chrome Origin Trial token:
- Go to https://developer.chrome.com/origintrials/#/register_trial/4163014905550602241
- Register your domain and get a token
- Add the token to your site's
<head>:
<meta http-equiv="origin-trial" content="YOUR_TOKEN_HERE">In Astro, add this to your base layout (src/layouts/Layout.astro or similar):
<meta http-equiv="origin-trial" content={import.meta.env.WEBMCP_ORIGIN_TRIAL_TOKEN}>Store the token in
.envasWEBMCP_ORIGIN_TRIAL_TOKEN=your-token— never hardcode in source.
Native support (no flag or token required) is targeted for H2 2026. Microsoft Edge is actively collaborating.
This integration follows Chrome Agent Security Guidelines:
- readOnlyHint on all non-mutating tools
- untrustedContentHint on tools returning page content
- requestUserInteraction() for state-mutating tools (
go_toprompts user consent before navigating) - Output truncation (default 1500 chars) prevents context overflow
- Prompt injection sanitization strips common instruction patterns
- Cross-origin control via
exposedTo(default: same-origin only)
This is a fork of the original astro-webmcp by fabricioctelles, maintained by FreshJuice with:
- Fixed script injection — uses
head-inlinestage for reliable delivery on Astro v6 and v7 - Custom tools API — expose your own domain-specific functionality declaratively in
astro.config.mjs - Search backends — Pagefind and Orama full-text search, with automatic fallback
- Declarative form scanning — auto-register annotated
<form>elements as tools - Enhanced metadata — tags, OpenGraph, canonical URL, language, word count in manifest
- English docs & comments — fully in English throughout
- Usage Guide — detailed setup, testing, and troubleshooting
- Architecture — design decisions and component breakdown
- Changelog — version history