mcpField
T
Telegram MCP Server

Telegram MCP Server

本地服务
github.com/chigwell通信协作1.9k今天更新

关于 Telegram MCP Server

Telegram MCP Server 通过 Telethon 将 Telegram 账号接入 Claude、Cursor 等兼容 MCP 的客户端。它提供账号、聊天、消息、联系人和媒体操作工具,并支持查看聊天记录及起草回复等工作流。

主要功能

  1. 01账号与聊天管理
  2. 02发送、搜索和编辑消息
  3. 03群组与频道管理
  4. 04联系人别名与查找
  5. 05媒体传输与语音转写
  6. 06聊天记录搜索与上下文查看

适用场景

  1. 01总结未读聊天并整理待办事项
  2. 02起草回复但暂不发送
  3. 03搜索历史消息以补充上下文
  4. 04转写语音消息

MCP 相关

向 MCP 客户端提供 80 多种 Telegram 工具,涵盖账号、聊天、消息、联系人、媒体、文件夹及管理操作。工具调用可按账号标签路由。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

Telegram MCP 服务

MCP 徽章 许可证:Apache 2.0 Python 代码检查与格式检查 Docker 构建与 Compose 验证

为 Claude、Cursor 和其他兼容 MCP 的客户端提供 Telegram 集成。它通过 Model Context Protocol,使用 Telethon 提供 Telegram 账号、聊天、消息、联系人、媒体、文件夹和管理操作。

🤖 MCP 实战演示

在 Claude 中使用 Telegram MCP 的基本示例:

Telegram MCP 实战演示

让 Claude 分析聊天记录并发送回复:

Telegram MCP 请求

消息已成功发送:

Telegram MCP 结果

目录

技能与工作流

想寻找可直接使用的工作流、提示词示例或集成方案? 请查看技能文档,其中提供了分步指南:

功能介绍

此服务目前包含 80 多个 MCP 工具,分为以下类别:

  • **账户:**列出已配置的账户,并按账户标签路由工具调用。
  • **聊天和群组:**列出聊天、查看元数据、创建群组/频道、将基本群组升级为超级群组、加入或退出聊天、邀请或移除用户、管理管理员、封禁、默认权限、慢速模式、话题及其允许使用的图标、邀请链接、共同聊天、已读回执和消息链接。
  • **消息:**发送、定时发送、编辑、删除、转发、置顶、取消置顶、标记为已读、回复、搜索、查看上下文、创建投票、管理回应、查看内联按钮并按下内联回调。send_message、reply_to_message 和 edit_message 支持经典格式(parse_mode='md'/'html')和服务端富文本格式(parse_mode='rich'/'rich_markdown'/'rich_html' — 完整的 Markdown/HTML,支持表格、标题、公式和可折叠部分)。富文本模式要求账户拥有 Telegram Premium;每次调用都会重新检查 Premium 状态,若没有 Premium,则不会发送任何内容 — 工具会返回结构化的 telegram_premium_required 结果,以便 Agent 使用经典模式重新排版并重试。send_message、reply_to_message 和 edit_message 还接受 format_date,可将日期呈现为可点击的标签。若编辑未造成任何更改,edit_message 会报告 not modified,而不是报错。

list_inline_buttons 会按行、列和 kind(按下按钮后会执行的操作)描述每个按钮,涵盖内联按钮和回复键盘。press_inline_button 会按下 callback 和 game 按钮,返回机器人的答复以及 alert 和 url,并拒绝按下需要 2FA 密码的按钮。

get_message_reactions 对没有回应的消息返回空列表。若要重复使用自定义回应,请将返回的 custom:<document_id> 值传给 send_reaction。

vote_poll(chat_id, message_id, option_indices, account=None) 可对现有投票进行投票。 请先使用 get_messages 读取投票,然后选择从 0 开始计数的答案索引:[0] 表示第一个答案;在多选投票中,[0, 2] 表示第一个和第三个答案。 这可能会替换已有投票;空选项、重复索引、超出范围的索引、已关闭的投票,以及单选投票中选择多个答案,都会被拒绝。 Telegram 会强制执行投票权限,以及更改测验投票时的限制。

在允许以多个身份发帖的超级群组中(例如以你拥有的频道身份发帖),get_send_as(chat_id) 会列出允许使用的发件人,而 set_default_send_as(chat_id, send_as) 会保存后续消息所用的发件人:使用 "me" 表示你自己的账户,或使用某个允许的发件人的 ID 或用户名。保存的发件人会应用于你的所有 Telegram 客户端。 以管理员身份匿名发帖属于管理员权限,不会因此改变。

  • **联系人:**列出、搜索、添加、删除、屏蔽、解除屏蔽、导入、导出联系人,查看私聊,查找近期联系人互动,并按你实际使用的名称记住联系人(见下文)。
正在输入指示器

send_typing(chat_id, seconds=5, topic_id=None, account=None) 会发送临时的正在输入指示器,而不会发送消息。持续时间必须为 0.5 至 45 秒;该工具会阻塞,直到操作完成,因此请在调用 send_message 或 reply_to_message 之前调用,不要并行调用。 它会以不超过四秒的间隔刷新指示器,并会在完成、失败或取消时尝试清除指示器。topic_id 用于指定论坛中的某个话题。

同一账户、对端和话题的重叠调用会被拒绝,而不会取消彼此的指示器。对于这些 RPC,不会自动等待 Flood 等待时间;输入阶段的超时时间为 50 秒,清理阶段另有三秒超时时间。若清理失败,会明确报告。成功的 RPC 响应只表示 Telegram 已接受请求,不代表其他客户端的界面已显示指示器。这是写操作,并遵循现有的账户路由和聊天允许列表。

记忆的联系人

set_contact_alias 会让服务知道你如何称呼某人,此后所有接受 chat_id 的工具都能识别这个称呼——send_message("андрей бекендер", ...) 直接就能使用。一个联系人可以有任意多个别名,这也是标签的实现方式:为同一个人保存 андрей бекендер 和 бекендер,使用任意一个都能找到对方。

只有与已保存称呼完全一致时才会发送消息。 相似的称呼(例如已保存 андрей бекендер 时输入 Андрею бекендеру)也会被识别,但仅用于建议:工具不会发送任何内容,而是请你按姓名确认联系人。这是有意为之——Лена/Леня 和 Иван/Иванов 的差异,与词尾变化完全相当,因此,一个足以处理词形变化的匹配器,在你想联系的人尚未保存时,也同样可能把消息发给错误的人。确认后,该称呼会作为独立别名保存,因此每种新说法第一次只需确认一次,此后再也不用确认。设置 TELEGRAM_CONTACT_FUZZY=0 可同时关闭这些建议。

