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 対応

80種類以上のTelegramツールをMCPクライアントに公開し、アカウント、チャット、メッセージ、連絡先、メディア、フォルダー、管理操作を提供します。ツール呼び出しはアカウントラベルで振り分けられます。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

インストール方法は未掲載です

このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。

リポジトリ

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

Telegram MCP サーバー

MCP バッジ ライセンス:Apache 2.0 Python のリントとフォーマットチェック Docker のビルドと Compose の検証

Claude、Cursor、その他の MCP 対応クライアント向けの Telegram 連携です。Telethon を使用し、Model Context Protocol を通じて、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 の結果を返すため、エージェントは従来のモードで書式を整え直して再試行できます。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]、複数選択可能な投票で最初と3番目の回答を選択するには [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 と並列ではなく、その前に呼び出してください。 最大4秒間隔でインジケーターを更新し、完了時、失敗時、キャンセル時には消去を試みます。topic_id を指定すると、特定のフォーラムトピックを対象にします。

同じアカウント、ピア、トピックに対する呼び出しが重複した場合、互いのインジケーターをキャンセルせずに拒否されます。これらの RPC ではフラッド待機中に自動で待機しません。入力中フェーズには50秒のタイムアウトがあり、クリーンアップには別途3秒のタイムアウトがあります。クリーンアップに失敗した場合は、その旨が明示的に報告されます。RPC の成功応答が確認するのは、Telegram がリクエストを受け付けたことだけであり、別のクライアントの UI に表示されたことではありません。これは書き込み操作であり、既存のアカウント振り分けとチャットの許可リストに従います。

記憶された連絡先

set_contact_alias を使うと、サーバーに相手の呼び方を覚えさせることができ、それ以降は chat_id を受け取るすべてのツールでその呼び方を使えます。send_message("андрей бекендер", ...) のように指定するだけで機能します。1人の連絡先にいくつでも別名を設定できます。これがタグの仕組みです。同じ人に андрей бекендер と бекендер の両方を保存すれば、どちらでも解決されます。

保存した表記と完全に一致する場合にのみ、メッセージが送信されます。 保存済みの андрей бекендер に対する Андрею бекендеру のような類似表記も照合されますが、あくまで 候補として提案 するだけです。ツールは何も送信せず、名前で連絡先を確認するよう求めます。これは意図的な仕様です。Лена/Леня と Иван/Иванов の違いは、格語尾の違いとまったく同じ程度です。そのため、格変化にも対応できるほど確信度の高い照合器は、意図した相手がまだ保存されていないときに、誤った相手へメッセージを送るほどの確信を持ってしまいます。確認すると、その表記は独立した別名として保存されます。そのため、新しい言い回しを使うときも、初回に「はい/いいえ」で確認するだけで、次回以降は確認不要です。候補の提案も無効にするには、TELEGRAM_CONTACT_FUZZY=0 を設定します。

参照先が不明な場合、1人の連絡先に似ている場合、複数の連絡先に一致する場合、またはすでに解決できない連絡先を指している場合、ツールは何も送信せず、エージェントに対してユーザーに何を尋ねるべきか、回答を set_contact_alias で保存してから一度だけ再試行するよう、明確に指示する構造化された応答を返します。list_contact_aliases では、すべての別名を含む連絡先1人につき1行が表示されます(誤った記憶がないか確認する際に使えます)。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) は、ボイスメッセージまたは動画メッセージをテキストに変換します。4つのエンジンを利用できます。

  • groq(デフォルト):録音をGroqのホスト型whisper-large-v3-turboにアップロードします。録音がサーバーの外に送信され、呼び出しごとにダウンロードとアップロードの通信コストがかかりますが、ネイティブの文字起こしのように録音の最後の数語が欠落することはありません。GROQ_API_KEYが必要です。Groqは1回のアップロードサイズに上限を設けているため、TELEGRAM_TRANSCRIBE_GROQ_MAX_MB(デフォルトは25、無料プランの上限)を超える録音は、ダウンロードされてAPIに拒否されるのではなく、サイズを示すtoo_largeエラーとともにローカルで拒否されます。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(キー不要のローカルサーバーでは省略可能)、モデルに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(モデルのダウンロード先)を設定して調整できます。モデルは初回使用時に一度読み込まれ、録音は一度に1件ずつ文字起こしされます。Alpine Dockerイメージでは利用できません。代わりに、コンテナーと同じ環境にあるParakeetなどのOpenAI互換サーバーに対してopenaiを使用してください。

TELEGRAM_TRANSCRIBE_LANGUAGE(ISO-639-1。例:nl)は、telegram以外のすべてのエンジンに言語ヒントとして渡されます。設定されていない場合、エンジンが言語を自動検出します。TELEGRAM_TRANSCRIBE_TIMEOUT(デフォルトは120秒)は、HTTPを使用するエンジン(groq、openai)への1回のリクエストのタイムアウトを設定します。

エンジンは呼び出しごとにengine引数で選択します。指定がない場合は、TELEGRAM_TRANSCRIBE_ENGINE(groq、telegram、openai、whisper)が使われます。結果はローカルのSQLiteファイルに(chat_id, message_id, engine)をキーとしてキャッシュされるため、同じメッセージを再読み込みまたは再一覧表示しても、文字起こしが繰り返されることはありません。同じ未キャッシュの録音への同時リクエストもまとめられます。2つ目のリクエストは1つ目の完了を待ち、その文字起こし結果を返すため、呼び出しが集中しても有料の呼び出しは呼び出しごとではなく1回だけです。すべての文字起こし結果には、逐語的な引用ではなく機械による文字起こしであることを示す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 でも、欠落している文字起こし結果を先行取得します。1 回の呼び出しあたりの上限は 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 を指定し、1 つのチャットだけを対象にできます。指定しない場合は、関係のない会話によっても待機が解除されます。また、コールバック形式で配信するオプトインの受信イベントフィードを有効にすることもできます(以下を参照)。チャットブリッジなど、チャットを追跡するインテグレーターは、代わりにメッセージごとのイベントログを使用してください(以下を参照)。

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はメッセージごとに1回だけ表示されます。フォールバック絵文字が同じに見えても、 異なるIDは別々に保持されます。これは再利用可能な絵文字バリエーションのリストであり、 絵文字の位置を示すマップでも、メッセージの書式情報全体のコピーでもありません。抽出には rich_messageのブロック形式コンテンツ内のTextCustomEmojiノードを含む、 元のTelegramエンティティが使われ、追加の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アカウントの制限が適用されます。

プレーンテキストメッセージの場合は、HTMLもエスケープも使わず、エントリをそのまま custom_emojisとして渡してください。テキストはそのまま送信されます。たとえば、 send_message(chat_id, "🍷 News for List<int> & co", custom_emojis=[{"emoji": "🍷", "id": "5368324170671202286"}])のように指定します。同じパラメーターは reply_to_messageとedit_messageでも使えます。各emojiの単独での出現箇所は、 URLやコード内にあるものも含め、すべてそのカスタム絵文字になります。1つを通常の絵文字のままにするには、 parse_mode="html"を使い、代わりに<tg-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 専用)

デフォルトでは、エージェントは wait_for_settled_message を呼び出して返信を待ちます。この呼び出しは MCP ツールのタイムアウトまでブロックされるため、再度呼び出す必要があります。これはどこでも(Codex、Cursor などで)機能し、動作に変更はありません。

外部出力を受けてエージェントを起動できるクライアント(tail -f を使う Claude Code の永続的な Monitor など)では、代わりにコールバックモードに切り替えられます。

  1. エージェントが enable_incoming_feed を呼び出します(または、環境変数に TELEGRAM_EVENT_FEED=1 を設定すると自動的に有効になります)。確定した受信バーストは、それぞれ 1 行の JSON として ${XDG_STATE_HOME:-~/.local/state}/telegram-mcp/incoming_feed.jsonl に追記されます。ファイルは所有者のみがアクセスできる権限(0600)で作成されます。TELEGRAM_EVENT_FEED_FILE でパスを上書きできます。明示的に指定したパスのディレクトリは、あらかじめ存在している必要があります。incoming_feed_status を呼び出すと、有効なパスと、すぐに使用できる監視コマンドが返されます。
  2. エージェントは、ツールから返された watch_command を使って永続的な Monitor を起動します。新しい行が追加されるたびに、バーストの概要とともにエージェントが再度呼び出されます。ブロックするツール呼び出しが継続することはなく、チャットも引き続き使用できます。

