federal-regulations-mcp-server

v0.1.1 pre-1.0

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.

federal-regulations.caseyjhand.com/mcp
claude mcp add --transport http federal-regulations-mcp-server https://federal-regulations.caseyjhand.com/mcp
codex mcp add federal-regulations-mcp-server --url https://federal-regulations.caseyjhand.com/mcp
{
  "mcpServers": {
    "federal-regulations-mcp-server": {
      "url": "https://federal-regulations.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http federal-regulations-mcp-server https://federal-regulations.caseyjhand.com/mcp
{
  "mcpServers": {
    "federal-regulations-mcp-server": {
      "command": "bunx",
      "args": [
        "mcp-remote",
        "https://federal-regulations.caseyjhand.com/mcp"
      ]
    }
  }
}
{
  "mcpServers": {
    "federal-regulations-mcp-server": {
      "type": "http",
      "url": "https://federal-regulations.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://federal-regulations.caseyjhand.com/mcp \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2025-11-25" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'

Tools

7

regulations_search_rules

open-world

Search the Federal Register — the daily journal of US proposed rules, final rules, notices, and presidential documents (1994–present) — filtering by full-text query, document type, agency slug, publication date range, and whether the rule is open for comment. The primary discovery entry point: results carry the document number (open with regulations_get_document), docket IDs, RINs, and affected CFR parts that chain into the comment and codified-text tools. The Federal Register caps navigation at 50 pages and the match count at 10,000; when a result set is larger, narrow with published_after/published_before rather than paging deeper.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "regulations_search_rules",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "query": {
      "description": "Full-text search across document title and body. Omit to browse by filters alone (e.g. all EPA proposed rules in a date range).",
      "type": "string"
    },
    "type": {
      "description": "Document types to include. PRORULE=Proposed Rule, RULE=Final Rule, NOTICE=Notice, PRESDOCU=Presidential Document. Omit for all types.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "PRORULE",
          "RULE",
          "NOTICE",
          "PRESDOCU"
        ]
      }
    },
    "agencies": {
      "description": "Filter to one or more agencies by Federal Register agency slug (e.g. \"environmental-protection-agency\", \"securities-and-exchange-commission\"). Slugs are the kebab-case agency name; if unsure, search by query and read the agency slugs off the results.",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "published_after": {
      "description": "Earliest publication date, ISO 8601 (YYYY-MM-DD). Combine with published_before to window large result sets — the FR caps navigation at 50 pages.",
      "anyOf": [
        {
          "type": "string",
          "const": ""
        },
        {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "description": "ISO 8601 date (YYYY-MM-DD)."
        }
      ]
    },
    "published_before": {
      "description": "Latest publication date, ISO 8601 (YYYY-MM-DD).",
      "anyOf": [
        {
          "type": "string",
          "const": ""
        },
        {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "description": "ISO 8601 date (YYYY-MM-DD)."
        }
      ]
    },
    "per_page": {
      "default": 20,
      "description": "Results per page (1–100, default 20).",
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    },
    "page": {
      "default": 1,
      "description": "Page number (1–50, default 1). The FR API caps total_pages at 50 — with per_page=100 this allows navigating up to 5,000 results. To reach beyond that window, narrow with published_after/published_before rather than paging deeper.",
      "type": "integer",
      "minimum": 1,
      "maximum": 50
    }
  },
  "required": [
    "per_page",
    "page"
  ],
  "additionalProperties": false
}
view source ↗

regulations_get_document

Fetch one Federal Register document by its FR document number — full metadata (title, type, agencies, abstract, action, effective/comment dates, RINs) plus the cross-source handles that make this a workflow server. The output carries the docket ID (chain into regulations_get_docket or regulations_find_comments) and the affected CFR parts (chain into regulations_get_cfr_section). Set include_full_text only when the rule body itself is needed — final rules can run tens of thousands of words.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "regulations_get_document",
    "arguments": {
      "document_number": "<document_number>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "document_number": {
      "type": "string",
      "pattern": "^[0-9]{4}-[0-9]+$",
      "description": "Federal Register document number (e.g. \"2025-14555\"). Obtain from regulations_search_rules results (the documentNumber field)."
    },
    "include_full_text": {
      "default": false,
      "description": "When true, fetch and inline the document body as plain text (can be large). Default false returns the body URLs only; fetch full text only when you need to read the rule itself, not just its metadata and cross-links.",
      "type": "boolean"
    }
  },
  "required": [
    "document_number",
    "include_full_text"
  ],
  "additionalProperties": false
}
view source ↗

regulations_browse_cfr

open-world

Explore the codified Code of Federal Regulations via eCFR in two modes. "structure" walks the CFR hierarchy (all 50 titles, or one title's chapters → parts → sections) to discover a cite when the exact citation is unknown. "search" runs a full-text query across the codified CFR and returns matching sections with their hierarchy path and a snippet. Both modes feed regulations_get_cfr_section. The source (mirror or live) is reported on each search result.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "regulations_browse_cfr",
    "arguments": {
      "mode": "<mode>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "mode": {
      "type": "string",
      "enum": [
        "structure",
        "search"
      ],
      "description": "\"structure\": browse the CFR tree (titles, or one title's chapters/parts/sections) to find a cite. \"search\": full-text search the codified CFR for sections matching a phrase."
    },
    "title": {
      "description": "CFR title number (1–50). Structure mode: omit to list all 50 titles, or provide to expand one title. Search mode: optional filter to restrict to one title.",
      "type": "integer",
      "minimum": 1,
      "maximum": 50
    },
    "part": {
      "description": "CFR part within the title (structure mode, optional) — narrows the returned tree to one part's sections. Parts can be alphanumeric.",
      "type": "string"
    },
    "query": {
      "description": "Full-text search phrase (search mode, required in that mode). Ignored in structure mode.",
      "anyOf": [
        {
          "type": "string",
          "const": ""
        },
        {
          "type": "string",
          "minLength": 2,
          "description": "Search phrase, at least 2 characters."
        }
      ]
    },
    "date": {
      "description": "Point-in-time date, ISO 8601 (YYYY-MM-DD). Defaults to current. Structure mode uses this date for historical hierarchy; in search mode, a past date enables point-in-time search.",
      "anyOf": [
        {
          "type": "string",
          "const": ""
        },
        {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "description": "ISO 8601 date (YYYY-MM-DD)."
        }
      ]
    },
    "per_page": {
      "default": 20,
      "description": "Results per page in search mode (1–50, default 20). Ignored in structure mode.",
      "type": "integer",
      "minimum": 1,
      "maximum": 50
    }
  },
  "required": [
    "mode",
    "per_page"
  ],
  "additionalProperties": false
}
view source ↗

