rfc-mcp
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., "@rfc-mcpwhat are the MUST and SHOULD requirements in RFC 8174?"
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.
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.
Tools | 15 read-only tools ( |
Resources | 10 snapshot-addressed |
Prompts | 6 reproducible workflows ( |
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 answerevery analysis runs on a content-addressed snapshot (
snp_<hash>), never on "whatever is current right now";every derived statement carries a
citation_idthat 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,warningsand hardlimits;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 buildQuick 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 requirementsOr 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 transportClaude 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 |
| Self-describing contract, limits, sources, policy |
| selector → pinned |
| title, authors, status, stream, area, WG, DOI, relations |
| one section, the full outline, an RFCXML outline, or a bounded raw byte slice |
| catalog + full-text search; every filter reports whether it applied |
| RFC 2119/8174 statements with clause structure and citations |
| normative/informative split, resolved targets, citation sites |
| bounded typed graph: cites, obsoletes, updates, inbound relations |
| text / structure / requirements / metadata / references between two snapshots |
| errata overlay (never applied to publication text) |
| Datatracker change feed |
| official TXT/XML/HTML/PDF asset with SHA-256, ETag, canonical URLs |
| re-verify a citation against the stored bytes |
| corpus health, index generation, versions, recent failures |
| ≤ 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 NOTis never split intoMUST+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_enumerationand excluded;clause parsing is explicit —
condition,actor,action,exception,parse_status,confidence— and a missing actor yieldspartialwithactor_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 ( |
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 |
|
| Corpus location ( |
|
| No network at all; cached snapshots only |
|
| HTTP User-Agent |
|
| Per-request timeout |
|
| Timeout for the ~7 MB catalog index |
|
| Response size cap |
|
| Per-host concurrency |
|
| Metadata cache freshness window |
|
| 404 cache window |
|
|
|
| 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 databaseDevelopment
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 + buildThe 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.
This server cannot be deployed
Maintenance
Related MCP Connectors
SpecProof: Search standards specs with MCP-ready precision.
Resolve, search and verify legal citations against the official sources, with provenance.
Machine-native research commons for agent evidence, discovery, rooms, and bounded research quests.
Read-only tools over the Safer Agentic AI framework: 238 patterns + 14 heuristics.
Related MCP Servers
- AlicenseAqualityFmaintenanceRead-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.5MIT
- AlicenseNot gradedqualityCmaintenanceProvides LLM-based access to IETF documents such as RFCs, Internet-Drafts, STD/BCP/FYI series, and errata through a Model Context Protocol server.MIT
- AlicenseNot gradedqualityBmaintenanceEnables 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
- AlicenseNot gradedqualityBmaintenanceEnables 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 npm2MIT