npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@freshjuice/astro-webmcp

v1.6.0

Published

Astro integration that exposes your site content via WebMCP for AI agents — by FreshJuice

Readme

@freshjuice/astro-webmcp

npm version Astro WebMCP License: MIT

Astro integration that exposes your site content via WebMCP for AI agents. Make your Astro site AI-agent ready in one line of code.


What is WebMCP?

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.


Installation

npm install @freshjuice/astro-webmcp

Basic Usage

// 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.


Configuration

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 toolname="..." tooldescription="..."> 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 |

Custom Tools

The customTools array lets you expose your own site-specific functionality. Each tool needs:

  • name — unique tool identifier
  • description — natural language description for AI agents
  • inputSchema — JSON Schema for the tool's parameters
  • executeBody — function body (runs in browser). Receives params, safeOutput, and signal (AbortSignal — pass to fetch() for cancellation, per spec PR #247). Must return data or a Promise.
  • annotations — optional security hints (readOnlyHint, untrustedContentHint)

Search Backends

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 |

Declarative Form Scanning

When formScanning: true, annotated <form> elements are auto-registered as WebMCP tools. Both the current spec attributes (Declarative API, Chrome 149+) and the legacy scheme are supported:

<!-- spec attributes (preferred) -->
<form toolname="search_products" tooldescription="Search product catalog by keyword">
  <input name="query" type="text" required toolparamdescription="Search term">
  <button type="submit">Search</button>
</form>

<!-- legacy attributes (still works) -->
<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. On Chrome 149+ the browser registers spec-annotated forms natively; the scanner polyfills the rest and dedupes by tool name.


Registered Tools

| 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 toolname="..." tooldescription="..."> (or legacy name/description) when formScanning: true | | your custom tools | Whatever you define via customTools |


Architecture

┌──────────────────────────────────────────────────────────┐
│                      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')                 │
│       │                                                  │
│       ├─ document.modelContext.registerTool()            │
│       │    ├─ search_content (manifest/pagefind/orama)   │
│       │    ├─ list_sections                              │
│       │    ├─ go_to (+ requestUserInteraction)           │
│       │    ├─ get_page_info (enhanced metadata)          │
│       │    └─ custom tools (user-defined)                │
│       │                                                  │
│       └─ scanDeclarativeForms() (if formScanning: true)  │
└──────────────────────────────────────────────────────────┘

Browser Support

WebMCP is currently in Origin Trial on Chrome 149–156 (desktop, Android, WebView) via one of two methods:

Development: Chrome Flag

  1. Open chrome://flags#enable-webmcp-testing
  2. Enable the flag
  3. Restart Chrome

Production: Origin Trial

For production sites (no flag required for visitors), register for a Chrome Origin Trial token:

  1. Go to https://developer.chrome.com/origintrials/#/register_trial/4163014905550602241
  2. Register your domain and get a token
  3. 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 .env as WEBMCP_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.


Security

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_to prompts 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)

Why FreshJuice?

This is a fork of the original astro-webmcp by fabricioctelles, maintained by FreshJuice with:

  • Fixed script injection — uses head-inline stage 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

Further Reading


License

MIT