如果引用的联系人未知、与某个联系人相似、匹配多个联系人,或指向的联系人已无法识别,工具都不会发送任何内容,而是返回一条结构化指令,明确告诉 Agent 应该向你询问什么、使用 set_contact_alias 保存回答,然后重试一次。list_contact_aliases 会为每个人显示一行及其所有别名(可用来检查是否记错),delete_contact_alias 会删除一个别名,而将别名改指向其他人则必须使用 replace=True。保存过程本身不会接受需要猜测的目标:联系人必须通过 @username、电话号码、数字 ID 或已为其确认的别名来保存。

别名存储在 ${XDG_STATE_HOME:-~/.local/state}/telegram-mcp/aliases.json 中(仅所有者可访问,并以原子方式写入);TELEGRAM_ALIASES_FILE 可覆盖该路径,并且仍会将代码旁已有的 aliases.json 作为备用文件读取。

  • 媒体: 发送文件、下载媒体、上传文件、发送语音消息、贴纸和 GIF、检查消息媒体,以及转录语音消息/视频消息(见下文)。
语音转录

transcribe_voice(chat_id, message_id, engine=None) 会将语音消息或视频消息转换为文本。共有四种引擎可用:

  • groq(默认):将录音上传到 Groq 托管的 whisper-large-v3-turbo。录音会离开服务器,每次调用都会产生下载和上传流量,但不会像原生转录那样漏掉录音末尾的几个词。需要 GROQ_API_KEY。Groq 限制单次上传的文件大小,因此,如果录音超过 TELEGRAM_TRANSCRIBE_GROQ_MAX_MB(默认值为 25,即免费套餐的限制),系统会在本地拒绝处理,并返回注明文件大小的 too_large 错误,而不会先下载再被 API 拒绝。如果 Groq 套餐允许上传更大的文件,可以调高此限制;或者使用 engine='telegram' 转录该消息,此引擎没有此限制。
  • telegram:使用 Telegram Premium 原生转录功能(messages.TranscribeAudioRequest)。免费,录音不会离开 Telegram,但根据实际测试,大约 3 条录音中有 2 条会漏掉最后一段语音,且账号必须开通 Telegram Premium。较长的录音会返回 pending,并自动轮询。
  • openai:适用于任何兼容 OpenAI 的 /audio/transcriptions 端点,例如 OpenAI 本身、自托管的 Parakeet 或 speaches 服务、LocalAI、vLLM Whisper 部署等。将 TELEGRAM_TRANSCRIBE_OPENAI_URL 设为 API 基础 URL(例如 https://api.openai.com/v1;完整的 .../audio/transcriptions URL 也可用),将 TELEGRAM_TRANSCRIBE_OPENAI_API_KEY 设为 bearer 令牌(本地服务不需要密钥时可选),并设置 TELEGRAM_TRANSCRIBE_OPENAI_MODEL(默认值为 whisper-1)。文件大小限制:TELEGRAM_TRANSCRIBE_OPENAI_MAX_MB(默认值为 25)。使用 Parakeet 时,将 TELEGRAM_TRANSCRIBE_OPENAI_URL=http://localhost:5092/v1;仅当服务设置了 PARAKEET_API_KEY 时才需要 API 密钥;对于英语以外的语言,请设置 TELEGRAM_TRANSCRIBE_LANGUAGE——如果未发送语言,Parakeet 会默认使用 en。
  • whisper:在 MCP 服务进程中加载本地 faster-whisper 模型。音频不会离开此设备。使用 pip install 'telegram-mcp[whisper]'(或 uv sync --extra whisper)安装附加依赖。可通过 TELEGRAM_TRANSCRIBE_WHISPER_MODEL 选择模型(默认值为 small;例如使用 large-v3-turbo 可获得更好的质量),通过 TELEGRAM_TRANSCRIBE_WHISPER_DEVICE(auto/cpu/cuda)、TELEGRAM_TRANSCRIBE_WHISPER_COMPUTE_TYPE(例如在 CPU 上使用 int8)和 TELEGRAM_TRANSCRIBE_WHISPER_MODEL_DIR(模型下载位置)调整设置。模型会在首次使用时加载一次,录音会逐条转录。Alpine Docker 镜像中不可用;请改用容器旁的 Parakeet 或其他兼容 OpenAI 的服务,并通过 openai 引擎使用。

TELEGRAM_TRANSCRIBE_LANGUAGE(ISO-639-1,例如 nl)会作为语言提示传递给除 telegram 以外的所有引擎;未设置时,引擎会自动检测语言。TELEGRAM_TRANSCRIBE_TIMEOUT(默认值为 120 秒)用于限制 HTTP 引擎(groq、openai)的单次请求时长。

每次调用都可以通过 engine 参数选择引擎;否则将使用 TELEGRAM_TRANSCRIBE_ENGINE(groq、telegram、openai 或 whisper)指定的默认引擎。结果会按 (chat_id, message_id, engine) 缓存在本地 SQLite 文件中,因此重复读取和重复列出时,不会再次转录同一条消息。对于同一条尚未缓存的录音,并发请求也会合并处理:第二个请求会等待第一个请求完成并返回其转录结果,因此一批调用只会产生一次付费调用,而不是每个调用各一次。每条转录结果都会附带 note,标明这是机器转录,而非逐字引述——请将其视为释义,而非原话。

get_history、get_messages、list_messages、search_messages、search_global 和 get_message_context 会填入语音消息中已缓存的转录文本,而不会让文本留空;此功能由 TELEGRAM_TRANSCRIBE 控制:

  • off:运行时禁用转录。transcribe_voice 工具仍会注册,但会返回 {"transcribed": false, "reason": "transcription_disabled"},而不会进行转录;列表中也不会显示转录文本。使用 TELEGRAM_EXPOSED_TOOLS 隐藏该工具本身。
  • on-demand(默认):列表会显示缓存的转录文本,但绝不会为获取新转录文本而调用 API。
  • auto:get_history、get_messages、list_messages 和 search_messages 也会预取缺失的转录文本,每次调用的预取量受 TELEGRAM_TRANSCRIBE_MAX_VOICES/TELEGRAM_TRANSCRIBE_MAX_SECONDS 限制(Groq 并非免费,因此预取有预算限制,不会无限进行)。

缓存位于 TELEGRAM_TRANSCRIPT_CACHE_DIR(默认为工作目录中的 data/transcripts;如果该目录不可写,则使用 ~/.cache/telegram-mcp/transcripts),保存为权限为 700 的目录和权限为 600 的文件,因为其中以纯文本形式存储了私人聊天内容。关于容器中为何需要为其单独挂载卷,请参见 Docker。

  • 个人资料和隐私: 获取自己的账户信息、更新个人资料字段、设置或删除个人资料照片、查看隐私设置、获取用户信息/照片/状态,以及管理机器人命令。

  • 文件夹和草稿: 列出、创建、更新、重新排序和删除 Telegram 文件夹;预览共享文件夹邀请(t.me/addlist/...),但不加入该文件夹;保存、列出和清除草稿。

    • get_folder_limits 会报告 Telegram 应用配置中的当前文件夹、显式聊天和置顶数量限制,并考虑 Premium 权限;不可用的限制为 null。
    • get_folder_snapshot 会捕获文件夹定义/顺序,包括标题实体、显示字段、标志、稳定的对等方 ID 和有序置顶项,但不包含访问哈希或聊天内容。其私有文件夹 definition 对象可作为恢复补丁传入;共享邀请和账户/聊天状态不在此快照的范围内。
    • update_folder(folder_id, patch, expected_revision?) 会原地编辑现有的私有文件夹,并保留未指定的字段。对等方列表只会替换指定的列表;[] 会清空该列表。例如,{"title": "Projects", "exclude_archived": false} 会重命名该文件夹,并允许已归档的聊天通过其规则,而不会取消归档任何聊天。编辑前请保存快照,并使用其 revision 拒绝过时的计划。共享文件夹和系统文件夹会被拒绝;请避免多个编辑者并发修改文件夹,因为 Telegram 不支持原子比较并交换。
  • 事件: 通过防抖等待收到新消息(wait_for_new_message、wait_for_settled_message),可选择仅针对一个聊天,方法是指定 chat_id——不指定时,任何无关对话都会唤醒等待;也可以启用选择加入的收件事件流,以回调式方式传递事件(见下文)。跟踪聊天的集成方(例如聊天桥接工具)则使用逐消息事件日志(见下文)。

所有包含 Telegram 用户控制内容的工具结果都会经过清理,并在可行时以结构化 JSON 返回。

重用自定义表情

get_history、list_messages、search_messages、search_global、 get_message_context(包括 replied_message)、get_pinned_messages 和 get_drafts 会在消息包含自定义表情时提供 custom_emojis。 get_messages 和 get_scheduled_messages 会在文本输出中以 JSON 列表形式提供相同的元数据。普通消息的输出保持不变。

{"text": "🍷 News", "custom_emojis": [{"emoji": "🍷", "id": "5368324170671202286"}]}

每个条目都包含备用表情及其字符串形式的 Telegram 文档 ID。 每条消息中重复的 ID 只会出现一次;即使备用表情看起来相同,不同的 ID 也会分别保留。这是可重用表情变体的列表,不是位置映射,也不是所有消息格式的副本。提取会使用原始 Telegram 实体,包括块格式 rich_message 内容中的 TextCustomEmoji 节点,且不会额外发起 API 请求。备用文本中的表情连接符和旗帜标签字符会保留。

要重用某个条目,请在 send_message、reply_to_message 或 edit_message 中设置 parse_mode="html",并使用其 id 和 emoji 插入 <tg-emoji emoji-id="ID">EMOJI</tg-emoji>。对备用文本和其他字面文本进行 HTML 转义。例如,上面的条目会变为 <tg-emoji emoji-id="5368324170671202286">🍷</tg-emoji>。 发送自定义表情仍受 Telegram 账号限制。

对于纯文本消息,请改为直接将条目作为 custom_emojis 传入,不使用 HTML,也不进行转义;文本会原样发送。例如, send_message(chat_id, "🍷 News for List<int> & co", custom_emojis=[{"emoji": "🍷", "id": "5368324170671202286"}])。reply_to_message 和 edit_message 也支持相同的参数。每个 emoji 的所有独立出现位置都会变成对应的自定义表情,包括 URL 或代码中的位置;若要保留某个普通表情,请使用 parse_mode="html" 和 <tg-emoji>。较长序列中的表情(例如 👍🏽 中的 👍)不匹配。若找不到 emoji、emoji 看起来不像表情(拒绝纯 ASCII/拉丁标点,例如 #)、id 不是正的 64 位整数、两个标记范围重叠,或设置了 parse_mode,则不会发送任何内容。它可以与 format_date 组合使用。

send_file 和 send_album 的说明文字也支持相同的 parse_mode 和 custom_emojis;媒体组的说明文字位于第一项中。不设置 parse_mode 时,说明文字仍会像以前一样按 Markdown 解析;parse_mode="plain" 会原样发送说明文字,不支持富文本模式,而且使用 custom_emojis 时必须提供说明文字。

可点按的日期和时间

向 send_message、reply_to_message 或 edit_message 传入 format_date,即可渲染可点按的日期/时间标签——与 Telegram 应用在你输入可识别日期时添加的实体相同。日期文本必须与消息中显示的内容完全一致:'13/09'、'13/09/2026' 或 '13/09 17:00'。点按标签会打开复制日期、添加到日历和设置提醒等操作。仅适用于纯文本消息——请省略 parse_mode。例如,send_message(chat_id, "Lunch 13/09 13:00", format_date="13/09 13:00") 会发送一条消息,点按日期即可打开该菜单。

收件事件馈送(回调模式,仅限 Claude Code)

默认情况下,Agent 会通过调用 wait_for_settled_message 等待回复,该调用会阻塞至 MCP 工具超时,且必须再次调用——这种方式适用于所有场景(Codex、Cursor 等),且保持不变。

能够在有外部输出时唤醒 Agent 的客户端(Claude Code 的持久化 Monitor 会监视 tail -f)可以改用回调模式:

  1. Agent 调用 enable_incoming_feed(或在环境中设置 TELEGRAM_EVENT_FEED=1 以自动启用)。每一批已稳定的收件消息都会作为一行 JSON 追加到 ${XDG_STATE_HOME:-~/.local/state}/telegram-mcp/incoming_feed.jsonl,并以仅所有者可访问的权限(0600)创建。使用 TELEGRAM_EVENT_FEED_FILE 覆盖路径——指定路径的目录必须已存在。incoming_feed_status 会报告实际使用的路径和可直接使用的监视命令。
  2. Agent 使用该工具返回的 watch_command 启动持久化 Monitor。每出现一行新内容,都会以该批消息的摘要重新调用 Agent;不会有阻塞的工具调用持续占用,聊天也能保持畅通。

disable_incoming_feed 会切回原模式;incoming_feed_status 会报告当前模式。启用馈送后,它会处理已稳定的消息批次,因此不要将它与 wait_for_settled_message 一起使用。馈送行中的 name 字段由用户生成——请将其视为不可信数据。

每条消息的事件(聊天桥接)

每条新消息,无论来自私聊、基本群组还是超级群组,都会在有界的内存日志中生成一个带编号的事件(TELEGRAM_EVENT_LOG_SIZE,默认值为 2000;设为 0 可关闭)。收到的消息会计入,从其他设备发送的所有者本人消息也会计入;此服务自身发送的消息不会计入。广播频道不在范围内;设置了 TELEGRAM_ALLOWED_CHAT_IDS 时,不在该设置范围内的聊天也不在范围内。事件不包含文本,也不会写入磁盘。

  • wait_for_events(chat_id?, after_seq, boot?, timeout, limit, account?) 会长轮询:只要 after_seq 之后存在事件就会立即返回(最长 100 秒,通常短于代理超时;timeout 请设为低于 MCP 客户端的请求超时时间)。after_seq=-1 表示从当前时刻开始,不重放日志。事件包含 seq、chat_id、chat_type、message_id、sender_id、sender_name、sender_bot、out、addressed(私聊始终为真;群组中仅当 Telegram 标记该消息提及此账号或回复此账号时为真;所有者本人发送的消息始终为假)、topic(论坛主题的 id,General 为 1;非论坛中省略)、reply_to、service 和 date;使用多个账号时,还会包含 account。务必传回 boot 和 last_seq;reset(服务已重启)或 gap(日志已溢出;这是全局状态,而非针对单个聊天)表示:从上次的消息 id 开始读取你关注的每个聊天,然后继续。
  • get_messages_after(chat_id, after_id?, limit) 会返回某个 id 之后的消息,按从旧到新的顺序排列,记录格式与 list_messages 相同,并额外包含 out、mentioned、addressed、date、论坛中的 topic 以及服务消息的 action。结果包含 chat_id、chat_type、has_more(存在比 after_id 更新的消息时为真;未提供 after_id 时表示存在更早的消息)、messages,以及论坛中的一个主题 id 到标题的 topics 映射。负数 after_id 会被拒绝。
  • send_message 接受 reply_to(主题 id 会让消息发送到相应的论坛主题中),并会标明已发送消息:普通发送的结果以 message_id=<id> 结尾;富文本发送(rich* 解析模式)会返回带有 message_id 键的 JSON(Telegram 的响应未标明消息 id 时,该值为 null),以便桥接程序在历史记录中识别自己发送的消息。

上文的防抖工具仍仅适用于私聊。

要求

  • Python 3.10+
  • 从 my.telegram.org/apps 获取的 Telegram API 凭据
  • Telegram 会话字符串或基于文件的会话
  • MCP 客户端,例如 Claude Desktop、Cursor 或其他兼容 MCP 的宿主
  • 可选:uv 用于本地开发

快速开始

请勿使用 uvx telegram-mcp、uvx --from telegram-mcp 或 pip install telegram-mcp 安装此服务。PyPI 上的 telegram-mcp 名称目前归另一项目所有,安装的并非此代码库。向该软件包传入 TELEGRAM_API_ID、TELEGRAM_API_HASH 或 TELEGRAM_SESSION_STRING,可能会将 Telegram 账户凭据暴露给无关的第三方代码。

1. 克隆并安装
git clone https://github.com/chigwell/telegram-mcp.git
cd telegram-mcp
uv sync
2. 生成会话字符串
uv run session_string_generator.py

按照提示操作。请安全保存生成的会话字符串。会话字符串便于初始设置和可移植部署;对于长期运行的服务,请先配置环境,然后将其迁移为持久化文件会话(见下文)。

对于脚本化设置或运维手册,请明确选择登录方式:

# QR login, recommended when you already have Telegram open on another device
uv run session_string_generator.py --qr

# Phone number + verification code login
uv run session_string_generator.py --phone

如果不指定标志,生成器会继续交互式询问登录方式。

3. 配置环境

复制示例文件并填入真实值:

cp .env.example .env

单账户设置:

TELEGRAM_API_ID=your_api_id_here
TELEGRAM_API_HASH=your_api_hash_here
TELEGRAM_SESSION_STRING=your_session_string_here
长期运行的服务:推荐使用持久化会话

StringSession 会存储 Telegram 授权密钥,但不会存储 Telethon 的更新状态。因此,繁忙账户在重启后可能会收到大量积压的更新。本地 SQLite 会话会持久化更新游标和实体缓存,因此后续重新连接时只会收到错过的增量更新。

停止所有正在运行的 telegram-mcp 进程,然后迁移 .env 中配置的字符串:

uv run telegram-mcp-migrate-session

该命令会向 Telegram 验证新会话,并打印要使用的确切设置。按照指示更新 .env,例如:

# Remove or comment this out; it takes precedence when both are present.
# TELEGRAM_SESSION_STRING=your_session_string_here
TELEGRAM_SESSION_NAME=/absolute/path/to/telegram_mcp_session

生成的 .session 文件包含账户凭据。请妥善保管,不要提交该文件。此代码库的 .gitignore 已排除会话文件。

对于带标签的账户,请使用相同标签的 --account:

uv run telegram-mcp-migrate-session --account work

该命令会读取 TELEGRAM_SESSION_STRING_WORK,并写入相应的 TELEGRAM_SESSION_NAME_WORK 设置说明。使用 --target PATH 选择其他目标位置。源会话正在被其他进程使用时,请勿运行迁移。

默认情况下,会公开所有 Telegram MCP 工具。如果要阻止 MCP 客户端发送消息或执行聊天/账户变更,请将 TELEGRAM_EXPOSED_TOOLS=read-only,仅公开标注了 readOnlyHint=True 的工具:

TELEGRAM_EXPOSED_TOOLS=read-only

如果只读模式限制过严,而 all 又范围过广,可在后面追加 + 和逗号分隔的工具名称列表,以额外公开这些特定的写入工具。其他所有写入工具都不会注册:

TELEGRAM_EXPOSED_TOOLS=read-only+send_message,reply_to_message,send_file

若要隐藏特定工具,可在任一基础模式后追加 - 和逗号分隔的工具名称列表。也可在 + 列表之后使用:

TELEGRAM_EXPOSED_TOOLS=all-delete_chat_history,delete_messages_bulk
TELEGRAM_EXPOSED_TOOLS=read-only-get_participants
TELEGRAM_EXPOSED_TOOLS=read-only+send_message,reply_to_message-get_participants

任一列表中出现未知名称都会导致启动中止,因此拼写错误不会悄然产生一个看似正常的不同工具集。列表为空、同一名称同时出现在两个列表中,或 - 列表中的名称已被基础模式隐藏(例如 read-only-send_message)时,启动也会中止,因为这些情况不会产生任何效果。若要关闭语音转录,请设置 TELEGRAM_TRANSCRIBE=off,而不要使用 -transcribe_voice:隐藏该工具不会移除列表中待处理转录的提示,也不会关闭 auto 预取。

启动时,服务会将该模式隐藏的工具名称打印到 stderr;这些名称可用于 + 列表。由 - 列表隐藏的工具会单独打印一行。

这是对 MCP 工具范围的限制,并非 Telegram 会话沙箱,也不会降低 Telegram 账户权限。Telegram 会话字符串在服务进程中仍拥有其通常的权限;只读模式仅会阻止非只读工具注册并通过 MCP 公开。可接受的值为 all(默认值)、read-only 和 read-only+<tool>,<tool>,每种值后还可选追加 -<tool>,<tool>。 单独的硬编码允许列表会将 send_voice、send_sticker、 set_profile_photo 和 edit_chat_photo 限定为各自预期的文件扩展名; send_file 和 upload_file 默认接受任何扩展名。使用 TELEGRAM_FILE_EXTENSIONS 为这两个工具添加允许列表,或收紧或替换 任何硬编码的允许列表;格式与 TELEGRAM_EXPOSED_TOOLS 相同,为 tool:.ext,.ext,各项之间用 ; 分隔:

TELEGRAM_FILE_EXTENSIONS=send_file:.pdf,.png,.jpg;upload_file:.pdf,.png

如果列出的工具已有硬编码默认值,则会替换该工具的整个扩展名集合,而不是在其上添加;未列出的工具保留默认值(因此,不设置此变量会保持当前行为不变)。扩展名不区分大小写,开头的点可省略(pdf 与 .pdf 等效)。工具名称未知、扩展名格式错误或同一工具被列出两次,都会导致启动中止,处理方式与 TELEGRAM_EXPOSED_TOOLS 中出现拼写错误相同。

这只是防止意外的纵深防御措施,并非安全边界。检查的是最终后缀,因此允许列表中有 .pdf 仍会接受 payload.exe.pdf,而且不会检查文件中的字节内容。它能可靠拦截的是粗心导致的情况:没有扩展名的机密文件(如 id_rsa)或裸露的 .env。普通扩展名的文件——.pem、.key、.json 令牌文件、.sqlite Cookie 存储——除非你自行从列表中排除,否则都不会被拦截。

语音转录(参见上文的语音转录)默认关闭,也就是说,除非你主动请求,否则绝不会获取转录内容——transcribe_voice 始终可用,列表操作只会获取已缓存的转录内容。启用预取功能,或显式选择引擎:

TELEGRAM_TRANSCRIBE=on-demand       # off / on-demand (default) / auto
TELEGRAM_TRANSCRIBE_ENGINE=groq     # groq (default), telegram, openai or whisper
GROQ_API_KEY=your_groq_api_key_here # required whenever engine=groq is used

engine=groq 需要 GROQ_API_KEY;engine=telegram 需要账号开通 Telegram Premium;engine=openai 需要 TELEGRAM_TRANSCRIBE_OPENAI_URL;engine=whisper 需要 whisper 扩展。TELEGRAM_TRANSCRIBE_MAX_VOICES(默认值为 5)和 TELEGRAM_TRANSCRIBE_MAX_SECONDS(默认值为 300)用于限制 auto 模式在每次列表调用中的预取量;TELEGRAM_TRANSCRIPT_CACHE_DIR(默认值为 data/transcripts)用于设置 SQLite 缓存的写入位置;TELEGRAM_TRANSCRIBE_GROQ_MAX_MB (默认值为 25)用于限制 groq 引擎上传的录音文件大小。

Telegram 速率限制(FloodWaitError)会连同精确的等待时长和明确的“请勿立即重试”指示,原样传递给 MCP 客户端和大模型 Agent。

使用 TELEGRAM_FLOOD_SLEEP_THRESHOLD 配置 Telethon 内部的静默休眠阈值(默认值:60 秒)。设为 0 可禁用静默休眠,并让 Agent 管理所有退避等待:

TELEGRAM_FLOOD_SLEEP_THRESHOLD=60   # Max seconds Telethon sleeps silently on FloodWait (default 60)

在本地运行服务:

uv run main.py

MCP 客户端配置

Claude Desktop 扩展(.mcpb)

仓库中包含 manifest.json,因此可以将其打包为 Claude Desktop 扩展,并在无需编辑任何 JSON 的情况下安装:

npx @anthropic-ai/mcpb pack . telegram-mcp.mcpb

使用 Claude Desktop 打开生成的 telegram-mcp.mcpb(或将其拖放到“设置” → “扩展”),然后填写 API ID、API hash 和 session string (如何生成,请参见快速开始)。Claude Desktop 会通过 uv 自行安装 Python 和依赖项,并将 API hash 和 session string 标记为敏感字段。allowed-chats 和 files-directory 字段分别对应 TELEGRAM_ALLOWED_CHAT_IDS 和 TELEGRAM_ALLOWED_ROOTS。.mcpbignore 会将 .env、会话文件和日志排除在软件包之外。

手动配置

对于 Claude Desktop 或 Cursor,将 MCP 服务指向此项目的克隆副本:

{
  "mcpServers": {
    "telegram-mcp": {
      "command": "uv",
      "args": [
        "--directory",
        "/full/path/to/telegram-mcp",
        "run",
        "main.py"
      ],
      "env": {
        "TELEGRAM_API_ID": "your_api_id_here",
        "TELEGRAM_API_HASH": "your_api_hash_here",
        "TELEGRAM_SESSION_STRING": "your_session_string_here"
      }
    }
  }
}

若要在 Claude Desktop 或 Cursor 中仅启用只读工具,请将以下内容添加到服务的 env 块中:

"TELEGRAM_EXPOSED_TOOLS": "read-only"

或者将只读工具作为默认配置,并在此基础上允许少数写入工具:

"TELEGRAM_EXPOSED_TOOLS": "read-only+send_message,reply_to_message"

也可以使用特定的发布标签或提交,将此仓库直接从 GitHub 安装到虚拟环境中:

python -m venv .venv
. .venv/bin/activate
pip install "git+https://github.com/chigwell/telegram-mcp.git@<tag-or-commit>"

然后配置 MCP 客户端运行已安装的控制台脚本:

{
  "mcpServers": {
    "telegram-mcp": {
      "command": "/full/path/to/.venv/bin/telegram-mcp",
      "env": {
        "TELEGRAM_API_ID": "your_api_id_here",
        "TELEGRAM_API_HASH": "your_api_hash_here",
        "TELEGRAM_SESSION_STRING": "your_session_string_here"
      }
    }
  }
}

无需克隆仓库,也可以通过明确指定此仓库来自 GitHub 来生成会话字符串:

uvx --from "git+https://github.com/chigwell/telegram-mcp.git@<pinned-release-tag-or-commit>" telegram-mcp-generate-session
传输方式

此服务支持三种 MCP 传输方式,通过 MCP_TRANSPORT 选择:

值传输方式用例
stdiostdio(默认)每个 MCP 客户端使用一个专用服务进程
http可流式传输的 HTTP多个客户端(Claude Code、Codex、Cursor)共用一个服务
sseSSE(旧版 HTTP)仅支持已弃用 SSE 传输方式的客户端

对于 http 和 sse,服务会绑定到 MCP_HOST:MCP_PORT(默认值为 127.0.0.1:8765);可流式传输的 HTTP 端点为 /mcp,SSE 端点为 /sse。

如果服务可通过域名访问(例如位于反向代理之后),而不仅仅通过 127.0.0.1/localhost 访问,请设置 MCP_ALLOWED_HOSTS(以及可选的 MCP_ALLOWED_ORIGINS),以启用 DNS 重绑定防护并允许该 Host 标头,例如 MCP_ALLOWED_HOSTS=mcp.example.com。多个值以逗号分隔;支持使用 :* 后缀以允许任意端口。若不设置,DNS 重绑定防护将保持关闭(沿用历史默认设置)。

如果有多个 MCP 客户端(或许多编码 Agent 会话)要使用此服务,建议使用 http:单个长期运行的进程只需保持一个 Telegram 连接,而不是让每个客户端都启动自己的 Telethon 会话——Telegram 会限制频率,并可能标记开启许多并行会话的账户。

每次工具调用还受服务端 55 秒的上限约束,该上限通过 TELEGRAM_TOOL_TIMEOUT_SECONDS 配置。超时的 Telegram 请求会返回明确的 MCP 错误,而不是让客户端无限期等待。错误会说明请求是否完成尚不确定:写入操作可能已经成功,因此重试前请检查目标位置。只有在有意进行不设上限的运维会话时,才将该值设为 0。

向客户端注册共享服务:

# Claude Code
claude mcp add --transport http telegram http://127.0.0.1:8765/mcp

# Codex
codex mcp add telegram --url http://127.0.0.1:8765/mcp

对于仅支持 stdio 的客户端,可通过 mcp-remote 进行桥接:

{
  "mcpServers": {
    "telegram-mcp": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "http://127.0.0.1:8765/mcp"]
    }
  }
}

