Self-hosting
Running the MCP server from the public repository, the four environment variables, and the parts that are not in it.
The server is MIT licensed and the code that answers a tool call is in the public repository, WellWorn-dev/wellworn, under packages/mcp, packages/db, packages/ratelimit and packages/verdict. Running it yourself is four commands. Filling it with a corpus is the part that takes work.
Run it
You need Node 24, pnpm 10, a Postgres database and a Redis instance.
git clone https://github.com/WellWorn-dev/wellworn
cd wellworn
pnpm install
cp packages/mcp/.env.example packages/mcp/.env
DATABASE_URL=postgres://user:pass@127.0.0.1:5432/wellworn pnpm --filter @wellworn/db migrate
pnpm --filter @wellworn/mcp devMigrations are drizzle-kit SQL files under packages/db/drizzle, applied in order and safe to re-run. pnpm test runs the suite and needs both Postgres and Redis up.
Environment
| Variable | Default | What it does |
|---|---|---|
DATABASE_URL | none, required | Postgres connection string. |
REDIS_URL | none, required | Holds the rate-limit counters and the call log. |
PORT | 3001 | Listen port. |
TRUST_PROXY | 0 | Set to 1 only when a proxy you run rewrites the client address. Leaving it off means forwarded headers are ignored and the socket address is used. |
The process exits at boot if DATABASE_URL or REDIS_URL is missing rather than starting in a state where the limiter cannot count.
There is no key resolver in the public build. createApp falls back to one that resolves nothing, so every caller counts as anonymous at 60 calls a day per address, and a request that does carry an Authorization: Bearer header is answered with 401 invalid key. Sending no header at all is the correct way to call your own copy.
Docker
packages/mcp/Dockerfile builds on node:24.20.0-alpine, produces a deploy output in a second stage, creates an unprivileged app user, exposes 3001 and health checks /health every ten seconds. It was written against the private monorepo's layout and still refers to apps/mcp, so building it from the public checkout needs those two paths changed to packages/mcp first.
What is not in the repository
The corpus files are public: verdicts/ holds one YAML file per verdict under CC BY-SA 4.0, validated by spec/verdict.schema.json, mirrored out of the review database after a reviewer publishes. What is not public is the machinery around them. There is no importer, no loader that turns those YAML files into database rows, no nightly job that re-reads the registries and raises the RECHECK flag, no review dashboard, no account or billing system.
So a self-hosted server starts with an empty database and answers no verified verdict yet for "..." to everything until you write your own loader against the schema in packages/db/src/schema. Running your own copy makes sense for keeping a private corpus of your team's decisions inside your network. It is not a way to get the hosted corpus without the hosted service; for that, the free tier is the corpus, and the verdict files are yours to copy under their license.