# TASK RESULT ## Research Notes 1. **当前最适合 pin 的 QMD 版本** - 选择 `v1.0.7`(`@tobilu/qmd@1.0.7`),是截至 2026-03-07 的最新非预发布 stable release(发布时间 2026-02-18)。 2. **是否已有官方 compose 参考** - 在 `tobi/qmd` 的 `v1.0.7` 源码树中未找到 `Dockerfile` / `docker-compose.yml` 参考,需要自行实现。 3. **QMD HTTP MCP 启动与健康检查方式** - 启动:`qmd mcp --http`(默认端口 8181) - 端点:`POST /mcp`、`GET /health` 4. **是否需要覆盖默认模型** - 第一版不覆盖,直接沿用源码默认模型(embeddinggemma / qwen3-reranker / qmd-query-expansion)。 5. **Node 与 Bun 在容器中选型** - 选 Node(`node:22-bookworm-slim`)。理由: - 上游 package `engines.node >=22` - `npm install -g @tobilu/qmd@1.0.7` 路径直接、可复现 - 官方生态和镜像稳定性更高,长期维护成本更低 6. **缓存目录、索引目录、知识库目录挂载策略** - `XDG_CACHE_HOME=/var/lib/qmd/cache`(模型缓存 + 默认 sqlite 索引) - `XDG_CONFIG_HOME=/var/lib/qmd/config`(collection YAML 配置) - 业务知识库挂载到 `/data/knowledge` - 测试数据挂载到 `/data/testdata` 7. **smoke test 最小闭环覆盖步骤** - compose 启动服务 - `/health` 检查通过 - 添加 collections(notes/docs/meetings) - `qmd update` + `qmd embed` - 至少一次 `qmd search` - 至少一次 `qmd query`(deep search 等价能力) ## Implemented Files ```text qmd-docker-http-mcp/ ├─ Dockerfile ├─ docker-compose.yml ├─ .dockerignore ├─ README.md ├─ TASK-RESULT.md ├─ scripts/ │ ├─ entrypoint.sh │ ├─ warmup.sh │ └─ smoke-test.sh ├─ knowledge/ └─ testdata/ ├─ notes/ ├─ docs/ └─ meetings/ ``` ## Commands Executed (Real) ```bash # Research curl -fsSL https://api.github.com/repos/tobi/qmd/releases?per_page=5 | jq ... curl -fsSL https://api.github.com/repos/tobi/qmd/git/trees/v1.0.7?recursive=1 | jq -r '.tree[].path' | rg 'docker|compose|Dockerfile|docker-compose' || true curl -fsSL https://raw.githubusercontent.com/tobi/qmd/v1.0.7/README.md curl -fsSL https://raw.githubusercontent.com/tobi/qmd/v1.0.7/src/llm.ts # Build / Run cd qmd-docker-http-mcp docker build -t hotwa/qmd:latest . docker compose up -d docker compose logs --no-color --tail=120 qmd curl -fsS http://127.0.0.1:8181/health # Warmup / Smoke ./scripts/warmup.sh ./scripts/smoke-test.sh # Extra MCP endpoint check curl -X POST http://127.0.0.1:8181/mcp -H 'content-type: application/json' -d '{}' ``` ## Build Result - Image built successfully: `hotwa/qmd:latest` - Image inspect summary: - `hotwa/qmd:latest b5c811d89722 1.99GB` ## Compose Startup Result - `docker compose up -d` 成功 - `docker compose ps` 结果: - `qmd-http-mcp ... Up ... (healthy) ... 0.0.0.0:8181->8181/tcp` ## Healthcheck Result - `GET /health` 返回成功: ```json {"status":"ok","uptime":244} ``` - `POST /mcp` 路由可达(示例请求返回协议校验错误而非 404): - HTTP `406` - `Not Acceptable: Client must accept both application/json and text/event-stream` ## Warmup Result - 成功创建并索引 3 个 collection:`notes` / `docs` / `meetings` - 成功执行 `qmd update` - 成功执行 `qmd embed` - 首次运行完成 embedding 模型下载并生成向量 ## Smoke Test Result `scripts/smoke-test.sh` 真实执行通过,覆盖: - 服务启动与 `/health` 成功 - collection 检查通过(3/3) - `qmd search "incident runbook" --json -n 5` 返回命中(含 `docs/incident-runbook.md`) - `qmd query "what is the RTO target for disaster recovery" --json -n 5` 返回命中(`docs/disaster-recovery.md` 得分最高) - 脚本最终输出:`[smoke] Smoke test passed` ## Problems Found and Fixes 1. **问题:容器外访问 8181 失败(连接被重置)** - 根因:QMD `v1.0.7` 的 HTTP MCP 在上游实现中绑定 `localhost`。 - 修复:在 `entrypoint.sh` 引入 `socat` 转发,将容器 `0.0.0.0:8181` 转发到容器内 QMD 监听端口。 2. **问题:初版转发到 `127.0.0.1:8182` 仍失败** - 根因:QMD 在容器内实际监听 `::1`(IPv6 localhost),`127.0.0.1` 不通。 - 修复:改为 `socat ... TCP6:[::1]:8182`。 3. **观察项:首次 query/embed 有 node-llama-cpp 的 CUDA 构建回退告警** - 现象:日志提示 `git/cmake not found`,随后回退并继续 CPU 路径,流程最终成功。 - 结论:当前不阻塞功能闭环,但会增加首次请求噪声与时延。 ## Final Acceptance 验收条件逐项结果: - [x] 成功构建 `hotwa/qmd:latest` - [x] `docker compose up -d` 后服务启动 - [x] `/health` 返回成功 - [x] 至少一组测试数据被索引 - [x] 至少一次关键词搜索成功 - [x] 至少一次深检索/混合检索成功 - [x] README 可指导复现 - [x] 本文件记录真实测试过程(无伪造) ## Sources - QMD releases: https://api.github.com/repos/tobi/qmd/releases - QMD v1.0.7 README: https://raw.githubusercontent.com/tobi/qmd/v1.0.7/README.md - QMD v1.0.7 llm.ts: https://raw.githubusercontent.com/tobi/qmd/v1.0.7/src/llm.ts - QMD v1.0.7 mcp.ts: https://raw.githubusercontent.com/tobi/qmd/v1.0.7/src/mcp.ts - Codex MCP docs: https://developers.openai.com/codex/mcp/ - Claude Code MCP docs: https://docs.anthropic.com/en/docs/claude-code/mcp