内容
# rfc-mcp
[](https://pkg.go.dev/github.com/higebu/rfc-mcp)
[](https://github.com/higebu/rfc-mcp/actions/workflows/ci.yml)
[](https://codecov.io/github/higebu/rfc-mcp)

一个使IETF RFCs可供LLMs访问的MCP(模型上下文协议)服务器。
## 背景
RFCs是互联网协议的主要参考资料,但它们对于LLMs来说很难有效处理:
- **文档太多** - 自1969年以来已经发布了近9800个RFC,涵盖了互联网协议设计的各个时代。
- **个别文档可能很大** - TCP(RFC 9293)或BGP-4(RFC 4271)等基础规范动辄就有100页或更多。
- **五十年来的格式不一致** - 纯文本RFC从现代无分页文档到1980年代的分页和换页布局,再到1970年代没有章节编号的自由格式文档。
- **交叉引用繁重** - RFCs不断引用、废弃和更新彼此(例如,RFC 9293废弃RFC 793和另外六个RFC,并更新另外三个RFC);阅读一篇文档会让人感到不完整。
- **状态和勘误复杂度** - 同一个协议可能在原始RFC、多个更新和勘误报告列表中描述,了解哪些部分仍然当前很重要。
该工具通过解析在[rfc-editor.org](https://www.rfc-editor.org/)发布的纯文本RFC主体,结构化内容并将其存储在具有全文搜索(FTS5)的SQLite数据库中来解决这些挑战。然后,MCP服务器提供浏览、搜索和跟随交叉引用的工具,让LLM可以像协议工程师一样导航RFCs。
### 为什么不使用RAG?
RAG(检索增强生成)方法 - 分割文档、生成嵌入并执行向量相似性搜索 - 是文档问答的常见解决方案。然而,RFCs是结构化技术文档,该方法有显著的缺点:
- **丢失结构** - RAG将文档分割成扁平的块,丢弃导航规范所需的章节层次结构(例如,直接跳转到RFC 9293的“第3.10.7.4节”)。
- **无法遍历关系** - 向量搜索无法跟随“废弃”、“更新”或RFC之间的交叉引用关系。
- **检索噪声** - 相似性搜索可能会返回松散相关的块而不是所需的确切章节。
- **额外成本** - 嵌入生成和向量数据库托管会增加基础设施和API成本。
该工具采用结构感知方法:它保留每个RFC的章节层次结构(包括旧版分页怪癖),实现精确的章节级检索,按编号或按slug,并支持使用FTS5语法的全文搜索以及RFC之间的交叉引用。所有数据存储在一个SQLite文件中,无需外部依赖。
## 入门指南
### 构建自包含的Docker镜像
`Dockerfile`是多阶段的,直接构建数据库,生成一个自包含的镜像,其中包含SQLite数据库。无需LibreOffice或其他重依赖 - RFCs直接从纯文本解析。
```bash
# 构建一个包含完整RFC语料库的镜像(默认,~8分钟,~865 MB)
docker build -t rfc-mcp:latest .
# ... 或限制数据库到数字RFC范围(快速烟雾测试镜像)
docker build --build-arg FROM_RFC=9290 --build-arg TO_RFC=9295 -t rfc-mcp:smoke .
# stdio传输(Claude Code / IDE集成)
docker run --rm -i rfc-mcp:latest
# HTTP传输
docker run --rm -p 8080:8080 rfc-mcp:latest serve --db /rfc.db --transport http --addr :8080
```
`FROM_RFC`/`TO_RFC`默认为空,构建时包含完整的语料库。设置其中一个(或两个)可构建限制在数字RFC范围内的数据库。
### 部署到Cloud Run
要运行在Cloud Run上,请参阅`cloudbuild.yaml`(构建+推送+部署)和`service.yaml`(Cloud Run服务规范)。
---
### 1. 安装
```bash
go install github.com/higebu/rfc-mcp/cmd/rfc-mcp@latest
```
需要Go 1.26+。无CGO,无外部运行时依赖 - RFC主体仅从纯文本解析。
### 2. 构建数据库
下载并将RFCs导入数据库。下载的`.txt`主体被缓存(参见[数据源和更新频率](#数据源和更新频率)),因此重新运行`build`后,中断后可以廉价地恢复。
```bash
# 下载并导入完整的RFC语料库(~8分钟,16个工作线程,~865 MB)
rfc-mcp build --db data/rfc.db
# ... 或限制在数字范围内,例如快速本地测试
rfc-mcp build --db data/rfc.db --from 9290 --to 9295
```
此操作获取`rfc-index.xml`和`errata.json`,然后单独获取每个RFC的纯文本主体(rfc-editor.org没有批量tarball),将其解析成章节,并将所有内容插入SQLite数据库。
### 3. 注册MCP客户端
#### Claude Code
```bash
claude mcp add --scope user rfc -- rfc-mcp serve --db /path/to/data/rfc.db
```
#### VS Code / GitHub Copilot
```bash
code --add-mcp '{"name":"rfc","command":"rfc-mcp","args":["serve","--db","/path/to/data/rfc.db"]}'
```
#### Claude Desktop
添加到配置文件(`~/Library/Application Support/Claude/claude_desktop_config.json`在macOS上,`%APPDATA%\Claude\claude_desktop_config.json`在Windows上):
```json
{
"mcpServers": {
"rfc": {
"command": "rfc-mcp",
"args": ["serve", "--db", "/path/to/data/rfc.db"]
}
}
}
```
#### 流式HTTP(远程部署)
使用HTTP传输启动服务器:
```bash
rfc-mcp serve --db data/rfc.db --transport http --addr :8080
```
可选地启用Bearer令牌身份验证:
```bash
export RFC_MCP_BEARER_TOKEN=$(openssl rand -hex 32)
rfc-mcp serve --db data/rfc.db --transport http --addr :8080
```
然后配置客户端通过HTTP连接:
```json
{
"mcpServers": {
"rfc": {
"url": "http://your-server:8080",
"headers": {
"Authorization": "Bearer YOUR_SECRET_TOKEN"
}
}
}
}
```
`GET /health`在没有身份验证的情况下返回`200 OK`,用于平台健康检查(Cloud Run、Kubernetes liveness/readiness探测等)。
对于Cloud Run或Heroku等容器平台,注入`PORT`环境变量,服务器自动切换到HTTP传输并绑定到`:$PORT`。显式标志或`RFC_MCP_TRANSPORT` / `RFC_MCP_ADDR`始终优先。
参见[`examples/systemd/`](examples/systemd/)用于systemd的生产部署。
## MCP工具
### 浏览RFCs
| 工具 | 描述 | 关键参数 |
|------|-------------|----------------|
| `list_rfcs` | 列出RFCs,可选过滤 | `query`(标题子字符串),`stream`,`status`,`wg`,`limit`,`offset` |
| `get_metadata` | 标题、状态、日期、废弃/更新、勘误 | `rfc`(必需) |
| `get_toc` | RFC的目录 | `rfc`(必需) |
| `get_section` | 章节内容,每个章节前缀为其标题行(分页)。仅获取标题的章节如果没有`include_subsections`,则返回其子章节的摘要而不是空文本 | `rfc`,`section_number`(必需),`include_subsections`,`offset`,`max_lines`,`max_chars` |
| `get_document` | RFC的全文作为一个文档(分页) | `rfc`(必需),`offset`,`max_lines`,`max_chars` |
`get_metadata(rfc: 4271)`返回:
```json
{
"rfc": 4271,
"title": "边界网关协议4(BGP-4)",
"status": "草案标准",
"stream": "IETF",
"date": "2006-01",
"page_count": 104,
"wg": "idr",
"area": "rtg",
"authors": ["Y. Rekhter", "T. Li", "S. Hares"],
"keywords": ["BGP-4", "routing"],
"abstract": "本文讨论边界网关协议(BGP),...",
"draft": "draft-ietf-idr-bgp4-26",
"doi": "10.17487/RFC4271",
"errata_url": "https://www.rfc-editor.org/errata/rfc4271",
"obsoletes": [1771],
"updated_by": [4724, 6286, 6608, 6793, 7606, 7607, 7705, 8212, 8654, 9072, 9687, 9774],
"errata": [
{ "id": 150, "status": "Verified", "type": "Editorial", "section": "9.1.1" },
{ "id": 1332, "status": "Rejected", "type": "Technical", "section": "4.5" }
]
}
```
`status`为标题大小写以提高可读性,即使`rfc-index.xml`存储为大写(`DRAFT STANDARD`);`list_rfcs`返回原始大写形式。
勘误是一个紧凑的摘要(仅限id/status/type/section) - 跟随`errata_url`获取特定勘误的完整原始/纠正文本。
### 搜索
| 工具 | 描述 | 关键参数 |
|------|-------------|----------------|
| `search` | 跨所有RFC的全文搜索 | `query`(必需),`rfc`,`rfcs`,`limit`(默认10) |
`search`工具支持[SQLite FTS5](https://www.sqlite.org/fts5.html)查询语法:
- 短语搜索:`"三方握手"`
- 布尔运算符:`AMF AND UE`,`retransmission OR retransmit`,`NOT deprecated`
- 前缀匹配:`retransmi*`
- 列过滤器:`title:security`,`content:handshake`
- 邻近度:`NEAR(SYN ACK, 5)`
- 连字符术语(例如`three-way-handshake`)自动引用以避免FTS5语法错误
示例 - `search(query: "three way handshake", rfc: 9293, limit: 3)`:
```json
[
{
"rfc": 9293,
"number": "3.5",
"title": "建立连接",
"snippet": "\"<mark>三</mark>-<mark>方</mark> <mark>握手</mark>\"是用于建立连接的程序。 ..."
}
]
```
### 交叉引用
| 工具 | 描述 | 关键参数 |
|------|-------------|----------------|
| `get_references` | 获取RFC之间的交叉引用 | `rfc`(必需),`section_number`,`direction`(默认`outgoing`或`incoming`),`include_subsections` |
`outgoing`需要`section_number`并返回从该部分引用的RFC;`incoming`仅需要`rfc`并返回每个部分(在任何RFC中)引用它。示例 - `get_references(rfc: 9293, section_number: "3.10.7.4", direction: "outgoing")`:
```json
[
{
"source_rfc": 9293,
"source_section": "3.10.7.4",
"target_rfc": 793,
"context": "...原始行为描述在RFC 793中遵循此段落。 ..."
},
{
"source_rfc": 9293,
"source_section": "3.10.7.4",
"target_rfc": 5961,
"target_section": "3",
"target_title": "使用RST位进行盲重置攻击",
"context": "...RFC 5961 [9], 第3节描述了一种潜在的盲重置..."
}
]
```
`target_section`/`target_title`仅在引用能解析到特定章节时存在(例如,通过数字括号引用`[9]`通过引用部分解析);裸`RFC 793`提及不带章节编号省略它们。
## 命令参考
### `serve`
启动MCP服务器。
| 标志 | 描述 | 默认值 |
|------|-------------|---------|
| `--db` | SQLite数据库路径 | `rfc.db` |
| `--transport`(`-t`)| 传输类型:`stdio`或`http`(env:`RFC_MCP_TRANSPORT`;默认为`http`,当设置`PORT`时) | `stdio` |
| `--addr` | HTTP监听地址(env:`RFC_MCP_ADDR`或`PORT`解释为`:$PORT`) | `:8080` |
| `--bearer-token` | HTTP身份验证的Bearer令牌(env:`RFC_MCP_BEARER_TOKEN`) | |
### `build`
下载并将RFCs导入数据库(建议用于初始设置)。
| 标志 | 描述 | 默认值 |
|------|-------------|---------|
| `--db` | 输出SQLite数据库路径 | `data/rfc.db` |
| `--workers` | 并行工作线程数 | NumCPU |
| `--timeout` | HTTP超时 | `30s` |
| `--from` | 仅处理RFC编号>=此(0 = 无下限) | `0` |
| `--to` | 仅处理RFC编号<=此(0 = 无上限) | `0` |
| `--raw-dir` | 下载的RFC `.txt`文件缓存目录 | `$XDG_CACHE_HOME/rfc-mcp/raw` |
| `--base-url` | 覆盖RFC编辑器根URL | `https://www.rfc-editor.org` |
### `download`
下载RFC纯文本主体而不导入它们。
| 标志 | 描述 | 默认值 |
|------|-------------|---------|
| `--raw-dir` | 保存下载的RFC `.txt`文件目录 | `$XDG_CACHE_HOME/rfc-mcp/raw` |
| `--workers` | 并行下载数 | NumCPU |
| `--timeout` | HTTP超时 | `30s` |
| `--from` | 仅下载RFC编号>=此 | `0` |
| `--to` | 仅下载RFC编号<=此 | `0` |
| `--base-url` | 覆盖RFC编辑器根URL | `https://www.rfc-editor.org` |
### `import`
导入单个RFC `.txt`文件到数据库。
| 标志 | 描述 | 默认值 |
|------|-------------|---------|
| `--db` | 输出SQLite数据库路径 | `data/rfc.db` |
用法:`rfc-mcp import --db data/rfc.db path/to/rfcNNNN.txt`
### `import-dir`
导入指定目录中的所有RFC `.txt`文件到数据库。
| 标志 | 描述 | 默认值 |
|------|-------------|---------|
| `--db` | 输出SQLite数据库路径 | `data/rfc.db` |
| `--workers` | 并行解析工作线程数 | NumCPU |
用法:`rfc-mcp import-dir --db data/rfc.db ./raw`
### `update`
在现有数据库中刷新:获取新发布的RFC编号,并刷新整个语料库的元数据和勘误(两者都是小且实时获取的文档,因此批量刷新很廉价)。已经缓存的RFC正文永远不会被重新获取,因为正文一旦发布就不可变。刷新发生在`VACUUM INTO`的副本上,如果数据库正在被`serve`读取,则原子交换为新数据库。
| 标志 | 描述 | 默认值 |
|------|-------------|---------|
| `--db` | SQLite数据库路径 | `data/rfc.db` |
| `--workers` | 并行工作线程数 | NumCPU |
| `--timeout` | HTTP超时 | `30s` |
| `--raw-dir` | 下载RFC `.txt`文件的目录 | `$XDG_CACHE_HOME/rfc-mcp/raw` |
| `--base-url` | 覆盖RFC编辑器根URL | `https://www.rfc-editor.org` |
### `completion`
生成shell补全脚本:`rfc-mcp completion <bash|zsh|fish>`。
## 数据源和更新频率
- **`rfc-index.xml`**(~13.6 MB) - 每个RFC的元数据:9,794个已发布条目 + 188个已分配但未发布的条目。默认缓存24小时(`RFC_MCP_CACHE_TTL_HOURS`)。
- **`errata.json`**(~11.5 MB) - 所有已发布的勘误报告(截至此写作时为7,961)。相同的24小时缓存。
- **RFC纯文本主体** (`https://www.rfc-editor.org/rfc/rfcN.txt`) - 逐一文件获取;rfc-editor.org不提供批量tarball也不支持`HEAD`请求,因此每次获取都是`GET`。RFC正文发布后永远不会改变,因此`--raw-dir`下的本地缓存有效期无限长,不会重新获取或过期。
- **`update`** 保持数据库最新而无需完整重建:仅获取数据库中尚不存在的RFC编号,并无条件刷新整个语料库的元数据和勘误(参见上面的`update`命令及其原子交换机制)。
完整语料库的`build`(2026-07-11测量,16个工作线程)需要约8分钟,生成一个~865 MB的SQLite数据库:9,982个RFC行(9,794个已发布 + 188个未发布),321,372个章节,284,869个提取的交叉引用,和7,961个勘误记录。
## 限制
- **7个RFC没有纯文本正文**,仅包含元数据(标题,状态,日期等来自`rfc-index.xml`,但没有章节,没有全文搜索,没有`get_section`/`get_toc`内容):RFC 8,9,51,418,500,530和598。这些是1969-1973年的文档,仅以扫描图像或纸质形式分发;rfc-editor.org没有它们的`.txt`文件。该管道从每个条目的`<format>`列表中检测到这一点,并在`build`/`update`运行中跳过获取正文(报告为`TEXT_UNAVAILABLE`在完成摘要中)。
- **~684个RFC(~7%的语料库,绝大多数在1000年之前)** 降级为单个整体章节,编号为`body`,而不是正确的章节分解。这是解析器的文档布局不匹配RFC编辑器`.txt`文件中的任何模式时的Tier-3回退(免费的1970年代备忘录,不寻常的排版等)。全文仍然可通过`search`,`get_section(rfc, "body")`或`get_document`检索;它只是不能按细粒度章节编号寻址。
- **纯文本解析** - RFCs从rfc-editor.org发布的`.txt`版本解析,而不是XML源。章节内容原样存储(无缩进或重流),保留ABNF和分组图对齐,但任何清理启发式算法错过的分页伪影将原样显示。
- **章节编号约定**:带点的数字(`4.1`),字母附录(`A.2`),或未编号标题的slug。未编号标题的slug为小写并将空格/撇号替换为连字符(`abstract`,`security-considerations`,`iana-considerations`,`acknowledgments`,`authors-address`等)。合成`header`slug涵盖RFC的标题块内容(文档系列标题,标题,作者列表,日期)在第一个实际标题之前,并且`body`涵盖上述第3层整章节回退。
## 许可
MIT
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器