cfr-free
Exposes Prometheus-compatible metrics via the /metrics HTTP endpoint, enabling monitoring and alerting on server health and usage.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@cfr-freeWhat does 38 CFR 4.125 say about diagnosing mental disorders?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
cfr-free
Self-hosted Title 38 CFR data service: it builds a local, full-text searchable index of Title 38 of the Code of Federal Regulations (the VA benefits rulebook) straight from the public eCFR API, and serves it through an MCP server (for AI assistants like Claude) and a small HTTP API ("Titan-style" query surface). No cloud dependencies, no API keys, no telemetry — one Node process and one SQLite file.
What you get
Local full-text search over every section and appendix of Title 38, powered by SQLite FTS5 (BM25-ranked with citation/heading weighting, relevance snippets, and the matched terms shown per hit).
MCP server with six read-only tools any MCP client can use:
search_regulations,get_section,browse_title38,index_status,list_parts,health.HTTP JSON API for scripts and apps: search, read sections, browse the CFR hierarchy, health check, Prometheus metrics.
Freshness tracking: the index records the eCFR issue date it was built from and warns when it goes stale or drifts from the structure tree.
Backup-friendly:
cfr-free export <path>writes a consistent snapshot of the index you can copy anywhere.
Related MCP server: mcp-fda-regulations
Requirements
Node.js ≥ 22.5 (uses the built-in
node:sqlite; SQLite ≥ 3.50 with FTS5, bundled with Node 22.5+)Network access only for
cfr-free sync(~2–3 MB from ecfr.gov); serving and searching are fully offline.
Quickstart
npm install -g cfr-free # or: npx cfr-free
cfr-free sync # build the local index (~2-3 MB download)
cfr-free serve # HTTP API on http://127.0.0.1:8787
# or
cfr-free mcp # MCP server on stdio (default command)
cfr-free export ./backup.sqlite # consistent snapshot of the local indexDocker
docker run -d --name cfr-free -p 8787:8787 -v cfr-data:/data \
ghcr.io/deffenda/cfr-free:latestThe container syncs on first start (~15 s, ~2–3 MB from eCFR), then serves
the HTTP API; the index persists in the cfr-data volume mounted at /data.
Any CLI command works the same way, e.g.
docker run --rm -v cfr-data:/data ghcr.io/deffenda/cfr-free:latest sync to
refresh, or … export /data/backup.sqlite to snapshot into the volume.
The image runs as a non-root user and binds 0.0.0.0 with the remote opt-in
already set — inside a container the published port (-p) is the exposure
gate, and loopback would make it unreachable. Outside Docker the CLI still
defaults to 127.0.0.1 with CFR_ALLOW_REMOTE=1 required. When you do
expose it, a per-peer token-bucket rate limit (60-burst, 10 req/s) turns on
automatically. Images are published to GHCR on v* tags with
build-provenance attestations.
Prefer Compose? docker compose up -d --build serves the API on
127.0.0.1:8787 with a named volume, healthcheck, and sync left explicit
(docker compose run --rm cfr-free sync) so starts never trigger a surprise
download.
Use with Claude (MCP)
Add to your MCP client config (e.g. claude_desktop_config.json):
{
"mcpServers": {
"cfr-free": {
"command": "cfr-free",
"args": ["mcp"]
}
}
}Then ask things like "What does 38 CFR 4.125 say about diagnosing mental disorders?" or "Search Title 38 for traumatic brain injury compensation."
MCP tools
Tool | Arguments | Returns |
|
| Ranked hits: citation (+ |
|
| Full section text as markdown + ecfr.gov link + cross-references with availability flags |
|
| Children of the requested hierarchy level |
| — | Issue date, last sync, row counts, staleness, drift flag, and what the last sync amended/added/removed |
| — | Parts in the index with titles and section/appendix counts |
| — | One-call readiness verdict: |
All tools are read-only and query only the local index — they never hit
the network. Search and section responses carry a freshness envelope
(indexStale + a notice when the local index has aged out) so a client can
never unknowingly quote a lapsed version.
Beyond tools, the server exposes two MCP resources that clients can read
directly — cfr://index/status (freshness JSON: issue date, last sync, row
counts, staleness, drift) and cfr://title38/parts (parts with titles and
counts) — plus two prompts: cfr_research (topic, part?), which walks
a model through the search → read → cite workflow, and
cfr_claim_evaluation (issue, part?, citation?), which encodes the
adjudicator workflow: readiness gate → locate criteria → quote verbatim →
follow cross-references → paste-ready citations with source URLs.
HTTP API
Method | Path | Query params |
|
| — |
|
| — (Prometheus text format) |
|
|
|
|
| — (URL-encode citations with spaces) |
|
|
|
curl 'http://127.0.0.1:8787/api/v1/search?q=traumatic%20brain%20injury&part=4'
curl 'http://127.0.0.1:8787/api/v1/sections/4.125'
curl 'http://127.0.0.1:8787/api/v1/browse?chapter=I&part=17'
curl 'http://127.0.0.1:8787/metrics'The API is intentionally minimal: GET-only, JSON-only, no request bodies,
no templating, bound to 127.0.0.1 by default. The single deliberate
exception is /metrics, which serves Prometheus exposition text for
scrapers. There is no authentication — if you bind it to a non-loopback
address you must put it behind your own reverse proxy/auth
(CFR_ALLOW_REMOTE=1 is required to allow that, as an explicit opt-in).
Configuration
All configuration is environment variables (flags are deliberately avoided so MCP client configs stay uniform):
Variable | Default | Meaning |
|
| SQLite index location |
|
| Index older than this is reported stale |
|
| Sync at startup when index empty/stale |
|
| HTTP bind address |
|
| HTTP bind port |
| unset | Set |
|
|
|
Logs are structured JSON lines on stderr only — stdout is reserved for MCP's JSON-RPC protocol.
Exit codes
Code | Meaning |
| Success |
| Generic error (sync failure, corrupt index, …) |
| Usage or configuration error |
| Index unavailable (empty, and auto-sync disabled) |
| HTTP port could not be bound (in use or permission denied) |
Scripts can branch on these — e.g. retry later on 3, pick another port
on 4.
Development
npm ci
npm run ci # format:check + lint + typecheck + tests + build + audit
npm run test:coverage
npm run scan # gitleaks + osv-scanner + trivy + semgrep (skips missing tools)Local LLM review (Gemma via LM Studio)
npm run review # reviews docs/SPEC.md + src/ with the local model
npm run review:spec # spec onlyTalks to LM Studio's OpenAI-compatible endpoint (http://localhost:1234 by
default, model google/gemma-4-12b). Configure with LMSTUDIO_BASE_URL,
LMSTUDIO_MODEL, LLM_REVIEW_TIMEOUT_MS, or --model / --base-url /
--max-tokens / --instruction flags. Reasoning models are handled
automatically (retries with a larger token budget when the visible answer
has not been emitted yet).
Architecture
eCFR API ──sync──▶ SQLite (sections + FTS5 + structure meta)
▲ ▲
│ │
MCP tools (stdio) HTTP API (node:http)src/core/— eCFR client, XML parser, FTS5 store, sync, service facadesrc/mcp/— MCP server and tool registrationssrc/titan/— HTTP JSON APIsrc/commands/—sync,serve,mcpdocs/SPEC.md— design decisions and review dispositions
Sync is atomic: the whole index is replaced inside one BEGIN IMMEDIATE
transaction under WAL, so concurrent readers never see a partial build, and
an interrupted sync simply rolls back.
Data source & attribution
Regulatory content comes from the eCFR API operated by the Office of the Federal Register and the Government Publishing Office. eCFR content is in the public domain (17 U.S.C. § 105). cfr-free is an independent project and is not endorsed by or affiliated with the VA, the OFR, or GPO. This tool is not legal advice; verify citations against the official eCFR.
Security
See SECURITY.md for reporting vulnerabilities and the security posture summary. Reported by default: Snyk/Sonar-ready lint and CI gates, zero runtime dependencies beyond the MCP SDK, XML parser hardening (no DOCTYPE, bounded depth/size), FTS query sanitization (no SQL injection surface), and loopback-only networking by default.
License
This server cannot be deployed
Maintenance
Related MCP Connectors
Veterans benefits and VA claims reference: VA disability ratings, compensation rates, 38 CFR search
Search and read US federal regulations with legal and inline citations linking to ecfr.io.
Search and trace US federal rules across the Federal Register, eCFR, and Regulations.gov.
US Federal Register for AI agents: rules, notices, executive orders, agency lookup. No keys.
Related MCP Servers
- AlicenseAqualityAmaintenanceProvides full-text search and retrieval tools for Apache Spark documentation using SQLite FTS5 with BM25 ranking. It enables AI assistants to efficiently search, filter by section, and read specific Spark documentation pages.2MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to access US FDA regulations (21 CFR) through natural language queries, providing tools for retrieving regulatory information.33 npmMIT
- AlicenseAqualityAmaintenanceEnables AI assistants to retrieve, search, and track changes to US Code of Federal Regulations sections via the eCFR API, returning actual regulation text with citations and point-in-time date support.721 PyPI1MIT
- FlicenseNot gradedqualityCmaintenanceEnables agents to search a local, fully offline personal document library (Markdown/txt/PDF/docx) via SQLite FTS5 trigram search with subject-terminology expansion, returning every hit with its domain, document title, section path, and page or offset provenance. It also exposes domain statistics, incremental ingestion, and document deprecation as tools, alongside a read-only, runtime-persona-scoped ask/coverage mode.-