disable_incoming_feed を呼び出すと元のモードに戻り、incoming_feed_status で現在のモードを確認できます。フィードが有効な間は確定したバーストを処理するため、wait_for_settled_message と併用しないでください。フィードの行にはユーザーが生成した name フィールドが含まれるため、信頼できないデータとして扱ってください。

メッセージごとのイベント(チャットブリッジ)

プライベートチャット、基本グループ、スーパーグループで新しいメッセージを受信するたびに、上限付きのインメモリログ(TELEGRAM_EVENT_LOG_SIZE、デフォルトは 2000。0 にすると無効になります)に番号付きイベントが 1 件記録されます。受信メッセージだけでなく、所有者が別のデバイスから送信したメッセージも対象です。このサーバー自身が送信したメッセージは対象外です。ブロードキャストチャンネル、および 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 が指定されている場合は新しいメッセージが残っているか、指定されていない場合は古いメッセージが存在するか)、messages が含まれます。フォーラムでは、トピック ID をタイトルに対応付ける topics マップも 1 つ含まれます。負の after_id は拒否されます。
  • send_message は reply_to を受け取ります(トピック ID を指定すると、そのフォーラムトピックに投稿されます)。また、送信したメッセージを識別できるよう、メッセージ ID も返します。通常の送信では末尾に message_id=<id> が付加されます。リッチ送信(rich* パースモード)では、message_id キーを含む JSON が返されます(Telegram の応答に ID が含まれない場合は null)。これにより、ブリッジは履歴に再表示された自分のメッセージを識別できます。

上記のデバウンスツールは、引き続きプライベートチャットのみを対象とします。

要件

  • Python 3.10+
  • my.telegram.org/apps の Telegram API 認証情報
  • Telegram セッション文字列またはファイルベースのセッション
  • Claude Desktop、Cursor などの MCP クライアント、またはその他の 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 など、何も変わらない指定)も、起動に失敗します。音声文字起こしを無効にするには、-transcribe_voice ではなく TELEGRAM_TRANSCRIBE=off を設定してください。ツールを非表示にしても、一覧に表示される文字起こし待ちのヒントや auto による先行取得はそのまま残ります。

起動時に、サーバーはモードによって非表示になるツール名を標準エラー出力に表示します。これらの名前は + のリストで指定できます。- のリストによって非表示になるツールは、別の行に表示されます。

これは 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 はデフォルトで任意の拡張子を受け付けます。これら2つのツールに許可リストを追加する場合、またはハードコードされた許可リストを厳しくしたり置き換えたりする場合は、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 クライアントと LLM エージェントにそのまま通知されます。

TELEGRAM_FLOOD_SLEEP_THRESHOLD を使用して、Telethon の内部サイレントスリープしきい値を設定します(デフォルト:60 秒)。0 に設定するとサイレントスリープが無効になり、すべてのバックオフ間隔の調整をエージェントに任せられます。

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

生成された telegram-mcp.mcpb を Claude Desktop で開くか(または「設定」→「拡張機能」にドラッグし)、API ID、API ハッシュ、セッション文字列を入力します(生成方法についてはクイックスタートを参照してください)。Claude Desktop は uv を使って Python と依存関係を自動でインストールし、API ハッシュとセッション文字列を機密フィールドとしてマスキングします。許可するチャットとファイルディレクトリの各フィールドは、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
トランスポート

サーバーは 3 種類の MCP トランスポートに対応しており、MCP_TRANSPORT で選択します。

