React Router
Integrate xmcp’s stateless Fetch handler with React Router, including automatic setup and deployment.
For the complete documentation index, see llms.txt. Markdown variants of every page are available by appending .md to the URL.The React Router adapter serves MCP inside your existing application. It generates .xmcp/adapter/index.js, an ESM module exporting xmcpHandler(request, options?), which returns a standard Response.
Automatic setup
Inside your existing TypeScript React Router app:
Initialization creates xmcp.config.ts, sample tools, prompts, and resources, and app/routes/mcp.ts. It prepends adapter builds to existing host scripts and preserves your TypeScript and hosting configuration. Use --route-path app/routes/api to choose a different route directory, or --skip-route to integrate the handler yourself. Existing route files are preserved and reported as conflicts before configuration changes. The component flags --skip-tools, --skip-prompts, and --skip-resources work independently.
Detection requires @react-router/dev, identifying a Framework Mode app. A browser-only React Router app needs a server before it can host MCP. Register the generated module in your existing app/routes.ts:
The initializer leaves the existing route registry intact. Adjust the module path for --route-path or a custom appDirectory. The registered URL determines the endpoint; set http.endpoint to match it. A resource route must not export a default UI component.
Workers mode is inferred from @cloudflare/vite-plugin. You can select it explicitly with npx init-xmcp@latest --cf. If multiple hosting targets are installed, check the generated scripts and remove --cf for Node builds. Initialization configures xmcp’s build only; retain your framework’s deployment setup.
Manual setup
Set discovery paths for prompts and resources to directories when you need them. Add a tool like the runnable example, then run pnpm exec xmcp build before importing the adapter.
The relative import preserves your existing aliases. Adjust it if you move the route. Import the adapter only in server modules. See React Router's routing documentation for the host route conventions.
Development and Node builds
The initial adapter build must finish before the host loads your routes. During development, xmcp updates discovery when handler files are added or removed, while the host processes their application imports. Keep .xmcp/ ignored by Git and retain your host’s type-check command in CI. skipTypeCheck only disables xmcp’s separate check.
The example uses React Router Framework Mode with SSR enabled. Run react-router-serve build/server/index.js after the Node build. It also runs react-router typegen and TypeScript checking. The example requires Node 22.22 or newer.
Cloudflare Workers
Use @cloudflare/vite-plugin alongside the React Router Vite plugin, with a Worker entry that invokes React Router’s createRequestHandler. Keep nodejs_compat enabled in Wrangler. The example selects the Cloudflare plugin using XMCP_CLOUDFLARE=1:
Its dev:cf script builds the xmcp adapter with --cf before starting the host and xmcp watchers. deploy:cf builds and deploys through Wrangler. Use the host’s generated Worker configuration rather than deploying .xmcp/adapter as a standalone Worker.
In adapter mode, xmcp build --cf emits an importable Workers runtime in .xmcp/adapter. It does not generate a standalone Worker or overwrite your Wrangler configuration. Your tools and their dependencies must also support Workers. Stop development processes before changing targets because both targets share the adapter output directory.
Authentication and CORS
Verify credentials in your resource route or server middleware. Once verified, pass MCP authentication information to the adapter:
These variables come from your application’s authentication step. The option forwards verified data to MCP handlers as extra.authInfo; it does not validate tokens. Reject unauthorized requests before invoking xmcp.
Handle browser CORS and OPTIONS in the host, including the MCP headers required by your clients. Return the adapter’s Response directly to preserve streaming. Do not consume the original request body in earlier middleware.
Stateless requests
Every request receives a fresh MCP server and isolated request context. No initialization state or identity is cached across requests. Clients must repeat authentication and client metadata on each request, using modern protocol metadata or the legacy x-mcp-client-name and x-mcp-client-version headers.
Protocol validation and method handling remain with the SDK. Forwarding GET and DELETE does not enable persistent sessions.