多账户设置

使用带后缀的会话变量来配置多个 Telegram 账户:

TELEGRAM_API_ID=your_api_id_here
TELEGRAM_API_HASH=your_api_hash_here
TELEGRAM_SESSION_STRING_WORK=session_string_for_work
TELEGRAM_SESSION_STRING_PERSONAL=session_string_for_personal

标签会转换为小写,并成为工具中 account 参数的值。

如果同时设置了 TELEGRAM_SESSION_NAME(Docker 镜像和 .env.example 中已设置),那么该会话在登录后会成为一个额外的 default 账户;如果尚未登录,服务会跳过该账户并在 stderr 上发出警告,而不会拒绝启动。

  • 在单账户模式下,account 为可选项。
  • 在多账户模式下,写入工具必须指定 account。
  • 如果未指定 account,只读工具会向所有账户分发请求。

示例提示词:

  • “列出我的账户”
  • “显示所有账户的未读消息”
会话池(一个账号,多个并发客户端)

要让多个 MCP 客户端同时连接同一个 Telegram 账号(例如桌面应用和终端 CLI),请为每个客户端提供各自已授权的会话。Telegram 禁止同一个会话(授权密钥)同时从两个 IP 使用,因此在 VPN 或双栈主机上,两个本地客户端可能会发生冲突并触发 AuthKeyDuplicatedError。在 TELEGRAM_SESSION_STRINGS 中列出多个可互换的会话字符串(以空格、逗号或分号分隔);每个进程通过建议文件锁占用一个空闲会话,因此客户端会确定性地选择不同会话:

