trm-mcp
# TRM MCP
本地、离线优先的超长 datasheet/TRM PDF 检索服务。它将页面级结构化解析、
BM25、Qwen3 dense embedding、Qwen3 reranker 和页面视觉 embedding 融合,
通过 MCP 提供 `search`、`grep`、`read`、`render` 和 `compare`。
## 快速开始
```bash
docker compose up -d
python -m venv .venv
.venv/bin/pip install -e '.[dev]'
.venv/bin/trm init
.venv/bin/trm models download
# 默认:只建立文本索引
.venv/bin/trm ingest /path/to/manual.pdf
# 也可递归导入目录及其所有子目录中的 PDF
.venv/bin/trm ingest /path/to/manuals/
# 可选:同时建立页面视觉索引
.venv/bin/trm ingest --visual /path/to/manual.pdf
# HTTP 服务必须设置一个固定 Bearer key
export TRM_MCP_API_KEY="$(openssl rand -hex 32)"
.venv/bin/trm serve --transport http
```
直接运行时服务默认监听 `http://127.0.0.1:8765/mcp`。HTTP 请求必须携带
`Authorization: Bearer <TRM_MCP_API_KEY>`;stdio 不需要网络认证。所有文档内容和查询均留在本机。
默认数据目录是 `${XDG_DATA_HOME:-~/.local/share}/trm-mcp`,可通过
`TRM_DATA_DIR` 覆盖。
生成数据包括:
- `trm.sqlite3`:文档、页面、布局 JSON、Markdown、切块和 FTS5/BM25;
- `documents/`:按内容哈希保存的只读 PDF 副本;
- `images/`:用于视觉索引的 144 DPI 页面图;
- `.trm-data/qdrant/`:Qdrant 文本和视觉向量,可用
`TRM_QDRANT_STORAGE` 覆盖。
## MCP 客户端
```bash
export TRM_MCP_API_KEY="...与服务端相同的值..."
codex mcp add trm --url http://127.0.0.1:8765/mcp \
--bearer-token-env-var TRM_MCP_API_KEY
```
`--bearer-token-env-var` 不会把密钥写进 Codex 配置。使用 systemd 部署时,
在启动 Codex 前加载同一私有环境文件:
```bash
set -a; . ~/.config/trm-mcp.env; set +a
codex
```
Claude Code 2.1.77 在本机使用 stdio(该版本的 HTTP 健康检查与当前
Streamable HTTP SDK 不兼容):
```bash
claude mcp add-json --scope user trm \
'{"type":"stdio","command":"/absolute/path/to/trm-mcp/.venv/bin/trm",
"args":["serve","--transport","stdio"],
"env":{"TRM_DATA_DIR":"/absolute/path/to/trm-data",
"TRM_QDRANT_URL":"http://127.0.0.1:6333","HF_HUB_OFFLINE":"1",
"TRANSFORMERS_OFFLINE":"1",
"TESSDATA_PREFIX":"/absolute/path/to/trm-data/tessdata"}}'
```
把示例中的绝对路径替换为本机仓库和数据目录;Claude Code 的 JSON
配置不会通过 shell 展开 `$HOME`。
服务本身同时支持 HTTP 与 stdio;较新的 Claude Code 可直接改用 HTTP URL。
## 管理命令
```bash
trm list
trm status
trm reindex DOCUMENT_ID
trm remove DOCUMENT_ID
trm eval evals/golden_queries.json -o eval-report.json
```
MCP 接口是只读的。导入、重建、删除只能由本地 CLI 显式执行。
默认混合检索分别召回 BM25、Qwen3 文本向量和 Qwen3-VL 页面向量,
先用 RRF 合并文本候选,再经 Qwen3 reranker 重排,最后以 0.7/0.3
权重融合文本与视觉页排名。所有结果均带稳定文档 ID 和一基页码。
模型在第一次搜索时按需加载,服务启动和纯 `list_documents`、`grep`、`read`、
`render` 调用不会占用模型显存。reranker 默认使用 batch 1,可通过
`TRM_RERANK_BATCH_SIZE` 调整。每次查询结束后会归还未使用的 CUDA allocator
缓存;连续 600 秒没有模型查询时会卸载全部模型,可通过
`TRM_MODEL_IDLE_TIMEOUT_SECONDS` 调整,设为 `0` 可关闭自动卸载。默认搜索模式
仍为 `hybrid`,因此首次搜索及空闲卸载后的首次搜索需要重新加载三个模型。
解析器会先检查每页的原生文字、坏字符、已有 OCR 文字层和图像覆盖,只对
确实需要识别的页面启用 OCR。视觉编码默认从 batch 8 开始;如果出现 CUDA
显存不足,会自动按 8 → 4 → 2 → 1 退避,并在当前进程中保持已验证的大小。
可通过 `TRM_VISUAL_BATCH_SIZE` 设置起始上限,通过
`TRM_VISUAL_BATCH_MIN` 设置退避下限。
导入默认只建立文本索引,不渲染页面。显式传入 `--visual` 时,页面渲染使用
与可用逻辑 CPU 数相同的独立 `spawn` 进程;每个进程独立
打开 PDF,并使用原子文件替换写入 JPEG。SQLite 路径每 25 页批量提交,因此
并行 worker 不会共享数据库连接。本机可通过 `TRM_RENDER_WORKERS` 指定固定
进程数,`0` 表示自动;用 `TRM_RENDER_PIN_CPUS=0/1` 控制 CPU 绑定。
之后可用 `trm ingest --visual` 或 `reindex` 补建图片与视觉索引。
PDF 结构化解析默认使用 8 个独立的 `spawn` 进程;每个进程独立打开 PDF、
绑定自己的 CPU 核集合,并将 ONNX Runtime intra-op 线程限制为 2。子进程
只返回页面结果,SQLite 写入和 Docling fallback 仍由主进程串行完成。可通过
`TRM_PARSE_WORKERS`、`TRM_PARSE_ORT_THREADS` 和
`TRM_PARSE_PIN_CPUS=0/1` 调整。
## 常驻服务与严格离线
仓库提供 `deploy/trm-mcp.service`,默认假定仓库位于 `~/trm-mcp`。如果
安装位置不同,先修改其中的路径。安装并启动:
```bash
mkdir -p ~/.config/systemd/user
cp deploy/trm-mcp.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now trm-mcp.service
```
该服务将 Hugging Face 和 Transformers 设置为离线模式,默认同时绑定 IPv6
`[::]:8765` 和 IPv4 `0.0.0.0:8765`。安装前创建仅当前用户可读的密钥文件:
```bash
install -m 600 /dev/null ~/.config/trm-mcp.env
openssl rand -hex 32 | sed 's/^/TRM_MCP_API_KEY=/' >> ~/.config/trm-mcp.env
```
本机 Codex 使用 IPv6 loopback 时,URL 写作 `http://[::1]:8765/mcp`。
访问其他主机时必须使用其实际 IPv6 地址,并在 URL 中加方括号。此内置认证是
固定 Bearer key,未提供 TLS;若流量会经过不可信网络,请在反向代理上启用 HTTPS。
首次运行前必须执行一次 `trm models download`。
TDQS
Scored across 6 tools
Each tool has a clearly distinct purpose: listing documents, searching with ranking, exact pattern matching, reading page content, rendering images, and comparing documents. There is no ambiguity about which tool to use for a given task.
Most tool names are single-word imperative verbs (search, grep, read, render, compare), which is consistent. However, list_documents deviates by using a verb_noun pattern, creating a minor inconsistency.
With 6 tools, the server is well-scoped for document retrieval and inspection. Each tool addresses a distinct aspect of the workflow, and the count feels appropriate for the domain.
The toolset covers listing, searching, grep-style extraction, reading, visual rendering, and comparison, which are the core operations for document analysis. Minor gaps might include a dedicated tool for fetching a single document's metadata, but list_documents already provides this.