内容
# mcp-telemetry
[](https://github.com/arnavranjan005/mcp-telemetry/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/mcp-telemetry-sdk)
[](https://www.npmjs.com/package/mcp-telemetry-server)
[](LICENSE)
**用于 AI 代理的 Socket.IO。** 仅需几行代码即可为任何 MCP 服务器的工具调用添加仪器,任何监视的 MCP 客户端(Claude Code、Cursor 或您自己的工具)都可以获得实时的结构化进度 — 无需轮询,无需上下文泛滥的工具调用。
```
您的 MCP 服务器 mcp-telemetry 服务器 代理
───────────────── ──────────────────── ─────
mcp-telemetry-sdk
job.stepStart('build')
│
│ 本地套接字(队列,持久连接)
▼
收集器接收事件
存储更新作业状态
│
│ MCP 通知/进度
▼
telemetry_subscribe 工具 Claude Code
将事件推送到代理 → 看到内联
直播状态
```
## 为什么存在
MCP 工具调用是同步的:代理调用工具,等待,获取结果。对于任何长时间运行的操作,这会留下两个不好的选择 — 阻塞整个调用而没有可见性,或者让代理以循环轮询状态工具,这会用重复的工具调用淹没对话,并因没有新信息而浪费上下文。
MCP 确实有一种合法的方式让服务器在调用过程中推送更新:`notifications/progress`,键控到飞行中的请求的 `progressToken` 上。但是,每个 MCP 服务器作者最终都会重新实现相同的管道 — 提取令牌,连接定时器,跟踪输出,在完成后清理。`mcp-telemetry` 就是这些管道,一旦实现,加上一个配套服务器,以便在完全不同的会话中监视作业。
## 如何组合
两个软件包,每个软件包一个作业:
| 软件包 | 使用者 | 功能 |
|---|---|---|
| [`mcp-telemetry-sdk`](packages/sdk) | MCP 服务器作者 | 导入它,从工具处理程序中调用 `job.start()` / `.stepDone()` / `.log()`。零运行时依赖 — 它只是一个具有持久、队列连接的套接字写入器。 |
| [`mcp-telemetry-server`](packages/server) | 代理用户 | 您注册一次的 MCP 服务器。公开 `telemetry_subscribe`(阻塞并流式传输作业的实时进度),以及 `telemetry_jobs`/`telemetry_job_status` 用于实时查询。 |
这两个软件包在架构上是独立的 — SDK 从未调用任何 MCP 工具,服务器从未导入您的工具代码。它们只在本地套接字上相遇,因此具有断开连接的生成器不会导致任何问题, overload 的收集器也不会阻塞您的工具调用。
## 快速入门
### 1. 为您的 MCP 服务器配备仪器(`mcp-telemetry-sdk`)
```bash
npm install mcp-telemetry-sdk
```
```js
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { MCPTelemetry } from 'mcp-telemetry-sdk';
const server = new McpServer({ name: 'my-deploy-server', version: '1.0.0' });
const telemetry = new MCPTelemetry(); // 零配置 — 从 cwd 派生套接字路径
server.tool('deploy', { env: z.string() }, async ({ env }) => {
const job = telemetry.createJob({ task: `deploy ${env}` });
job.start();
job.stepStart('build');
await runBuild();
job.stepDone('build', { duration: 2100 });
job.stepStart('test');
const passed = await runTests();
if (!passed) {
job.stepFailed('test', '3 tests failed');
await job.done(1);
return { content: [{ type: 'text', text: 'Deploy failed at test stage' }] };
}
job.stepDone('test');
await job.done(0);
return { content: [{ type: 'text', text: 'Deployed successfully' }] };
});
```
这就是整个集成。如果没有人在套接字上监听,每个调用都是快速的无操作 — 您的服务器在有或没有收集器的情况下表现相同。
### 2. 从代理监视(`mcp-telemetry-server`)
```bash
npm install -g mcp-telemetry-server
```
将其注册为 MCP 服务器,与您已有的仪器一起:
```json
{
"mcpServers": {
"deploy": { "command": "npx", "args": ["-y", "deploy-mcp"] },
"telemetry": { "command": "npx", "args": ["-y", "mcp-telemetry-server"] }
}
}
```
然后,在您的代理会话中:
```
You: deploy to staging
Agent: calls the deploy tool, then telemetry_subscribe with the returned job id
▶ deploy staging
↻ build
✓ build (duration=2100)
↻ test
✓ test
✓ job done (exit 0)
Agent: "Deployed to staging successfully."
```
无需轮询,无需单独的终端,无需上下文泛滥的工具调用 — 一个 `deploy` 调用加上一个 `telemetry_subscribe` 调用,无论作业运行多长时间。
## API 参考
### `mcp-telemetry-sdk`
**`new MCPTelemetry(opts?)`**
创建 telemetry 客户端。`opts.socketPath` 覆盖默认路径(通过 `getSocketPath()` 从 `process.cwd()` 派生)。拥有一个持久的、队列化的连接,由它创建的每个作业共享。
**`telemetry.createJob({ id?, task })` → `JobHandle`**
开始跟踪作业。`id` 默认值为自动递增的 `job-N`。
**`telemetry.disconnect()`**
关闭底层连接。在服务器关闭时调用,如果您希望干净地关闭而不是让它空闲。
| `JobHandle` 方法 | 发出 | 备注 |
|---|---|---|
| `start()` | `job_start` | 在工具处理程序开始时调用一次。 |
| `stepStart(name, meta?)` | `step_start` | `name` 是任何字符串 — `'build'`、`'implement'`,或适合您领域的任何字符串。 |
| `stepDone(name, meta?)` | `step_done` | `meta` 是任意键/值数据(在 `telemetry_subscribe` 的实时输出中显示)。 |
| `stepFailed(name, reason?)` | `step_failed` | |
| `log(line, stream?)` | `log` | `stream` 是 `'stdout' \| 'stderr'`,可选。快速日志行会在推送实时之前被服务器合并 — 请参见下文。 |
| `cost(amount, meta?)` | `cost` | `amount` 以美元为单位。 |
| `done(exitCode?)` | `job_done` | **异步。** 这是终端事件 — 之后不能发送其他事件,因此它会积极地重试传递长达 1.5 秒,而不是依赖未来的 `send()` 来恢复暂时的连接故障。 可以在不等待的情况下安全调用。 |
`getSocketPath(root?)` 也被导出,用于需要独立派生生产者和服务器将计算的相同路径的高级情况。
### `mcp-telemetry-server`
公开三个 MCP 工具:
| 工具 | 行为 |
|---|---|
| `telemetry_subscribe({ jobId?, timeoutMs? })` | **阻塞** 并流式传输给定作业(或下一个要启动的作业,如果省略 `jobId`)的实时 `notifications/progress`,直到它完成或 `timeoutMs` 结束(默认为 5 分钟)。这是您的代理调用以监视作业的工具。 |
| `telemetry_jobs()` | 列出服务器当前已知的所有作业,包含状态和成本。 |
| `telemetry_job_status({ jobId })` | 一个作业的完整状态 — 每个步骤、成本和任何失败原因。 |
## 比较
该领域存在三种真正不同的方法 — 它们都不能解决相同的问题:
| | **mcp-telemetry** | 异步作业运行器 | 完成通知器 | OpenTelemetry MCP 仪器 |
|---|---|---|---|---|
| 机制 | 推送(`notifications/progress`) | 轮询(自己调用状态/尾部工具) | 推送,但仅在完成时(webhook/声音) | 跟踪/指标到可观察性后端 |
| 实时逐步进度 | 是 | 否 — 您询问,它回答 | 否 — 只有“完成” | 否 — 事后分析 |
| 从不同会话监视 | 是 | 否 — 与启动它的会话绑定 | 部分(webhook 可以在任何地方触发) | 不适用 — 不面向代理 |
| 适用对象 | 任何 MCP 服务器作者 + 任何代理 | 需要异步 shell 执行的任何人 | 想要完成 ping 的任何人 | 监视自己部署的服务器操作员 |
**与 [SEP-1686 (MCP Tasks)](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1686) 的关系:**MCP 规范自己的答案 — **已接受** 进入规范(不仅是提议),给予请求一个持久的任务句柄(`taskId`)和 `tasks/get` 轮询以及一个在整个任务生命周期中有效的 `progressToken`。这是最终的“正确”修复,由现实生产案例支持(亚马逊在 SEP 中引用了医疗保健数据管道、CI/CD 包装和多代理系统)。 捕获:它被标记为 `awaiting-sdk-change` — 标准已经确定,但客户端/服务器 SDK 尚未实现,因此它不能被今天依赖。 `mcp-telemetry` 解决了相同的问题,现在,在当前的稳定协议上 — 一个您可以今天采用的工作桥,并在您依赖的 SDK 中实现任务时将其退休,不是一个竞争标准。
## 设计注意事项
- **生产者→服务器连接是一个持久的、队列化的套接字**,不是每个事件一个连接。事件在连接后按顺序刷新;如果在连接建立之前到达的突发事件,则排队并在建立后按顺序交付。
- **交付是尽力而为的,不是保证的**,除了一个例外:`done()`。其他事件如果收集器无法访问则会静默丢失,这是故意的(telemetry 永远不应该能够阻塞或崩溃您的实际工具调用)。`done()` 是一个事件,积极重试长达一段有限的时间,因为它通常是作业发送的最后一件事。
- **`telemetry_subscribe` 只显示实时转发事件** — 它不会重放历史。如果作业在您订阅之前已经完成,请改用 `telemetry_job_status`。
- **这不是分布式作业队列。** 没有跨收集器重启的持久性,没有跨机器交付,也没有上述描述的重试策略。如果您需要这些,您需要一个真正的消息队列 — 这只是为了“监视本地 MCP 工具调用实时”而做,什么都不多。
## 开发
```bash
git clone https://github.com/arnavranjan005/mcp-telemetry.git
cd mcp-telemetry
npm install
npm run build
npm test
```
参见 [CONTRIBUTING.md](CONTRIBUTING.md) 以获取完整的设置、monorepo 布局和 PR 期望。
## License
[MIT](LICENSE) © [Arnav Ranjan](https://github.com/arnavranjan005)