値トランスポート用途
stdiostdio(デフォルト)MCP クライアントごとに専用のサーバープロセスを 1 つ起動します
httpストリーム可能 HTTP多数のクライアント(Claude Code、Codex、Cursor)でサーバーを 1 つ共有します
sseSSE(レガシー HTTP)非推奨の SSE トランスポートのみをサポートするクライアント向け

http と sse の場合、サーバーは MCP_HOST:MCP_PORT(デフォルトは 127.0.0.1:8765)にバインドします。ストリーム可能 HTTP のエンドポイントは /mcp、SSE のエンドポイントは /sse です。

サーバーが 127.0.0.1/localhost のみではなく、ドメイン経由(リバースプロキシの背後など)で アクセス可能な場合は、DNS リバインディング保護を有効にしてその Host ヘッダーを許可するため、 MCP_ALLOWED_HOSTS(および必要に応じて MCP_ALLOWED_ORIGINS)を設定します。例: MCP_ALLOWED_HOSTS=mcp.example.com。カンマ区切りで指定します。任意のポートを許可するには :* サフィックスを使用できます。未設定の場合、DNS リバインディング保護はオフのままです (従来のデフォルト)。

複数の MCP クライアント(または多数のコーディングエージェントのセッション)でサーバーを使用する場合は、 http をおすすめします。クライアントごとに独自の Telethon セッションを起動する代わりに、 単一の長時間稼働プロセスが Telegram 接続を 1 つ保持します。Telegram は多数の並行セッションを 開くアカウントに対して、スロットリングを行ったり、フラグを付けたりすることがあります。

各ツール呼び出しには、TELEGRAM_TOOL_TIMEOUT_SECONDS で設定する 55 秒のサーバー側上限も あります。タイムアウトした 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 を省略するとすべてのアカウントに対して実行されます。

プロンプトの例:

  • 「自分のアカウントを一覧表示して」
  • 「すべてのアカウントの未読メッセージを表示して」
セッションプール(1 つのアカウントで複数のクライアントを同時に利用)

同じ Telegram アカウントに対して複数の MCP クライアント(たとえば、デスクトップアプリとターミナルの CLI)を同時に実行するには、各クライアントにそれぞれ認証済みセッションを割り当てます。Telegram では、1 つのセッション(認証キー)を 2 つの IP から同時に使用することは禁止されているため、VPN またはデュアルスタックのホストでは、ローカルの 2 つのクライアントが競合して 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 にこれを送信」
1 つのホストで 1 つのセッションを共有する

