navigator.modelContext) that don’t exist on the server. TanStack Start renders components on both server and client during SSR, so you must ensure WebMCP code only runs in the browser.
The challenge
Unlike Next.js which has explicit'use client' directives, TanStack Start components run during both SSR and client-side hydration by default. This means:
@mcp-b/globalpolyfill cannot be imported at module leveluseWebMCPhooks will fail during SSR if not guarded- You need explicit client-only patterns
Client-only tool registration
Wrap your WebMCP tools in a client-only component using dynamic imports:Alternative: Environment check
If you prefer keeping tools in the same file, guard with an environment check:The lazy import pattern (first example) is cleaner and recommended. The environment check pattern is useful when you can’t easily split into separate files.
Tools that persist across navigation
For tools that should remain registered across route changes, place them in__root.tsx using the same client-only pattern:
Common errors
Hydration mismatch errors
Hydration mismatch errors
Cause: Server HTML doesn’t match client HTML because tools render differentlySolution: Ensure tool components return
null and use Suspense with fallback={null} for consistent server/client output.