TELEGRAM_SESSION_STRINGS=<session A> <session B> <session C>

使用 uv run session_string_generator.py 生成额外会话。对于默认账号,会话池的优先级高于 TELEGRAM_SESSION_STRING。作为额外的安全措施,如果连接时暂时触发 AuthKeyDuplicatedError(例如 VPN 重新连接期间),服务器会先通过退避重试,之后才会放弃。

请根据实际并发运行的客户端数量设置会话池大小。如果所有槽位都已被占用,服务器会明确报错并拒绝启动,而不会重复使用其他客户端正在持有的会话;重复使用会导致 Telegram 永久使该会话对两个客户端都失效。

  • “用我的工作账号把这条消息发送给 @example”
在同一台主机上共享一个会话

连接前,每个服务器进程都会获取一个会话级锁(参见“故障排查”下的 AuthKeyDuplicatedError 条目)。默认情况下,该锁为独占锁:同一会话的第二个实例会短暂等待第一个实例退出,否则拒绝启动。该锁只能检测同一台主机上的进程,而 Telegram 的规则针对的是 IP,而非进程:同一台主机上的实例只有在通过不同 IP 连接 Telegram 时才会发生冲突(双栈或分流隧道 VPN 主机)。当它们都使用同一个出口 IP 时(例如一台笔记本运行多个 MCP 客户端),可以让它们共享会话,而无需使用会话池:

