Deploy
Run bitmcp on Node, Vercel, or Cloudflare from one server artifact.
bitmcp build emits dist/server.js, hashed View HTML under dist/ui/, and dist/manifest.json. The server exports a Web-standard fetch handler plus GET, POST, and OPTIONS. Use that file on every platform.
Set deploy in bitmcp.config.ts. Default is "node". Scaffold a target with npx create-bitmcp my-app --deploy vercel or --deploy cloudflare.
Set BITMCP_STATE_KEY in production. Confirmations and ctx.ask mint requestState tokens that must verify on any replica.
Configure http.allowedHosts and http.cors in bitmcp.config.ts for public HTTP.
Node
pnpm build
BITMCP_STATE_KEY=... pnpm startbitmcp start loads dist/server.js and listens on Streamable HTTP.
Default listen address: http://127.0.0.1:3000/mcp
Override with --port or MCP_PORT, MCP_HOST, and MCP_PATH. GET /health is also served.
Vercel
npx create-bitmcp my-app --deploy vercelThat writes deploy: "vercel" and vercel.json with a rewrite from /mcp to /api/mcp.
- Set
BITMCP_STATE_KEYin the Vercel project - Set
http.allowedHoststo your deployment host vercel
bitmcp build writes gitignored api/mcp.js that re-exports dist/server.js. vercel runs pnpm build first.
Cloudflare Workers
npx create-bitmcp my-app --deploy cloudflareThat writes deploy: "cloudflare" and wrangler.jsonc with main set to dist/server.js.
- Set
BITMCP_STATE_KEYas a Worker secret or var - Set
http.allowedHoststo your workers.dev or custom domain wrangler deploy
nodejs_compat is required. Wrangler runs pnpm build and serves dist/server.js directly.
Embed in an existing app
dist/server.js already exports GET, POST, OPTIONS, and default.fetch. Point a platform entry at that file, or call app.fetch yourself:
import app from "../dist/server.js";
export const GET = (request: Request) => app.fetch(request);
export const POST = GET;
export const OPTIONS = GET;Stateless replicas
Every request builds a fresh MCP server. There is no Mcp-Session-Id.
- Pass handles and ids in tool arguments
- Store job state behind a
HandleStore(KV, Redis, D1) - View HTML is content-addressed. Every replica serves the same hash for the same build
Host and Origin guards
localhost bindings include Host and Origin checks. Production app.fetch only enforces hosts you put in allowedHosts.
Not in v1
OAuth, CIMD, Smithery, and Netlify presets are out of this pass.