regulations_get_cfr_section

Read the codified text of a specific CFR section (or a whole part) via eCFR — current or as of a past date. Answers "what does 40 CFR 50.1 say today?" and "...as of 2019-01-01?". Provide title + part + section for one section, or omit section to fetch the whole part (large parts can be very long; prefer a specific section when you know it). eCFR retains historical versions back to roughly 2017; a date before coverage is rejected with guidance. Current single-section reads are served from a synced local mirror when available; the source is reported.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "regulations_get_cfr_section",
    "arguments": {
      "title": "<title>",
      "part": "<part>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "title": {
      "type": "integer",
      "minimum": 1,
      "maximum": 50,
      "description": "CFR title number (1–50). E.g. 40 for \"Protection of Environment\"."
    },
    "part": {
      "type": "string",
      "description": "CFR part within the title (e.g. \"50\"). Parts can be alphanumeric. Obtain from regulations_browse_cfr or a Federal Register document's cfrReferences."
    },
    "section": {
      "description": "Section identifier within the part (e.g. \"50.1\"). Omit to fetch the entire part — large parts can be very long; prefer a specific section when you know it.",
      "anyOf": [
        {
          "type": "string",
          "const": ""
        },
        {
          "type": "string",
          "description": "Section identifier (e.g. \"50.1\")."
        }
      ]
    },
    "date": {
      "description": "Point-in-time date, ISO 8601 (YYYY-MM-DD). Default current. eCFR retains historical versions back to ~2017; a date before coverage is rejected.",
      "anyOf": [
        {
          "type": "string",
          "const": ""
        },
        {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "description": "ISO 8601 date (YYYY-MM-DD)."
        }
      ]
    }
  },
  "required": [
    "title",
    "part"
  ],
  "additionalProperties": false
}
view source ↗

regulations_get_docket

Pull a rulemaking docket from Regulations.gov by docket ID (e.g. "EPA-HQ-OAR-2025-0194") — the docket's metadata (title, agency, RIN, abstract) and the documents filed in it (NPRM, final rule, supporting materials). The docket is the folder holding a rule's whole paper trail; each returned document's objectId feeds regulations_find_comments. A docket often contains hundreds of supporting materials — filter document_types to "Proposed Rule"/"Rule" to find the rule documents themselves. Requires REGULATIONS_GOV_API_KEY (free at https://api.data.gov/signup/); the Federal Register and eCFR tools work without it.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "regulations_get_docket",
    "arguments": {
      "docket_id": "<docket_id>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "docket_id": {
      "type": "string",
      "pattern": "^[A-Za-z0-9_-]+$",
      "description": "Regulations.gov docket ID (e.g. \"EPA-HQ-OAR-2025-0194\"). Obtain from a Federal Register document's docketId (regulations_get_document) or an agency rulemaking reference."
    },
    "document_types": {
      "description": "Filter the docket's documents to these types. Omit for all. A docket often contains hundreds of \"Supporting & Related Material\" items — filter to \"Proposed Rule\"/\"Rule\" to find the rule documents.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "Proposed Rule",
          "Rule",
          "Notice",
          "Supporting & Related Material",
          "Other"
        ]
      }
    },
    "per_page": {
      "default": 25,
      "description": "Documents per page (5–250, default 25). Regulations.gov requires a minimum page size of 5.",
      "type": "integer",
      "minimum": 5,
      "maximum": 250
    },
    "page": {
      "default": 1,
      "description": "Page number (1-based). Regulations.gov caps a query at 20 pages (5,000 records); beyond that, narrow with document_types.",
      "type": "integer",
      "minimum": 1,
      "maximum": 20
    }
  },
  "required": [
    "docket_id",
    "per_page",
    "page"
  ],
  "additionalProperties": false
}
view source ↗

