congressgov-mcp-server
U.S. congressional data
Install
Install and configure the MCP from https://github.com/cyanheads/congressgov-mcp-server now. Follow the repository's installation instructions, ask me for anything you can't complete yourself, and verify its tools load.@cyanheads/congressgov-mcp-server
Access U.S. congressional data - bills, votes, members, committees - through MCP. STDIO & Streamable HTTP.
Public Hosted Server: https://congressgov.caseyjhand.com/mcp
Overview
U.S. congressional data from the Congress.gov API v3 and the Senate's official vote feed: bills, enacted laws, members, committees, roll call votes, nominations, CRS and committee reports, and the Congressional Record. Browse legislative activity, read bill and report text, and follow the Senate confirmation pipeline from any MCP client. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
Tools
| Tool | Description |
|---|---|
congressgov_bill_lookup | Browse and retrieve bills: actions, sponsors, summaries, text, related bills |
congressgov_enacted_laws | Browse enacted public and private laws by congress |
congressgov_member_lookup | Find members by state, district, or congress, and retrieve their legislative portfolios |
congressgov_committee_lookup | Browse committees and their legislation, reports, and nominations |
congressgov_roll_votes | Retrieve House and Senate roll call votes and each member's position |
congressgov_senate_nominations | Browse presidential nominations and track Senate confirmation |
congressgov_bill_summaries | Browse recently updated CRS bill summaries |
congressgov_crs_reports | Browse and retrieve nonpartisan CRS policy reports |
congressgov_committee_reports | Browse and read committee reports accompanying legislation |
congressgov_daily_record | Browse and read the daily Congressional Record |
congressgov_search_bills | Keyword-search bill titles and CRS summaries via a local full-text mirror (opt-in) |
Resources
| Resource | Description |
|---|---|
congress://current | Current congress number, session dates, chamber info |
congress://bill-types | Reference table of valid bill type codes |
congress://member/{bioguideId} | Member profile by bioguide ID |
congress://bill/{congress}/{billType}/{billNumber} | Bill detail by congress, type, and number |
congress://committee/{committeeCode} | Committee detail by committee code |
Bill, member, and committee data is also reachable through congressgov_bill_lookup, congressgov_member_lookup, and congressgov_committee_lookup (operation get), since many MCP clients are tool-only and never surface resources.
Prompts
| Prompt | Description |
|---|---|
congressgov_bill_analysis | Structured framework for analyzing a bill |
congressgov_legislative_research | Research framework for a policy area across Congress |
Capability reference
congressgov_bill_lookup tool
listbrowses onecongress, narrowed bybillTypeand afromDateTime/toDateTimerange on the record's update date, newest first unlessorder: 'oldest';get,actions,amendments,cosponsors,committees,subjects,summaries,text,titles,related, andcontentneedcongress+billType+billNumbercontentreads the text version attextVersionIndex(0-based intextorder, 0 is the most recent) and returns one character window incontent.textwithtotalCharacters,truncated, andnextOffsetsummariestakes an optionalversionCode(00introduced,49public law) and applies the same page budget and row window ascongressgov_bill_summaries, steered bycharacterOffset/characterLimit; a cut row carriestextTotalCharacters,textTruncated, andtextNextOffset
congressgov_enacted_laws tool
listbrowses onecongress, optionally bylawType(puborpriv), the enactment filtercongressgov_bill_lookuplacks;getneedslawType+lawNumber, taken from a list row'slaws[].number(118-90) or its bare number (90)getreturns the origin bill record, with the law citation on itslaws[]array
congressgov_member_lookup tool
- No name search:
listfilters bystateCode(plusdistrict,0for at-large, which requiresstateCode),congress, andcurrentMember getreturns the profile for abioguideId(e.g.P000197);sponsoredandcosponsoredreturn that member's legislation
congressgov_committee_lookup tool
committeeCodeis a chamber prefix (h/s/j), letters, and a 2-digit suffix (e.g.hsju00);get,bills,reports, and the Senate-onlynominationsinferchamberfrom the prefix- A committee name in
committeeCoderesolves when exactly one committee matches, and otherwise returns the candidate rows with a notice;listwithfiltername-matches every committee in scope, past the 250-row page cap, and fuzzy hits carryapproximate: true billsis newest first by default (order), and its rows carry no titles, so chaincongressgov_bill_lookupgetper row
congressgov_roll_votes tool
chamberishouse(default, Congress.gov API) orsenate(the Senate's LIS feed); every call needscongress+session(1 or 2), andget/membersaddvoteNumber, which resets each session and is specific to one chamberlistis newest first unlessorder: 'oldest';getreturns the question, result, tallies, and party breakdown, andmembersreturns each member's position- Senate votes start at the 101st Congress (1989), and Senate rows pair the feed's year-less
voteDatewith a derivedvoteDateIso
congressgov_senate_nominations tool
listbrowses onecongress;get,actions,committees,hearings, andnomineesneed anominationNumber(1000for PN1000), andnomineesalso needs anordinalfrom thenomineesarraygetreturns- Multi-part nominations (e.g. PN851) keep their activity on partitioned children (
851-1,851-2, …); an empty sub-resource call on the bare number returns a notice pointing there
congressgov_bill_summaries tool
- Optional
congressandbillType(which requirescongress);fromDateTime/toDateTimefilter on the summary's update time, not the bill's action date, and cover the last 7 days when both are omitted - A page stops adding rows at 50,000 serialized characters (at least one row always returns, and
pagination.nextOffsetresumes); a summary over 25,000 characters arrives windowed withtextTotalCharacters,textTruncated, andtextNextOffset - For one bill's summaries, or to read a windowed summary to the end, use
congressgov_bill_lookupsummaries
congressgov_crs_reports tool
listbrowses the catalog;gettakes areportNumbersuch asR40097,RL33612, orIF12345getreturns authors, topics, summary, and download formats
congressgov_committee_reports tool
listbrowses onecongress, optionally byreportType(hrptHouse,srptSenate,erptExecutive);get,text, andcontentneedreportType+reportNumbergetreturns the citation, title, committees, and associated bill;textlists{type, url}format links, andcontentreads the report as one character window
congressgov_daily_record tool
- Navigation runs
list(volumes) →issues(byvolumeNumber) →articles(byvolumeNumber+issueNumber) contentreads the article atarticleIndex(0-based across the issue) as one character window; Record articles publish Formatted Text and PDF only, soformat: 'xml'fails asformat_unavailable
congressgov_search_bills tool
querykeywords (AND-combined) over bill titles and CRS summaries, narrowed bycongress,billType, andoriginChamber;limit1–100,offsetpagination- BM25-ranked rows carry
billIdpluscongress/billType/billNumberforcongressgov_bill_lookup, and asummaryPreview; policy area and full bill text are not indexed - Listed only when
CONGRESS_MIRROR_ENABLED=true; untilbun run mirror:initbuilds the index, it returns an empty result with a notice
congress://current resource
- Current congress number, session dates, and chamber info, the baseline for other queries
- Cached publicly for 1 hour
congress://bill-types resource
- The 8 bill type codes (
hr,s,hjres,sjres,hconres,sconres,hres,sres) with description, chamber, and an example citation - Static, with no upstream call; cached publicly for 24 hours
congress://member/{bioguideId} resource
bioguideIdis one uppercase letter and 6 digits (e.g.P000197)- Returns the member profile: name, state, party, terms, leadership, office, legislation counts
congress://bill/{congress}/{billType}/{billNumber} resource
congressandbillNumberare positive integers;billTypeis one of the 8 bill type codes- Returns bill detail: sponsor, status, policy area, committees, latest action
congress://committee/{committeeCode} resource
committeeCodeish/s/jfollowed by 3–8 lowercase alphanumeric characters (e.g.hsju00); chamber comes from the first letter- Returns committee detail: name, chamber, subcommittees, history, legislation counts
congressgov_bill_analysis prompt
- Arguments:
congress,billType, andbillNumber, all required - Returns one user message framing a seven-part analysis, from summary to outlook, with the tools to call for each part
congressgov_legislative_research prompt
- Arguments:
topicrequired;congressoptional, defaulting to the current congress - With
CONGRESS_MIRROR_ENABLED, the plan opens withcongressgov_search_bills; without it, the prompt asks for a seed bill, member, committee, or CRS report ID, since no other tool takes a topic
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
Congress.gov-specific:
- Type-safe client for the Congress.gov REST API v3, plus a client for the Senate's LIS XML feed that backs Senate roll votes
- The Congress.gov API has no keyword search, so tools browse by congress, type, date range, chamber, state, and district, and address bills by
congress+billType+billNumber, members bybioguideId, and committees by system code; list operations page withlimit1–250 (default 20) andoffset contenton bill text, committee reports, and Record articles readsformattext(default) orxmlthrough acharacterOffset/characterLimitwindow (1–100,000 characters, default 25,000), fetched only fromwww.congress.govunder a 25 MB ceiling and a 30s deadline- Optional API key from api.data.gov:
DEMO_KEYallows 30 req/hr, your own key 5,000 req/hr - Opt-in local SQLite FTS5 mirror (
CONGRESS_MIRROR_ENABLED) adds keyword search over bill titles and CRS summaries
Agent-friendly output:
- Every list response carries
effectiveQueryandtotalCount; anoticefires when nothing matched, and a page past the end says so in the rendered output - Exact character windows:
contentreturnsoffset,truncated, andnextOffset, so walking a multi-megabyte bill never skips or repeats a character - Typed
contentfailures (document_unavailable,format_unavailable,document_fetch_failed,document_too_large,offset_past_end) alongside the sharednot_found,rate_limited,invalid_request, andupstream_errorreasons, each with a recovery hint
Getting started
Public Hosted Instance
A public instance is available at https://congressgov.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"congressgov-mcp-server": {
"type": "streamable-http",
"url": "https://congressgov.caseyjhand.com/mcp"
}
}
}
Self-Hosted / Local
Add the following to your MCP client configuration file.
{
"mcpServers": {
"congressgov-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/congressgov-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"CONGRESS_API_KEY": "your-api-key"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"congressgov-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/congressgov-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"CONGRESS_API_KEY": "your-api-key"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"congressgov-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "CONGRESS_API_KEY=your-api-key",
"ghcr.io/cyanheads/congressgov-mcp-server:latest"
]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 CONGRESS_API_KEY=your-api-key bun run start:http
# Server listens at http://localhost:3010/mcp
Prerequisites
- Bun v1.4.0 or higher (or Node.js v24+).
- Optional: a free api.data.gov key raises the limit from 30 to 5,000 requests per hour.
Installation
- Clone the repository:
git clone https://github.com/cyanheads/congressgov-mcp-server.git
- Navigate into the directory:
cd congressgov-mcp-server
- Install dependencies:
bun install
- Configure environment:
cp .env.example .env
# edit .env and set CONGRESS_API_KEY (and the mirror vars, if you want keyword search)
Configuration
| Variable | Description | Default |
|---|---|---|
CONGRESS_API_KEY | API key from api.data.gov. DEMO_KEY allows 30 req/hr; your own key 5,000 req/hr. | DEMO_KEY |
CONGRESS_API_BASE_URL | Congress.gov API base URL. | https://api.congress.gov/v3 |
CONGRESS_MIRROR_ENABLED | Enable the local bill search mirror and the congressgov_search_bills tool. | false |
CONGRESS_MIRROR_PATH | Filesystem path to the SQLite mirror index. | .mirror/bills.sqlite3 |
CONGRESS_MIRROR_REFRESH_CRON | Cron schedule for the in-process mirror refresh (HTTP transport only). Unset means running mirror:refresh yourself. | — |
CONGRESS_MIRROR_CONGRESSES | Comma-separated congress numbers to mirror (e.g. 118,119). | current congress + 1 prior |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | HTTP server port. | 3010 |
MCP_SESSION_MODE | HTTP session mode: stateless, stateful, or auto; auto resolves to stateful. | stateless |
MCP_AUTH_MODE | Authentication: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (debug, info, notice, warning, error, etc.). | info |
LOGS_DIR | Directory for log files (Node.js only). | <project-root>/logs |
OTEL_ENABLED | Enable OpenTelemetry. | false |
OTEL_EXPORTER_OTLP_ENDPOINT | Base OTLP endpoint for traces and metrics. | — |
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT | Explicit OTLP logs endpoint; the base endpoint does not enable log export. | — |
LOG_TOOL_FAILURE_PAYLOADS | Log failed-call input and output with key-based redaction; secrets inside free-form values are not redacted. | false |
LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES | Maximum bytes per failed-call input or output record. | 16384 |
See .env.example for the full list of optional overrides.
Running the server
Local development
-
Build and run the production version:
bun run rebuild bun run start:http # or start:stdio -
Build the bill search mirror (with
CONGRESS_MIRROR_ENABLED=true):bun run mirror:init # full build bun run mirror:refresh # incremental refresh bun run mirror:verify # readiness and integrity check -
Run checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t congressgov-mcp-server .
docker run --rm -e CONGRESS_API_KEY=your-api-key -p 3010:3010 congressgov-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/congressgov-mcp-server. OpenTelemetry peer dependencies are installed by default; build with --build-arg OTEL_ENABLED=false to omit them. The image carries the mirror scripts, so docker exec <container> bun run mirror:init builds the index in place.
Project structure
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point: registers tools, resources, and prompts, inits services, and schedules the mirror refresh. |
src/config/ | Server-specific environment variable parsing and validation with Zod. |
src/mcp-server/tools/ | Tool definitions (definitions/*.tool.ts) plus shared input, formatting, and summary-window helpers. |
src/mcp-server/resources/definitions/ | Resource definitions (*.resource.ts). |
src/mcp-server/prompts/definitions/ | Prompt definitions (*.prompt.ts). |
src/services/congress-api/ | Congress.gov API client: auth, pagination, rate limiting. |
src/services/congress-documents/ | Bounded document-text fetch: host allowlist, byte ceiling, character window. |
src/services/congress-mirror/ | Local SQLite FTS5 bill-search mirror: ingest, normalize, schema. |
src/services/senate-lis/ | Senate LIS XML client for Senate roll call votes. |
src/utils/ | HTML/XML character-reference decoding. |
scripts/ | Build, devcheck, and release tooling, plus the mirror:init / mirror:refresh / mirror:verify CLIs. |
tests/ | Unit and integration tests, mirroring the src/ structure. |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storage - All tools are read-only, with
readOnlyHint: trueandidempotentHint: trueannotations - Wrap external API calls: validate raw → normalize to a domain type → return the output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
License
Apache-2.0 — see LICENSE for details.
