Skip to content

hub-channel.ts 在 Hub 重启后不自动重连,导致 MCP 断开且消息持续丢失 #11

@wangviola7

Description

@wangviola7

问题描述

Hub 进程重启后(无论是崩溃恢复还是手动重启),hub-channel.ts(MCP server)不会自动重连到新的 Hub 实例。结果:

  1. Claude Code 收到 MCP 断开通知
  2. 新的 Hub 进程没有任何已注册的 Claude Code 实例
  3. 所有后续入站消息都打印 (无在线实例) 并被丢弃
  4. 用户必须手动重启 Claude Code 会话才能恢复

复现步骤

  1. 正常启动 Hub + Claude Code 会话(MCP 连接正常)
  2. 重启 Hub(pkill -f forge-hub && bun run start,或 Hub 自动崩溃恢复)
  3. 从微信/飞书发送消息
  4. 观察:Hub 日志显示 (无在线实例),Claude Code 收不到消息

日志证据

hub.log(Hub 重启后收到消息,无实例):

[2026-04-26 10:21:56] [hub] 收到 SIGTERM,正常关闭
[2026-04-26 10:21:58] [hub] Forge Hub v0.2.0 · PID 32130 · 启动完成
[2026-04-26 15:45:54] [hub:wechat] ← viola: ...消息内容...
[2026-04-26 15:45:54] [hub] ← [wechat] viola: ... (无在线实例)

hub-client.log(hub-channel.ts MCP server 最后日志停留在 Hub 被 SIGTERM 的时刻):

[2026-04-26T02:21:56.840Z] [forge-86486] INFO 🔐 permission_request ijgta 已转发给 hub
# 此后无任何日志——hub-channel.ts 已断开但未重连

根本原因

hub-channel.ts 是由 Claude Code 以子进程方式启动的 MCP server。当底层 Hub HTTP server(端口 9900)重启时:

  • Hub 进程变为新 PID,之前注册的实例记录全部清空
  • hub-channel.ts 没有检测 Hub 重启的机制(无心跳、无重连逻辑)
  • Claude Code 检测到 MCP server 异常,标记为 "disconnected"
  • 即使 hub-channel.ts 进程本身还在运行,也无法向 Hub 重新注册

建议修复方案

方案 A(推荐):在 hub-channel.ts 中加入心跳 + 自动重连

// hub-channel.ts 伪代码
async function healthCheckLoop() {
  while (true) {
    await sleep(15_000);
    try {
      const res = await fetch('http://localhost:9900/health');
      const data = await res.json();
      if (data.hub.pid !== lastKnownPid) {
        // Hub 已重启,重新注册
        lastKnownPid = data.hub.pid;
        await reregisterInstance();
      }
    } catch {
      // Hub 暂时不可达,等待下次重试
    }
  }
}

方案 B:Hub 提供 SSE 端点,hub-channel.ts 订阅

Hub 暴露 GET /events(Server-Sent Events),hub-channel.ts 订阅。Hub 重启后 SSE 连接断开,hub-channel.ts 检测到断连后重新连接并重新注册。

临时 Workaround

用户在 Claude Code 终端中关闭并重新打开灯塔会话(claude),或重启 Claude Code IDE,hub-channel.ts 会随新会话重启并注册到新 Hub 实例。

环境

  • Hub: v0.2.0
  • 平台: macOS 26.3 (Darwin 25.3.0)
  • 触发场景: Hub 手动重启 / 端口占用强制重启

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions