Hermes Agent 一周动态-2026-W22:用 SQLite 与 Docker 搭一套可复现的 MCP 调试环境

1. 为什么我要在本地复现 Hermes Agent 的 MCP 调试环境

Hermes Agent 在 2026-W22 这一周的主线动作很集中:SQLite Kanban 稳定性修复、Docker 架构重构、Web 仪表盘体验优化,以及一个还没合并但很关键的 PR——把 Hermes 全部工具通过 MCP 端点暴露出去。对做本地工具链复现的开发者来说,这意味着两件事:一是 SQLite 持久化层现在值得单独拉出来调试,二是 Docker 容器化部署的骨架已经足够稳定,可以拿来搭一套最小可跑环境。

我关心的不是周报里那些提交号,而是能不能把「Hermes Agent + SQLite + Docker + MCP」这套组合在本地跑通,并且每次重建都能复现同样的结果。MCP(Model Context Protocol)本身是让不同客户端调用同一套工具的标准协议,Hermes 如果真把工具链暴露成 MCP 端点,那 Claude Desktop、Cursor 这类客户端就能直接调它的工具。但在 PR #95 合并之前,我们完全可以先用现有能力搭一个可复现的调试环境,把 SQLite 表结构、Docker 编排、MCP 调用链验证这三块拆开跑。

这套环境适合谁:手上有 Hermes Agent 源码或镜像、想验证 MCP 工具调用链、又不想每次手动重建数据库和容器的开发者。下面我会给出 docker-compose 骨架、config.toml 配置、SQLite 初始化脚本,以及一次完整的 MCP 调用验证动作。目标很明确——把周报里的更新变成你本地能跑通的最小环境。

2. 前置准备:TaoToken 接入与 Hermes 环境依赖

在动手搭 Docker 之前,先把模型接入这一层理清楚。Hermes Agent 本身是工具链框架,真正跑推理还是要接一个兼容 OpenAI 协议的端点。我这边用的是 TaoToken 的 API 来做模型调用,它的接口地址是https://taotoken.net/api,兼容 OpenAI 的/v1/chat/completions格式,Hermes 的 provider 配置里直接填 base_url 就能接上。

你需要先去控制台拿一个 API Key。打开https://taotoken.net/console,登录后在 API Keys 页面创建一个新 Key,复制出来备用。这个 Key 后面会写进 Hermes 的 config.toml,或者通过环境变量注入到 Docker 容器里。

如果你只是想先验证模型能不能通,可以用模型对话页面直接测一条请求:https://taotoken.net/model-chat。但我们要做的是 MCP 调试环境,所以重点还是放在本地容器编排上。

环境依赖清单:

  • Docker 24+ 和 docker compose v2(docker compose version能输出即可)
  • SQLite 3.40+(容器内自带,本地调试可选装)
  • Hermes Agent 源码或镜像(本文按源码挂载方式写,镜像方式同理)
  • 一个可用的 TaoToken API Key

注意:不要把 API Key 硬编码进 docker-compose.yml 提交到仓库。用.env文件加env_file引用,或者用 Docker secrets。下面示例里我用.env方式。

3. 可复制配置:docker-compose 与 config.toml 骨架

3.1 docker-compose.yml

这份编排把 Hermes gateway、SQLite 数据卷、MCP 调试端口三块拆开。SQLite 文件放在命名卷里,容器重建不会丢数据,但每次docker compose down -v又能干净重来,保证可复现。

version: "3.9" services: hermes-gateway: image: hermes-agent:local build: context: . dockerfile: Dockerfile container_name: hermes-gateway env_file: - .env environment: - HERMES_DB_PATH=/data/hermes.db - HERMES_MCP_ENABLED=true - HERMES_MCP_PORT=8765 - HERMES_LOG_LEVEL=debug volumes: - hermes-data:/data - ./config.toml:/app/config.toml:ro - ./init_db.sql:/app/init_db.sql:ro ports: - "8648:8648" # Web 仪表盘 - "8765:8765" # MCP 端点 command: > sh -c "sqlite3 /data/hermes.db < /app/init_db.sql && hermes gateway run --supervised" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8648/health"] interval: 10s timeout: 3s retries: 5 volumes: hermes-data:

