federal-regulations-mcp-server
This server has a remotely hosted endpoint. Open its connector listing for connection details, authentication requirements, and setup instructions:
Public Hosted Server: https://federal-regulations.caseyjhand.com/mcp
Overview
US federal regulations from the Federal Register, the eCFR, and Regulations.gov. Search proposed and final rules, trace a rule from proposal through public comments to codified text, and read any CFR section as it stands today or stood on a past date.
Tools
Tool | Description |
| Search Federal Register proposed rules, final rules, notices, and presidential documents by query, type, agency, date range, CFR part, docket number, RIN, significance, effective date, and executive order number, president, or signing date, or resolve a page cite to its document |
| Fetch one Federal Register document by number, with the docket IDs, CFR parts, citation, significance, comment count, and comment URL that chain into other tools |
| List CFR titles, a title's chapters, or every section and appendix in a part, full-text-search the codified CFR, or list when a part's or section's text changed |
| Read codified CFR text for a section, whole part, or appendix, current or as of a past date |
| Pull a rulemaking docket and its filed documents from Regulations.gov, or read one document's files and attachments (key required) |
| Fetch public comments on a document or docket, or one comment's full body and attachments (key required) |
| List documents currently open for public comment, soonest closing first |
Resources
Resource | Description |
| One Federal Register document's metadata and cross-source handles |
| Codified text of a current CFR section |
| Guide to tracing rulemaking, CFR text, and public-comment evidence across sources |
The two data resources mirror regulations_get_document and regulations_get_cfr_section. The federal-regulations guide also ships with plugin installs, npm, Docker, and the desktop bundle.
Related MCP server: fedreg-mcp
Capability reference
regulations_search_rules tool
Optional full-text
query, filtered bytype(PRORULE/RULE/NOTICE/PRESDOCU),agencies(Federal Register slugs such asenvironmental-protection-agency, not names or acronyms),published_after/published_before,cfr_title+cfr_part(a part number or range such as140-143;cfr_partneedscfr_title, elsetitle_required_for_part),docket_id(a docket number as the Federal Register prints it),rin,significant(the Federal Register's EO 12866 flag:trueandfalseeach match only documents with a determination), andeffective_after/effective_before, all combined;per_pagefrom 2 (default 20; above 100 serves 100 with a notice),page1–50Presidential documents narrow by
executive_order_number(bare digits,14192),presidential_document_type(executive_order,proclamation,memorandum,determination,notice,presidential_order,other),president(a slug such asdonald-trump), and asigned_after/signed_beforewindow, which differs from the publication window because signing precedes publication. These filters beside atypethat leaves outPRESDOCU, orsignificantbeside them or besidetypeofPRESDOCUalone, fail withtype_conflictcitation("89 FR 49102") withcitation_date(the date its source note prints beside it) returns the documents printed on that page, in page order, volume 59 (1994) onward, narrowed by any other filter. A cite missing its date, or combined with the publication date window, fails withcitation_incomplete; a volume before 59 or a date from another year fails withcitation_out_of_range. When no document spans the page, the notice gives that day's page rangeEach result carries
documentNumber,citation/startPage/endPage,agencies[].slug, the printeddocketIds,regulationsGovDocketIdandregulationsGovDocumentId,commentCount,commentUrl,commentsCloseOnwithcommentPeriodOpen(open through 11:59 PM Eastern on the close date),regulationIdNumbers,significant(null when no determination is recorded),presidential(type,number,signingDate, andpresident; null unless the document is a presidential document), andcfrReferencesfor the follow-up tools.totalPagesandnextPagepage the results. The Federal Register serves 50 pages, sotruncatedmarks a set larger than 50 ×per_page(1,000 at the default, 5,000 at 100); narrow the date window rather than paging deeper.totalCountstops at 10,000, which means at least that many. A window whose start falls after its end (publication, signing, or effective) fails withdate_range_inverted, andinvalid_filternames a rejected parameter
regulations_get_document tool
document_numberin any form the Federal Register issues:2024-07773from 2010 on, and older and correction numbers such as98-1572,E9-25990, orC1-2009-30484;include_full_textadds the plain-text body as one window ofmax_chars(default 64,000; above 200,000 serves 200,000 with a notice) starting atoffset, and passing either of those implies itReturns metadata plus the handles other tools take: the Regulations.gov
docketIdandregulationsGovDocumentId, the printeddocketIds,citation/startPage/endPage,commentCount,commentUrl,commentPeriodOpen,significant,presidentialfor a presidential document, andcfrReferences. With text,fullTextLengthandfullTextNextOffset(present while text remains) page the body; a major final rule runs past a million characters
regulations_browse_cfr tool
mode: "structure"lists the 50 titles, a title's top-level divisions, or, withtitle+part, every section and appendix in the part with itssubpartandsubjectGroup;mode: "search"full-text-searches the codified CFR and requiresquery;mode: "versions"lists the dates a part's or one section's text changed.title,part(needstitle), and a point-in-timedatescope structure and search, andper_pagefrom 1 (default 20; above 50 serves 50 with a notice) pages search results, part listings, and versionsVersions mode takes
titlewithpart(and optionallysection, written asregulations_get_cfr_sectionaccepts it) or withchanged_since(YYYY-MM-DD: versions published by an eCFR issue on or after it, across the whole title when nopartis given); any other scope fails withversions_scope_required, and asectionciting another title fails withconflicting_title.versions[]rows carrycfrCite,heading,part,subpart,date,issueDate,substantive, andremoved, in eCFR's order (by identifier, oldest first within each), andlatestAmendmentDatecovers the whole filtered set. Pass a row'sdateasdatetoregulations_get_cfr_sectionto read that version: a row dated before 2017-01-01 reads at 2017-01-01, and a removed row's date reads nothingSearch rows carry
cfrCite,heading,hierarchyPath, andexcerpt, one per section.source(mirror/live) andsourceScopename the corpus that answered and what it covers, andcountBasissays whethertotalCountcountssectionsorsection_versions; live search reaches eCFR's first 10,000 hits only (page_out_of_windowpast them)
regulations_get_cfr_section tool
One section (
title+part+section), a whole part (sectionomitted), or one appendix (appendix, verbatim asregulations_browse_cfremits it, e.g.Appendix A-1 to Part 50).sectionalso takes cites as people write them ("61","§ 141.61","141.61(c)") and thecfrCitethe server returns ("40 CFR 141.61","14 CFR 241 § 25"; a cite naming another title fails withconflicting_title),parttakes"Part 141", anddatereads text from 2017-01-01 through the title's up-to-date dateText comes back as one
bodyTextwindow (max_charsdefault 64,000, above 200,000 serves 200,000 with a notice, fromoffset), paged bybodyTextLengthandbodyTextNextOffset. A whole-part read adds asections[]index with each section'soffsetand names itsappendiceswithout their text;source(mirror/live) reports provenancehierarchyPathruns from the title down to the location read. If eCFR cannot supply it, the read still answers, with only the cited levels (Title 40 › Part 141 › § 141.61), andnoticesays soA whole-part read also returns the part's
heading,authority,sourceNote, andnotes, and eachsections[]entry carries the Authority or Source its subpart or subject group states for itSuperscripts read
^xand subscripts_x(3 × 10^−8,CO_{2}e), footnote markers[n], and diacritics and overlines are combining marks (x̄)
regulations_get_docket tool · key required
Exactly one of
docket_id(list mode) ordocument_id(detail mode): neither fails withtarget_required, both withmultiple_targets, andsearch_termordocument_typesbesidedocument_idwithfilter_requires_list_mode. IDs are case-insensitiveList mode takes
docket_id, the Regulations.gov docket ID (e.g.EPA-HQ-OAR-2025-0194) —regulationsGovDocketIdon a search or open-comments row,docketIdfromregulations_get_document, not a printeddocketIdsentry.search_termkeeps the documents whose text matches, ranked by relevance instead of newest first;document_typesfilters toProposed Rule,Rule,Notice,Supporting & Related Material, orOther, and combines with it;per_pagefrom 5 (default 25; above 250 serves 250 with a notice),page1–40List mode returns the docket's metadata,
documentCount, anddocuments[], each with anobjectIdforregulations_find_comments, afrDocNumback toregulations_get_document, andcommentPeriodOpenas Regulations.gov reports it.totalPagesandnextPagepage the documents; Regulations.gov serves 40 pages, sotruncatedmarks a docket larger than 40 ×per_page(10,000 at 250)Detail mode takes
document_id(documentIdfrom a listing, orregulationsGovDocumentIdfromregulations_get_document) and returns onedocumentwithfileFormats(the main file's download URLs),attachmentsin upload order with withheld ones kept,pageCount,abstract, andrestrictReasonType. A document whose content is only in attachments, or that has no file at all, gets a notice saying so
regulations_find_comments tool · key required
Exactly one of
docket_id,document_object_id,fr_document_number, orcomment_id; list scopes takeper_pagefrom 5 (default 25; above 250 serves 250 with a notice) andpage1–40document_object_idtakes an object ID (0900006485883ec6) or a document ID (EPA-HQ-OW-2022-0114-0027).fr_document_numberresolves to the Regulations.gov document carrying that exact number and answersnot_foundwhen none does. Docket, document, and comment IDs are case-insensitiveA
docket_idthat lists no comments is looked up: a docket Regulations.gov does not hold (a printed docket number such asREG-101355-26) answersnot_found, and an existing docket answers an empty list with a noticeLists narrow by comment text with
search_term, and each hit then carrieshighlightedContent, the matched passages.posted_after/posted_beforeset an inclusive posted-date window. A backwards window fails withdate_range_inverted, and filters passed withcomment_idfail withfilter_requires_list_modemodeislistordetail. Lists return comment summaries without body text.comment_idreturns the body, submitter,receivedDate,postmarkDate,duplicateComments(above 1 marks a mass-mail campaign record), andattachmentsin upload order, withattachmentOnly: truewhen the substance is in a PDF/DOCX file. An attachment whose file is withheld stays in the list with emptyformatsand itsrestrictReasonType(e.g.Copyrighted). Lists carrytotalPagesandnextPage;truncatedmarks a set larger than the 40 pages Regulations.gov serves reach (40 ×per_page, 10,000 at 250), and posted-date windows take it one slice at a time
regulations_list_open_comments tool
Optional
query,type(PRORULE,RULE,NOTICE; default["PRORULE", "RULE"]),agencies(Federal Register slugs), andclosing_before;per_pagefrom 1 (default 20; above 100 serves 100 with a notice)Rows sort by closing date, soonest first, and carry
commentsCloseOn,daysRemaining,documentNumber, the printeddocketIds,regulationsGovDocketIdandregulationsGovDocumentId,commentCount, andcommentUrl.asOfis today's date in Eastern time, so a document stays listed through its close day.totalPagesandnextPagepage the window;truncatedmeans the Federal Register's 10,000-document limit was reachedKeyless.
keyedreports whetherREGULATIONS_GOV_API_KEYis set, whichregulations_get_docketandregulations_find_commentsneed to follow up on a row
regulations://document/{documentNumber} resource
documentNumberin any Federal Register form (2024-07773,98-1572,E9-25990); the payload isregulations_get_document's without the body textdocketId,regulationsGovDocumentId, the printeddocketIds,cfrReferences,citation,commentCount, andcommentUrlchain into the search, comment, and CFR tools
regulations://cfr/{title}/{part}/{section} resource
Sections only, at the current date and the tool's default 64,000-character window; the
partandsectionsegments resolve the way the tool resolves them ("Part 141";"61","§ 141.61","40 CFR 141.61")source(mirror/live) reports provenance, andnoticesays how a part or section written another way resolved and whenhierarchyPathholds only the cited levels.bodyTextNextOffsetmarks a section longer than the window; read the rest throughregulations_get_cfr_sectionwithoffset
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.
Federal Register / eCFR / Regulations.gov-specific:
One workflow over three official sources: the agent calls regulatory verbs (
search_rules,get_cfr_section,find_comments) rather than three API clientsCross-source stitching: every Federal Register document surfaces its docket ID and CFR-part handles, which feed the proposal → comments → final rule → codified text trace
Keyless core: the five Federal Register and eCFR tools need no key.
regulations_get_docketandregulations_find_commentsneedREGULATIONS_GOV_API_KEY(free at api.data.gov/signup, 1,000 requests/hour) and fail withauth_required, naming the variable and signup URL, when it is missing or rejectedLocally mirrored codified CFR: the eCFR syncs into embedded SQLite + FTS5 for exact-cite reads and full-text search, and falls back to the live API for historical dates, whole parts, appendices, titles outside the mirror, and titles eCFR has re-issued since the mirror last synced them
A 45-second budget per request, shared by every upstream call, retry, and backoff, so a stalled source answers with
upstream_unavailableinside a client's timeout
Agent-friendly output:
Provenance:
source: "mirror" | "live"on every CFR read, plus asourceScopeline on search naming what the corpus coversHonest paging:
totalPagesandnextPagesay how far a list goes, a page past the end names the last page instead of reading as "nothing matched", and matches beyond the Federal Register's 50 pages or Regulations.gov's 40 surface throughtruncatedandnotice, never as silently dropped rowsAttachment-aware comments:
attachmentOnlyflags a comment whose substance is a file, with the download URLs
Getting started
Connect to the hosted instance:
claude mcp add --transport http federal-regulations-mcp-server https://federal-regulations.caseyjhand.com/mcpOr run it locally:
claude mcp add federal-regulations-mcp-server -- npx -y @cyanheads/federal-regulations-mcp-serverFor other clients, add this to your MCP configuration file:
{
"mcpServers": {
"federal-regulations-mcp-server": {
"command": "npx",
"args": ["-y", "@cyanheads/federal-regulations-mcp-server"]
}
}
}Set optional REGULATIONS_GOV_API_KEY to enable docket and comment tools; get a free key at api.data.gov/signup. The Federal Register and eCFR tools work without it. For Docker or a source build, see Running the server.
Configuration
Variable | Description | Default |
| api.data.gov key for | none |
| Federal Register API v1 base URL. |
|
| eCFR API base URL. |
|
| Regulations.gov API v4 base URL. |
|
| Path to the eCFR SQLite mirror database. |
|
| Cron expression for an in-process mirror refresh (HTTP transport only), e.g. | none (no job) |
| Comma-separated CFR titles to mirror (e.g. | all 50 titles |
| Serve a |
|
| Transport: |
|
| HTTP server port. |
|
| Authentication: |
|
| Log level ( |
|
| Storage backend: |
|
| Enable OpenTelemetry. |
|
See .env.example for the full list of optional overrides.
Running the server
Local development
Requires Bun v1.4.0 or higher (or Node.js v24+).
git clone https://github.com/cyanheads/federal-regulations-mcp-server.git
cd federal-regulations-mcp-server && bun install
cp .env.example .envBuild and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:httpBuild or refresh the eCFR mirror (out of band and idempotent; the CFR tools use the live eCFR API until the first build completes):
bun run mirror:init # full build, resumable (scope with ECFR_MIRROR_TITLES) bun run mirror:refresh # re-harvest every configured title against the latest eCFR issues bun run mirror:verify # report row counts and the last-synced issue dateRun checks and tests:
bun run devcheck # Lint, format, typecheck, security, changelog sync bun run test # Vitest test suite
Docker
docker run --rm -e REGULATIONS_GOV_API_KEY=your-key -p 3010:3010 ghcr.io/cyanheads/federal-regulations-mcp-server:latestThe Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/federal-regulations-mcp-server. Build the mirror inside a running container with docker exec <container> bun run mirror:init, and mount a volume over /usr/src/app/data so it survives recreation. OpenTelemetry peer dependencies are installed by default; build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Directory | Purpose |
|
|
| Server-specific environment variable parsing and validation with Zod. |
| Tool definitions ( |
| Resource definitions ( |
| Federal Register API v1 client (keyless). |
| eCFR API client (keyless): versioner, structure, search, section XML parsing, and cite resolution. |
| eCFR codified-text mirror (SQLite + FTS5) and the opt-in refresh job. |
| Regulations.gov v4 client ( |
| Shared request budget, text windowing, character-reference decoding, and upstream-failure handling. |
| Out-of-band mirror lifecycle: |
| Unit and integration tests mirroring |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
Handlers throw, framework catches — no
try/catchin tool logicUse
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storageRegister new tools and resources via the barrels in
src/mcp-server/*/definitions/index.tsWrap external API calls: validate raw → normalize to the domain type → return the output schema; never fabricate missing upstream fields
Data disclaimer
eCFR content is "authoritative but unofficial" per the Office of the Federal Register, not the official legal edition of the Code of Federal Regulations; verify against govinfo.gov for legal research. This server is not affiliated with or endorsed by the Office of the Federal Register, the Government Publishing Office, or the General Services Administration.
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Apache-2.0 — see LICENSE for details.
This server cannot be deployed
Maintenance
Related MCP Connectors
Read a CFR or eCFR section, or search US federal regulations and the Federal Register.
MCP for CourtListener: US federal and state opinions, dockets, judges, plus eCFR regulations.
Search US lobbying disclosures and foreign-agent registrations via MCP.
Federal Register monitoring and regulations.gov tracking. 4 MCP tools for regulatory compliance.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceEnables interaction with the Regulations.gov API to search federal rulemaking dockets, proposed and final rules, public comments, and comment periods. Supports tracking FAR/DFARS case histories and monitoring open comment periods across federal agencies with optional API key authentication for higher rate limits.MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server that provides AI agents with access to U.S. Federal Register rules and Regulations.gov public comments, enabling searches, rule retrieval, and comment fetching.MIT
- AlicenseNot gradedqualityBmaintenanceMCP server for searching and retrieving FCC ECFS filings, dockets, and proceedings via the public API.401 npmMIT
- AlicenseNot gradedqualityAmaintenanceSearch bills, legislators, committees, and events across all 50 US states, DC, and 5 US territories via MCP.333 npm2Apache 2.0