TELEGRAM_SESSION_LOCK=shared

共享实例可以彼此共存,但不会与独占实例重叠。如果不确定所有客户端是否都使用同一个出口 IP,请使用会话池。

设备身份

以下可选变量用于控制客户端在 Telegram 设置 > 设备(活动会话列表)中的显示方式:

TELEGRAM_DEVICE_MODEL=Telegram MCP
TELEGRAM_SYSTEM_VERSION=1.0
TELEGRAM_APP_VERSION=1.0

如果未设置,Telethon 会回退到主机平台(例如 arm64)。由于每次连接时都会重新发送这些值,长期运行的服务器会在每次重新连接时覆盖登录期间选择的名称,因此请设置这些值,以保持设备名称稳定且易于识别。会话字符串生成器(登录时)和服务器(每次连接时)都会读取相同的变量,因此请将它们设置在与其他凭据相同的位置。

预期账号检查

设置 TELEGRAM_EXPECTED_USERNAME(或按账号设置 TELEGRAM_EXPECTED_USERNAME_<LABEL>),如果会话属于其他账号,服务器就会拒绝启动。比较时不区分大小写,并忽略开头的 @。未设置时不进行检查。

代理支持

通过设置 TELEGRAM_PROXY_* 环境变量,将 Telegram 流量通过代理路由。支持的类型包括 socks5、socks4、http 和 mtproxy。