这里有几个点对应本周的 Docker 提交:gateway run --supervised对应 s6 镜像内自动重定向到督进程模式那条改动,stdout 日志会 tee 到docker logs,所以排障时直接docker logs hermes-gateway就能看到 gateway 输出。Web 仪表盘端口 8648 对应本周新增的可折叠侧边栏那批 Web UI 迭代。

3.2 config.toml

config.toml 里配 provider、MCP 端点、SQLite 路径。provider 这块接 TaoToken 的 OpenAI 兼容端点。

[provider.taotoken] type = "openai_compatible" base_url = "https://taotoken.net/api" api_key_env = "TAOTOKEN_API_KEY" default_model = "gpt-4o-mini" max_context = 128000 [gateway] host = "0.0.0.0" port = 8648 log_level = "debug" [mcp] enabled = true port = 8765 expose_tools = ["shell", "file_read", "file_write", "sqlite_query"] [database] path = "/data/hermes.db" journal_mode = "WAL" secure_delete = true cell_size_check = true

journal_mode = "WAL"和secure_delete、cell_size_check这三个参数直接对应本周 Kanban SQLite 稳定性修复里的fix: secure_delete + cell_size_check 防止撕裂写入和fix: never silently downgrade WAL to DELETE on transient EIO。在本地调试环境里显式打开,能提前暴露写入可靠性问题。

3.3 .env 文件

TAOTOKEN_API_KEY=sk-你的key HERMES_YOLO_MODE=false

HERMES_YOLO_MODE对应本周安全 PR #7994 里提到的「import 时缓存 HERMES_YOLO_MODE 以防止子进程绕过检查」。本地调试建议保持 false,避免工具链在无审批情况下执行危险命令。

4. SQLite 表结构初始化脚本

Hermes 的 Kanban 任务队列和 MCP 工具调用记录都落在 SQLite 里。下面这份 init_db.sql 建三张表:任务队列、工具调用日志、MCP 会话。字段设计参考了本周 Kanban 稳定性修复关注的写入场景。

PRAGMA journal_mode = WAL; PRAGMA secure_delete = ON; PRAGMA cell_size_check = ON; PRAGMA synchronous = NORMAL; CREATE TABLE IF NOT EXISTS kanban_tasks ( id INTEGER PRIMARY KEY AUTOINCREMENT, task_uuid TEXT NOT NULL UNIQUE, title TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'pending', payload TEXT, worker_id TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, grace_until DATETIME ); CREATE INDEX IF NOT EXISTS idx_kanban_status ON kanban_tasks(status, updated_at); CREATE TABLE IF NOT EXISTS tool_invocations ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id TEXT NOT NULL, tool_name TEXT NOT NULL, args_json TEXT, result_json TEXT, duration_ms INTEGER, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_tool_session ON tool_invocations(session_id, created_at); CREATE TABLE IF NOT EXISTS mcp_sessions ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id TEXT NOT NULL UNIQUE, client_name TEXT, connected_at DATETIME DEFAULT CURRENT_TIMESTAMP, last_ping DATETIME );

grace_until字段对应本周fix: add grace period 改善崩溃 worker 检测的误判。worker 崩溃后不会立刻被回收,而是等 grace period 过期,避免误判正在执行的长任务。

初始化动作在 docker-compose 的 command 里已经串好:容器启动时先跑sqlite3 /data/hermes.db < /app/init_db.sql,再启动 gateway。这样每次docker compose up都是幂等的,CREATE TABLE IF NOT EXISTS保证重复执行不报错。

5. 验证请求:跑通一次 MCP 调用链

5.1 启动环境

docker compose up -d --build docker compose logs -f hermes-gateway

看到MCP endpoint listening on 0.0.0.0:8765和gateway supervised mode active就算起来了。Web 仪表盘在http://localhost:8648,打开能看到可折叠侧边栏。

5.2 验证 SQLite 写入

先进容器确认表建好了:

docker compose exec hermes-gateway sqlite3 /data/hermes.db ".tables"

应该输出kanban_tasks mcp_sessions tool_invocations。再插一条测试任务:

docker compose exec hermes-gateway sqlite3 /data/hermes.db \ "INSERT INTO kanban_tasks (task_uuid, title, status) VALUES ('test-001', 'mcp smoke test', 'pending');"

5.3 验证 MCP 端点

MCP 走的是 JSON-RPC over HTTP。用 curl 发一条tools/list请求:

curl -s -X POST http://localhost:8765/mcp \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {} }' | jq .

