内容
<div align="center">
# ⇄ 调度
**`调度` 将您的整个 MCP 服务器群组置于一个端点之下 — 并使其保持活跃。**


-black)


[是什么 & 为什么](#是什么--为什么) · [工作原理](#工作原理) · [验证内容](#验证内容) · [快速开始](#快速开始) · [功能](#功能) · [审计追踪](#审计追踪) · [布局](#布局)
</div>
---
## 是什么 & 为什么
MCP 服务器后台可能会宕机。当一个后台服务器(momento、serval等)在会话过程中崩溃或断开连接时,客户端会**丢失所有工具**,直到手动重新连接 `/mcp`。由于 Claude Code 为每个配置的 MCP **每个会话**启动 — 包括预热备件 — 一个像浏览器这样的有状态服务器会启动两到三次:重复进程、端口竞争、分割状态。
`调度` 修复了两者。在连接处,它是一个客户端连接到的 stdio MCP 服务器;在此之后,它**生成、命名空间、多路复用和监督**您的后台服务器。崩溃的后台服务器将被透明地重新启动 — 客户端连接永远不会断开。无论 Claude 打开多少会话,恰好**一个**后台服务器舰队运行。
> **客户端永远不应看到后台服务器宕机。**
这就是整个产品:您从任何网关获得的聚合,加上两个网关通常**不做的事情** — **自我修复** 和 **防篡改审计追踪** — 约 270 行无依赖关系的 Node 代码。
## 工作原理
- **一个端点,多台服务器。** 每个后台服务器的工具都在 `backend.tool` 命名空间下公开(`momento.search`、`serval.navigate`),路由到所属的子服务器。**资源和提示** 也会聚合(按后台服务器能力分区):资源按其原始 URI 路由,提示类似于工具命名空间。
- **清晰的子工具。** 客户端标记每个调用的*服务器* — 因此一个服务器后面的舰队都将读取为“调度”。每个代理工具/提示都带有规范 `title`(`momento · search`)和 `[backend]`-prefixed 描述;`marshal.recent` 工具报告实际运行的后台工具。
- **自我修复。** 崩溃的后台服务器将被重新启动(300毫秒延迟),重新初始化,其工具将刷新;调度发出 `notifications/tools/list_changed` 以便客户端更新。客户端连接永远不会中断。后台服务器若**挂起**(而不是退出)而不是退出,会被每个调用的超时时间(`MARSHAL_CALL_TIMEOUT`,默认为 120 秒)捕获,以免客户端永远阻塞。
- **单例。** Claude 预热备用会话,因此它可能会启动调度多次。第一个成为**主节点**(拥有后台服务器 + 审计,监听 `~/.marshal/marshal.sock`);任何后来的节点都成为一个薄**代理**,将 stdio ⇄ 主节点并生成无后台服务器。一个舰队,一个审计写入器 — 无论会话次数多少。
- **热添加/删除。** 主节点监视 `marshal.config.json`;编辑它并后台服务器会实时启动或停止,无需重启。人类授权(配置文件 — 而不是一个注入代理可以滥用的代理调用工具)。
## 验证内容
调度的**机制通过可证伪的探针验证**,您可以运行它们(`node <probe>.mjs`):
| 探针 | 验证 |
|---|---|
| `probe.mjs` | **自我修复** — 杀死后台服务器;工具在重新启动后存活并且调用有效 |
| `singleton-probe.mjs` | **单例** — 2 调度 → 1 后台服务器舰队;代理通过主节点提供服务 |
| `audit-probe.mjs` | **审计** — 编写行,参数**已编辑**,哈希链有效 |
| `rotation-probe.mjs` | **旋转** — 日志旋转 + 剪切;链在段之间不断裂 |
| `hot-add-probe.mjs` | **热添加** — 编辑配置 → 后台服务器出现/消失,无需重启 |
| `introspect-probe.mjs` | **可观察性** — 工具携带 `title` + `[backend]` 描述;`marshal.recent` 报告实际的子工具 |
| `timeout-probe.mjs` | **超时** — 挂起的后台服务器超时并出现错误,而不是无限期阻塞 |
| `resources-probe.mjs` | **资源/提示** — 后台服务器资源 + 提示聚合和路由 |
未验证的内容:任何比较性声明(比网关 *X* 更快/更轻/更好)。调度适用于单个机器 + stdio MCP;如果您需要 HTTP 传输、身份验证、多租户或多机器扩展,请选择一个完整的网关(ContextForge、MetaMCP)。在发布数字之前,请将效率或优越性声明视为未经验证。
## 快速开始
```bash
git clone https://github.com/campbellcharlie/marshal.git ~/src/marshal
cd ~/src/marshal
cp marshal.config.example.json marshal.config.json # 然后设置后台服务器路径
```
将其连接到 Claude Code 作为**单个** MCP 服务器(替换直接后台服务器条目):
```bash
claude mcp add -s user marshal /opt/homebrew/bin/node -- ~/src/marshal/marshal.mjs
# 重启 Claude Code
```
`marshal.config.json`(gitignored — 机器特定):
```json
{ "backends": [ { "name": "momento", "command": "node", "args": [".../momento/dist/server.js"] } ] }
```
旋钮(env):`MARSHAL_CALL_TIMEOUT`(120 秒)· `MARSHAL_AUDIT_MAX`(5 MB)· `MARSHAL_AUDIT_KEEP`(10)· `MARSHAL_AUDIT` · `MARSHAL_SOCK` · `MARSHAL_CONFIG`.
## 功能
| 功能 | 功能描述 | 验证 |
|---|---|---|
| **聚合** | 多个 stdio MCP 服务器在一个端点后面 — 工具、资源和提示命名空间 | ✅ |
| **清晰的子工具** | 每个工具的 `title` + `[backend]` 描述;`marshal.recent` 显示实际的子工具 | ✅ |
| **自我修复** | 崩溃的后台服务器被透明地重新启动;客户端永远不会断开连接 | ✅ |
| **调用超时** | 挂起的后台服务器调用超时而不是阻塞客户端 | ✅ |
| **单例** | N 调度实例 → 1 后台服务器舰队(主节点 + 薄代理) | ✅ |
| **审计追踪** | 哈希链接,编辑, 每行 JSONL 工具调用 | ✅ |
| **旋转** | 基于大小的旋转 + 保留;链在段之间不断裂 | ✅ |
| **热添加/删除** | 编辑配置 → 后台服务器实时启动/停止,无需重启 | ✅ |
## 审计追踪
每个调用都通过调度的一个检查点,因此它将每个事件记录到一个追加的 JSONL 行中到 `~/.marshal/audit.jsonl` (`$MARSHAL_AUDIT`) — `call`(工具),`read`(资源),`prompt`(提示获取),
以及后台服务器生命周期(`backend_ready`/`_exit`/`_add`/`_remove`):
```json
{"ts":"…","event":"call","backend":"serval","tool":"navigate","arg_keys":["url:str[42]"],"ok":true,"ms":412,"result_bytes":1840,"prev":"7c9c34…"}
```
- **已编辑** — 参数*键 + 类型/长度*,而非原始值(日志值本身将是一个信息泄露表面)。
- **哈希链接** — 每行的 `prev` = 前一行的 sha256,因此日志是**防篡改**的;链在旋转过程中不断裂。
- **旋转** 在 `MARSHAL_AUDIT_MAX` 处进入时间戳段,保持 `MARSHAL_AUDIT_KEEP`.
<details>
<summary><strong>已知限制(v0.1)</strong></summary>
- **超时按调用,而不是挂起触发重启** — 调用超时(`MARSHAL_CALL_TIMEOUT`),但调度尚未杀死并重启一个持续无响应的后台服务器;仅*退出*触发重启。
- **仅stdio传输** — 无 HTTP/SSE,身份验证或多租户(按设计;使用完整网关如果需要它们)。
- **主节点死亡 → 短暂间隙** — 代理在主节点丢失时退出;Claude 重新启动并提升一个(数秒)。
- **`fs.watch` 是尽力而为** — 热添加是一个方便的功能,而不是每个文件系统的保证。
</details>
## 布局
```
marshal.mjs # 聚合器 + 监督器(零依赖,~270 行)
marshal.config.example.json # 复制 → marshal.config.json(gitignored)
probe.mjs # 自我修复探针
singleton-probe.mjs # 主/代理单例探针
audit-probe.mjs # 审计链 + 编辑探针
rotation-probe.mjs # 旋转 + 保留探针
hot-add-probe.mjs # 实时配置协调探针
introspect-probe.mjs # 标题/描述 + marshal.recent 可观察性探针
timeout-probe.mjs # 调用超时探针
resources-probe.mjs # 资源 + 提示聚合探针
fake-backend.mjs # 最小MCP后台服务器装置,用于上述探针
serval-probe.mjs # 隔离的serval后台服务器检查
check-fleet.mjs # 聚合健全性(所有后台服务器命名空间)
```
## 许可证
[MIT](LICENSE) © 2026 Charlie Campbell