Skip to main content
Glama

cfr-free

CI License: MIT

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: cfr-mcp

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 index

Docker

docker run -d --name cfr-free -p 8787:8787 -v cfr-data:/data \
  ghcr.io/deffenda/cfr-free:latest

The 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

search_regulations

query, page?, per_page?, part?

Ranked hits: citation (+ 38 C.F.R. § display form, ecfr.gov link), heading, snippet, score, matches — with exact-citation pinning, "quoted phrase" search, and claims-acronym expansion (PTSD, TDIU, SMC, …)

get_section

citation (e.g. 38 CFR 4.125)

Full section text as markdown + ecfr.gov link + cross-references with availability flags

browse_title38

chapter?, part?, subpart?

Children of the requested hierarchy level

index_status

—

Issue date, last sync, row counts, staleness, drift flag, and what the last sync amended/added/removed

list_parts

—

Parts in the index with titles and section/appendix counts

health

—

One-call readiness verdict: ready, stale, degraded (structure drift), or empty

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 three MCP resources that clients can read directly — cfr://index/status (freshness JSON: issue date, last sync, row counts, staleness, drift), cfr://title38/parts (parts with titles and counts), and cfr://title38/definitions (§ 3.1 master definitions section detail) — 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

GET / HEAD

/health

—

GET / HEAD

/metrics

— (Prometheus text format)

GET / HEAD

/api/v1/search

q (required), page, per_page, part

GET / HEAD

/api/v1/sections/:citation

— (URL-encode citations with spaces)

GET / HEAD

/api/v1/browse

chapter, part, subpart

/health and /metrics additionally expose diskFree/diskTotal and the cfr_free_disk_free_bytes/cfr_free_disk_total_bytes gauges when the platform provides fs.statfs (as of boot or last refresh round); omitted otherwise.

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 full request/response contract (schemas, error envelopes) is documented in docs/openapi.yaml (OpenAPI 3.1).

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

CFR_INDEX_PATH

~/.cfr-free/index.sqlite

SQLite index location

CFR_MAX_AGE_DAYS

7

Index older than this is reported stale

CFR_AUTO_SYNC

1

Sync at startup when index empty/stale

CFR_REFRESH_HOURS

0

Hours between background refreshes while serving (0 = off)

CFR_HOST

127.0.0.1

HTTP bind address

CFR_PORT

8787

HTTP bind port

CFR_ALLOW_REMOTE

unset

Set 1 to permit non-loopback binds

CFR_LOG_LEVEL

info

debug | info | warn | error

Logs are structured JSON lines on stderr only — stdout is reserved for MCP's JSON-RPC protocol.

Exit codes

Code

Meaning

0

Success

1

Generic error (sync failure, corrupt index, …)

2

Usage or configuration error

3

Index unavailable (empty, and auto-sync disabled)

4

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 only

Talks 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 facade

  • src/mcp/ — MCP server and tool registrations

  • src/titan/ — HTTP JSON API

  • src/commands/ — sync, serve, mcp

  • docs/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: lint/strict-TS/typecheck/coverage/Audit gates (plus local trivy/semgrep/osv-scanner/gitleaks scans), 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

MIT

Available Tools

6 tools
browse_title38Browse the CFR structureA
Read-onlyIdempotent

Navigate the Title 38 hierarchy (title → chapter → part → subpart) and list what exists at a level. With no arguments, returns the chapters. Use this to discover valid parts/subparts before searching.

ParametersJSON Schema
NameRequiredDescriptionDefault
partNopart number, e.g. "4"
chapterNochapter identifier, e.g. "I"
subpartNosubpart letter, e.g. "B" (requires part)

Output Schema

ParametersJSON Schema
NameRequiredDescription
nodeYes
pathYes
childrenYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive and closed-world, so the safety profile is covered. The description adds genuinely useful behavior beyond that: the hierarchy shape being navigated and the no-argument default returning chapters. It stops short of disclosing deep-level behavior (e.g., what happens with an unknown part).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler. The hierarchy shape is front-loaded, followed immediately by the default no-argument behavior and the recommended use. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and annotations covering the safety profile, the description supplies what's needed to invoke correctly, including the zero-argument default. The only meaningful gap is not clarifying its boundary against the overlapping list_parts sibling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so chapter/part/subpart semantics and the 'requires part' constraint are already documented in the schema. The description restates the hierarchy order but adds no format, valid-value, or error-handling detail beyond it. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Navigate') and resource ('Title 38 hierarchy'), and enumerates the path shape (title → chapter → part → subpart) plus the listing behavior. It does not explicitly distinguish itself from the sibling list_parts, which appears to overlap in scope, so it falls short of the 5-level sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear use case: 'Use this to discover valid parts/subparts before searching', which positions it ahead of search_regulations. However, it never names the overlapping sibling list_parts or states when browsing is preferred over it, so no explicit alternative is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_sectionRead a CFR sectionA
Read-onlyIdempotent

