Skip to main content
Glama

rfc-mcp

Evidence-first, strictly read-only Model Context Protocol server for the IETF RFC corpus. Every analysis runs on an immutable, content-addressed snapshot; every derived fact carries a citation id that can be re-verified byte-for-byte against the published file.

license node protocol types tests

Tools

15 read-only tools (rfc_resolve, rfc_read, rfc_requirements, rfc_verify_citation, …)

Resources

10 snapshot-addressed rfc:// templates

Prompts

6 reproducible workflows (/rfc:brief, /rfc:requirements_audit, …)

Sources

RFC Editor + IETF Datatracker only

Storage

SQLite (built-in) + FTS5, ~54 MB for 17 documents, 7 MB catalog index for all 9 842 RFCs

Dependencies

one runtime dependency tree from the official SDK; no native modules


Why this exists

An LLM asked "what does RFC 9110 say about HEAD requests" must be able to answer with a quote it can point at. Most tooling makes that impossible: it returns something plausible that nobody can verify. This server is built around the opposite idea:

Document → immutable snapshot → parsed structure → analysis → cited answer
  • every analysis runs on a content-addressed snapshot (snp_<hash>), never on "whatever is current right now";

  • every derived statement carries a citation_id that is re-checked against the raw bytes on demand (rfc_verify_citation → verified | stale | ambiguous | not_found | integrity_failure);

  • every response is an envelope with status, provenance, warnings and hard limits;

  • nothing is inferred silently: unresolved references, degraded parses, partial pages and offline misses are reported, never repaired or invented.

Related MCP server: IETF RFC MCP Server

Install

Requires Node.js ≥ 24 (uses the built-in node:sqlite with FTS5 — no native builds).

git clone https://github.com/vitkuz573/rfc-mcp.git
cd rfc-mcp
npm ci
npm run build

Quick start

# 1. Catalog: metadata for all 9 842 RFCs (one ~7 MB download)
node dist/cli.js sync index

# 2. Ingest documents you actually work with (parse + requirements + references)
node dist/cli.js sync rfc 2119 8174 9110 9000

# 3. Use it
node dist/cli.js outline 9110
node dist/cli.js requirements 9110 --scope 9.3.2 --term "MUST NOT"
node dist/cli.js search '"Idempotent"' --scope text
node dist/cli.js search 'cache relation:normative' --scope text   # only blocks citing a normative RFC
node dist/cli.js show 9110 --section 9.3.2
node dist/cli.js diff 7230 9110 --mode requirements

Or run the curated seed in one step: ./scripts/sync.sh (catalog + 20 documents).

Connect a host

OpenCode

The repository ships a working opencode.jsonc:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "timeout": { "startup": 60000, "catalog": 60000, "execution": 600000 },
    "servers": {
      "rfc": {
        "type": "local",
        "command": ["node", "dist/index.js"],
        "cwd": ".",
        "disabled": false,
        "protocol": "auto",
      },
    },
  },
}

protocol: "auto" probes for MCP revision 2026-07-28 and falls back to the classic initialize handshake; the same binary serves both.

Restarting the server without restarting the host: flip disabled in opencode.jsonc. true detaches the server immediately, false spawns a fresh process, so a rebuilt dist/ is live in the current session. Confirm with opencode mcp list (expect ✓ rfc connected) or /mcps inside OpenCode.

Any other MCP client

node dist/index.js                 # stdio transport

Claude Desktop (claude_desktop_config.json):

{ "mcpServers": { "rfc": { "command": "node", "args": ["/abs/path/rfc-mcp/dist/index.js"] } } }

The tool surface

With the server named rfc, hosts expose rfc_<tool>. All tools are readOnlyHint: true, destructiveHint: false, idempotentHint: true and carry an outputSchema.

Tool

Purpose

rfc_capabilities

Self-describing contract, limits, sources, policy

rfc_resolve

selector → pinned snapshot_id (the only "current" resolution)

rfc_metadata

title, authors, status, stream, area, WG, DOI, relations

rfc_read

one section, the full outline, an RFCXML outline, or a bounded raw byte slice

rfc_search

catalog + full-text search; every filter reports whether it applied

rfc_requirements

RFC 2119/8174 statements with clause structure and citations

rfc_references

normative/informative split, resolved targets, citation sites

rfc_dependencies

bounded typed graph: cites, obsoletes, updates, inbound relations

rfc_diff

text / structure / requirements / metadata / references between two snapshots

rfc_errata

errata overlay (never applied to publication text)

rfc_history

Datatracker change feed

rfc_source

official TXT/XML/HTML/PDF asset with SHA-256, ETag, canonical URLs

rfc_verify_citation

re-verify a citation against the stored bytes

rfc_status

corpus health, index generation, versions, recent failures

rfc_batch

≤ 10 read-only operations, per-item status, generation pinned

Resources

