Deployment

Node and custom

Run your app on Node with pnpm start and verify /health.

When you finish this guide, your app listens on Streamable HTTP at http://127.0.0.1:3000/mcp (or your configured host and port).

Complete the production checklist first.

Build

pnpm build

Set environment variables

Generate a production state key:

export BITMCP_STATE_KEY=$(openssl rand -hex 32)

For public HTTP, set http.allowedHosts and http.cors in bitmcp.config.ts. See environment variables.

Start

pnpm start

bitmcp start loads dist/server.js and listens on Streamable HTTP. Default address: http://127.0.0.1:3000/mcp.

Override with --port or MCP_PORT, MCP_HOST, and MCP_PATH. Set deploy: "node" in bitmcp.config.ts (this is the default).

Verify

curl http://127.0.0.1:3000/health

Expect { "ok": true }. Connect an MCP client to your /mcp endpoint and call a tool.

Run behind a reverse proxy

Terminate TLS with nginx or Caddy and proxy to your Node process:

location /mcp {
  proxy_pass http://127.0.0.1:3000;
  proxy_http_version 1.1;
  proxy_set_header Host $host;
}

Run under a process manager for production:

pm2 start "pnpm start" --name my-mcp

Embed in an existing app

dist/server.js exports GET, POST, OPTIONS, and default.fetch. Point a platform entry at that file, or call app.fetch yourself:

api/mcp.ts
import app from "../dist/server.js";

export const GET = (request: Request) => app.fetch(request);
export const POST = GET;
export const OPTIONS = GET;

Operating at scale

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

localhost bindings include Host and Origin checks. Production app.fetch only enforces hosts you put in allowedHosts.

Minimal store shape:

type HandleStore<T> = {
  get: (id: string) => Promise<T | undefined>;
  set: (id: string, value: T) => Promise<void>;
};

See Handles for a full walkthrough.

Troubleshooting

  • Connection refused — Confirm pnpm build succeeded and pnpm start is running.
  • Host rejected — Add your public hostname to http.allowedHosts.
  • MRTR errors — Set BITMCP_STATE_KEY before starting in production.
  • CORS errors from browsers — Configure http.cors in bitmcp.config.ts.

Reference

For programmatic servers and subpath imports, see Package exports.