io.github.cyanheads/federal-regulations-mcp-server
Search and trace US federal rules across the Federal Register, eCFR, and Regulations.gov.
Que pouvez-vous faire avec io.github.cyanheads/federal-regulations-mcp-server ?
- One workflow over three official sources: the agent calls regulatory verbs (
search_rules,get_cfr_section,find_comments) rather than three API clients - Cross-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 with `aut... - Locally 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...
- 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 - Provenance:
source: "mirror" | "live"on every CFR read, plus asourceScopeline on search naming what the corpus covers - Honest 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 throughtruncatedand `... - Attachment-aware comments:
attachmentOnlyflags a comment whose substance is a file, with the download URLs
Installation
Ajoutez ceci à la configuration MCP de votre client (Claude Desktop : claude_desktop_config.json ; Cursor : .cursor/mcp.json ; VS Code et les autres utilisent la même forme « mcpServers »).
claude mcp add --transport http federal-regulations-mcp-server 'https://federal-regulations.caseyjhand.com/mcp'
{
"mcpServers": {
"federal-regulations-mcp-server": {
"type": "http",
"url": "https://federal-regulations.caseyjhand.com/mcp"
}
}
}
@cyanheads/federal-regulations-mcp-serverclaude mcp add federal-regulations-mcp-server -e 'REGULATIONS_GOV_API_KEY=<your regulations_gov_api_key>' -e 'MCP_LOG_LEVEL=info' -- npx -y @cyanheads/federal-regulations-mcp-server@0.6.0
{
"mcpServers": {
"federal-regulations-mcp-server": {
"command": "npx",
"args": [
"-y",
"@cyanheads/federal-regulations-mcp-server@0.6.0"
],
"env": {
"REGULATIONS_GOV_API_KEY": "<your regulations_gov_api_key>",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Variables d'environnement
REGULATIONS_GOV_API_KEYsecret api.data.gov key for the Regulations.gov tools (get_docket, find_comments). Free at https://api.data.gov/signup/. The Federal Register and eCFR tools work without it.MCP_LOG_LEVELSets the minimum log level for output (e.g., 'debug', 'info', 'warn').
@cyanheads/federal-regulations-mcp-serverclaude mcp add federal-regulations-mcp-server -e 'MCP_TRANSPORT_TYPE=<MCP_TRANSPORT_TYPE>' -e 'MCP_HTTP_HOST=127.0.0.1' -e 'MCP_HTTP_PORT=3010' -e 'MCP_HTTP_ENDPOINT_PATH=/mcp' -e 'MCP_AUTH_MODE=none' -e 'REGULATIONS_GOV_API_KEY=<your regulations_gov_api_key>' -e 'ECFR_MIRROR_REFRESH_CRON=<ECFR_MIRROR_REFRESH_CRON>' -e 'MCP_LOG_LEVEL=info' -- npx -y @cyanheads/federal-regulations-mcp-server@0.6.0
{
"mcpServers": {
"federal-regulations-mcp-server": {
"command": "npx",
"args": [
"-y",
"@cyanheads/federal-regulations-mcp-server@0.6.0"
],
"env": {
"MCP_TRANSPORT_TYPE": "<MCP_TRANSPORT_TYPE>",
"MCP_HTTP_HOST": "127.0.0.1",
"MCP_HTTP_PORT": "3010",
"MCP_HTTP_ENDPOINT_PATH": "/mcp",
"MCP_AUTH_MODE": "none",
"REGULATIONS_GOV_API_KEY": "<your regulations_gov_api_key>",
"ECFR_MIRROR_REFRESH_CRON": "<ECFR_MIRROR_REFRESH_CRON>",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Variables d'environnement
MCP_TRANSPORT_TYPESelects the HTTP transport.MCP_HTTP_HOSTThe hostname for the HTTP server.MCP_HTTP_PORTThe port to run the HTTP server on.MCP_HTTP_ENDPOINT_PATHThe endpoint path for the MCP server.MCP_AUTH_MODEAuthentication mode to use: 'none', 'jwt', or 'oauth'.REGULATIONS_GOV_API_KEYsecret api.data.gov key for the Regulations.gov tools (get_docket, find_comments). Free at https://api.data.gov/signup/. The Federal Register and eCFR tools work without it.ECFR_MIRROR_REFRESH_CRONCron expression for an in-process eCFR mirror refresh (e.g. '0 4 * * 0'). Unset registers no job. Each run re-harvests every configured title in full, and a tick is skipped until mirror:init has completed once.MCP_LOG_LEVELSets the minimum log level for output (e.g., 'debug', 'info', 'warn').
Documentation
Tirée du README du projet sur GitHub, actualisée chaque semaine. Les liens ouvrent GitHub.
Sommaire
@cyanheads/federal-regulations-mcp-server
Search and trace US federal rules across the Federal Register (proposed/final rules and notices), the eCFR (codified, point-in-time CFR full text, locally mirrored), and Regulations.gov (rulemaking dockets and public comments) via MCP. STDIO or Streamable HTTP.
7 Tools • 2 Resources
Public Hosted Server: https://federal-regulations.caseyjhand.com/mcp
Overview
US federal regulatory law from three official sources: the Federal Register (proposed rules, final rules, and notices), the eCFR (codified CFR text, current or as of a past date), and Regulations.gov (rulemaking dockets and public comments). Search rules, trace a document from proposal through its comments to the codified text, and read CFR sections. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
Tools
| Tool | Description |
|---|---|
regulations_search_rules | Search Federal Register proposed rules, final rules, notices, and presidential documents by query, type, agency, date range, CFR part, docket number, and RIN, or resolve a page cite to its document |
regulations_get_document | Fetch one Federal Register document by number, with the docket IDs, CFR parts, citation, comment count, and comment URL that chain into other tools |
regulations_browse_cfr | List CFR titles, a title's chapters, or every section and appendix in a part, or full-text-search the codified CFR |
regulations_get_cfr_section | Read codified CFR text for a section, whole part, or appendix, current or as of a past date |
regulations_get_docket | Pull a rulemaking docket and its filed documents from Regulations.gov (key required) |
regulations_find_comments | Fetch public comments on a document or docket, or one comment's full body and attachments (key required) |
regulations_list_open_comments | List documents currently open for public comment, soonest closing first |
Resources
| Resource | Description |
|---|---|
regulations://document/{documentNumber} | One Federal Register document's metadata and cross-source handles |
regulations://cfr/{title}/{part}/{section} | Codified text of a current CFR section |
Both resources mirror a tool (regulations_get_document, regulations_get_cfr_section), so tool-only clients lose nothing.
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), andrin, all combined;per_page2–100 (default 20),page1–50 citation("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. A cite missing its date, or combined with the 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 range- Each 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, 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 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, max 200,000) starting atoffset, and passing either of those implies it- Returns metadata plus the handles other tools take: the Regulations.gov
docketIdandregulationsGovDocumentId, the printeddocketIds,citation/startPage/endPage,commentCount,commentUrl,commentPeriodOpen, 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.title,part(needstitle), and a point-in-timedatescope both modes, andper_page1–50 (default 20) pages search results and part listings- Search 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 date - Text comes back as one
bodyTextwindow (max_charsdefault 64,000, max 200,000, fromoffset), paged bybodyTextLengthandbodyTextNextOffset. A whole-part read adds asections[]index with each section'soffsetand names itsappendiceswithout their text;source(mirror/live) reports provenance - A 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 it - Superscripts 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
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;document_typesfilters toProposed Rule,Rule,Notice,Supporting & Related Material, orOther;per_page5–250 (default 25),page1–40- 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)
regulations_find_comments tool · key required
- Exactly one of
docket_id,document_object_id,fr_document_number, orcomment_id; list scopes takeper_page5–250 (default 25) andpage1–40 document_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- Lists 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_mode modeislistordetail. Lists return comment summaries without body text.comment_idreturns the body, submitter,receivedDate,postmarkDate,duplicateComments(above 1 marks a mass-mail campaign record), andattachments, withattachmentOnly: truewhen the substance is in a PDF/DOCX file. 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_page1–100 (default 20) - 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 reached - Keyless.
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.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 clients - Cross-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 rejected - Locally 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 covers - Honest 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 rows - Attachment-aware comments:
attachmentOnlyflags a comment whose substance is a file, with the download URLs
Getting started
Public Hosted Instance
A public instance is available at https://federal-regulations.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"federal-regulations-mcp-server": {
"type": "streamable-http",
"url": "https://federal-regulations.caseyjhand.com/mcp"
}
}
}
Self-Hosted / Local
Add the following to your MCP client configuration file. REGULATIONS_GOV_API_KEY enables the docket and comment tools; omit it to run the keyless Federal Register and eCFR tools alone.
{
"mcpServers": {
"federal-regulations-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/federal-regulations-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"REGULATIONS_GOV_API_KEY": "your-key-here"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"federal-regulations-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/federal-regulations-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"REGULATIONS_GOV_API_KEY": "your-key-here"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"federal-regulations-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "REGULATIONS_GOV_API_KEY=your-key-here",
"ghcr.io/cyanheads/federal-regulations-mcp-server:latest"
]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 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 for the Regulations.gov tools.
Installation
- Clone the repository:
git clone https://github.com/cyanheads/federal-regulations-mcp-server.git
- Navigate into the directory:
cd federal-regulations-mcp-server
- Install dependencies:
bun install
- Configure environment:
cp .env.example .env
# optionally set REGULATIONS_GOV_API_KEY
Configuration
| Variable | Description | Default |
|---|---|---|
REGULATIONS_GOV_API_KEY | api.data.gov key for regulations_get_docket and regulations_find_comments. | none |
FEDERAL_REGISTER_BASE_URL | Federal Register API v1 base URL. | https://www.federalregister.gov/api/v1 |
ECFR_BASE_URL | eCFR API base URL. | https://www.ecfr.gov/api |
REGULATIONS_GOV_BASE_URL | Regulations.gov API v4 base URL. | https://api.regulations.gov/v4 |
ECFR_MIRROR_PATH | Path to the eCFR SQLite mirror database. | ./data/ecfr-mirror.sqlite |
ECFR_MIRROR_REFRESH_CRON | Cron expression for an in-process mirror refresh (HTTP transport only), e.g. 0 4 * * 0. Each run re-harvests every configured title in full. | none (no job) |
ECFR_MIRROR_TITLES | Comma-separated CFR titles to mirror (e.g. 21,40). Reads and searches outside the set, and all-titles searches, go to the live eCFR API. | all 50 titles |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | HTTP server port. | 3010 |
MCP_AUTH_MODE | Authentication: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (debug, info, warning, error, etc.). | info |
STORAGE_PROVIDER_TYPE | Storage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1. | in-memory |
OTEL_ENABLED | Enable OpenTelemetry. | false |
See .env.example for the full list of optional overrides.
Running the server
Local development
- Build and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:http - Build 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 date - Run checks and tests:
bun run devcheck # Lint, format, typecheck, security, changelog sync bun run test # Vitest test suite
Docker
docker build -t federal-regulations-mcp-server .
docker run --rm -e REGULATIONS_GOV_API_KEY=your-key -p 3010:3010 federal-regulations-mcp-server
The 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 |
|---|---|
src/index.ts | createApp() entry point: registers tools and resources, inits the three services, and schedules the mirror refresh when ECFR_MIRROR_REFRESH_CRON is set. |
src/config | Server-specific environment variable parsing and validation with Zod. |
src/mcp-server/tools | Tool definitions (*.tool.ts), the seven regulations_* tools. |
src/mcp-server/resources | Resource definitions (*.resource.ts), the document and CFR-section resources. |
src/services/federal-register | Federal Register API v1 client (keyless). |
src/services/ecfr | eCFR API client (keyless): versioner, structure, search, section XML parsing, and cite resolution. |
src/services/ecfr-mirror | eCFR codified-text mirror (SQLite + FTS5) and the opt-in refresh job. |
src/services/regulations-gov | Regulations.gov v4 client (X-Api-Key): dockets and comments. |
src/services | Shared request budget, text windowing, character-reference decoding, and upstream-failure handling. |
scripts/ecfr-mirror-*.ts | Out-of-band mirror lifecycle: init, refresh, verify. |
tests/ | Unit and integration tests mirroring src/. |
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 - Register new tools and resources via the barrels in
src/mcp-server/*/definitions/index.ts - Wrap 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 test
License
Apache-2.0 — see LICENSE for details.
Questions fréquentes
Qu'est-ce que io.github.cyanheads/federal-regulations-mcp-server ?
Search and trace US federal rules across the Federal Register, eCFR, and Regulations.gov.
Comment installer io.github.cyanheads/federal-regulations-mcp-server ?
Il fonctionne comme serveur distant. Dans Claude Code : claude mcp add --transport http federal-regulations-mcp-server 'https://federal-regulations.caseyjhand.com/mcp'. Pour les autres clients, collez la configuration JSON de cette page dans leurs réglages MCP.
Faut-il une clé API pour io.github.cyanheads/federal-regulations-mcp-server ?
Oui. Il attend REGULATIONS_GOV_API_KEY, à renseigner dans sa configuration.
io.github.cyanheads/federal-regulations-mcp-server est-il open source ?
Oui. Son code est sur GitHub sous licence Apache-2.0.
Qui maintient io.github.cyanheads/federal-regulations-mcp-server ?
Il est publié par cyanheads. AI.tn le référence sans le maintenir ni le recommander.
Issu du registre MCP officiel. Être listé n'est pas une recommandation : vérifiez le code et les permissions d'un serveur avant de lui donner accès à vos données.