Bill Commons

Claude Code

One command in your terminal:

shell
claude mcp add bill-commons --transport http https://mcp.billcommons.org/mcp

Then just ask: "Using bill-commons, list every enacted data privacy bill from 2026 and summarize what each one requires."

Claude Desktop / Claude.ai

Settings → Connectors → Add custom connector, and paste the server URL:

https://mcp.billcommons.org/mcp

Cursor / other MCP clients

mcp.json
{
  "mcpServers": {
    "bill-commons": {
      "url": "https://mcp.billcommons.org/mcp",
      "transport": "http"
    }
  }
}

Any client that speaks MCP over Streamable HTTP works. Full tool list and a Python example are on the MCP server page.

Building an automated monitor

For standing watchlists — a lobbying shop tracking 100 bills, a policy team watching a topic — pair two endpoints. Resolve your watchlist once:

shell — resolve bill numbers to IDs
curl -X POST "https://api.billcommons.org/api/v1/bills/lookup" \
  -H "Content-Type: application/json" \
  -d '{"keys": [
        {"jurisdiction": "AZ", "identifier": "HB 2192"},
        {"jurisdiction": "GA", "identifier": "SB 594"}
      ]}'

Then poll the change feed — it returns only what moved, with the transition itself ("in_committee → enacted") in each event:

shell — what changed since my last check?
curl "https://api.billcommons.org/api/v1/changes?kind=status&ids=<your-bill-ids>"
# store next_cursor from the response, pass it back next time:
curl "https://api.billcommons.org/api/v1/changes?cursor=<next_cursor>&kind=status&ids=..."

Give those two snippets to your agent and ask it to build the monitor for you — this page is written to be readable by agents, too. Full reference: API docs.

Three prompts, and what you should get back

Worked examples, including the answers that look unhelpful and are actually correct. If your agent returns something confidently different from the third one, it is guessing — see the data-integrity contract.

1. A straight lookup

prompt
Did Hawaii SB 2135 become law? Give me the source URL.

Expect: enacted, with the signing date and a source_url pointing at the Hawaii legislature. Note the session adjourned 2026-05-08 and it was signed 2026-07-07 — a tracker that assumes everything dies at adjournment gets this wrong.

2. A multi-state scan

prompt
Search all states for bills about algorithmic pricing this session.
For each one tell me the state, bill number, status, and whether the
session has already adjourned. Flag any state where coverage is degraded.

Expect: a table, plus a coverage_warning for any jurisdiction below the search threshold. The warning is the point — it is what stops an empty result from reading as "no such legislation exists".

3. The one that should refuse

prompt
What happened to Texas HB 1?

Expect a refusal. "TX HB 1" matches three different sessions, so there is no single answer. A correct response lists the candidate sessions and asks which one you mean. An answer that confidently reports one status has picked a session for you without saying so — that is the single most common failure in legislative tooling, and it is why match_type: bill_number_ambiguous exists.

Producing something a human can check

build_legislative_evidence_packet returns a how_to_cite block. Pass what you were asked as question and the packet records its own scope.

  • cite_as — one quotable sentence. It names derived status as derived, inside the sentence, because that is the field a quoter drops first.
  • permalink — a page a person can open. Put this in the answer, not the bill UUID.
  • snapshot_id — changes if and only if a cited fact changes. It is a change detector, not an archive: nothing is stored, so it cannot retrieve the version that was cited. If the exact wording matters later, keep a copy.

The same packet is available without MCP at GET /api/v1/bills/{id}/evidence, and returns the same snapshot_id for the same record.

What this system will not tell you

Stated up front, because an agent that discovers a gap mid-answer tends to fill it:

  • No hearing schedules. A hearings tool exists but there are zero hearing records. An empty result there means "not collected", never "none scheduled".
  • No federal legislation. 50 states and DC only.
  • No historical sessions. Current session or biennium only — not an archive.
  • Status is derived, not reported. Especially died_on_adjournment, which exists precisely because nothing was filed. Cite it as our conclusion, not the legislature's.
  • Roughly 5% of bills have no status at all, on purpose. States disagree on identical wording, so the derivation returns nothing rather than guess.

Not technical? You're done after step one.

The whole point of the agent integration is that the API disappears: connect once, then talk to your assistant like you'd talk to a research analyst. It knows how to search, look up, compare versions, and check coverage on its own.