rfc://index/status
rfc://catalog/manifest
rfc://snapshot/{snapshot_id}/metadata | /provenance | /outline
rfc://snapshot/{snapshot_id}/sections/{section_id}
rfc://snapshot/{snapshot_id}/blocks/{block_id}
rfc://snapshot/{snapshot_id}/requirements/{requirement_id}
rfc://snapshot/{snapshot_id}/references/{reference_id}
rfc://snapshot/{snapshot_id}/citations/{citation_id}

Prompts

/rfc:brief, /rfc:requirements_audit, /rfc:compare, /rfc:dependency_review, /rfc:citation_check, /rfc:offline_review — reproducible workflows, each carrying the same evidence discipline and the rule that RFC text is untrusted data.

Response envelope

{
  "contract": "ietf-rfc/1",
  "status": "ok",
  "data": { "…": "tool specific" },
  "provenance": {
    "corpus_id": "rfc-mcp:9a3591827422",
    "index_generation": 50,
    "parser_version": "rfc-text-1.2.0",
    "extractor_version": "normative-2119-8174-1.4.0",
    "observed_at": "2026-09-26T16:42:30.669Z",
    "source_urls": ["https://www.rfc-editor.org/rfc/rfc9110.txt"],
    "freshness": "current"
  },
  "warnings": [],
  "next_cursor": null,
  "limits": { "applied": { "max_results": 20 }, "truncated": false }
}

status describes the operation, never the RFC: ok complete, partial paginated or budget-limited, degraded an assumption did not hold (stale cache, degraded parse, offline).

Full specification: docs/CONTRACT.md. Design: docs/ARCHITECTURE.md.

Evidence model

Snapshots. snp_<hash> is derived from (rfc, format, raw bytes, metadata hash, parser version, extractor version). Identical inputs always produce the same id; changed bytes or a bumped parser/extractor version produce a new id and never mutate the old one. rfc_resolve is the only tool that turns "current" into a snapshot — every other tool either receives an explicit snapshot_id or reports warnings: ["snapshot_not_explicitly_pinned"].

Citations. A citation id is sha256(snapshot | block | byte offset | quote). Every section and block reports offsets in three units — UTF-8 bytes, UTF-16 code units, Unicode code points — plus line numbers, so a quote can be located in the raw file, the decoded text, or any Unicode-aware tooling. The guarantee is exact: rawBytes.slice(byte_start, byte_end) reproduces text.

Normative language (RFC 2119 / RFC 8174).

  • only the eleven keywords, upper case only (RFC 8174 §3);

  • the longest phrase wins: MUST NOT is never split into MUST + NOT;

  • strength (absolute / recommendation / optional) and polarity are derived, the original word is preserved;

  • code, tables, figures, reference sections and quoted keyword definitions become mentions, never requirements;

  • a sentence that merely discusses the keywords ("the effects of not implementing a MUST or SHOULD…") is flagged keyword_enumeration and excluded;

  • clause parsing is explicit — condition, actor, action, exception, parse_status, confidence — and a missing actor yields partial with actor_not_explicit, never a fabricated one.

References and dependencies. Reference sections become labelled entries with resolved targets (RFC / BCP / STD / FYI) and a relation (normative, informative); in-body citations are attached with exact offsets. A normative reference is not automatically a dependency: the graph keeps cites_normative and metadata relations separate, never emits inferred edges, and leaves unresolved labels unresolved.

Errata are an overlay. The RFC Editor does not incorporate them into the published TXT/PDF/XML, and neither does this server. rfc_errata shows them with section, original and corrected text, and says so explicitly.

Parsing

rfc-text-1.2.0 parses the RFC Editor plain-text publication version (RFC 9920 §5), which exists for every RFC:

  • column-1 headings, with the table of contents used as an authority when present;

  • appendices, references, authors, index and status sections classified separately;

  • page furniture ([Page 7], [RFC2119], form feeds) and the ToC removed from content — and a page break inside a paragraph splits the block, so a sentence is always contiguous in the file;

  • paragraph / list / preformatted / table / reference-entry classification;

  • exact offsets for every section and block, including BOM-prefixed and multi-byte content.

Ambiguity is never hidden. RFC 2119-style documents that use column-1 numbered content keep it as exact blocks, emit col0_numbered_items_rejected:N and mark the parse degraded, instead of inventing sections.

rfc_read(target="xml_outline") exposes the authoritative RFCXML tree (RFC 7991 v3 / RFC 7749 v2) with anchors, per-section normative terms and the targets of every <xref>. Section numbers are recovered from the v3 page name (section-appendix.a → Appendix A), and the two representations of a document never disagree: for RFC 9110 all 293 section numbers shared by the plain-text and XML outlines carry the same kind in both. RFCXML is read by a hardened parser: DTDs and entity declarations are rejected, XInclude is never resolved, and depth/node/text budgets are enforced.