Fetch the full text of one Title 38 CFR section or appendix as markdown. Accepts flexible citations: "4.125", "§ 4.125", "38 CFR 4.125", or appendix names like "Appendix A to Part 4". Returns heading, hierarchy path, issue date and an ecfr.gov permalink.

ParametersJSON Schema
NameRequiredDescriptionDefault
citationYesthe citation to read, e.g. "38 CFR 4.125"

Output Schema

ParametersJSON Schema
NameRequiredDescription
kindYes
partYes
pathYes
textYes
noticeYes
chapterYes
headingYes
subpartYes
citationYes
markdownYes
issueDateYes
sourceUrlYes
indexStaleYes
referencesYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), and the description adds useful context about what comes back: heading, hierarchy path, issue date, and an ecfr.gov permalink. It does not mention error behavior for unmatched citations, but that is a minor gap given annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero filler, with the core action front-loaded and the citation flexibility examples placed exactly where they are needed. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return-value detail is optional, yet the description still summarizes the payload, and it fully covers the single required parameter. Nothing essential for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description genuinely adds meaning: it enumerates several citation spellings ("4.125", "§ 4.125", "38 CFR 4.125") and notes that appendix names like "Appendix A to Part 4" are also valid. That is richer than the schema's single example.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (fetch) and resource (full text of one Title 38 CFR section or appendix) plus the output format (markdown). This clearly separates it from siblings like search_regulations and browse_title38, which are browsing/search rather than single-document retrieval.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The single-section scope and the accepted citation forms imply this is the right tool when you already know which section you want, but the description never states that explicitly nor names search_regulations as the alternative for discovery. Usage is inferable rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

healthIndex readinessA
Read-onlyIdempotent

One-call readiness verdict for the local index: "ready" (query away), "stale" (older than CFR_MAX_AGE_DAYS — verify results against the current eCFR), "degraded" (structure drift — provisions may be missing; verify against the current eCFR), or "empty" (no index yet — run cfr-free sync). Clients should gate queries on this before spending tool calls.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
staleYes
statusYes
syncedAtYes
issueDateYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds real value beyond that: the semantics of each state, the remediation for 'empty' (run `cfr-free sync`), and the obligation to verify 'stale'/'degraded' results against the current eCFR. It does not mention latency or whether the check is cheap, so a 4 rather than a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single front-loaded sentence that leads with the verdict concept, then defines each state inline. Dense with nested parentheses and em-dashes, which makes it slightly harder to scan, but no sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present the description need not explain return values, yet it still defines the four verdicts and their follow-up actions — more than enough for a zero-param read tool. The one gap is failing to clarify the boundary with the sibling 'index_status'.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline of 4 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('one-call readiness verdict for the local index') and enumerates all four possible verdicts with their meanings, so an agent knows exactly what comes back. It does not, however, distinguish itself from the sibling 'index_status', which sounds like an overlapping concept — that ambiguity keeps it from a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Clients should gate queries on this before spending tool calls' gives an explicit when-to-use rule and even a cost rationale. It stops short of naming an alternative or a when-not-to-use case (e.g., after a sync is known to be fresh), and never mentions the similar-sounding 'index_status' sibling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

index_statusLocal index freshnessA
Read-onlyIdempotent

Report how current the local Title 38 index is: eCFR issue date, last sync time, row counts and whether the index is stale relative to CFR_MAX_AGE_DAYS. Check this before relying on search results.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
staleYes
sectionsYes
syncedAtYes
issueDateYes
appendicesYes
maxAgeDaysYes
lastChangesYes
parserVersionYes
structureDriftYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive and closed-world, so the safety profile is covered. The description adds real behavioral context beyond that: the staleness verdict is computed relative to the CFR_MAX_AGE_DAYS threshold, and the report's components are named. It omits cost/latency and any permission notes, so not a full 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with the content of the report front-loaded and the actionable instruction ('check this before relying on search results') placed last. No filler, no restatement of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the description need not enumerate return values in detail, and annotations carry the safety profile. Combined with the stated staleness semantics and pre-flight usage advice, an agent has everything needed to call this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline for a no-parameter tool is 4. The description correctly implies the call needs no input.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Report how current the local Title 38 index is') and enumerates exactly what is reported: eCFR issue date, last sync time, row counts, staleness. This is clearly distinguishable from siblings like search_regulations or health without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit situational guidance: 'Check this before relying on search results,' which tells the agent when to reach for it. It stops short of naming an alternative or exclusion (e.g., versus the sibling 'health'), so it is clear context rather than full when/when-not routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_partsList CFR parts in the local indexA
Read-onlyIdempotent

