v2.0.0
fedreg-mcp-server v2.0.0
Two headline changes: a third data source and a stateless protocol core.
regulations.gov support (regs.*)
The model can now reach public comments, dockets, and live comment-period
status alongside the Federal Register and eCFR:
// Find the comments on a specific FR rule (the fr → regs bridge):
const fr1 = await fr.documents.search({ conditions: { term: 'methane', type: ['RULE'] }, per_page: 1, order: 'newest' });
const rd = await regs.documents.search({ filter: { searchTerm: fr1.results[0].document_number } });
const comments = await regs.comments.search({ filter: { commentOnId: rd.data[0].attributes.objectId }, page: { size: 250 } });Bring a free API key (FEDREG_REGS_API_KEY, from api.data.gov). The key stays
host-side — sandboxed code can never see it. Without a key, regs.* degrades
gracefully to SourceUnavailable while fr/ecfr keep working. Four layered
rate guardrails protect the shared key: a per-execute call budget, a
per-subject hourly quota, a process-wide hourly token bucket, and no-retry on
upstream 429s.
Under the hood, sources are now a pluggable registry — adding a fourth
source is one factory, one registry line, and one corpus file.
Stateless MCP 2026-07-28
The HTTP transport now speaks the stateless protocol revision on MCP SDK v2:
- No sessions. No
initializehandshake, noMcp-Session-Id, nothing to
replay or steal. Every request is self-contained and re-authenticated, so
per-tenant quota integrity holds by construction. - Load-balancer friendly. Replicas are interchangeable — no sticky
routing, no shared session store. server/discover, required routing headers (Mcp-Method/Mcp-Name)
with mismatch rejection, and cache metadata (ttlMs/cacheScope) on list
results.- Old clients keep working. Pre-2026 MCP clients are answered by a
per-request stateless legacy fallback.
Validated end-to-end with MCP Inspector (legacy leg) and the official
@modelcontextprotocol/client@2 SDK (modern leg), including live sandboxed
calls against the real government APIs.
Breaking changes
- Unknown tool-argument keys are now rejected (
additionalProperties: false) instead of silently stripped. - Unknown tool names return a JSON-RPC error (
-32602), not an
isErrortool result. GET/DELETE /mcp→405; the standalone SSE stream is gone.FEDREG_MAX_SESSIONSis removed (ignored if set).
stdio users (Claude Desktop): the transport and protocol changes above do
not apply — but the two tool-layer changes do. Unknown argument keys are now
rejected with isError: true, and an unknown tool name now returns JSON-RPC
-32602 instead of an isError result, on stdio as well as HTTP. Full
details and upgrade steps:
docs/migration-v2.md.
Verification
tsc --noEmit clean · eslint clean · 71 tests across 12 files (including a
conformance spec driving the server with the official v2 client SDK) · live
round-trips on both protocol legs against real upstream APIs.