预期返回里能看到shell、file_read、file_write、sqlite_query四个工具,对应 config.toml 里expose_tools的配置。这一步验证的是 PR #95 想做的事——把 Hermes 工具暴露成 MCP 端点。即使 PR 还没合并,本地这套配置也能让你先跑通调用链。

5.4 验证一次工具调用

调sqlite_query工具查刚才插的任务:

curl -s -X POST http://localhost:8765/mcp \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "sqlite_query", "arguments": { "sql": "SELECT task_uuid, title, status FROM kanban_tasks WHERE task_uuid = ?", "params": ["test-001"] } } }' | jq .

返回里result.content[0].text应该包含test-001和mcp smoke test。同时去查tool_invocations表,应该多了一条记录:

docker compose exec hermes-gateway sqlite3 /data/hermes.db \ "SELECT tool_name, duration_ms FROM tool_invocations ORDER BY id DESC LIMIT 1;"

到这里,SQLite 持久化、Docker 容器化、MCP 调用链三块都验证过了。整个过程从docker compose up到工具调用返回,可复现,重建环境只需docker compose down -v && docker compose up -d。

6. 本篇常见错排查

容器启动后 8648 端口连不上:先看docker compose logs hermes-gateway里有没有gateway run的报错。如果是 s6 镜像,确认 command 里带了--supervised,否则 gateway 可能以前台模式跑但没绑定到 0.0.0.0。检查 config.toml 里host = "0.0.0.0"而不是127.0.0.1。

SQLite 报database is locked:WAL 模式下多连接写入会排队,但如果看到 locked,先确认journal_mode真的是 WAL。进容器跑sqlite3 /data/hermes.db "PRAGMA journal_mode;",返回wal才对。如果返回delete,说明某次 I/O 错误触发了降级——这正是本周fix: never silently downgrade WAL to DELETE on transient EIO要修的问题。本地环境可以重启容器重新初始化。

MCP 端点返回 404 或 connection refused:确认HERMES_MCP_ENABLED=true和HERMES_MCP_PORT=8765都注入了容器。docker compose exec hermes-gateway env | grep MCP能查。另外确认 ports 映射里 8765 没被占用,lsof -i :8765看一下。

工具调用返回tool not found:config.toml 里expose_tools列表和实际注册的工具名要对上。Hermes 内部工具名可能是sqlite.query这种带命名空间的,MCP 暴露时会转成sqlite_query。如果对不上,先调tools/list看实际暴露了哪些名字,再按返回的名字调。

API Key 没生效导致模型调用 401:检查.env里TAOTOKEN_API_KEY有没有被 docker compose 读到。docker compose exec hermes-gateway env | grep TAOTOKEN确认。如果 Key 是对的但还 401,去https://taotoken.net/api-keys确认 Key 状态和额度。

上下文污染导致 MCP 调用结果串味:本周 P1 bug #33670 提到 v0.14.0 会把历史回复碎片回注到新请求。如果你在同一个 session 里连续调多个工具,发现返回结果混入了上一轮的文本,那就是这个回归问题。本地调试的规避方式是每次验证用新的session_id,或者在 config.toml 里显式关掉 session 历史注入(如果版本支持)。这个 bug 在 v0.12.0 没有,v0.14.0 才出现,怀疑是 PromptAssembler 重构引入的。

7. 把周报更新变成可跑通的最小环境

这套环境跑通之后,你手上就有了一个可复现的 MCP 调试底座。SQLite 表结构对应本周 Kanban 稳定性修复关注的写入场景,Docker 编排对应 s6 督进程模式和日志 tee 的改动,MCP 端点对应 PR #95 想暴露的工具链。每次周报有新提交,你都可以在这套环境里拉最新代码重建容器,验证改动是否影响工具调用链。

如果你要长期跑编码类 Agent 任务,建议把模型接入换成更稳定的方案。TaoToken 的 Coding Plan 页面有按周期计费的选项,适合需要持续调用模型的场景:https://taotoken.net/coding-plan。接入文档在https://taotoken.net/doc,里面有 OpenAI 兼容端点的完整参数说明。API Key 管理还是走https://taotoken.net/api-keys。

本地调试环境的价值在于可复现。docker compose down -v && docker compose up -d这一条命令能让你在任何时候回到干净状态,SQLite 初始化脚本保证表结构一致,MCP 调用验证脚本保证工具链没断。周报里的提交号会变,但这套验证动作不变。