Enumerate every Title 38 CFR part present in the local index, with its structure-tree title and section/appendix counts. Use this to discover which parts are searchable.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
partsYes

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive, and closed-world behavior, so the safety profile is fully covered. The description adds that results come specifically from the 'local index' and what fields are returned, but the return fields are already in the output schema, so the incremental behavioral disclosure is modest.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences: the first states scope and return content, the second states the use case. Front-loaded and free of filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a rich output schema and complete annotations, the description covers purpose, scope, and use case, leaving little for an agent to guess. Only minor details (ordering, whether the index can be stale/incomplete) are unstated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero parameters, so the baseline is 4; nothing about parameter meaning needs documenting and the schema fully covers the (empty) input.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Enumerate') and resource ('Title 38 CFR part') scoped to the local index, and states the returned fields (structure-tree title, section/appendix counts). It is clear on its own, but it never names or contrasts with siblings like browse_title38 or search_regulations, which could plausibly overlap.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Use this to discover which parts are searchable' gives a concrete when-to-use condition tied to a downstream action. It stops short of stating when-not-to-use or pointing to an alternative sibling for related tasks, so it is clear context without exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_regulationsSearch Title 38 CFR regulationsA
Read-onlyIdempotent

Full-text search across the local Title 38 (VA) CFR index using ranked keyword matching. Returns section citations, headings, relevance snippets, bm25 scores (lower is better) and the query terms visible in each hit. Use part to scope results to a single CFR part (e.g. "4" for ratings, "17" for prosthetics). Follow up with get_section to read a hit in full. If the query itself is a citation (e.g. "4.130" or "38 CFR 4.16"), that exact section is pinned to the top of page 1 (totals include the pin on every page) and marked direct: true — the reliable client signal; the pinned hit's inResults flag reports whether it also matched the ranked results. Quoted spans (e.g. "exact regulatory language") are emitted as FTS5 phrase queries — the last token gets a prefix wildcard (so "language" also matches "languages"); earlier tokens are matched exactly.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo1-based result page (default 1)
partNorestrict to one CFR part number
queryYessearch terms, e.g. "traumatic brain injury compensation"
per_pageNoresults per page (default 10, max 20)

Output Schema

ParametersJSON Schema
NameRequiredDescription
hitsYes
pageYes
queryYes
totalYes
noticeYes
perPageYes
matchModeYes
indexStaleYes
indexIssueDateYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), and the description adds substantial behavior beyond that: bm25 scoring direction (lower is better), citation-pinning behavior with the `direct: true` signal and `inResults` flag semantics, and FTS5 phrase-query handling where only the last token gets a prefix wildcard.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose, then usage, then the citation-pinning and phrase-query nuances in roughly descending priority. Dense and largely waste-free, though the final FTS5 sentence is long and detailed enough to test the bounds of conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, yet the description still explains the non-obvious return fields (bm25, direct, inResults) that an agent needs to interpret hits, plus pagination behavior on pinned citations. Nothing needed to call or interpret this tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real value: it explains `part` scoping with domain examples beyond the schema's terse 'restrict to one CFR part number', and describes how quoted `query` spans are tokenized into FTS5 phrase queries.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Full-text search across the local Title 38 (VA) CFR index using ranked keyword matching') and implicitly distinguishes itself from get_section, which it names as the follow-up for reading full sections. An agent can tell what this does versus its siblings without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear usage context: use `part` to scope results (with concrete examples '4' for ratings, '17' for prosthetics) and follow up with get_section to read a hit in full. It stops short of stating when-not to use it versus browse_title38 or list_parts, so no explicit exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 6 tool updatesv0.1.0
    • First observedbrowse_title38
    • First observedget_section
    • First observedhealth
    • First observedindex_status
    • First observedlist_parts
    • First observedsearch_regulations

TDQS

A4.1/5.0

Scored across 6 tools

Disambiguation3/5

Search vs. fetch (search_regulations/get_section) is clearly distinct, but two pairs overlap: browse_title38 and list_parts both serve discovery of available parts, and index_status and health both report index state. The descriptions explain the nuances (hierarchy navigation vs. flat enumeration; detailed status vs. one-call verdict), but an agent could still reasonably pick the wrong one.

Naming Consistency4/5

Most names follow a verb_noun pattern (search_regulations, get_section, browse_title38, list_parts), but 'health' is a bare noun and 'index_status' inverts to noun_noun. The deviations are minor and readable, so the set stays predictable.

Tool Count5/5

Six tools is well-scoped for a read-only regulatory lookup server: discovery, search, retrieval, and index-health checks each earn their place without redundancy bloat. No tool feels trivial or missing a counterpart.

Completeness4/5

The surface covers the full read lifecycle (discover parts, navigate hierarchy, search, fetch full text) plus index freshness/readiness, which is strong for this domain. The only notable omission is an in-server sync/refresh operation, which is relegated to the CLI, a minor gap agents can work around.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Enables 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.
    7
    45 PyPI
    1
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables 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.
    -
  • A
    license
    A
    quality
    B
    maintenance
    Enables searching and reading the US Code of Federal Regulations through tools that return excerpts, full text, legal citations, and linked source URLs, with read-only, stateless access.
    3
    MIT