Getting started
This guide gets you from zero to registered WebMCP tools using direct mode — the Delivery SDK runs in the browser tab, so there is no server side to build. If your environment holds content you would not publish, use proxy mode instead; step 5 shows the switch.
Prerequisites
- Node.js 18+
- A Contentstack stack with published content
- Delivery API credentials (API key, delivery token, environment)
- A Chrome build exposing
document.modelContext— origin trial 149+, or#enable-webmcp-testingon older builds (see Browser support)
1. Install
npm install @timbenniks/contentstack-webmcp @contentstack/delivery-sdkOptional adapters:
npm install react # @timbenniks/contentstack-webmcp/react
npm install next # @timbenniks/contentstack-webmcp/next2. Define your content types
export const contentTypes = [
{
uid: "blogpost",
label: "Blog Post",
urlField: "url",
titleField: "title",
bodyField: "body",
searchableFields: ["title", "body"],
},
];searchableFields drives which fields contentstack_search_entries matches against, CDA-side.
3. Register tools in the browser
import contentstack from "@contentstack/delivery-sdk";
import { createContentstackWebMcp, isWebMcpSupported } from "@timbenniks/contentstack-webmcp";
import { contentTypes } from "./content-types";
const stack = contentstack.stack({
apiKey: import.meta.env.VITE_CONTENTSTACK_API_KEY,
deliveryToken: import.meta.env.VITE_CONTENTSTACK_DELIVERY_TOKEN,
environment: import.meta.env.VITE_CONTENTSTACK_ENVIRONMENT,
});
const webmcp = createContentstackWebMcp({ mode: "direct", stack, contentTypes });
async function initWebMcp() {
if (!isWebMcpSupported()) return;
const controller = new AbortController();
await webmcp.register({
signal: controller.signal,
navigate: (path) => window.location.assign(path),
});
window.addEventListener("pagehide", () => controller.abort());
}
initWebMcp();That is the whole integration. Use a read-only delivery token scoped to an environment containing only content you are happy to have public — it grants read access to every content type in that environment, not just the ones configured above.
4. Permissions-Policy header
Add to your site so browser agents can access tools:
Permissions-Policy: tools=(self)See Security for nginx, Vercel, and Next.js examples.
5. Verify in Chrome
- Confirm
document.modelContextexists — origin trial (149+) or#enable-webmcp-testing - Open DevTools → Application → WebMCP
- Confirm tools are registered
- Try
contentstack_search_entriesmanually, thencontentstack_get_entry_by_urlon a result, thennavigate_to(requires thenavigatecallback)
6. Optional — switch to proxy mode
To keep the delivery token off the client, add a server route and change one config line. Tools and response shapes are identical either way.
// app/api/contentstack/[...path]/route.ts
import contentstack from "@contentstack/delivery-sdk";
import { createContentstackWebMcpRouteHandlers } from "@timbenniks/contentstack-webmcp/next";
import { contentTypes } from "@/content-types";
const stack = contentstack.stack({
apiKey: process.env.CONTENTSTACK_API_KEY!,
deliveryToken: process.env.CONTENTSTACK_DELIVERY_TOKEN!,
environment: process.env.CONTENTSTACK_ENVIRONMENT!,
});
export const { GET } = createContentstackWebMcpRouteHandlers({ stack, contentTypes });import contentstack from "@contentstack/delivery-sdk";
import { createContentstackWebMcpProxyHandler } from "@timbenniks/contentstack-webmcp/server";
import { contentTypes } from "./content-types";
const stack = contentstack.stack({
apiKey: process.env.CONTENTSTACK_API_KEY!,
deliveryToken: process.env.CONTENTSTACK_DELIVERY_TOKEN!,
environment: process.env.CONTENTSTACK_ENVIRONMENT!,
});
export default createContentstackWebMcpProxyHandler({ stack, contentTypes });Then in the browser, drop the stack entirely:
createContentstackWebMcp({ mode: "proxy", proxyBasePath: "/api/contentstack", contentTypes });Framework-specific guides
Troubleshooting
| Symptom | Fix |
|---|---|
| No tools registered | Check document.modelContext exists; call isWebMcpSupported() |
| CDA requests blocked in direct mode | Allow the Contentstack CDA host in your CSP |
| 404 on proxy routes | Verify server route path matches proxyBasePath |
| Empty search results | Confirm content type UIDs and searchableFields |
| Tools disabled entirely | Set CONTENTSTACK_WEBMCP_ENABLED=true |
See FAQ for more.