Policy

Concern

Behaviour

Network

HTTPS only, host allowlist (www.rfc-editor.org, errata.rfc-editor.org, datatracker.ietf.org); no user-supplied URL ever reaches fetch

HTTP

ETag/If-None-Match revalidation, bounded size/time/concurrency, retry with backoff, stale-on-error with an explicit warning

Integrity

Snapshot content hash verified before every citation check

XML

No DTD, no entities, no XInclude, bounded depth/nodes/text

Prompt injection

RFC text is data; the server never treats it as instructions

Privacy

Author email addresses stripped at the source boundary; no document text in logs

Licensing

RFC text reproduced unmodified with attribution (IETF Trust TLP)

Mutation

No model-visible write tool; corpus maintenance is CLI-only

Logs

JSON lines on stderr, secrets and document text redacted

Configuration

Variable

Default

Meaning

RFC_MCP_DATA_DIR

~/.local/share/rfc-mcp

Corpus location (corpus.sqlite, WAL)

RFC_MCP_OFFLINE

0

No network at all; cached snapshots only

RFC_MCP_USER_AGENT

rfc-mcp/<version> (+https://github.com/vitkuz573/rfc-mcp)

HTTP User-Agent

RFC_MCP_HTTP_TIMEOUT_MS

15000

Per-request timeout

RFC_MCP_INDEX_TIMEOUT_MS

180000

Timeout for the ~7 MB catalog index

RFC_MCP_MAX_HTTP_BYTES

16777216

Response size cap

RFC_MCP_MAX_CONCURRENCY

4

Per-host concurrency

RFC_MCP_METADATA_TTL_MS

21600000

Metadata cache freshness window

RFC_MCP_NEGATIVE_TTL_MS

3600000

404 cache window

RFC_MCP_LOG_LEVEL

info

debug…silent

RFC_MCP_CURSOR_SECRET

derived

HMAC key binding opaque cursors to a corpus generation

Operator CLI

rfc-mcp sync index                  # catalog refresh
rfc-mcp sync rfc 2119 8174          # ingest documents
rfc-mcp sync all --limit 500        # bulk ingest
rfc-mcp status                      # corpus health
rfc-mcp outline 9110                # section tree
rfc-mcp requirements 9110 --term "MUST NOT"
rfc-mcp references 9110 --relation normative
rfc-mcp search '"Idempotent"' --scope text
rfc-mcp show 9110 --section 9.3.2
rfc-mcp verify cit_…                # exit code 2 when not verified
rfc-mcp diff 7230 9110 --mode requirements
rfc-mcp reanalyze 9110 2119         # re-derive analysis offline after a rules change
rfc-mcp reindex                     # rebuild FTS5 from stored blocks
rfc-mcp vacuum                      # purge stale search-index rows, compact the database

Development

npm ci
npm run typecheck     # tsc --noEmit, strict
npm test              # 89 tests: parser, normative, XML, store, HTTP policy, service, live protocol
npm run build         # dist/
npm run verify        # format check + typecheck + test + build

The suite includes a black-box protocol test that spawns dist/index.js and speaks raw JSON-RPC on stdio, covering both the legacy initialize handshake and the modern server/discover revision, tool/prompt/resource listing, error codes and stdout hygiene.

Roadmap

  • internet-draft revisions and Datatracker history as first-class snapshots;

  • signed, reproducible corpus bundles;

  • IANA registries as a separate allow-listed layer;

  • calibrated confidence for clause extraction on labelled data;

  • JSON-LD / SARIF export of citation bundles.

Contributing

See CONTRIBUTING.md. Security reports: SECURITY.md. Changelog: CHANGELOG.md.

License

The code is licensed under Apache-2.0.

RFC content retrieved by this software is not covered by that license. It is reproduced unmodified from the RFC Editor and remains subject to the IETF Trust's Legal Provisions (TLP); errata are an independent overlay and are never merged into publication text. See docs/LICENSING.md for how the two are kept separate.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    F
    maintenance
    Read-only ProofRelay MCP verifier for non-confidential evidence bundles. Exposes 22 public-safe tools, 11 resources, and 11 prompts for bundle integrity checks, receipt-chain review, checkpoint recommendations, MCP risk metadata review, and real-estate closing proof-pack readiness.
    5
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides LLM-based access to IETF documents such as RFCs, Internet-Drafts, STD/BCP/FYI series, and errata through a Model Context Protocol server.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables cited, revision-aware retrieval over real IETF RFC chunks with zero LLM in the answer path, including graph-based supersession resolution and relationship queries via MCP tools.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables MCP-capable assistants to answer questions about Bitcoin SV from a pinned, auditable snapshot of specifications, SDKs, opcodes, and related documents, with read-only tools for investigation, search, and dependency checks.
    301 npm
    2
    MIT