regulations_find_comments

open-world

Fetch public comments on a Federal Register document or a Regulations.gov docket — the unique corpus of what citizens and organizations actually submitted. Provide exactly one targeting parameter: docket_id (all comments in a docket, broadest), document_object_id (comments on one document, from regulations_get_docket), fr_document_number (convenience — resolves the FR number to its Regulations.gov document internally), or comment_id (one comment's full detail and attachments). The list endpoint returns no body text or attachment info — call with comment_id to read a comment's body. When a comment's real content is a PDF/DOCX attachment, the body is a stub and attachmentOnly is true; the attachment download URLs are returned. Requires REGULATIONS_GOV_API_KEY (free at https://api.data.gov/signup/).

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "regulations_find_comments",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "docket_id": {
      "description": "Fetch all comments in a docket by docket ID (e.g. \"EPA-HQ-OAR-2025-0194\"). Broadest scope. One of docket_id / document_object_id / fr_document_number / comment_id is required.",
      "type": "string"
    },
    "document_object_id": {
      "description": "Fetch comments on one specific document by its Regulations.gov object ID (the objectId from regulations_get_docket's documents). Comments usually attach to the docket's primary (proposed-rule) document.",
      "type": "string"
    },
    "fr_document_number": {
      "description": "Convenience: fetch comments for a Federal Register document by its FR number (e.g. \"2025-14555\"). Resolves to the Regulations.gov document internally. Saves a get_document → get_docket hop.",
      "type": "string"
    },
    "comment_id": {
      "description": "Fetch one comment's full detail and attachments by its Regulations.gov comment ID (e.g. \"EPA-HQ-OAR-2025-0194-31102\"). Use to read a single comment's body after finding it in a list.",
      "type": "string"
    },
    "per_page": {
      "default": 25,
      "description": "Comments per page (5–250, default 25). Regulations.gov requires a minimum page size of 5.",
      "type": "integer",
      "minimum": 5,
      "maximum": 250
    },
    "page": {
      "default": 1,
      "description": "Page number (1-based). Regulations.gov caps a query at 20 pages (5,000 records); for a high-volume docket this surfaces a sample — narrow by document_object_id.",
      "type": "integer",
      "minimum": 1,
      "maximum": 20
    }
  },
  "required": [
    "per_page",
    "page"
  ],
  "additionalProperties": false
}
view source ↗

regulations_list_open_comments

open-world

List rules currently open for public comment, filterable by agency slug and topic, sorted by closing date (soonest first). "What can I still weigh in on?" Runs on the Federal Register's open-comment window and is fully functional without a key. When REGULATIONS_GOV_API_KEY is configured, each row is enriched with the comment count from the Federal Register document's embedded Regulations.gov info (no extra rate-limited call). Open one row with regulations_get_document for the full proposal, or pull the comments with regulations_find_comments.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "regulations_list_open_comments",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "query": {
      "description": "Full-text filter across open rules. Omit to list all rules currently open for comment.",
      "type": "string"
    },
    "agencies": {
      "description": "Filter to one or more agencies by Federal Register agency slug (e.g. \"environmental-protection-agency\").",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "closing_before": {
      "description": "Only rules whose comment period closes on or before this date, ISO 8601 (YYYY-MM-DD). Use to find deadlines you need to act on soon.",
      "anyOf": [
        {
          "type": "string",
          "const": ""
        },
        {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "description": "ISO 8601 date (YYYY-MM-DD)."
        }
      ]
    },
    "per_page": {
      "default": 20,
      "description": "Results per page (1–100, default 20).",
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    },
    "page": {
      "default": 1,
      "description": "Page number (1–50). The FR caps total_pages at 50; with per_page=100 this covers up to 5,000 open rules.",
      "type": "integer",
      "minimum": 1,
      "maximum": 50
    }
  },
  "required": [
    "per_page",
    "page"
  ],
  "additionalProperties": false
}
view source ↗

Resources

2

A single Federal Register document by FR number: metadata plus the cross-source handles (docket ID, affected CFR parts, comment count) that chain into the comment and codified-text tools. Mirrors regulations_get_document (full text omitted).

uri regulations://document/{documentNumber} mime application/json

Codified text of a current CFR section by title/part/section (e.g. regulations://cfr/40/50/50.1). Mirrors regulations_get_cfr_section at the current date — mirror-backed with a live eCFR fallback.

uri regulations://cfr/{title}/{part}/{section} mime application/json