SOCKS 和 HTTP 代理需要可选的 python-socks 包:

uv sync --extra proxy
# or
pip install python-socks

单账号配置:

TELEGRAM_PROXY_TYPE=socks5
TELEGRAM_PROXY_HOST=127.0.0.1
TELEGRAM_PROXY_PORT=1080
TELEGRAM_PROXY_USERNAME=optional_user
TELEGRAM_PROXY_PASSWORD=optional_pass
TELEGRAM_PROXY_RDNS=true

MTProxy:

TELEGRAM_PROXY_TYPE=mtproxy
TELEGRAM_PROXY_HOST=mtproxy.example
TELEGRAM_PROXY_PORT=443
TELEGRAM_PROXY_SECRET=ee0123456789abcdef...

按账号设置的覆盖项使用与会话变量相同的 _<LABEL> 后缀,并优先于不带后缀的默认值:

TELEGRAM_PROXY_TYPE=socks5
TELEGRAM_PROXY_HOST=127.0.0.1
TELEGRAM_PROXY_PORT=1080

TELEGRAM_PROXY_TYPE_WORK=http
TELEGRAM_PROXY_HOST_WORK=proxy.work.example
TELEGRAM_PROXY_PORT_WORK=3128

代理设置错误(类型未知、缺少主机或端口、端口无效、缺少 MTProxy 密钥,或缺少 python-socks 包)会导致服务器在启动时快速失败并显示明确的错误信息,而不会静默绕过代理。

