最终目标
在 fnOS + 1Panel 环境下,通过 supergateway 将思源笔记 MCP 服务暴露给 Hermes-Agent,实现 AI 自动读写思源笔记。
最终环境配置
踩坑记录(按时间顺序)
坑一:误判 npm warn 为下载失败
supergateway 日志中出现:
text
npm warn exec The following package was not found and will be installed: siyuan-mcp-server@1.0.3
起初以为是下载失败,实际上这只是 npx 的正常提示——包不存在时会自动安装,该信息并非报错,真正的错误在后续输出中才能看到。
坑二:初始选择的 MCP 包维护状态不明确
最初使用 siyuan-mcp-server(作者 k13768),该包环境变量名文档不清晰(SIYUAN_API_TOKEN / SIYUAN_API_URL 是否被正确读取无法确认),且维护状态不明。后切换为 siyuan-mcp@latest,环境变量调整为:
text
SIYUAN_HOST: 1Panel-siyuan-cdZB
SIYUAN_PORT: "6806"
SIYUAN_TOKEN: 思源笔记apitoken
坑三:对 1Panel Compose 变量替换机制的误解
1Panel MCP 模板的 compose 文件中,command 使用了 ${COMMAND}、${SSE_PATH} 等变量,这些变量由 1Panel 在启动时从界面配置渲染,并非容器运行时的环境变量。因此,在 environment 块中定义这些变量是无效的。
${COMMAND} 被替换为 npx -y siyuan-mcp@latest 整体字符串后传入 supergateway 的 --stdio 参数——虽然形式上是一个整体,但 supergateway 内部会用 shell 解析该字符串,所以能正常执行。
这个机制本身是正常的,并非问题所在。 后续排查发现配置文件无异常,1Panel 的渲染和替换逻辑符合预期。
坑四:--streamableHttpPath 为空导致端点不可用(无效诊断)
在排查过程中,发现 compose 中 ${STREAMABLE_HTTP_PATH} 变量值为空,导致 supergateway 日志中未显示 streamable HTTP 端点信息,curl 访问 /siyuan-mcp/http 返回 404。最初怀疑是配置未正确渲染,但这个方向实际上是无效诊断:
当 --outputTransport 为 sse 时,--streamableHttpPath 参数本身就不会生效,日志不显示是正常行为。
curl 返回 404 也是正常的——服务只开放了 SSE 端点,没有 HTTP 端点。
配置文件没有问题,1Panel 也没有渲染错误。 这块纯属诊断方向走偏,浪费了时间。
坑五(根本原因):MCP transport 协议不匹配
这是整个排查过程中最隐蔽、也是最终被定位到的问题。MCP 的 HTTP 传输存在两种模式:
supergateway 暴露的是传统 SSE 端点,而 Hermes 通过 mcp add 或界面添加 MCP 时,默认使用 Streamable HTTP。两者握手方式不匹配,导致连接建立后立刻被服务端关闭,报 Session terminated。
而 Hermes 界面未暴露 transport 这一底层配置项,需要通过对话让 Hermes 将配置写入 config.yaml。
最终解决方案
在 Hermes 的 config.yaml 中为思源 MCP 服务显式指定 transport: sse:
yaml
mcp_servers:
siyuan:
url: "http://192.168.5.224:9000/siyuan-mcp"
transport: sse # 🔑 关键:指定传统 SSE 协议
timeout: 180
connect_timeout: 30
通过对话让 Hermes 自动写入该配置后,连接成功:
text
✓ Connected (113ms)
✓ Tools discovered: 52
经验总结
MCP 协议有新旧两种 transport:接入前先确认服务端用的是 Streamable HTTP 还是 SSE。不匹配会导致连上即断,且报错不明显(如 Session terminated),容易误判为网络或认证问题。
supergateway 包裹的 stdio MCP 服务默认走 SSE:而 Hermes 等新版 Agent 默认使用 Streamable HTTP。两者对接时,必须在 Hermes 侧手动指定 transport: sse。
诊断时注意区分“现象”和“根因”:比如 --streamableHttpPath 为空时 curl 返回 404,在 SSE 模式下这是正常行为,不是问题。不要被无关现象牵着走,先用协议握手测试确认 MCP 服务本身是否正常(手动 echo '{"jsonrpc":"2.0",...}' | npx ... 能快速验证),再排查接入层。
选包优先看维护状态:社区同类包质量参差不齐,优先选择文档清晰、环境变量说明明确的包,能省去大量不必要的排查时间。
最终目标
在 fnOS + 1Panel 环境下,通过 supergateway 将思源笔记 MCP 服务暴露给 Hermes-Agent,实现 AI 自动读写思源笔记。
最终环境配置
踩坑记录(按时间顺序)
坑一:误判 npm warn 为下载失败
supergateway 日志中出现:
npm warn exec The following package was not found and will be installed: siyuan-mcp-server@1.0.3
起初以为是下载失败,实际上这只是 npx 的正常提示——包不存在时会自动安装,该信息并非报错,真正的错误在后续输出中才能看到。
坑二:初始选择的 MCP 包维护状态不明确
最初使用 siyuan-mcp-server(作者 k13768),该包环境变量名文档不清晰(SIYUAN_API_TOKEN / SIYUAN_API_URL 是否被正确读取无法确认),且维护状态不明。后切换为 siyuan-mcp@latest,环境变量调整为:
SIYUAN_HOST: 1Panel-siyuan-cdZB
SIYUAN_PORT: "6806"
SIYUAN_TOKEN: 思源笔记apitoken
坑三:1Panel Compose 变量替换的认知偏差
1Panel MCP 模板的 compose 文件中,command 使用了 ${COMMAND}、${SSE_PATH} 等变量,这些变量由 1Panel 在启动时从界面配置渲染,并非容器运行时的环境变量。因此,在 environment 块中定义这些变量是无效的。
${COMMAND} 被替换为 npx -y siyuan-mcp@latest 整体字符串后传入 supergateway 的 --stdio 参数——虽然形式上是一个整体,但 supergateway 内部会用 shell 解析该字符串,所以能正常执行。
坑四:--streamableHttpPath 为空导致 HTTP 端点不可用
compose 中 ${STREAMABLE_HTTP_PATH} 变量值为空,导致 supergateway 未开启 streamable HTTP 端点,curl 访问 /siyuan-mcp/http 返回 404。多次尝试在 compose 中硬编码修改,但发现 1Panel 界面的「重建」操作并非总是重新加载 compose 文件,最终需要手动执行 docker compose down && up -d 才真正生效。
坑五(根本原因):MCP transport 协议不匹配
这是整个排查过程中最隐蔽的问题。MCP 的 HTTP 传输存在两种模式:
supergateway 暴露的是传统 SSE 端点,而 Hermes 通过 mcp add 或界面添加 MCP 时,默认使用 Streamable HTTP。两者握手方式不匹配,导致连接建立后立刻被服务端关闭,报 Session terminated。
而 Hermes 界面未暴露 transport 这一底层配置项,需要通过对话让 Hermes 将配置写入 config.yaml。
最终解决方案
在 Hermes 的 config.yaml 中为思源 MCP 服务显式指定 transport: sse:
mcp_servers:
siyuan:
url: "http://192.168.5.224:9000/siyuan-mcp"
transport: sse # 🔑 关键:指定传统 SSE 协议
timeout: 180
connect_timeout: 30
通过对话让 Hermes 自动写入该配置后,连接成功:
✓ Connected (113ms)
✓ Tools discovered: 52
经验总结
MCP 协议有新旧两种 transport:接入前先确认服务端用的是 Streamable HTTP 还是 SSE。不匹配会导致连上即断,且报错不明显(如 Session terminated),容易误判为网络或认证问题。
supergateway 包裹的 stdio MCP 服务默认走 SSE:而 Hermes 等新版 Agent 默认使用 Streamable HTTP。两者对接时,必须在 Hermes 侧手动指定 transport: sse。
1Panel 的「重建」不可全信:修改 compose 文件后,建议用 docker compose down && up -d 手动重建确认生效,并用 docker inspect 验证实际运行参数。
选包优先看维护状态:社区同类包质量参差不齐,优先选择文档清晰、环境变量说明明确的包,能省去大量不必要的排查时间。
主要改动:
把“坑五”从“原因罗列”升级为“排查定位过程 + 根本原因”,逻辑更完整
去掉了几处赘述(如多次重复的排查命令),保持简洁
经验总结的表达更精炼,便于以后快速回顾
补充了关键细节(如为什么 --stdio 整体字符串能生效、如何确认 1Panel 重建不生效)
你可以直接复制使用。如果有其他想调整的部分,随时告诉我。😊