Skip to main content
Glama
README.md
# docket-mcp

[![M8ven Score](https://m8ven.ai/badge/mcp/coltonshawproctor-docket-mcp-tfo9oo?v=a0a8e66f75e2fde076bf151665f14d27)](https://m8ven.ai/mcp/coltonshawproctor-docket-mcp-tfo9oo)

An MCP server for [Regulations.gov](https://www.regulations.gov). It gives an LLM agent read access to federal rulemaking: search dockets, fetch a docket's abstract and metadata, and list the documents filed in it. Built for agents that answer questions like "what is in the BIS docket on AI reporting requirements and is it still open for comment?"

## Quickstart

You need a free Regulations.gov API key from [api.data.gov](https://open.gsa.gov/api/regulationsgov/). `DEMO_KEY` works for light use.

```bash
pip install git+https://github.com/ColtonShawProctor/docket-mcp
export REGULATIONS_GOV_API_KEY=your-key-here
docket-mcp
```

Claude Code:

```bash
claude mcp add docket -e REGULATIONS_GOV_API_KEY=your-key-here -- docket-mcp
```

Claude Desktop or Cursor (`mcpServers` in the client config):

```json
{
  "mcpServers": {
    "docket": {
      "command": "docket-mcp",
      "env": { "REGULATIONS_GOV_API_KEY": "your-key-here" }
    }
  }
}
```

## Getting an API key

Request a free key at [api.data.gov](https://open.gsa.gov/api/regulationsgov/) (the signup takes about a minute) and set it as `REGULATIONS_GOV_API_KEY` in your environment or in the MCP client config shown above.

If you skip this, `DEMO_KEY` works for a quick try, but it shares a low hourly limit with everyone else using it, so real use rate-limits fast. The server retries with backoff when that happens, but the honest fix is a personal key: same API, same data, a far higher limit. The fixtures in `tests/` were recorded with `DEMO_KEY`, which is also why the tests never call the API at all.

## Tools

This section is written for both humans and the models that call the tools. The short version a model needs: start with `search_dockets`, take an `id` from the results, and hand it to `get_docket` or `list_documents`. Never guess docket IDs. If every call fails, call `ping` and check `api_key_configured`.

### `ping`

Health and configuration check. No network call. Returns the server version, the API base URL, and whether an API key is configured, plus the env var name to set if it is not.

### `search_dockets(query, page=1, page_size=20, agency_id=None)`

Full-text search of dockets. Returns `total`, paging fields, and a `dockets` list of summaries: `id`, `title`, `docket_type` (`Rulemaking` or `Nonrulemaking`), `agency_id`, `last_modified`, and `match_context`, a plain-text snippet showing why the docket matched (the API's HTML highlighting is stripped before it reaches the model). `agency_id` filters to one agency, for example `"EPA"` or `"BIS"`.

Real output, produced from a response recorded from the live API (trimmed):

```json
{
  "query": "artificial intelligence",
  "total": 68,
  "page": 1,
  "page_size": 5,
  "has_next_page": true,
  "dockets": [
    {
      "id": "BIS-2024-0047",
      "title": "Establishment of Reporting Requirements for the Development of Advanced Artificial Intelligence Models and Computing Clusters",
      "docket_type": "Rulemaking",
      "agency_id": "BIS",
      "last_modified": "2024-10-22T15:46:37Z",
      "match_context": "Data Collections regulations by establishing reporting requirements for the development of advanced artificial intelligence (AI) models [...]"
    }
  ]
}
```

### `get_docket(docket_id)`

One docket's full detail: `id`, `title`, `agency_id`, `docket_type`, `abstract` (the docket's own summary of the rulemaking), `keywords`, `rin` (Regulation Identifier Number), and `last_modified`. An unknown ID is a clear not-found error carrying the API's message.

### `list_documents(docket_id, page=1, page_size=20)`

The documents filed in a docket: `id`, `title`, `document_type` (`Proposed Rule`, `Rule`, `Notice`, `Supporting & Related Material`, and so on), `posted_date`, `fr_doc_num` (Federal Register document number), `open_for_comment`, `comment_end_date`, and `withdrawn`. A docket ID that matches nothing yields an empty list, not an error; that is the API's recorded behavior, not an assumption.

### Errors a model may see

- Malformed IDs (wrong characters, lookalike unicode, path separators) are rejected locally with a message showing the expected shape. No request is sent.
- `page` beyond 20 or `page_size` outside 5 to 250 are the API's own limits, rejected locally with the limit in the message. Narrow the query instead of paging deeper.
- Rate limiting is retried automatically with backoff, honoring the server's `Retry-After`. If the limit is still exceeded after retries, the error says the limit is hourly, so retrying immediately is pointless.

## Data source notes

The upstream is the Regulations.gov v4 API. Keys are issued through api.data.gov and rate limits are hourly per key; `DEMO_KEY` has a much lower limit than a personal key. Search results are capped by the API at page 20, with up to 250 results per page. Transient gateway errors (500, 502, 503, 504) are retried with capped exponential backoff.

## Testing

`pytest` runs 39 tests in well under a second and never touches the network. The fixtures in `tests/fixtures/` are verbatim response bodies recorded from the live API on 2026-09-08, so the parsers are tested against actual field shapes rather than invented ones. The retry suite injects the sleep function and asserts exact request and delay sequences; reverting the retry loop turns five tests red, which was verified, not assumed.

```bash
pip install -e '.[dev]'
pytest
```

## Limitations

- Read-only. No comment submission, and none planned.
- No document full text yet. `get_document_text` (PDF and HTML extraction) and a chunking tool for RAG consumers are the next milestone.
- No comment retrieval yet.
- Search covers dockets only; the API's document and comment search endpoints are not exposed yet.

## License

MIT.

TDQS

A4.5/5.0

Scored across 4 tools

Disambiguation5/5

Each tool has a distinct role: ping is health-only, search_dockets is the fuzzy query entry point, get_docket is exact-ID detail lookup, and list_documents returns child documents. The descriptions explicitly cross-reference IDs, so an agent should not confuse which tool to call.

Naming Consistency4/5

The three data tools follow a clean verb_noun snake_case pattern: search_dockets, get_docket, list_documents. ping is a conventional health-check exception, but it is the only minor deviation and does not create confusion.

Tool Count5/5

Four tools are well-scoped for a docket-browsing server: health check, search, detail lookup, and document listing. There is no redundancy, and the count fits comfortably within an appropriate MCP server size.

Completeness4/5

The core docket workflow is covered end-to-end: search dockets, fetch full docket details, and list the documents within a docket. The main gap is the absence of a per-document detail/search tool, so deeper document-level retrieval is not possible.

Maintenance

ActivityMaintained
ResponsivenessNo issues