Skip to main content

Full Example

Production-ready React example with useWebMCP() hooks
React users should use @mcp-b/react-webmcp instead of @mcp-b/global directly—it handles lifecycle automatically and provides Zod validation. This guide covers SSR-specific challenges when using WebMCP with Next.js App Router.

The fundamental challenge

WebMCP relies on browser APIs (navigator.modelContext, postMessage, DOM access) that do not exist on the server. Next.js App Router defaults to Server Components, which means:
  • Tools cannot be registered in Server Components
  • The @mcp-b/global polyfill must run on the client
  • Any component using useWebMCP or useWebMCPPrompt must be a Client Component

Polyfill placement

The @mcp-b/global polyfill must be imported in a Client Component before any tools are registered. Import it at the highest layout that contains your tools—but not necessarily at the root.
Don’t make your root layout a Client Component unless you need to. This disables SSR for your entire application. Instead, import the polyfill in the feature layout(s) where tools are used.
If you have tools in multiple unrelated sections, import the polyfill in each feature layout:
The polyfill is small and idempotent—importing it multiple times is fine.
If the polyfill isn’t working, you’ll see:
  • navigator.modelContext is undefined
  • Tools don’t appear in the MCP inspector
  • No errors, but tools simply don’t register

Client components are required

Every WebMCP hook needs 'use client':
Hooks that require Client Components:
  • useWebMCP() - tool registration
  • useWebMCPPrompt() - prompt registration
  • useWebMCPResource() - resource registration
  • useWebMCPContext() - context registration
  • useMcpClient() - MCP client access

Embedded agent setup

The embedded agent uses browser APIs and must be loaded client-side only using dynamic import:
ssr: false is required because the embedded agent accesses window, document, and other browser APIs. Server-side rendering will crash with “window is not defined”.

Avoiding duplicate components

Next.js App Router supports nested layouts. If you add the embedded agent to multiple layouts, it will render multiple times:
Place the agent in ONE feature layout that wraps all pages needing AI access:
This keeps your root layout as a Server Component while giving tools access to the context they need.

Tool registration with context

WebMCP tools frequently need access to application state. This creates a dependency chain:
Tools placed outside the provider can’t access context:
Tools can navigate using Next.js router:
In Next.js App Router, the root layout persists across navigations. Tools registered in root layout stay registered, while tools in page components unmount/remount on navigation.

Common errors

Cause: Browser-only code running during SSRSolution:
Cause: Polyfill hasn’t initialized yetSolution:
Possible Causes:
  1. Component using useWebMCP isn’t mounted
  2. Component is a Server Component (missing 'use client')
  3. Tool registration is conditional and condition is false
  4. Polyfill loaded after tools tried to register
Debug:
Cause: Component mounted multiple times (e.g., in nested layouts)Solution: Only render WebMCP components in ONE layout. Use React DevTools to check component tree for duplicates.

Deployment checklist

Before deploying your WebMCP + Next.js app:
  • Root layout is a Server Component (no 'use client') to preserve SSR
  • Feature layout(s) have 'use client' and import @mcp-b/global
  • All components using WebMCP hooks have 'use client'
  • Embedded agent uses dynamic() with { ssr: false }
  • Embedded agent is rendered in only ONE layout
  • Tools that need context are inside their Provider
  • Environment variables use NEXT_PUBLIC_ prefix for client access
This structure ensures:
  1. Root layout stays a Server Component (SSR preserved)
  2. Polyfill loads in feature layouts where tools are used
  3. Tools have access to context (feature layout)
  4. Agent renders once (feature layout only)
  5. Pages can still use Server Components for data fetching

Development

Use Chrome DevTools MCP for AI-driven development - your AI can write, discover, and test tools in real-time.