rfclib 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rfclib-0.2.0/.gitignore +20 -0
- rfclib-0.2.0/CHANGELOG.md +39 -0
- rfclib-0.2.0/LICENSE +21 -0
- rfclib-0.2.0/NOTICE +24 -0
- rfclib-0.2.0/PKG-INFO +511 -0
- rfclib-0.2.0/README.md +465 -0
- rfclib-0.2.0/docs/retrieval-design.md +350 -0
- rfclib-0.2.0/pyproject.toml +88 -0
- rfclib-0.2.0/rfclib/__init__.py +3 -0
- rfclib-0.2.0/rfclib/__main__.py +6 -0
- rfclib-0.2.0/rfclib/cite.py +204 -0
- rfclib-0.2.0/rfclib/cli.py +848 -0
- rfclib-0.2.0/rfclib/config.py +119 -0
- rfclib-0.2.0/rfclib/errata.py +203 -0
- rfclib-0.2.0/rfclib/fsutil.py +82 -0
- rfclib-0.2.0/rfclib/graph.py +213 -0
- rfclib-0.2.0/rfclib/index/__init__.py +1 -0
- rfclib-0.2.0/rfclib/index/chunker.py +268 -0
- rfclib-0.2.0/rfclib/index/embed.py +166 -0
- rfclib-0.2.0/rfclib/index/hybrid.py +305 -0
- rfclib-0.2.0/rfclib/index/lexical.py +223 -0
- rfclib-0.2.0/rfclib/index/rfcxml.py +673 -0
- rfclib-0.2.0/rfclib/index/search.py +496 -0
- rfclib-0.2.0/rfclib/index/txtseg.py +516 -0
- rfclib-0.2.0/rfclib/library.py +285 -0
- rfclib-0.2.0/rfclib/mcp/__init__.py +1 -0
- rfclib-0.2.0/rfclib/mcp/server.py +327 -0
- rfclib-0.2.0/rfclib/packs/__init__.py +1 -0
- rfclib-0.2.0/rfclib/packs/builder.py +228 -0
- rfclib-0.2.0/rfclib/packs/collections/all-current-txt.json +10 -0
- rfclib-0.2.0/rfclib/packs/collections/essentials.json +19 -0
- rfclib-0.2.0/rfclib/packs/collections/fyi-current.json +10 -0
- rfclib-0.2.0/rfclib/packs/collections/standards-current.json +10 -0
- rfclib-0.2.0/rfclib/packs/collections/year-2025.json +10 -0
- rfclib-0.2.0/rfclib/packs/collections/year-2026.json +10 -0
- rfclib-0.2.0/rfclib/packs/collections.py +163 -0
- rfclib-0.2.0/rfclib/packs/docsetexport.py +163 -0
- rfclib-0.2.0/rfclib/packs/epub.py +159 -0
- rfclib-0.2.0/rfclib/packs/export.py +306 -0
- rfclib-0.2.0/rfclib/packs/htmlexport.py +82 -0
- rfclib-0.2.0/rfclib/packs/serve.py +143 -0
- rfclib-0.2.0/rfclib/packs/zimexport.py +171 -0
- rfclib-0.2.0/rfclib/query.py +466 -0
- rfclib-0.2.0/rfclib/subjects.py +448 -0
- rfclib-0.2.0/rfclib/sync/__init__.py +1 -0
- rfclib-0.2.0/rfclib/sync/downloader.py +129 -0
- rfclib-0.2.0/rfclib/sync/manifest.py +163 -0
- rfclib-0.2.0/rfclib/sync/scanner.py +49 -0
- rfclib-0.2.0/rfclib/sync/state.py +445 -0
- rfclib-0.2.0/rfclib/views.py +1050 -0
- rfclib-0.2.0/scripts/make_test_fixture.py +79 -0
- rfclib-0.2.0/tests/conftest.py +43 -0
- rfclib-0.2.0/tests/fixtures/library/README.md +3 -0
- rfclib-0.2.0/tests/fixtures/library/errata.json +1997 -0
- rfclib-0.2.0/tests/fixtures/library/meta/rfc-index.xml +695 -0
- rfclib-0.2.0/tests/fixtures/library/mirror/rfc/rfc2119.txt +171 -0
- rfclib-0.2.0/tests/fixtures/library/mirror/rfc/rfc5234.txt +899 -0
- rfclib-0.2.0/tests/fixtures/library/mirror/rfc/rfc7405.txt +227 -0
- rfclib-0.2.0/tests/fixtures/library/mirror/rfc/rfc768.txt +174 -0
- rfclib-0.2.0/tests/fixtures/library/mirror/rfc/rfc8174.txt +227 -0
- rfclib-0.2.0/tests/fixtures/library/mirror/rfc/rfc8651.txt +577 -0
- rfclib-0.2.0/tests/fixtures/library/mirror/rfc/rfc8651.xml +973 -0
- rfclib-0.2.0/tests/test_features.py +40 -0
- rfclib-0.2.0/tests/test_lexical.py +48 -0
- rfclib-0.2.0/tests/test_library.py +195 -0
rfclib-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.pyc
|
|
3
|
+
.venv/
|
|
4
|
+
dist/
|
|
5
|
+
build/
|
|
6
|
+
*.egg-info/
|
|
7
|
+
data/
|
|
8
|
+
*.db
|
|
9
|
+
*.db-wal
|
|
10
|
+
*.db-shm
|
|
11
|
+
|
|
12
|
+
export-packs/
|
|
13
|
+
export-formats/
|
|
14
|
+
android-reader/local.properties
|
|
15
|
+
android-reader/.gradle/
|
|
16
|
+
android-reader/build/
|
|
17
|
+
android-reader/app/build/
|
|
18
|
+
|
|
19
|
+
# the reader UI lives on the reader-ui branch; ignore local leftovers
|
|
20
|
+
reader-ui/
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0 (unreleased)
|
|
4
|
+
|
|
5
|
+
First release intended for PyPI
|
|
6
|
+
(`uvx --from "rfclib[mcp,semantic]" rfclib mcp`).
|
|
7
|
+
|
|
8
|
+
- **Optional features.** The core package (CLI, library, keyword search)
|
|
9
|
+
has four dependencies (~9 MB); the MCP server (`rfclib[mcp]`), semantic
|
|
10
|
+
search (`rfclib[semantic]`) and ZIM export (`rfclib[zim]`) are extras,
|
|
11
|
+
loaded lazily and reported by `rfclib status`. The reader UI and the
|
|
12
|
+
Docker images moved to the `reader-ui` branch.
|
|
13
|
+
|
|
14
|
+
- **Library lifecycle.** Data lives in the per-user platform data directory
|
|
15
|
+
(or `$RFCLIB_HOME`), never the working directory. `rfclib init` sets up
|
|
16
|
+
the catalog (RFC index, errata, subject tree) in seconds; each RFC is
|
|
17
|
+
fetched from rfc-editor.org and indexed the first time it is read;
|
|
18
|
+
`rfclib init --content current|all` prefetches everything. `rfclib status`
|
|
19
|
+
reports what the library holds. `RFCLIB_NETWORK=auto|on-demand|offline`
|
|
20
|
+
controls fetching. The library is portable (relative file paths), safe
|
|
21
|
+
to share between processes, and loads its embedding model offline.
|
|
22
|
+
- **MCP server: nine tools** (`search`, `read`, `outline`, `grep`, `cite`,
|
|
23
|
+
`links`, `info`, `browse`, `errata`), compact plain text, one reference
|
|
24
|
+
grammar (`RFC9000§9.6¶2`) that every tool accepts and every page footer
|
|
25
|
+
emits, prompts (`/rfclib:explain`, `checklist`, `current`), an
|
|
26
|
+
`rfc://{ref}` resource template and completions.
|
|
27
|
+
- **Structure.** RFC 8650+ from RFCXML (exact sections and paragraph ids);
|
|
28
|
+
older RFCs segmented from their own Table of Contents (heading recall
|
|
29
|
+
59% -> 98%). Section-precise citation links for every era.
|
|
30
|
+
- **Search.** Hybrid BM25 + embeddings + document titles, plus an exact
|
|
31
|
+
identifier index (`preferred_address`, `SETTINGS_INITIAL_WINDOW_SIZE`)
|
|
32
|
+
and acronym-aware title matching. Status-aware: obsolete documents are
|
|
33
|
+
flagged with their current replacement.
|
|
34
|
+
- **Errata** from the RFC Editor bulk API, shown per section.
|
|
35
|
+
|
|
36
|
+
## 0.1.0
|
|
37
|
+
|
|
38
|
+
Initial local library: RFC Editor sync, SQLite metadata and full-text
|
|
39
|
+
index, CLI, reader UI, content packs.
|
rfclib-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Justin Capella
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
rfclib-0.2.0/NOTICE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
rfclib
|
|
2
|
+
Copyright (c) 2026 Justin Capella. Licensed under the MIT License (LICENSE).
|
|
3
|
+
|
|
4
|
+
RFC content is not part of this software's license
|
|
5
|
+
----------------------------------------------------
|
|
6
|
+
rfclib downloads documents of the RFC Series and their metadata from the
|
|
7
|
+
RFC Editor (https://www.rfc-editor.org) at the user's request and stores
|
|
8
|
+
them locally. Those documents are published by the IETF Trust under the
|
|
9
|
+
IETF Trust Legal Provisions (https://trustee.ietf.org/license-info), not
|
|
10
|
+
under this software's license. In particular, RFCs may be copied and
|
|
11
|
+
distributed in full but not modified outside the IETF Standards Process;
|
|
12
|
+
code components in documents published on or after November 10, 2008 are
|
|
13
|
+
available under the Revised BSD License. Documents published before 1986
|
|
14
|
+
may carry different terms. See the IETF Trust FAQ
|
|
15
|
+
(https://trustee.ietf.org/about/faq).
|
|
16
|
+
|
|
17
|
+
The test fixtures in tests/fixtures/library are unmodified copies of a few
|
|
18
|
+
RFCs and trimmed copies of RFC Editor metadata, included for offline tests
|
|
19
|
+
under the same terms.
|
|
20
|
+
|
|
21
|
+
Subject taxonomy and errata are fetched from the RFC Editor's published
|
|
22
|
+
pages and API (rfc-editor.org/subjects, rfc-editor.org/api/v1/errata.json).
|
|
23
|
+
The embedding model (minishlab/potion-base-8M) is downloaded from Hugging
|
|
24
|
+
Face under its own license when semantic search is first built.
|
rfclib-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: rfclib
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: The RFC series as a local library and MCP server: section-precise search, paging by citation, status, errata and citations
|
|
5
|
+
Project-URL: Homepage, https://github.com/b1tninja/rfclib
|
|
6
|
+
Project-URL: Source, https://github.com/b1tninja/rfclib
|
|
7
|
+
Project-URL: Issues, https://github.com/b1tninja/rfclib/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/b1tninja/rfclib/blob/master/CHANGELOG.md
|
|
9
|
+
Author-email: Justin Capella <justincapella@gmail.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
License-File: NOTICE
|
|
13
|
+
Keywords: agents,ietf,llm,mcp,model-context-protocol,rfc,rfc-editor,search,standards
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Environment :: Console
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Intended Audience :: Information Technology
|
|
18
|
+
Classifier: Intended Audience :: Science/Research
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
25
|
+
Classifier: Topic :: Internet
|
|
26
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
27
|
+
Classifier: Topic :: Text Processing :: Indexing
|
|
28
|
+
Requires-Python: >=3.12
|
|
29
|
+
Requires-Dist: httpx>=0.27
|
|
30
|
+
Requires-Dist: platformdirs>=4.2
|
|
31
|
+
Requires-Dist: rich>=13
|
|
32
|
+
Requires-Dist: typer>=0.12
|
|
33
|
+
Provides-Extra: all
|
|
34
|
+
Requires-Dist: libzim>=3.7; extra == 'all'
|
|
35
|
+
Requires-Dist: mcp>=1.2; extra == 'all'
|
|
36
|
+
Requires-Dist: model2vec>=0.3; extra == 'all'
|
|
37
|
+
Requires-Dist: sqlite-vec; extra == 'all'
|
|
38
|
+
Provides-Extra: mcp
|
|
39
|
+
Requires-Dist: mcp>=1.2; extra == 'mcp'
|
|
40
|
+
Provides-Extra: semantic
|
|
41
|
+
Requires-Dist: model2vec>=0.3; extra == 'semantic'
|
|
42
|
+
Requires-Dist: sqlite-vec; extra == 'semantic'
|
|
43
|
+
Provides-Extra: zim
|
|
44
|
+
Requires-Dist: libzim>=3.7; extra == 'zim'
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
|
|
47
|
+
# rfclib — Local RFC Library + MCP Server
|
|
48
|
+
|
|
49
|
+
A local, self-maintaining library of **every published RFC** (plus BCP/STD/FYI),
|
|
50
|
+
sourced exclusively from the **official RFC Editor infrastructure**
|
|
51
|
+
([rfc-editor.org](https://www.rfc-editor.org/) — the authoritative publisher of
|
|
52
|
+
the RFC Series for all five streams, operating under the IETF Administration
|
|
53
|
+
LLC; see RFC 9280, RFC 4714, RFC 7841).
|
|
54
|
+
|
|
55
|
+
Everything lives in **one SQLite file** and is exposed to AI agents over **MCP**,
|
|
56
|
+
and to scripts over a CLI. Fully offline after the initial sync: no API keys,
|
|
57
|
+
no external services; embeddings run locally on CPU.
|
|
58
|
+
|
|
59
|
+
## Install
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
uvx rfclib init # catalog: RFC index, errata, subjects (~1 min)
|
|
63
|
+
claude mcp add rfclib -- uvx --from "rfclib[mcp,semantic]" rfclib mcp
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The core package is small (CLI, library, keyword search, ~9 MB with its
|
|
67
|
+
dependencies); heavier features are extras:
|
|
68
|
+
|
|
69
|
+
| Extra | Adds | Size |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| `rfclib[mcp]` | the MCP server (`rfclib mcp`) | ~29 MB |
|
|
72
|
+
| `rfclib[semantic]` | embedding search fused into hybrid search | ~69 MB |
|
|
73
|
+
| `rfclib[zim]` | Kiwix ZIM export | native wheel |
|
|
74
|
+
| `rfclib[all]` | all of the above | |
|
|
75
|
+
|
|
76
|
+
`rfclib status` shows which are installed; a missing one says how to add it,
|
|
77
|
+
and search without `semantic` uses keywords, identifiers and titles.
|
|
78
|
+
|
|
79
|
+
[`uvx`](https://docs.astral.sh/uv/) fetches rfclib into an isolated, cached
|
|
80
|
+
environment (and a suitable Python if needed); `pip install rfclib` works
|
|
81
|
+
too. RFCs are then fetched from rfc-editor.org the first time they are read;
|
|
82
|
+
`uvx rfclib init --content current` prefetches every current RFC so
|
|
83
|
+
full-text section search covers them all (~10 min, ~1.5 GB).
|
|
84
|
+
|
|
85
|
+
Requirements: Python 3.12+ on Windows, macOS or Linux. Semantic search
|
|
86
|
+
(`rfclib[semantic]`) uses a ~30 MB local embedding model (`minishlab/potion-base-8M`,
|
|
87
|
+
[model2vec](https://github.com/MinishLab/model2vec)) and `sqlite-vec`; on a
|
|
88
|
+
Python whose sqlite3 cannot load extensions, search is keyword-only.
|
|
89
|
+
|
|
90
|
+
## Sources (first-party only)
|
|
91
|
+
|
|
92
|
+
| What | Source |
|
|
93
|
+
|---|---|
|
|
94
|
+
| Bulk mirror / periodic re-mirror | `rsync.rfc-editor.org::rfcs` (official rsync modules, see [download docs](https://www.rfc-editor.org/series/rfc-download/)) |
|
|
95
|
+
| Master manifest (all docs + obsoletes/updates/alias graph) | `https://www.rfc-editor.org/rfc-index.xml` |
|
|
96
|
+
| Per-document content | `https://www.rfc-editor.org/{rfc,bcp,std,fyi}/<id>.{txt,html,xml,pdf}` |
|
|
97
|
+
| New-publication feed | `https://www.rfc-editor.org/rfcrss.xml` |
|
|
98
|
+
| Errata (bulk, `rfclib init`; per-doc fallback) | `https://www.rfc-editor.org/api/v1/errata.json`, `https://errata.rfc-editor.org/` |
|
|
99
|
+
|
|
100
|
+
Every local file is recorded with source URL + SHA-256 for provenance.
|
|
101
|
+
|
|
102
|
+
## From source
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
git clone https://github.com/b1tninja/rfclib && cd rfclib
|
|
106
|
+
uv sync --group dev # .venv with rfclib (editable) + pytest
|
|
107
|
+
uv run pytest -q # offline tests, sample library
|
|
108
|
+
|
|
109
|
+
rfclib init # catalog: RFC index, errata, subject tree
|
|
110
|
+
rfclib status # where the library lives, what it holds
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
That is enough to use the MCP server: status, obsolete chains, document
|
|
114
|
+
search, browsing and errata cover every RFC, and each RFC is fetched from
|
|
115
|
+
rfc-editor.org, segmented and indexed the first time it is read (about a
|
|
116
|
+
second). To make full-text section search cover everything up front:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
rfclib init --content current # + every current RFC, indexes, vectors (~10 min)
|
|
120
|
+
rfclib init --content all # + obsolete RFCs too
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Later updates are incremental (`rfclib sync && rfclib index build && rfclib
|
|
124
|
+
index embed`). The official rsync service still works for a bulk mirror:
|
|
125
|
+
`scripts\mirror.ps1`, then `rfclib scan`.
|
|
126
|
+
|
|
127
|
+
```powershell
|
|
128
|
+
# Explore
|
|
129
|
+
.venv\Scripts\rfclib.exe hsearch "proving address ownership" # hybrid — recommended
|
|
130
|
+
.venv\Scripts\rfclib.exe search "congestion control" # titles/abstracts
|
|
131
|
+
.venv\Scripts\rfclib.exe search "KeyUpdate" --body # BM25, sections
|
|
132
|
+
.venv\Scripts\rfclib.exe vsearch "proving address ownership" # semantic only
|
|
133
|
+
.venv\Scripts\rfclib.exe toc rfc9000 # outline + line ranges
|
|
134
|
+
.venv\Scripts\rfclib.exe get rfc9000 --start-line 6858 --lines 40
|
|
135
|
+
.venv\Scripts\rfclib.exe rels rfc2616
|
|
136
|
+
.venv\Scripts\rfclib.exe resolve bcp14
|
|
137
|
+
.venv\Scripts\rfclib.exe subjects get quic # curated topic listing
|
|
138
|
+
.venv\Scripts\rfclib.exe status
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## CLI reference
|
|
142
|
+
|
|
143
|
+
| Command | Purpose |
|
|
144
|
+
|---|---|
|
|
145
|
+
| `manifest` | Fetch/parse the official rfc-index.xml into the DB (metadata + relations) |
|
|
146
|
+
| `sync` | Incremental HTTP sync of missing docs (`--include-obsolete`, `--formats txt,html`, `--concurrency`) |
|
|
147
|
+
| `scan` | Register files from an rsync-produced mirror into the DB |
|
|
148
|
+
| `status` | Library + index statistics |
|
|
149
|
+
| `search <q> [--body]` | Titles/abstracts/keywords; `--body` = BM25 over sections (raw FTS5 syntax allowed) |
|
|
150
|
+
| `vsearch <q>` | Semantic (embedding) search over sections — needs `index embed` |
|
|
151
|
+
| `hsearch <q>` | Hybrid BM25 + embeddings + title coverage fused (RRF) — the recommended default |
|
|
152
|
+
| `get <id>` | Print a document (`--start-line N --lines N`, `--fmt txt\|html\|xml`) |
|
|
153
|
+
| `meta <id>` / `rels <id>` / `resolve <id>` | Bibliographic record / relation graph / BCP→RFC |
|
|
154
|
+
| `toc <id>` | Section outline with exact line ranges (feed into `get --start-line`) |
|
|
155
|
+
| `refs [<id>] [--build]` | Citation graph mined from txt: what an RFC cites / cites it, with §-level anchors (`--build` = incremental mine, ~50 s full corpus) |
|
|
156
|
+
| `errata <id> [--refresh]` | Verified-errata overlay from the RFC Editor errata service (on-demand fetch + local cache; `--all` for other statuses) |
|
|
157
|
+
| `subjects sync [--force] [--limit N]` | Mirror the RFC Editor subject taxonomy (~640 pages, one polite crawl) |
|
|
158
|
+
| `subjects list [filter] [--descriptions]` | Show the subject tree (or a filtered slice), parents before children |
|
|
159
|
+
| `subjects get <name> [--limit N]` | Documents inside one subject incl. descendants, newest first |
|
|
160
|
+
| `index build\|embed\|status` | Maintain retrieval indexes (`embed --limit N`, `--model <id>`) |
|
|
161
|
+
| `packs list [--collections-dir D]` | Show collection manifests and resolved doc counts |
|
|
162
|
+
| `packs build <id...> \| --all` | Export `.rfcpack` zips (embedded FTS5 search, `--formats`, `--out`, `--no-search`) |
|
|
163
|
+
| `packs export <id...> \| --all` | Export for third-party readers: EPUB e-books + static HTML mirror + Kiwix ZIM + Dash docset (`--formats epub,html,zim,docset`, `--link-refs none\|internal\|external`) |
|
|
164
|
+
| `packs catalog [--out D]` | Rebuild `catalog.json` (name/size/sha256 per pack) |
|
|
165
|
+
| `packs serve [--dir D] [--port 8100]` | LAN HTTP distribution for the Android reader |
|
|
166
|
+
| `mcp` | Run the MCP server on stdio |
|
|
167
|
+
|
|
168
|
+
All searches accept `--include-obsolete` (obsolete docs are hidden by design —
|
|
169
|
+
an agent reading RFC 2616 in 2026 is a failure mode).
|
|
170
|
+
|
|
171
|
+
## Retrieval indexes (full-text + semantic)
|
|
172
|
+
|
|
173
|
+
Documents are chunked by section (heuristic parser for RFC txt, exact source
|
|
174
|
+
line ranges kept; long sections split into ~2.4k-char parts with per-part
|
|
175
|
+
line ranges). All three search modes live in the same SQLite file: BM25 via
|
|
176
|
+
FTS5 (`search --body`), KNN via sqlite-vec (`vsearch`), and hybrid
|
|
177
|
+
(`hsearch`). Chunk IDs are content-addressed, so re-chunking preserves
|
|
178
|
+
embeddings for every section whose text didn't change (a chunker tweak
|
|
179
|
+
re-embeds only the diff, e.g. 15k of 298k chunks in ~11 s).
|
|
180
|
+
|
|
181
|
+
`hsearch` fuses up to four lists with diversified, weighted RRF (the fourth,
|
|
182
|
+
an exact-identifier index, joins when the query contains tokens such as
|
|
183
|
+
`preferred_address`, `SETTINGS_INITIAL_WINDOW_SIZE` or `X25519`, weighted by
|
|
184
|
+
how rare they are; see docs/retrieval-design.md): section-level
|
|
185
|
+
BM25 (terms OR'd + proximity-boosted), the embedding KNN list, and a
|
|
186
|
+
document-level list ranked by how much of the query the doc's own **title**
|
|
187
|
+
carries (IDF-weighted term coverage — the spec titled "TCP Congestion
|
|
188
|
+
Control" beats one that merely mentions "NewReno"). Each doc appears once
|
|
189
|
+
per list before fusion, chunks of the same doc corroborate each other, and
|
|
190
|
+
standards-track/BCP docs get a status boost while References/boilerplate
|
|
191
|
+
sections are penalized. Without `index embed` it still works (BM25 + title).
|
|
192
|
+
|
|
193
|
+
Full design rationale, measured trade-offs, and FTS5/chunker gotchas:
|
|
194
|
+
[docs/retrieval-design.md](docs/retrieval-design.md).
|
|
195
|
+
|
|
196
|
+
### Accuracy loop (regression-test retrieval changes)
|
|
197
|
+
|
|
198
|
+
```powershell
|
|
199
|
+
python scripts\eval_retrieval.py # golden queries -> expected doc, top-5
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
A set of hand-picked (query → canonical-RFC) pairs run through `hsearch`.
|
|
203
|
+
Any change to chunking, FTS query shape, or fusion should be built,
|
|
204
|
+
re-embedded, and re-evaluated with this script before shipping
|
|
205
|
+
(currently 10/12 in top-5; slowest cold query ~1.8 s — see
|
|
206
|
+
[docs/retrieval-design.md §5](docs/retrieval-design.md) for the two known-hard misses).
|
|
207
|
+
|
|
208
|
+
## MCP server
|
|
209
|
+
|
|
210
|
+
Any MCP client launches the server as a subprocess over stdio. With `uvx`
|
|
211
|
+
there is nothing to install first (`--from "rfclib[mcp,semantic]"` brings the
|
|
212
|
+
MCP and semantic-search extras); set `RFCLIB_HOME` in `env` only to use a
|
|
213
|
+
library somewhere other than the default per-user data directory.
|
|
214
|
+
|
|
215
|
+
**Claude Code**
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
claude mcp add rfclib -- uvx --from "rfclib[mcp,semantic]" rfclib mcp
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Claude Desktop** (`claude_desktop_config.json`) and **Cursor**
|
|
222
|
+
(`~/.cursor/mcp.json`):
|
|
223
|
+
|
|
224
|
+
```json
|
|
225
|
+
{
|
|
226
|
+
"mcpServers": {
|
|
227
|
+
"rfclib": {
|
|
228
|
+
"command": "uvx",
|
|
229
|
+
"args": ["--from", "rfclib[mcp,semantic]", "rfclib", "mcp"]
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**VS Code** (`.vscode/mcp.json`):
|
|
236
|
+
|
|
237
|
+
```json
|
|
238
|
+
{
|
|
239
|
+
"servers": {
|
|
240
|
+
"rfclib": {
|
|
241
|
+
"type": "stdio",
|
|
242
|
+
"command": "uvx",
|
|
243
|
+
"args": ["--from", "rfclib[mcp,semantic]", "rfclib", "mcp"]
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
GUI clients don't always see your shell's `PATH`; if `uvx` isn't found,
|
|
250
|
+
use its absolute path (`which uvx` / `where uvx`). From a source checkout,
|
|
251
|
+
point `command` at the venv's `rfclib` executable instead (this repository's
|
|
252
|
+
`.mcp.json` does that for development).
|
|
253
|
+
|
|
254
|
+
### Tools (9)
|
|
255
|
+
|
|
256
|
+
One job per tool, all answering in compact plain text; every tool's main
|
|
257
|
+
argument is `ref` (only `search` takes `query`), all addressed by
|
|
258
|
+
**refs**, which are also citations. Every page of `read` ends with
|
|
259
|
+
`next: <ref>` to continue from:
|
|
260
|
+
`RFC9000` (abstract + outline), `RFC9000§9.6` (section incl. subsections),
|
|
261
|
+
`RFC9000§9.6¶2` (paragraph), `RFC9000#table-2` (RFCXML block id),
|
|
262
|
+
`RFC9000:2964-2979` (txt lines); `BCP14`/`STD7` resolve to their RFCs.
|
|
263
|
+
Errors come back as `isError` results with the fix in the message; all
|
|
264
|
+
tools are annotated read-only; `search` and `read` carry
|
|
265
|
+
`_meta["anthropic/alwaysLoad"]` so they stay visible when a client defers
|
|
266
|
+
tools behind tool search.
|
|
267
|
+
|
|
268
|
+
| Tool | Args | What it returns |
|
|
269
|
+
|---|---|---|
|
|
270
|
+
| `search` | `query`, `scope`, `mode`, `subject`, `status`, `limit`, `detail` | Paragraph-precise hits with snippets. `scope=sections` (default) or `documents` (titles/abstracts); `mode=hybrid` (BM25 + embeddings), `exact` (FTS5 syntax) or `semantic` |
|
|
271
|
+
| `read` | `ref`, `max_tokens`, `view`, `lang`, `format` | **The way to read text.** Pages cut at paragraph boundaries, page furniture stripped, `[§9.6¶2]` markers, footer `next:`/`up:`/`after:` refs, status + errata in the header. `view=normative` (MUST/SHOULD statements), `code` (ABNF/figures, `lang=`), `refs`; `format=xml\|html\|json` for raw slices of other renderings |
|
|
272
|
+
| `outline` | `ref`, `depth`, `contains` | One line per section with its line range (depth 2 by default; RFC 9000 ≈ 6k chars) |
|
|
273
|
+
| `grep` | `ref`, `pattern` | Regex inside one document or section; hits labelled with paragraph refs + lines |
|
|
274
|
+
| `cite` | `ref`, `style` | Checkable citation: label, status/obsolescence, anchor URL, errata status, span hash |
|
|
275
|
+
| `links` | `ref`, `direction` | What a section cites / is cited by, section-precise (`RFC9000§8.1 → RFC9002 §6.2 [normative]`), plus reference-list edges; `related` for subject neighbours |
|
|
276
|
+
| `info` | `ref`, `detail` | Status, obsoletes/updates graph with the **current** replacement (RFC2616 → RFC9110–9112), alias members, authors, subjects, errata summary, abstract; `detail=full` = JSON record |
|
|
277
|
+
| `browse` | `subject`, `parent`, `contains`, `recent`, `offset` | RFC Editor subject tree one level at a time, a subject's documents, or the newest RFCs |
|
|
278
|
+
| `errata` | `ref`, `status`, `section` | Verified (default), open or all errata with the corrected text; `RFC791§3.1` narrows to a section |
|
|
279
|
+
|
|
280
|
+
**Prompts** (user-invoked slash commands in Claude Code):
|
|
281
|
+
`/rfclib:explain <ref>`, `/rfclib:checklist <ref>` (normative statements →
|
|
282
|
+
implementation checklist), `/rfclib:current <topic>` (which RFCs are
|
|
283
|
+
current). **Resource template** `rfc://{ref}`: `@rfclib:rfc://RFC9112§6.3`
|
|
284
|
+
attaches a section to a prompt. **Completions** for document ids and
|
|
285
|
+
section numbers.
|
|
286
|
+
|
|
287
|
+
**Agent guidance shipped in the repo** (`.claude/`): the `rfc-research`
|
|
288
|
+
skill (workflow, ref grammar, recipes) and a `PreToolUse` hook
|
|
289
|
+
(`scripts/hooks/guard_mirror.py`) that denies `Read`/`Grep`/`Glob` on
|
|
290
|
+
`data/mirror/**` and points at the MCP call to use instead.
|
|
291
|
+
|
|
292
|
+
Missing documents are fetched on demand from rfc-editor.org.
|
|
293
|
+
|
|
294
|
+
### Subject views (RFC-Editor organization)
|
|
295
|
+
|
|
296
|
+
The RFC Editor curates a ~640-subject tree (`web > http > http2`,
|
|
297
|
+
`transport > quic`, …) and assigns every document to one or more
|
|
298
|
+
subjects; it is published only as HTML at
|
|
299
|
+
[rfc-editor.org/subjects/](https://www.rfc-editor.org/subjects/).
|
|
300
|
+
`rfclib subjects sync` mirrors it (one polite crawl, a few minutes; HTML
|
|
301
|
+
cached under `meta/subjects/` so re-parses are offline) into `subjects` +
|
|
302
|
+
`doc_subjects` tables. On top of that: the `browse` /
|
|
303
|
+
`links(direction='related')` MCP tools, `search(scope='documents',
|
|
304
|
+
subject=...)`, subject tags in `info`, and the same via CLI
|
|
305
|
+
(`rfclib subjects list|get`). This answers *"what RFCs exist about X"*
|
|
306
|
+
and *"what else is like this RFC"* without a keyword query — the
|
|
307
|
+
citation-graph view (`links`) stays available for normative context.
|
|
308
|
+
|
|
309
|
+
## Configuration
|
|
310
|
+
|
|
311
|
+
Environment variables (the same in a shell or an MCP client's `env`
|
|
312
|
+
block):
|
|
313
|
+
|
|
314
|
+
- `RFCLIB_HOME`: the library root. Default: the per-user data directory
|
|
315
|
+
(`%LOCALAPPDATA%
|
|
316
|
+
fclib` on Windows, `~/.local/share/rfclib` or
|
|
317
|
+
`$XDG_DATA_HOME/rfclib` on Linux, `~/Library/Application Support/rfclib`
|
|
318
|
+
on macOS). Never the working directory, because MCP clients start
|
|
319
|
+
servers from arbitrary directories. Older versions defaulted to `./data`;
|
|
320
|
+
`rfclib status` points out such a library and how to keep using it.
|
|
321
|
+
- `RFCLIB_NETWORK`: `auto` (default; fetch documents on demand),
|
|
322
|
+
`on-demand`, or `offline` (never touch the network; answer from what
|
|
323
|
+
is local, and say so).
|
|
324
|
+
- `RFCLIB_AUTO_INIT=1`: let the MCP server initialize an empty library's
|
|
325
|
+
catalog in the background on first use (opt-in; off by default).
|
|
326
|
+
|
|
327
|
+
The library is portable: file paths are stored relative to `mirror/`, so a
|
|
328
|
+
library can be moved, copied to another OS, or mounted into a container.
|
|
329
|
+
Several processes can share it (one MCP server per client session plus
|
|
330
|
+
`rfclib sync`): SQLite runs in WAL mode with a busy timeout, downloads are
|
|
331
|
+
written atomically, and bulk writers take a lock file.
|
|
332
|
+
|
|
333
|
+
```
|
|
334
|
+
<RFCLIB_HOME>/
|
|
335
|
+
rfclib.db one SQLite file: docs, doc_relations, files (sha256 provenance),
|
|
336
|
+
chunks, chunks_fts + docs_fts (FTS5), chunks_vec (sqlite-vec),
|
|
337
|
+
embed_state (content-hashed embed coverage),
|
|
338
|
+
blocks + xrefs (paragraphs and section-level citations),
|
|
339
|
+
seg_quality (how each document was segmented), errata
|
|
340
|
+
meta/ rfc-index.xml (official manifest)
|
|
341
|
+
mirror/ document files in rfc-editor.org layout (rfc/, bcp/, ...)
|
|
342
|
+
models/ the embedding model (~30 MB), loaded offline
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Query tips
|
|
346
|
+
|
|
347
|
+
- `hsearch`/`search` treat words as OR + proximity — natural phrasing
|
|
348
|
+
works ("does this spec allow sending packets early?"); no operators needed.
|
|
349
|
+
- `search --body` and `search(mode='exact')` pass your query **raw to FTS5**:
|
|
350
|
+
quote phrases (`"KeyUpdate message"`), combine with `AND`/`OR`/`NOT`,
|
|
351
|
+
prefix with `*`. NEAR takes the comma form: `NEAR(tls handshake, 40)`
|
|
352
|
+
(`NEAR(tls handshake / 40)` is a syntax error).
|
|
353
|
+
- Keep version tokens in queries (`TLS 1.3`, `802.11`): they are strong
|
|
354
|
+
discriminators and hybrid search preserves them unstemmed.
|
|
355
|
+
- For a long RFC, `outline` first, then `read('RFC9000§9.6')` and follow
|
|
356
|
+
the `next:` ref — don't page through 8,000-line documents, and never point
|
|
357
|
+
an agent at the mirror files (its file reader truncates them).
|
|
358
|
+
- RFCs since 8650 are indexed from their RFCXML source (`rfclib sync
|
|
359
|
+
--formats xml && rfclib index build`); older RFCs are segmented from
|
|
360
|
+
their own Table of Contents (`rfclib/index/txtseg.py`, quality per doc
|
|
361
|
+
in the `seg_quality` table). Either way you get exact sections,
|
|
362
|
+
paragraph refs, `view=normative`/`code` and section-level `links`.
|
|
363
|
+
- `rfclib errata --sync-all` loads every erratum from the RFC Editor bulk
|
|
364
|
+
API once, so errata status is known offline for every document.
|
|
365
|
+
|
|
366
|
+
## Troubleshooting
|
|
367
|
+
|
|
368
|
+
| Symptom | Fix |
|
|
369
|
+
|---|---|
|
|
370
|
+
| `vsearch`/`search(mode='semantic')` return nothing | Run `rfclib index embed` (`index status` shows chunk vs embedded counts) |
|
|
371
|
+
| Hybrid results lack conceptual recall | Same — `hsearch` degrades to BM25+title without vectors |
|
|
372
|
+
| Section titles look like ToC junk | Chunker heuristics improved since your index; `rfclib index build && rfclib index embed` (only the diff re-embeds) |
|
|
373
|
+
| `database is locked` | An `index build`/`embed` is running elsewhere; they commit in batches — wait or stop the other run |
|
|
374
|
+
| Expected old/obsolete RFC missing | It's obsoleted and hidden by default: add `--include-obsolete` / `include_obsolete: true` |
|
|
375
|
+
| `sync` too slow / rsync unavailable (Windows) | `sync` is HTTP-based and cross-platform; `scripts\mirror.ps1` shells out to rsync under WSL for the initial bulk pull |
|
|
376
|
+
|
|
377
|
+
## Content packs & Android reader
|
|
378
|
+
|
|
379
|
+
RFCs are published rolling (~5–25/month, no official batches), so updates are
|
|
380
|
+
distributed as **content packs**: a `.rfcpack` zip holds one curated
|
|
381
|
+
collection — document files + a `pack.json` manifest (per-file sha256) + an
|
|
382
|
+
offline SQLite **FTS5** index (`search.sqlite`) so the phone searches without
|
|
383
|
+
a backend. Collections are tiny JSON manifests (explicit doc ids and/or
|
|
384
|
+
selectors over series/stream/area/WG/year); built-ins:
|
|
385
|
+
|
|
386
|
+
| Collection | Contents |
|
|
387
|
+
|---|---|
|
|
388
|
+
| `essentials` | ~52 hand-picked current core protocols (IP/TCP/DNS/TLS 1.3/QUIC/HTTP/DHCP/email + process docs) |
|
|
389
|
+
| `standards-current` | Every RFC that is a member of a current STD or BCP — the closest thing to an official essential list |
|
|
390
|
+
| `fyi-current` | Current FYI notes |
|
|
391
|
+
| `year-2025` / `year-2026` | Everything published that year (example of the year selector) |
|
|
392
|
+
| `all-current-txt` | The whole current archive (~8.8k docs) |
|
|
393
|
+
|
|
394
|
+
Put your own `<id>.json` in `data/collections/` (or `--collections-dir`) to
|
|
395
|
+
define new ones. `history: true` pulls in the obsoleted lineage too.
|
|
396
|
+
|
|
397
|
+
```powershell
|
|
398
|
+
.venv\Scripts\rfclib.exe packs list
|
|
399
|
+
.venv\Scripts\rfclib.exe packs build essentials standards-current # -> export-packs/
|
|
400
|
+
.venv\Scripts\rfclib.exe packs serve --dir export-packs --port 8100
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
`android-reader/` is a dependency-free Android app (Java, mirrors the
|
|
404
|
+
caionline pack-install design): install a `.rfcpack` via the file picker,
|
|
405
|
+
`adb push`, or **Sync** against `packs serve` on your LAN (downloads are
|
|
406
|
+
sha256-verified against `catalog.json`, installs are verified file-by-file
|
|
407
|
+
against `pack.json` before promotion). Browse packs → documents, full-text
|
|
408
|
+
search across all installed packs, and read in the WebView via a loopback
|
|
409
|
+
server — fully offline after sync.
|
|
410
|
+
|
|
411
|
+
### Third-party export formats (`packs export`)
|
|
412
|
+
|
|
413
|
+
For readers outside this repo (e-book apps, offline browsing), the same
|
|
414
|
+
collections export to standard formats — one RFC .txt becomes one clean
|
|
415
|
+
XHTML chapter: page furniture stripped, ASCII diagrams preserved verbatim
|
|
416
|
+
in `<pre>`, section anchors generated with the same heuristics as the
|
|
417
|
+
search index, and `RFC 9000`/`[RFC9000]` references linkified (internal to
|
|
418
|
+
the set by default; `--link-refs external` adds rfc-editor.org links).
|
|
419
|
+
|
|
420
|
+
```powershell
|
|
421
|
+
.venv\Scripts\rfclib.exe packs export essentials # -> export-formats/essentials.epub + essentials/
|
|
422
|
+
.venv\Scripts\rfclib.exe packs export standards-current --formats epub
|
|
423
|
+
.venv\Scripts\rfclib.exe packs export standards-current --formats zim # needs: uv sync --extra zim
|
|
424
|
+
.venv\Scripts\rfclib.exe packs export standards-current --formats docset
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
* **EPUB** (EPUB3, pure stdlib zip): works in ReadEra/Apple Books/Play
|
|
428
|
+
Books; the nav document gives per-document chapters nested with their
|
|
429
|
+
top sections. Reader-side full-text search indexes the chapters.
|
|
430
|
+
* **Dash docset** (`--formats docset`, pure stdlib): `<id>.docset` bundle +
|
|
431
|
+
`.tgz` — drag into Dash (or Zeal/Xcode). The `docSet.dsidx` lookup index
|
|
432
|
+
carries one entry per document plus one per top-level section/appendix
|
|
433
|
+
(`RFC9110: 4.2. HTTP Messaging` → deep-link straight to that anchor).
|
|
434
|
+
* **HTML mirror**: plain folder of pages + `index.html` — greppable,
|
|
435
|
+
Everything/Windows-Search friendly, opens anywhere (the CHM successor,
|
|
436
|
+
without CHM's dead tooling; CHM itself was rejected: no maintained
|
|
437
|
+
Python writer, no Android support).
|
|
438
|
+
* **ZIM (Kiwix)** (`--formats zim`; optional native bindings, `uv sync
|
|
439
|
+
--extra zim` — libzim wheels carry Xapian): one `.zim` per collection
|
|
440
|
+
with a **full-text index + title suggestions built at write time**, so
|
|
441
|
+
Kiwix apps / `kiwix-serve --port 8080 export-formats\standards-current.zim`
|
|
442
|
+
give offline full-text search over the corpus. Entries are flat and
|
|
443
|
+
lowercase (`rfc9000`), the main page is the collection index, and a
|
|
444
|
+
generated 48x48 PNG icon shows in the Kiwix catalogue.
|
|
445
|
+
|
|
446
|
+
Validation: `python scripts\check_export.py` verifies EPUB/HTML structure
|
|
447
|
+
(mimetype placement, OPF/nav well-formedness, anchors, cross-links,
|
|
448
|
+
furniture stripping), `python scripts\check_zim.py` reopens a built
|
|
449
|
+
ZIM with the libzim reader (entry counts, main-page redirect, metadata,
|
|
450
|
+
illustration, anchors/links, and live Xapian suggestion + full-text
|
|
451
|
+
queries), and `python scripts\check_docset.py` validates the docset
|
|
452
|
+
bundle (plist, dsidx rows + every url/anchor resolving, tgz layout) —
|
|
453
|
+
all end-to-end against the `essentials` collection.
|
|
454
|
+
|
|
455
|
+
Search engine compatibility: the packs carry an FTS5 index, but **AOSP's
|
|
456
|
+
system SQLite does not enable FTS5** — `external/sqlite/dist/Android.bp`
|
|
457
|
+
on Android 11 and 16 defines FTS3/FTS4 only, and an API 36 emulator image
|
|
458
|
+
has no `fts5` module (`MATCH` fails with `no such module: fts5`; OEM ROMs
|
|
459
|
+
sometimes add it). `RfcSearch` therefore probes FTS5 once per process and
|
|
460
|
+
falls back to portable LIKE-based AND matching with density ranking when
|
|
461
|
+
the module is absent — correct, though slower and unstemmed. Queries pass
|
|
462
|
+
a stop-word filter: SQLite FTS5 has no native stop-word support (no
|
|
463
|
+
built-in tokenizer option exists, verified through SQLite 3.54), so
|
|
464
|
+
filtering happens at query time and needs no pack rebuild; RFC normative
|
|
465
|
+
keywords (MUST/SHOULD/MAY/CAN) are deliberately kept out of the stop list
|
|
466
|
+
because they carry meaning in this corpus. A future option for indexed
|
|
467
|
+
search on every device is an FTS4 mirror table (FTS4 is guaranteed on
|
|
468
|
+
AOSP) or bundling a native SQLite with FTS5.
|
|
469
|
+
|
|
470
|
+
```powershell
|
|
471
|
+
cd android-reader
|
|
472
|
+
.\gradlew.bat assembleDebug # APK: app\build\outputs\apk\debug
|
|
473
|
+
.\gradlew.bat test # installer validation unit tests
|
|
474
|
+
adb install app\build\outputs\apk\debug\app-debug.apk
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## Reader UI and Docker images
|
|
478
|
+
|
|
479
|
+
The React reader UI (`rfclib ui`, with its stdlib JSON API) and the Docker
|
|
480
|
+
images that serve it live on the [`reader-ui`](https://github.com/b1tninja/rfclib/tree/reader-ui)
|
|
481
|
+
branch, kept out of the package so it needs no npm toolchain. Check that
|
|
482
|
+
branch out to build or run them.
|
|
483
|
+
|
|
484
|
+
## Roadmap
|
|
485
|
+
|
|
486
|
+
1. ✅ Bulk download + incremental sync (rsync bootstrap + HTTP syncer)
|
|
487
|
+
2. ✅ MCP presentation (search / get / metadata / aliases / recents)
|
|
488
|
+
3. ✅ Full-text + semantic + hybrid retrieval, golden-set eval harness
|
|
489
|
+
4. ✅ React + Vite reader UI (`rfclib ui`): JSON API + SPA — now on the
|
|
490
|
+
`reader-ui` branch
|
|
491
|
+
5. ✅ Cross-references: citation graph mined from txt (normative/
|
|
492
|
+
informative/mention + section-level anchors, `rfclib refs`), exposed
|
|
493
|
+
in CLI and MCP with section deep links
|
|
494
|
+
6. ✅ Verified-errata overlay from the RFC Editor errata service
|
|
495
|
+
(bulk API + per-doc fallback, `rfclib errata`, MCP `errata`)
|
|
496
|
+
7. ✅ Content packs (`.rfcpack` + collections + LAN serve) and offline
|
|
497
|
+
Android reader (`android-reader/`) with FTS5 search
|
|
498
|
+
8. ✅ Third-party export (`packs export`): EPUB3, static HTML mirror, Kiwix
|
|
499
|
+
ZIM (libzim + Xapian full-text index, optional `zim` extra) and Dash
|
|
500
|
+
docset (stdlib dsidx with section deep-links) — all four over the
|
|
501
|
+
shared txt→XHTML render layer
|
|
502
|
+
9. ✅ Multi-stage Docker workflow serving the reader UI — on the
|
|
503
|
+
`reader-ui` branch
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
## License
|
|
507
|
+
|
|
508
|
+
rfclib is MIT-licensed (see [LICENSE](LICENSE)). The RFCs it downloads are
|
|
509
|
+
not: they are published by the IETF Trust under the
|
|
510
|
+
[Trust Legal Provisions](https://trustee.ietf.org/license-info). They may be
|
|
511
|
+
copied and distributed in full but not modified; see [NOTICE](NOTICE).
|