内容
<!-- ---
!-- Timestamp: 2026-04-10 18:13:14
!-- Author: ywatanabe
!-- File: /home/ywatanabe/proj/claude-code-telegrammer/README.md
!-- --- -->
<!-- SciTeX Convention: Header (logo, tagline, badges) -->
# 克劳德代码 Telegrammer
<p align="center">
<a href="https://scitex.ai">
<img src="docs/scitex-logo-blue-cropped.png" alt="SciTeX" width="400">
</a>
</p>
<p align="center"><b>自定义 Telegram MCP 服务器 + TUI 自动响应程序,用于将克劳德代码运行为自主 Telegram 代理</b></p>
<p align="center">
<a href="https://badge.fury.io/py/claude-code-telegrammer"><img src="https://badge.fury.io/py/claude-code-telegrammer.svg" alt="PyPI 版本"></a>
<a href="https://claude-code-telegrammer.readthedocs.io/"><img src="https://readthedocs.org/projects/claude-code-telegrammer/badge/?version=latest" alt="文档"></a>
<a href="https://github.com/ywatanabe1989/claude-code-telegrammer/actions/workflows/test.yml"><img src="https://github.com/ywatanabe1989/claude-code-telegrammer/actions/workflows/test.yml/badge.svg" alt="测试"></a>
<a href="https://www.gnu.org/licenses/agpl-3.0"><img src="https://img.shields.io/badge/License-AGPL--3.0-blue.svg" alt="许可证:AGPL-3.0"></a>
</p>
<p align="center">
<a href="https://claude-code-telegrammer.readthedocs.io/">文档</a> ·
<code>pip install claude-code-telegrammer</code>
</p>
---
## 问题与解决方案
<table>
<tr>
<th align="center">#</th>
<th>问题</th>
<th>解决方案</th>
</tr>
<tr valign="top">
<td align="center">1</td>
<td><h4>硬编码路径</h4>官方插件硬编码 <code>~/.claude/</code> 作为其状态目录(<a href="https://github.com/anthropics/claude-code/issues/851">#851</a>),使得无法运行多个机器人或自定义 access.json 的位置。</td>
<td><h4>可配置状态目录</h4>所有状态(数据库、锁、访问配置)都位于 <code>CLAUDE_CODE_TELEGRAMMER_TELEGRAM_STATE_DIR</code> 下。可以运行任意多个机器人,每个机器人都有自己的隔离状态。</td>
</tr>
<tr valign="top">
<td align="center">2</td>
<td><h4>409 冲突崩溃</h4>没有单实例保护机制 - 多个会话同时访问同一个机器人时会收到 409 错误并崩溃(<a href="https://github.com/anthropics/claude-code/issues/1075">#1075</a>)。</td>
<td><h4>基于 PID 的锁</h4>通过 PID 锁文件自动执行单实例保护。第二个实例检测到冲突后会等待而不是崩溃。</td>
</tr>
<tr valign="top">
<td align="center">3</td>
<td><h4>僵尸 CPU 消耗</h4>会话结束后,插件进程会以 100% CPU 运行,需要手动杀死(<a href="https://github.com/anthropics/claude-code/issues/1146">#1146</a>)。</td>
<td><h4>干净的关闭</h4>在 stdin 关闭、SIGTERM 或 SIGINT 时正常退出。没有僵尸进程,不需要手动清理。</td>
</tr>
<tr valign="top">
<td align="center">4</td>
<td><h4>仅限 3 个基本工具</h4>官方插件仅提供发送、获取更新和设置反应 - 没有历史记录、搜索、文件处理或消息编辑。</td>
<td><h4>10 个 MCP 工具</h4>回复、反应、编辑消息、获取历史记录、获取未读消息、标记已读、下载附件、发送文档、搜索消息、获取上下文 - 自主代理所需的一切。</td>
</tr>
<tr valign="top">
<td align="center">5</td>
<td><h4>没有消息持久性</h4>消息在传递后消失。无法搜索过去的对话、跟踪已读状态或从历史记录中构建上下文。</td>
<td><h4>SQLite 消息存储</h4>所有消息都存储在 WAL 模式的 SQLite 中,支持全文搜索、回复线程(reply_to_message_id)、已读/回复跟踪和附件元数据。</td>
</tr>
<tr valign="top">
<td align="center">6</td>
<td><h4>群组无访问控制</h4>基本允许名单 - 没有每个群组的策略,没有配置更改时的热重载。</td>
<td><h4>DM + 群组策略</h4>基于允许名单的访问控制,分别具有 DM 和群聊策略,通过 <code>access.json</code>,在文件更改时热重载(基于 mtime)。</td>
</tr>
<tr valign="top">
<td align="center">7</td>
<td><h4>没有附件支持</h4>无法下载入站文件或将文档上传到聊天中。</td>
<td><h4>完整的附件处理</h4>入站照片、文档、语音、音频和视频会自动下载。通过 <code>send_document</code> 工具上传本地文件。</td>
</tr>
<tr valign="top">
<td align="center">8</td>
<td><h4>会话无人值守时停滞</h4>克劳德代码在权限提示或空闲状态下会停止工作,无法恢复 - 代理直接停止工作。</td>
<td><h4>TUI 看门狗</h4>轮询 GNU Screen 缓冲区,通过模式匹配检测克劳德代码的 TUI 状态,发送按键以自动接受提示并在空闲时重新参与。带有突发限制。</td>
</tr>
</table>
<p align="center"><sub><b>表 1.</b> 官方 Telegram 插件(截至 2026 年 4 月)与 claude-code-telegrammer 解决的 8 个问题。这些问题使得官方插件对于生产自主代理不可用。</sub></p>
### 架构
1. **自定义 Telegram MCP 服务器** (`ts/`) -- 自包含的 Bun + MCP 服务器。10 个工具、SQLite 持久性、允许名单访问控制、附件处理、反应支持。传入的消息会确认 📩。内置的响应策略指示代理立即回复并将繁重的工作委派给后台子代理。
2. **TUI 看门狗** (`lib/`) -- 轮询 GNU Screen 会话,通过模式匹配检测克劳德代码的 TUI 状态,并发送按键以保持代理运行无人值守(自动接受权限提示,在空闲时重新参与)。带有突发限制以防止失控的响应。编排由 [scitex-agent-container](https://github.com/ywatanabe1989/scitex-agent-container) 处理。
<details>
<summary><strong>MCP 工具(10 个)</strong></summary>
| 工具 | 描述 |
|------|-------------|
| `reply` | 在 Telegram 上回复。支持线程(`reply_to`),自动将入站消息标记为已读。入站回复消息引用将被跟踪并转发。 |
| `react` | 添加表情符号反应到消息。入站反应(`message_reaction`)也会作为频道通知传递。 |
| `edit_message` | 编辑以前发送的机器人消息。 |
| `get_history` | 从本地 SQLite 检索聊天记录。 |
| `get_unread` | 列出未读的入站消息,可选过滤 `chat_id`。 |
| `mark_read` | 通过 `chat_id` 或 `message_ids` 标记消息为已读。 |
| `download_attachment` | 下载 Telegram 文件,返回本地路径。 |
| `send_document` | 将本地文件上传到 Telegram 聊天。 |
| `search_messages` | 跨存储的消息进行文本搜索。 |
| `get_context` | 最近的对话格式化为 LLM 上下文的紧凑文本。 |
</details>
### 重要:机器人令牌排他性
此 MCP 服务器**必须**是其配置的 Telegram 机器人令牌的**唯一使用者**。Telegram 机器人 API 允许每个令牌只有一个 `getUpdates` 长轮询连接。
**如果出现重复使用者的情况:**
| 场景 | 症状 | 检测 |
|----------|---------|-----------|
| 两个轮询器同时启动 | 一个获取 409,另一个静默获胜 | 失败者日志中看到 `409 Conflict` |
| 两个轮询器顺序启动 | 两个似乎都有效,但只有一个接收消息 | **无错误** - 另一个轮询器永久获得空响应 |
| 活动 webhook + 轮询器 | 轮询器获取不到任何消息 | **无错误** - Telegram 忽略 `getUpdates` 设置 webhook 时 |
**为什么仅 409 检测是不够的:** Telegram API 不会为所有冲突情况可靠地返回 409。当两个使用者顺序轮询(不重叠)时,两个连接都成功 - 一个简单地接收所有消息,而另一个获取不到任何消息,并且没有任何错误。服务器在启动时执行 `timeout=3` 的预检以捕获重叠的轮询,但这无法检测到顺序情况。
**如果消息未到达:**
1. 检查另一个进程是否正在轮询相同的令牌:`ps aux | grep telegram-server`
2. 检查是否设置了 webhook:`curl https://api.telegram.org/bot<TOKEN>/getWebhookInfo`
3. 为每个组件使用单独的机器人令牌(推荐)
4. 或禁用另一个使用者
**替代方案:通过 scitex-orochi 使用 webhook 模式。** 如果您运行 [scitex-orochi](https://github.com/ywatanabe1989/scitex-orochi),它支持 Telegram webhook 模式(`POST /webhook/telegram/`),从而完全消除轮询冲突。 Telegram 将更新推送到单个 HTTPS 端点,而不是竞争轮询器。参见 orochi 文档中的 `SCITEX_OROCHI_TELEGRAM_WEBHOOK_URL`。
## 安装
### 先决条件
- [Bun](https://bun.sh/) >= 1.0(用于 MCP 服务器)
- GNU Screen(用于看门狗,可选)
### 安装
```bash
git clone https://github.com/ywatanabe1989/claude-code-telegrammer.git
cd claude-code-telegrammer/ts && bun install
```
## 快速开始
### 获取 Telegram 机器人令牌
1. 打开 Telegram 并给 [@BotFather](https://t.me/BotFather) 发送消息
2. 发送 `/newbot`,然后输入一个名称(例如 `Claude Code Telegrammer`)和用户名(例如 `ClaudeCodeTelegrammerBot`)
3. BotFather 回复您的令牌:`123456789:AAH...`
4. 验证您的令牌是否有效:
```bash
curl -s "https://api.telegram.org/bot<YOUR_TOKEN>/getMe"
# 应该返回 {"ok":true,"result":{"is_bot":true,...}}
```
5. 打开您的机器人(例如 [t.me/ClaudeCodeTelegrammerBot](https://t.me/ClaudeCodeTelegrammerBot))并发送任意消息以开始对话
### 将 MCP 服务器与克劳德代码注册
复制示例并填写您的值(`.mcp.json` 被 gitignore):
```json
{
"mcpServers": {
"claude-code-telegrammer": {
"type": "stdio",
"command": "bun",
"args": ["run", "/path/to/claude-code-telegrammer/ts/telegram-server.ts"],
"env": {
"CLAUDE_CODE_TELEGRAMMER_TELEGRAM_BOT_TOKEN": "123456789:AAH...",
"CLAUDE_CODE_TELEGRAMMER_TELEGRAM_ALLOWED_USERS": "YOUR_TELEGRAM_USER_ID",
"CLAUDE_CODE_TELEGRAMMER_TELEGRAM_STATE_DIR": "~/.claude-code-telegrammer"
}
}
}
}
```
```bash
cp .mcp.json.example .mcp.json
# 编辑 .mcp.json 您的令牌,用户 ID 和路径
```
通过消息 [@userinfobot](https://t.me/userinfobot) 查找您的 Telegram 用户 ID。
### 运行
```bash
claude \
--dangerously-skip-permissions \
--dangerously-load-development-channels server:claude-code-telegrammer
```
您应该在克劳德代码 TUI 中看到 `Listening for channel messages from: server:claude-code-telegrammer`。给您的机器人发送 Telegram 消息 - 克劳德代码将收到一个频道通知。
## 接口
<details>
<summary><strong>MCP 服务器 -- 用于 AI 代理</strong></summary>
启动命令:
```bash
bun run ts/telegram-server.ts
```
通过 MCP stdio 协议公开 10 个工具。参见上面的解决方案。服务器的 MCP 指令包括响应策略,指示代理立即确认消息并将繁重的工作委派给后台子代理。
</details>
<details>
<summary><strong>技能 -- 用于 AI 代理发现</strong></summary>
技能在 `src/claude_code_telegrammer/_skills/claude-code-telegrammer/SKILL.md` 中捆绑。
</details>
## 架构
```
用户(Telegram)
|
| 机器人 API(getUpdates 长轮询)
v
┌──────────────────────────────────────────────────────────────┐
│ 自定义 Telegram MCP 服务器(ts/telegram-server.ts) │
│ Bun + @modelcontextprotocol/sdk │
│ │
│ ┌─────────┐ ┌─────────┐ ┌──────────┐ ┌────────────┐ │
│ │ 轮询器 │ │ 存储 │ │ 工具 │ │ 附件处理器 │ │
│ │ (长轮询) │ │ (10 个 MCP │ │ (下载队列) │ │
│ └─────────┘ └─────────┘ └──────────┘ └────────────┘ │
│ ┌─────────┐ ┌─────────┐ ┌──────────┐ │
│ │ 访问 │ │ 配置 │ │ 锁 (PID) │ │
│ │ (允许名单) │ │ (环境变量) │ │ 文件) │ │
│ └─────────┘ └─────────┘ └──────────┘ │
└──────────────────────┬───────────────────────────────────────┘
│ MCP stdio
v
┌──────────────────────────────────────────────────────────────┐
│ 克劳德代码(在 GNU Screen 会话中) │
│ --mcp-config 指向自定义 MCP 服务器 │
└──────────────────────┬───────────────────────────────────────┘
│ screen buffer
v
┌──────────────────────────────────────────────────────────────┐
│ 监视器(claude-code-telegrammer-watchdog) │
│ 每 1.5 秒轮询一次 screen 缓冲区 │
│ 检测:y/n 提示 -> "1",y/y/n -> "2",空闲 -> 命令 │
│ 限流:突发限制,相同状态延迟,最小间隔 │
└──────────────────────────────────────────────────────────────┘
```
<details>
<summary><strong>状态检测</strong></summary>
| 状态 | 模式 | 响应 |
|-------|---------|----------|
| `running` | `(esc to interrupt)`,`tokens ·`,`ing...` | 无操作 |
| `y_n` | `1. Yes` + `3. No` (两项选择提示) | 发送 `1`(接受) |
| `y_y_n` | `2. Yes, and...` / `2. Yes, allow...` / `2. Yes, don't ask...` | 发送 `2`(全部接受) |
| `waiting` | 制作 puns(`Crafted for` 等),空 `>` 提示,空闲提示 | 发送可配置的命令 |
响应限流:响应之间的最小间隔,突发限制(3 个请求,3 秒窗口),相同状态延迟。
</details>
<details>
<summary><strong>配置(环境变量)</strong></summary>
**MCP 服务器:**
| 变量 | 必需 | 默认值 | 描述 |
|----------|----------|---------|-------------|
| `CLAUDE_CODE_TELEGRAMMER_TELEGRAM_BOT_TOKEN` | 是 | -- | Telegram 机器人 API 令牌 |
| `CLAUDE_CODE_TELEGRAMMER_TELEGRAM_STATE_DIR` | 否 | `~/.claude-code-telegrammer` | SQLite 数据库、access.json、锁文件目录 |
| `CLAUDE_CODE_TELEGRAMMER_TELEGRAM_ALLOWED_USERS` | 否 | -- | DM 允许名单的逗号分隔的 Telegram 用户 ID |
| `CLAUDE_CODE_TELEGRAMMER_TELEGRAM_HOST_NAME` | 否 | `os.hostname()` | 存储的 hostname |
| `CLAUDE_CODE_TELEGRAMMER_TELEGRAM_PROJECT` | 否 | `process.cwd()` | 存储的项目路径 |
| `CLAUDE_CODE_TELEGRAMMER_TELEGRAM_AGENT_ID` | 否 | `'telegram'` | 存储的代理标识 |
**监视器:**
| 变量 | 默认值 | 描述 |
|----------|---------|-------------|
| `CLAUDE_CODE_TELEGRAMMER_SESSION` | `claude-code-telegrammer` | GNU Screen 会话名称 |
| `CLAUDE_CODE_TELEGRAMMER_WATCHDOG_INTERVAL` | `1.5` | 秒为单位的轮询间隔 |
| `CLAUDE_CODE_TELEGRAMMER_RESP_Y_N` | `1` | y/n 提示的响应 |
| `CLAUDE_CODE_TELEGRAMMER_RESP_Y_Y_N` | `2` | y/y/n 提示的响应 |
| `CLAUDE_CODE_TELEGRAMMER_RESP_WAITING` | `/speak-and-call` | 空闲/等待时的响应 |
</details>
<details>
<summary><strong>SQLite 架构(v2)</strong></summary>
所有消息存储在 `$CLAUDE_CODE_TELEGRAMMER_TELEGRAM_STATE_DIR/messages.db` 中,使用 WAL 模式。
**messages 表:** 方向,chat_id,message_id,user_id,username,文本,时间戳(telegram_ts,received_at,read_at,replied_at),线程(reply_to_message_id,reply_to_row_id),身份(host,project,agent_id,bot_token_hash),raw_json。
**attachments 表:** message_row_id(FK),类型,file_id,file_name,mime_type,file_size,local_path,downloaded_at。
**meta 表:** 键值存储,用于 schema_version,update_offset。
</details>
<details>
<summary><strong>与 scitex-agent-container 集成</strong></summary>
有关 YAML 代理编排(screen 会话、看门狗生命周期、重启策略),请参阅 [scitex-agent-container](https://github.com/ywatanabe1989/scitex-agent-container)。
</details>
<details>
<summary><strong>访问控制</strong></summary>
通过 `$CLAUDE_CODE_TELEGRAMMER_TELEGRAM_STATE_DIR` 中的 `access.json` 进行管理:
```json
{
"dmPolicy": "allowlist",
"allowFrom": ["123456789"],
"groups": {
"-100123456": {
"requireMention": true,
"allowFrom": ["123456789"]
}
}
}
```
在运行时与 `CLAUDE_CODE_TELEGRAMMER_TELEGRAM_ALLOWED_USERS` 环境变量合并。mtime 缓存意味着编辑后无需重启即可生效。
</details>
<!-- SciTeX Convention: 生态 -->
## SciTeX 组成部分
claude-code-telegrammer 是 [**SciTeX**](https://scitex.ai) 的一部分。它提供了 Telegram 通信层和 TUI 看门狗,用于 [scitex-agent-container](https://github.com/ywatanabe1989/scitex-agent-container) 进行自主代理操作。
```
┌─────────────────────────────────────────────────────────┐
│ scitex-orochi — 代理定义,仪表板 │
└──────────────────────────┬──────────────────────────────┘
v
┌─────────────────────────────────────────────────────────┐
│ scitex-agent-container — 生命周期,健康,重启 │
└──────────────────────────┬──────────────────────────────┘
v
┌─────────────────────────────────────────────────────────┐
│ claude-code-telegrammer <-- 你在这里 │
│ MCP 服务器:Telegram API,消息数据库,10 个工具 │
│ 监视器:TUI 自动响应,屏幕轮询 │
└─────────────────────────────────────────────────────────┘
```
## 参考
- [克劳德代码通道](https://docs.anthropic.com/en/docs/claude-code/channels) -- 克劳德代码通道系统的官方文档
- [官方 Telegram 插件](https://github.com/anthropics/claude-code/tree/main/plugins/telegram) -- `plugin:telegram@claude-plugins-official` 源代码
- [#851: STATE_DIR 不受尊重](https://github.com/anthropics/claude-code/issues/851) -- 硬编码的 access.json 路径
- [#1075: 409 冲突错误](https://github.com/anthropics/claude-code/issues/1075) -- 多个实例轮询同一个机器人
- [#1146: 僵尸 CPU 消耗](https://github.com/anthropics/claude-code/issues/1146) -- 会话结束后运行失控的进程
- [Telegram BotFather](https://t.me/BotFather) -- 创建和管理 Telegram 机器人
- [Telegram 机器人 API](https://core.telegram.org/bots/api) -- 官方机器人 API 文档
- [MCP 规范](https://modelcontextprotocol.io/) -- 模型上下文协议标准
- [claude-code-telegrammer 问题](https://github.com/ywatanabe1989/claude-code-telegrammer/issues) -- 错误报告和功能请求
- [claude-code-telegrammer 拉取请求](https://github.com/ywatanabe1989/claude-code-telegrammer/pulls) -- 贡献
<!-- SciTeX Convention: 页脚(四大自由 + 图标) -->
>研究自由的四项原则
>
>0. 在任何地方运行研究的自由 -- 您的机器,您自己的条件。
>1. 研究如何工作的自由 -- 从原始数据到最终的手稿。
>2. 发布您的工作流的自由,而不仅仅是您的论文。
>3. 修改任何模块并分享改进的自由,与社区共享。
>
>AGPL-3.0 -- 因为我们相信运行研究的软件基础设施应该具有与运行软件的自由。
>
<p align="center">
<a href="https://scitex.ai" target="_blank"><img src="docs/scitex-icon-navy-inverted.png" alt="SciTeX" width="40"/></a>
</p>
<!-- EOF -->
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器