文件路径安全

文件路径和媒体工具(send_file、download_media、upload_file、send_voice、send_sticker、set_profile_photo、edit_chat_photo 和 send_album)已注册并受支持,但默认情况下会严格禁用,直到配置允许的根目录(默认采用安全设置,以防止未经授权的文件访问)。

允许的根目录可以来自:

  • 环境变量(TELEGRAM_ALLOWED_ROOTS): 使用分号(;)或逗号(,)分隔的路径(POSIX 系统也支持冒号 :)。适用于 Docker、无头守护进程设置,以及通过环境变量传递设置的 MCP 客户端。
  • 服务 CLI 参数: 传递给 main.py 的位置文件夹路径,作为服务端备用配置。
  • MCP 客户端 Roots: 在受支持的 MCP 客户端中直接配置(roots/list)。

安全行为:

  • 有可用的客户端 MCP Roots 时,它们会替代服务 CLI 根目录。
  • 某些客户端(尤其是 Cursor)会将工作区根目录作为裸绝对路径返回,而不是 file:// URI。这会导致 MCP SDK 验证 list_roots 失败;服务会从验证错误中恢复这些绝对路径,以便文件路径工具继续工作。
  • 默认情况下,空的客户端 Roots 会被视为拒绝所有访问。某些客户端实现了 Roots 功能,但返回空列表;即使配置了服务 CLI 根目录,这也会禁用文件工具。在这种情况下,设置 TELEGRAM_ALLOW_SERVER_ROOTS_FALLBACK=1 可回退到服务 CLI 根目录(需主动选择;默认仍然拒绝所有访问)。如果 list_roots 意外失败且无法恢复客户端路径,同样适用此设置。
  • roots/list 会在 TELEGRAM_ROOTS_TIMEOUT_SECONDS 指定的时间后超时(默认为 10)。配置了服务根目录时,TELEGRAM_SERVER_ROOTS_ONLY=1 会直接使用这些根目录并跳过 roots/list;此时会忽略客户端 Roots。
  • 路径会解析为真实路径,且必须位于允许的根目录内。
  • 不允许包含路径遍历、类似通配符、类似 Shell 或空字节的路径模式。
  • 相对路径会相对于第一个允许的根目录进行解析。
  • 默认情况下,下载内容会保存到 <first_root>/downloads/(如果根文件夹本身已命名为 downloads / Downloads,则直接保存到 <first_root>/)。可通过 TELEGRAM_DOWNLOAD_SUBDIR 配置。
  • 敏感媒体工具会强制执行大小和扩展名限制。默认情况下,send_file 和 upload_file 不限制扩展名;如需添加限制,请参阅上文的 TELEGRAM_FILE_EXTENSIONS。

通过环境变量设置允许的根目录后运行:

# Semicolon- or comma-separated roots
TELEGRAM_ALLOWED_ROOTS="/data/telegram,/tmp/telegram-mcp" uv run main.py

或者通过 CLI 位置参数设置允许的根目录后运行:

uv run main.py /data/telegram /tmp/telegram-mcp

在 MCP 客户端配置中,可以通过 env 传递根目录,或将其作为参数放在 main.py 后面:

{
  "mcpServers": {
    "telegram-mcp": {
      "command": "uv",
      "args": [
        "--directory",
        "/full/path/to/telegram-mcp",
        "run",
        "main.py",
        "/data/telegram",
        "/tmp/telegram-mcp"
      ],
      "env": {
        "TELEGRAM_API_ID": "your_api_id_here",
        "TELEGRAM_API_HASH": "your_api_hash_here",
        "TELEGRAM_SESSION_STRING": "your_session_string_here"
      }
    }
  }
}

聊天访问隐私(允许列表)

若要将 AI Agent 或 MCP 客户端限制为只能访问特定聊天(防止其访问所有私人或企业对话),请配置 TELEGRAM_ALLOWED_CHAT_IDS:

# Comma-separated list of allowed chat IDs, supergroup IDs, or usernames
TELEGRAM_ALLOWED_CHAT_IDS=12345678,-100123456789,@allowed_channel

设置 TELEGRAM_ALLOWED_CHAT_IDS 后:

  • list_chats / get_chats: 仅返回与允许列表匹配的聊天;Agent 完全无法看到其他对话。
  • 消息与聊天工具(send_message、get_messages、get_chat、create_poll 等): 任何与允许列表之外聊天进行交互的尝试都会被拒绝,并返回结构化错误消息:Access to chat '<chat_id>' is restricted by privacy policy (TELEGRAM_ALLOWED_CHAT_IDS)。
  • 搜索与草稿(search_global、get_drafts): 全局搜索和草稿列表会省略不在允许列表中的对话。
  • 联系人、文件夹和群组管理员工具: 对由 contact_id 或 group_id 指定的聊天(get_last_interaction、get_contact_chats、invite_to_group、promote_admin、demote_admin),会像对 chat_id 一样进行检查;get_common_chats、get_contact_chats、get_direct_chat_by_contact 和 get_folder 会从结果中排除不在允许列表中的聊天;create_folder 会拒绝不在允许列表中的 chat_ids。
  • 传入事件: 通知和防抖事件流仅处理来自允许列表中聊天的事件。

若未设置 TELEGRAM_ALLOWED_CHAT_IDS 或其值为空,服务将以不受限制的模式运行(默认设置),完全保持向后兼容。

Docker

构建镜像:

docker build -t telegram-mcp:latest .
共享服务(推荐)

运行一个长期运行的容器以提供可流式传输的 HTTP,并让每个 MCP 客户端都连接到该容器(客户端注册请参见传输方式):

docker run -d --name telegram-mcp --restart unless-stopped \
  --env-file .env \
  -e MCP_TRANSPORT=http \
  -e MCP_HOST=0.0.0.0 \
  -p 127.0.0.1:8765:8765 \
  telegram-mcp:latest

MCP_HOST=0.0.0.0 会在容器内绑定地址,以确保已发布的端口可用; -p 127.0.0.1:8765:8765 会将服务限制为只能从本地 计算机访问——该端点未经身份验证,因此切勿将其发布到公共 网络接口。

