Bill Commons
Bill Commons is a public, open-source legislative search platform covering the
current session/biennium for all 50 U.S. states plus DC. It provides a web
search UI, a REST API, an MCP (Model Context Protocol) server, and a public
status/coverage page. Public infrastructure first: no paywall on ordinary
search or reasonable API use.
See docs/architecture/ARCHITECTURE.md
for the locked architecture and data model.
Production
Hosted on Railway (project billcommons: api, mcp, worker services +
managed Postgres) and Vercel (project billcommons-web). See
docs/operations/deployment-runbook.md
for the full deploy/rollback procedure.
Use with Claude (or any MCP client)
The hosted MCP server gives AI assistants direct access to all 209k+ bills β
no API key, no setup beyond one command:
claude mcp add bill-commons --transport http https://mcp.billcommons.org/mcp
Claude Desktop: Settings β Connectors β Add custom connector with URL
https://mcp.billcommons.org/mcp. Cursor and other clients: add the same URL
as a Streamable HTTP server in mcp.json.
Ten tools including search_legislation, get_bill_record,
compare_bill_versions, and trace_legislative_history. Full walkthrough
(including REST recipes for agents without MCP):
https://billcommons.org/docs/agents
Architecture at a glance
βββββββββββββββ
users ββββββββββΆ β apps/web β Next.js, billcommons.org
β (Vercel) β status.billcommons.org (rewrite β /coverage)
ββββββββ¬βββββββ
β HTTPS (NEXT_PUBLIC_API_BASE)
βΌ
βββββββββββββββ ββββββββββββββββ
β apps/api βββββββββΆβ apps/mcp β Streamable HTTP
β FastAPI β β 10 MCP toolsβ mcp.billcommons.org
β /api/v1 β ββββββββββββββββ
β api.billcommons.org
ββββββββ¬βββββββ
β reads (SQLAlchemy)
βΌ
βββββββββββββββββββββββββββββββ
β Postgres 16 (Railway) β
β jurisdictions, sessions, β
β bills, actions, sponsorships,β
β votes, ingest_jobs, coverage β
ββββββββββββββββ²βββββββββββββββ
β writes (idempotent upserts)
ββββββββββββββββ΄βββββββββββββββ
β workers/ingest (worker svc) β
β autoboot: seed β bootstrap ββ
β schedule-refresh β job loop β
β sources: Open States bulk CSVβ
β (T2 bootstrap) + v3 API (T2 β
β incremental, OPENSTATES_API_ β
β KEY) + full-text fetcher β
ββββββββββββββββ¬βββββββββββββββ
βΌ
RawStore (filesystem, RAWSTORE_ROOT
volume in prod) β sha256-addressed
raw payload archive
packages/schema (SQLAlchemy models + Alembic) is the single source of
truth every other package/app imports from β no service owns its own copy
of the data model.
Monorepo layout
apps/web Next.js 15 (App Router, TS) β search UI + status page
apps/api FastAPI β REST API (/api/v1)
apps/mcp MCP server (Streamable HTTP, mounted at /mcp)
workers/ingest Ingestion workers, job queue, per-source adapters
packages/schema SQLAlchemy models + Alembic migrations (single source of truth)
packages/shared Shared Python utils: bill-number normalization, rawstore, http client
packages/source-registry Per-jurisdiction source registry (data + loader)
packages/search Search SQL builders / query parsing
infra/docker Dockerfiles + docker-compose.yml (local stack)
infra/deployment Railway/Vercel configs, DNS runbook
docs/ Architecture, API, sources, operations, state-coverage docs
data/registry Machine-readable registry (sessions, sources)
Local development setup
Prerequisites
- Python 3.12
- PostgreSQL 16 (with
pg_trgm, unaccent, pgcrypto extensions available)
- Node.js 20+ (for
apps/web)
Python environment
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
This installs packages/schema and packages/shared as editable installs
(single source of truth for the data model + shared utils), plus the
worker package: .venv/bin/pip install -e workers/ingest. Install the API
package too if you're working on it: .venv/bin/pip install -e apps/api.
Database
Set DATABASE_URL in your environment (or in ~/.config/billcommons/.env,
which is read as a fallback and is never committed):
DATABASE_URL=postgresql://user:password@host:port/dbname
Requires Postgres 16 with the pg_trgm and unaccent extensions available
(created by migration 0001). Run migrations:
cd packages/schema
../../.venv/bin/alembic upgrade head
Seeding data locally
.venv/bin/python -m billcommons_ingest seed-registry
python3 workers/ingest/download_bulk.py --only NC
.venv/bin/python -m billcommons_ingest bootstrap --state NC --zip data/bulkzips/NC_2025.zip
.venv/bin/python -m billcommons_ingest recompute-coverage
Running the apps locally
.venv/bin/uvicorn main:app --app-dir apps/api --reload --port 8000
.venv/bin/python apps/mcp/server.py
.venv/bin/python -m billcommons_ingest worker
cd apps/web
npm install
NEXT_PUBLIC_API_BASE=http://localhost:8000 npm run dev
Tests
.venv/bin/pytest packages/shared/tests
.venv/bin/pytest workers/ingest/tests
.venv/bin/pytest apps/api/tests
Running the stack locally with Docker
cd infra/docker
docker compose up --build
This brings up Postgres, the API, the ingestion worker, and the MCP server.
The web app (apps/web) is run separately via npm run dev during local
development (see infra/docker/docker-compose.yml for the placeholder
service definition).
Documentation
License
Apache-2.0. See LICENSE and NOTICE for data attribution
(Open States / Plural Policy, public-domain legislative data).
Contributing
See CONTRIBUTING.md. This project follows the
Contributor Covenant.
Security
See SECURITY.md for responsible disclosure.