5.4 KiB
5.4 KiB
claw-rag-mcp — 独立 RAG MCP Server 设计
日期:2026-08-13 状态:已批准(设计评审通过)
背景与目标
将 claw-rag-service 的 RAG 能力(语义检索 / 索引 / 统计)封装为一个完全独立的 MCP server 可执行文件,放入系统 PATH,供任意 MCP host(opencode、Claude Desktop、Cursor 等)通过标准 command 方式启动,走 stdio 传输协议。
关键约束:
- 与 claw-analog / 原 HTTP 服务的
retrieve_context实现无任何耦合。工具名、实现、行为均为全新设计,不沿用原版的工具名(retrieve_context)与调用约定。 - 独立可分发 exe(
cargo build --release后单文件),放 PATH 即用。 - 传输层自研极简 stdio(参考
runtime::mcp_server.rs的 framing/dispatch 模式),零外部协议依赖,符合仓库forbid(unsafe_code)lint。 - 依赖
claw-rag-service的 lib(query_index/run_ingest/chunk_count/EmbedConfig)复用索引、分块、embedding 逻辑;与现有 HTTP 服务共享同一份 SQLite 索引(CLAW_RAG_DB,默认.claw-rag/index.sqlite)。
架构总览
独立项目: D:\tempo\claw-rag-mcp(不在 claw-code 仓库内)
├─ Cargo.toml(独立 workspace,仅含本 crate)
└─ bin: claw-rag-mcp
│ - 自研极简 stdio MCP server(LSP Content-Length framing + JSON-RPC dispatch)
│ - 协议子集: initialize / tools/list / tools/call
│ - 依赖: tokio, serde_json
│ - path 依赖: claw-rag-service lib(query_index / run_ingest / chunk_count / EmbedConfig)
│ = D:\tempo\claw-code\rust\crates\claw-rag-service
└─ serverInfo: name=claw-rag, version=独立定义
注意:位置决策已更新(用户确认)——独立文件夹 D:\tempo\claw-rag-mcp,path 依赖指向 claw-code 仓库的 rag-service,二者各自独立构建,不共享 workspace 依赖解析(serde_json 需在独立 Cargo.toml 中显式声明,不能引用 workspace = true)。
- 二进制名:
claw-rag-mcp - 协议版本:
2025-03-26 - 能力声明:
{"tools": {}} - 配置环境变量(复用 claw-rag-service 现有约定):
CLAW_RAG_DB:SQLite 索引路径(默认.claw-rag/index.sqlite)CLAW_RAG_OPENAI_API_KEY/OPENAI_API_KEY:embedding API keyCLAW_RAG_EMBEDDING_BASE_URL:默认https://api.openai.com/v1CLAW_RAG_EMBEDDING_MODEL:默认text-embedding-3-smallCLAW_RAG_MOCK_PROVIDERS=1:确定性 mock embedding(测试/试用)
暴露的工具(全新命名,前缀 rag_)
| 工具 | 入参 | 返回 | 权限 |
|---|---|---|---|
rag_query |
query(必填), top_k(默认8, ≤32) |
格式化 hits(path/snippet/score)+ phase |
只读 |
rag_stats |
{} |
chunks 数 + phase |
只读 |
rag_ingest |
workspaces: 路径数组 |
立即返回 job_id(后台任务) |
写索引 |
rag_ingest_status |
job_id |
running(进度) / done(统计) / failed(错误) / unknown |
只读 |
phase 取值(沿用索引状态语义,但作为输出字段而非协议):
1-sqlite-no-db:索引文件不存在1-sqlite-empty:索引存在但无 chunk1-sqlite:有数据
异步 ingest job 机制
- 进程内存
JobRegistry(Mutex<HashMap<job_id, JobState>>)。stdio server 为长驻进程,job 跨tools/call有效。 - 限制:host 重启进程后 job 丢失(不持久化)。在文档中注明;符合"查询 + 维护性索引"定位。
- 进度上报:给
claw-rag-service增加run_ingest_with_progress(workspaces, db_path, cfg, client, progress: impl FnMut(IngestProgress));现有run_ingest委托它并传 no-op。IngestProgress { files_done, files_total, chunks_total }。现有调用方零改动。 - SQLite 单写者约束:ingest job 用全局
Mutex串行执行,避免 SQLITE_BUSY。 - job_id:进程内递增整数转字符串(如
"1"、"2")。
错误处理
- JSON-RPC 规范错误码:
-32700parse error-32600invalid request-32601method not found-32602invalid params
- 工具执行错误 →
isError: true+ text 消息(与 claw 现有约定一致),例如:no index (run rag_ingest first)embedding dimension mismatch ...(索引维度与查询维度不一致提示)- 工具参数缺失/非法
测试
- 单元:dispatch 层各分支(initialize / tools/list / tools/call 正常与错误 / 未知方法 / 非法参数)。
- 集成:
CLAW_RAG_MOCK_PROVIDERS=1+ tempdir,全流程:rag_ingest起 job → 立即返回 job_id- 轮询
rag_ingest_status至done rag_query命中相关文件rag_stats反映 chunks 数
- framing:进程内 pipe 模拟 stdin/stdout 往返验证 LSP 帧格式与 dispatch。
非目标(YAGNI)
- 不做 HTTP/SSE 传输。
- 不持久化 job 状态。
- 不实现 MCP resources / prompts / 认证。
- 不改动 claw-analog 的
retrieve_context实现。 - 不新增对
runtimecrate 的依赖(避免引入 plugins/telemetry)。 - 不把项目放入 claw-code 仓库(独立文件夹,独立版本号)。
文档
- 在
rust/README或 crate 内README.md记录安装与配置方式:cargo build --release -p claw-rag-mcp→ 将target/release/claw-rag-mcp.exe放入 PATH- opencode / Claude Desktop 配置
command: "claw-rag-mcp" - 环境变量说明