附带的 Compose 文件也会运行相同的配置:

docker compose up --build -d

它还会将 ./transcript_cache 挂载到容器中的 /app/data/transcripts,以便语音转录 SQLite 缓存(参见 语音转录)在重新构建后仍能保留,而不是 存放在容器的可写层中。启动前请先创建该目录,并将其所有者设为 容器的 appuser(uid 1000):

mkdir -p ./transcript_cache && chown 1000:1000 ./transcript_cache
每个客户端使用一个容器(stdio)

或者,MCP 客户端可以自行启动专用容器:

{
  "mcpServers": {
    "telegram-mcp": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "--env-file", "/full/path/to/.env", "telegram-mcp:latest"]
    }
  }
}

单个客户端使用这种方式没有问题,但如果有多个客户端(或会 启动子 Agent 会话的编码 Agent),每个客户端都会启动自己的容器和 Telegram 会话,而 Telegram 会对这些会话进行限流;异常退出的客户端 也可能导致容器继续运行。在这种情况下,建议优先使用上面的共享服务。

如需使用多个账号,请传入 TELEGRAM_SESSION_STRING_WORK 和 TELEGRAM_SESSION_STRING_PERSONAL 等变量。

开发

实现分为一个精简的兼容入口和模块化的软件包代码:

main.py                    # historical entrypoint and compatibility exports
telegram_mcp/runtime.py    # shared MCP setup, account routing, validation, file safety
telegram_mcp/runner.py     # application startup
telegram_mcp/tools/        # tool modules grouped by domain
sanitize.py                # output sanitization helpers
tests/                     # pytest suite

运行测试:

uv run pytest

运行测试并生成覆盖率报告:

uv run pytest --cov --cov-report=term-missing --cov-report=xml

覆盖率配置位于 pyproject.toml 中,针对可进行确定性单元测试的核心模块,最低门槛为 80%。GitHub Actions 会运行相同的覆盖率命令并上传 coverage.xml。

运行格式检查:

uv run black --check .
uv run flake8 .

安全说明

  • 切勿提交 .env、会话字符串或 .session 文件。
  • Telegram 会话字符串可用于访问其所属账户。
  • PyPI 上的 telegram-mcp 包名不受本项目控制。 除非所有权发生变更且该包经过验证,否则请避免使用基于 PyPI 的 telegram-mcp 安装命令。
  • 此代码库包含一项尽力而为的启动保护机制:如果已安装的 telegram-mcp 发行包没有源码检出记录或直接通过 git/文件安装的记录,保护机制会拒绝启动。启动不相关的 PyPI 包本身时,此保护机制无法运行,因此请使用基于克隆或显式 git 的安装方式。
  • 运行多个服务实例时,优先使用会话字符串,而非文件会话。
  • 默认情况下,Telegram API 调用会从你的机器/容器直接发送到 Telegram。 如果配置了 TELEGRAM_PROXY_*,Telegram 流量则会通过所配置的 SOCKS/HTTP/MTProxy 代理路由。
  • 用户生成的 Telegram 内容在返回给 MCP 客户端前会经过清理。
提示词注入防护

Telegram 消息、显示名称、聊天标题和按钮标签均为不可信内容。服务会通过以下方式降低提示词注入风险:

  • 在可行时,对用户控制的数据使用结构化 JSON 输出。
  • 使用 sanitize_user_content()、sanitize_name() 和 sanitize_dict() 去除控制字符、不可见字符并限制长度。
  • 使用 MCP 内容注释,将返回内容标记为用户受众数据。
  • 工具说明会提醒客户端,不要将返回的 Telegram 字段视为模型指令。
  • 不使用脆弱的基于关键词的过滤。

故障排除

  • 未配置 Telegram 会话: 设置 TELEGRAM_SESSION_STRING、TELEGRAM_SESSION_NAME 或带后缀的多账户变体。
  • 会话未获授权: 如果可以通过现有 Telegram 应用扫码,请在 MCP 服务之外运行 uv run session_string_generator.py --qr;如果需要使用手机号验证码登录,请运行 uv run session_string_generator.py --phone。 然后在 .env 中设置 TELEGRAM_SESSION_STRING。MCP 服务不会通过 stdio 执行交互式手机号验证码登录,包括重新连接后:如果会话在服务运行期间终止,则会因“重新连接后未获授权”而失败。
  • API 凭据无效: 在 my.telegram.org/apps 验证 TELEGRAM_API_ID 和 TELEGRAM_API_HASH。
  • 数据库已锁定: 确保没有其他进程正在使用同一个文件会话。
  • AuthKeyDuplicatedError /“Another telegram-mcp process is already connected with this session”: 两个进程尝试同时连接同一个 Telegram 会话(例如,MCP 客户端在旧进程退出前重启了连接器),Telegram 会拒绝连接,并可能导致两个进程的会话均失效。现在,服务会在连接前为每个会话获取独占锁;第二个并发启动会短暂等待(默认 20s,可通过 TELEGRAM_LOCK_GRACE_SECONDS 覆盖),等待第一个进程释放锁;否则会直接退出,不会调用 connect(),从而避免发生重复连接竞争。仅在一个实例运行时重试——拒绝信息会指出持有锁的 PID。如果此主机上的多个实例需要共享一个会话(所有实例都从同一 IP 连接 Telegram),请设置 TELEGRAM_SESSION_LOCK=shared;参见从一台主机共享一个会话。
  • 文件工具已禁用: 向客户端传递允许的根目录,或配置 MCP Roots。
  • 文件工具等待 roots/list: 配置服务根目录并设置 TELEGRAM_SERVER_ROOTS_ONLY=1。
  • 路径被拒绝: 确保路径位于允许的根目录内,且不使用路径遍历或通配符模式。
  • 更改密码后出现身份验证错误: 重新生成会话字符串。
  • 仅限 Bot 的工具遭拒: 普通用户账户无法管理 Bot 命令设置。
  • 需要更多详情: 查看 MCP 客户端日志、终端输出和 mcp_errors.log。

贡献

  1. Fork 并克隆仓库。
  2. 安装依赖项和 Git 钩子:
    • uv sync
    • uv run pre-commit install --hook-type pre-commit --hook-type pre-push
  3. 创建一个目标明确的分支。
  4. 行为发生变化时,添加或更新测试。
  5. 在本地运行检查:
    • uv run pre-commit run --all-files
    • uv run pre-commit run --hook-stage pre-push --all-files
  6. 提交 Pull Request,并附上简洁的说明。

许可证

本项目采用 Apache 2.0 License 许可。

致谢

由 @chigwell 和 @l1v0n1 维护。欢迎提交 PR。

Star 历史

Star History Chart

贡献者

README 配图

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。