接続前に、各サーバープロセスはセッションごとのロックを取得します(トラブルシューティングの AuthKeyDuplicatedError の項を参照)。デフォルトでは排他的で、同じセッションを使う 2 つ目のインスタンスは、1 つ目のインスタンスが終了するまで短時間待機し、終了しない場合は起動を拒否します。このロックで確認できるのは同じホスト上のプロセスだけです。一方、Telegram のルールはプロセスではなく IP に関するものです。つまり、同じホスト上のインスタンスが競合するのは、異なる IP から Telegram に接続する場合(デュアルスタックまたはスプリットトンネル VPN のホスト)だけです。すべてのインスタンスが同じ送信元 IP を共有している場合(複数の MCP クライアントを実行するノート PC など)は、プールを使わずにセッションを共有できます。

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 Roots に置き換わります。
  • 一部のクライアント(特に Cursor)は、file:// URI ではなく、ワークスペースのルートを絶対パスのまま返します。これにより、MCP SDK の list_roots 検証でエラーになります。サーバーは検証エラーからこれらの絶対パスを復元するため、ファイルパス関連のツールは引き続き動作します。
  • クライアントの Roots が空の場合、デフォルトではすべてのアクセスが拒否されます。Roots 機能を実装していても空のリストを通知するクライアントがあり、その場合、サーバーの CLI Roots が設定されていてもファイルツールは無効になります。この場合にサーバーの CLI Roots を使うには、TELEGRAM_ALLOW_SERVER_ROOTS_FALLBACK=1 を設定します(明示的なオプトインです。デフォルトでは引き続きすべてのアクセスが拒否されます)。このオプトインは、list_roots が予期せず失敗し、クライアントのパスを復元できなかった場合にも適用されます。
  • roots/list は TELEGRAM_ROOTS_TIMEOUT_SECONDS(デフォルトは 10)を過ぎるとタイムアウトします。サーバーのルートが設定されている場合、TELEGRAM_SERVER_ROOTS_ONLY=1 を指定すると、それらを直接使用し、roots/list をスキップします。この場合、クライアントの Roots は無視されます。
  • パスは実際のパスに解決され、許可されたルート内に収まる必要があります。
  • トラバーサル、ワイルドカード風、シェル風、ヌルバイトを含むパスパターンは拒否されます。
  • 相対パスは、最初の許可されたルートを基準に解決されます。
  • ダウンロード先のデフォルトは <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 エージェントまたは 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: 許可リストに一致するチャットのみが返され、その他の会話はすべてエージェントから完全に見えなくなります。
  • メッセージ送信およびチャットツール(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 が未設定または空の場合、サーバーは無制限モード(デフォルト)で動作し、100%の後方互換性が維持されます。

Docker

イメージをビルドします:

docker build -t telegram-mcp:latest .
共有サーバー(推奨)

ストリーミング可能な HTTP を提供する長時間稼働のコンテナを 1 つ実行し、すべての 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
クライアントごとに 1 つのコンテナ(stdio)

代わりに、MCP クライアント自身が専用コンテナを起動することもできます:

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

単一のクライアントであれば問題ありませんが、複数のクライアント(またはサブエージェントのセッションを起動するコーディングエージェント)がある場合、それぞれが独自のコンテナと 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 のインストールコマンドは避けてください。
  • このリポジトリには、ソースコードのチェックアウトまたは直接の Git/ファイルインストール記録がない telegram-mcp ディストリビューションのインストールを拒否する、ベストエフォートの起動時ガードが含まれています。このガードは、無関係な 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 アプリから QR コードをスキャンできる場合は、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」: 2 つのプロセスが同じ Telegram セッションに同時に接続しようとしました(例:古いプロセスの終了前に MCP クライアントがコネクターを再起動した場合)。この操作は Telegram に拒否され、両方のプロセスでセッションが無効になることがあります。サーバーは接続前にセッションごとの排他的ロックを取得するようになりました。同時に起動した 2 つ目のプロセスは、最初のプロセスがロックを解放するまで短時間(デフォルトは 20 秒。TELEGRAM_LOCK_GRACE_SECONDS で変更可能)待機し、解放されなければ connect() を呼び出さずに終了します。重複接続を試みることはありません。1 つのインスタンスだけが実行されている状態で再試行してください。拒否メッセージには、ロックを保持している PID が表示されます。このホスト上の複数のインスタンスで 1 つのセッションを共有する場合(すべて同じ IP から Telegram に接続する場合)は、TELEGRAM_SESSION_LOCK=shared を設定してください。1 つのホストからセッションを共有するを参照してください。
  • ファイルツールが無効になっています: 許可するルートを指定するか、クライアントで MCP Roots を設定してください。
  • ファイルツールが roots/list を待機しています: サーバーのルートを設定し、TELEGRAM_SERVER_ROOTS_ONLY=1 を設定してください。
  • パスが拒否されます: パスが許可されたルート内にあり、トラバーサルやワイルドカードパターンを使用していないことを確認してください。
  • パスワード変更後に認証エラーが発生します: セッション文字列を再生成してください。
  • ボット専用ツールが拒否されます: 通常のユーザーアカウントでは、ボットのコマンド設定を管理できません。
  • 詳細が必要な場合: MCP クライアントのログ、ターミナル出力、mcp_errors.log を確認してください。

貢献

  1. リポジトリをフォークしてクローンします。
  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. 簡潔な説明を添えてプルリクエストを作成します。

ライセンス

このプロジェクトは、Apache 2.0 License のもとでライセンスされています。

謝辞

@chigwell と @l1v0n1 がメンテナンスしています。プルリクエストを歓迎します。

スター履歴

スター履歴グラフ

コントリビューター

README の画像

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。