Run your own finch

Everything behind finchmcp.com is in the open-source repository: the hub, this website and the CLI. This guide deploys the hub and website on your own Cloudflare account, with your own Clerk sign-in, and points the finch CLI at them.

A self-hosted hub serves one account. Every service you publish lives under one hub hostname, at https://finch.example.dev/<service>/mcp. The layout finchmcp.com uses, where each account gets its own subdomain, is tied to the finchmcp.com name in the code today. The changes needed to run it on another domain are listed in the coupling checklist. This single-account mode is how finch's own staging deployment runs.

What you deploy

PieceWhat it does
HubA Cloudflare Worker with three Durable Objects. It relays calls, checks keys, serves the CLI's API and the /install script. Source: worker/.
WebsiteA Cloudflare Worker running Next.js. Sign-in and the finch login approval page, plus the landing page and docs. Source: web/.
ClerkYour sign-in, and the OAuth server for MCP clients that sign in instead of using a key.
Release binariesWhat /install and finch update download: this repository's GitHub releases, or an R2 bucket you fill.

Before you start

git clone https://github.com/DigiBugCat/finch && cd finch
git checkout v1.8.0

1. Set up Clerk

  1. Create an application. A development instance is simplest for one person: it works on any origin. A production instance needs DNS on your domain; see the Clerk note under Known limitations.
  2. Restrict sign-ups to your email, or turn them off once your user exists. This step is required: development instances accept anyone by default, and a stranger who can sign in can log a CLI in to your hub, register your hub's own hostname to their account with finch domain add, and receive every call made to it. The VANITY_SUFFIXES and VANITY_TENANT settings below close the same hole in the hub. Do both.
  3. Create your user and copy its ID (user_…). It becomes your finch account ID.
  4. For MCP clients that sign in with OAuth (such as claude.ai custom connectors), open OAuth applications, turn on dynamic client registration, and set the default scopes for dynamically registered clients to openid email profile.
  5. Note the publishable key, the secret key, and the Frontend API URL.

2. Deploy the hub

Add a selfhost environment to worker/wrangler.jsonc. The full block, with every binding and migration it must repeat, is in the self-hosting guide on GitHub. The settings that are yours:

SettingWhat it does
DEV = "1"Turns on single-account mode. Keys, OAuth and machine tokens are checked exactly as in production.
DEFAULT_TENANTYour Clerk user ID. Every call on the hub host belongs to this account.
WEB_URLYour website origin. finch login sends you to <WEB_URL>/cli.
CLERK_ISSUERClerk's Frontend API URL. Turns on OAuth sign-in for MCP clients.
VANITY_SUFFIXESYour hub hostname (finch.example.dev). Required on your own domain: with VANITY_TENANT, only your account can register it, so no one else can take over the hub. Not needed on workers.dev.
VANITY_TENANTYour Clerk user ID, the same value as DEFAULT_TENANT.
FINCH_SERVICE_SECRET (secret)Shared with the website; authenticates its calls and signs CLI tokens. It is a hub-wide credential: whoever holds it can act for any account on the hub.
TICKET_SECRET (secret)Signs the tokens your machines use to connect.
FINCH_ASSERTION_PRIVATE_JWKS (secret, required by the guide's block)Signs X-Finch-Assertion, the caller identity your services can verify. The guide's block sets FINCH_ASSERTION_ACTIVE_KID and FINCH_ASSERTION_ISSUER, which turn signing on; without this secret every authenticated call fails with 503. To run without assertions, remove those two and skip this secret.
RELEASES_BASE or an R2 RELEASES bucketWhere binaries come from. Point RELEASES_BASE at https://github.com/DigiBugCat/finch/releases/download/v1.8.0 to use this repository's release.

Set the secrets with fresh values and deploy. The assertion key's kid (selfhost-2026-09 here) must match FINCH_ASSERTION_ACTIVE_KID:

cd worker && npm ci
SERVICE_SECRET="$(openssl rand -hex 32)"
printf %s "$SERVICE_SECRET" | npx wrangler secret put FINCH_SERVICE_SECRET --env selfhost
openssl rand -hex 32 | npx wrangler secret put TICKET_SECRET --env selfhost
node scripts/generate-assertion-jwks.mjs selfhost-2026-09 \
  | node scripts/validate-assertion-jwks.mjs selfhost-2026-09 --passthrough \
  | npx wrangler secret put FINCH_ASSERTION_PRIVATE_JWKS --env selfhost
node scripts/deploy-preflight.mjs selfhost
npx wrangler deploy --env selfhost

The website needs the same FINCH_SERVICE_SECRET, so deploy it from the same shell or keep the value somewhere safe.

3. Deploy the website

Add the matching selfhost environment to web/wrangler.jsonc (again, the full block is in the guide): a FINCH_HUB service binding to your hub Worker, HUB_URL set to your hub's origin, NEXT_PUBLIC_APP_ORIGIN set to your website's exact origin, and your Clerk publishable key. Deploy the hub first, so the binding has something to point at.

cd ../web && npm ci
npx wrangler secret put CLERK_SECRET_KEY --env selfhost
printf %s "$SERVICE_SECRET" | npx wrangler secret put FINCH_SERVICE_SECRET --env selfhost
node scripts/deploy-preflight.mjs selfhost
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_... npx opennextjs-cloudflare build --env selfhost
npx opennextjs-cloudflare deploy -- --env selfhost

4. Point the CLI at your hub

curl -fsSL https://finch.example.dev/install | sh
finch login --hub https://finch.example.dev

Sign in on your website and approve the code. The CLI remembers the hub, so the rest of the usual flow needs no --hub:

finch add notes --service http://127.0.0.1:8000
finch service install
finch test notes
finch connect notes --client claude-code

5. Check that it works

RunExpect
curl https://finch.example.dev/api/versionThe version you deployed
finch add hello --service http://127.0.0.1:8000Prints https://finch.example.dev/hello/mcp
finch test helloLists the server's tools
curl -i https://finch.example.dev/hello/mcp401 with a WWW-Authenticate: Bearer challenge
curl https://finch.example.dev/.well-known/oauth-protected-resource/hello/mcpauthorization_servers is your Clerk Frontend API URL

Known limitations

These come from an audit of every finchmcp.com reference in the code. The coupling checklist lists the change that would remove each one.

Updating is the same steps from a newer tag: deploy the hub, then the website, then run finch update on each machine (with --hub where there is no saved login). The full guide, with every configuration block, is docs/self-host.md.