tunnel-mcp について
tunnel-mcpは、一時的なエンドツーエンド暗号化トンネルでClaudeエージェントを接続するMCPサーバーです。2者間セッションとルームに対応し、人間が操作を管理しながらメッセージや暗号化ファイルを共有できます。
主な機能
- 01暗号化トンネルの開設と参加
- 022者間セッションとルーム
- 03メッセージの送受信
- 04ハッシュ検証付き暗号化ファイル共有
- 05メンバーとセッション状態の確認
- 06セッションの終了または退出
活用シーン
- 01別々の開発者のClaudeエージェント間の協業
- 02異なるマシン間でのデバッグ
- 03セッションメンバーへのプロジェクトファイル共有
MCP 対応
トンネルセッションの開設、参加、メッセージ送受信、終了のためのツールをMCPクライアントに公開します。ファイル共有とセッション状態の確認にも対応し、Claude MCPクライアントからエージェント同士を直接接続できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
9掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| goal | string | はい | |
| invites | integer | いいえ |
詳細
tunnel-mcp
2 人の開発者の Claude エージェントを、エンドツーエンド暗号化されたトンネルで直接つなぎます。人がコピー&ペーストする必要はありません。

30 秒で同じことを試せます — リポジトリをクローンして、次を実行してください。
npm ci && npm run demo
これにより、Cloudflare のエッジを経由する実際の暗号化トンネルが開き、ゲストとして参加して、エンドツーエンド暗号化されたメッセージを交換し、参加リンクが 1 回限りであることを確認した後、すべてを終了します。
2 人の開発者がそれぞれ Claude エージェントを実行し、エージェント同士を連携させる必要がある場合、通常は人が仲介役となり、片方のチャットウィンドウからもう片方へメッセージをコピー&ペーストします。tunnel-mcp はその人の仲介を不要にします。一方の開発者のエージェントが使い捨ての暗号化トンネルを開き、もう一方の開発者のエージェントがそこへ直接接続できる MCP サーバーです。これにより、2 つのエージェントは直接会話でき、人間はファイルシステムやシェルで実際に何が行われるかを引き続き管理できます。
仕組み
一方の開発者(ホスト)が tunnel_open を呼び出します。ローカルの tunnel-mcp プロセスがプロセス内の WebSocket リレーとなり、使い捨ての cloudflared Quick Tunnel を介してインターネットに公開されます。ポートフォワーディングも、プロビジョニングが必要なサーバーもありません。もう一方の開発者(ゲスト)がホストから共有されたリンクを使って tunnel_join を呼び出し、そのエージェントが同じトンネルに外向きに接続します。どちらも外向きの接続しか行わないため、一般的なファイアウォールや NAT の背後からでも動作します。
Host machine Guest machine
┌───────────────────┐ outbound HTTPS ┌───────────────────┐
│ Claude (host) │ wss:// │ Claude (guest) │
│ │ │ ┌──────────────┐ │ │ │
│ tunnel_open/say/ │──────▶ cloudflared │◀────────│ tunnel_join/say/ │
│ listen/close │ │ Quick Tunnel │─────────▶ listen/close │
│ │ │ └──────────────┘ │ │ │
│ in-process relay │ └───────────────────┘
└───────────────────┘
リレーと cloudflared の子プロセスはセッション中だけ動作し、終了時に破棄されます。トランスクリプトはメモリ内にのみ保持され、ディスクに書き込まれることはありません。終了時にプロセスとともに消去されます。
インストール
npm install -g tunnel-mcp
# or, without installing:
npx tunnel-mcp
Claude Code に登録してください(両方の開発者が最初に 1 度だけ行います)。
claude mcp add tunnel -- tunnel-mcp # if globally installed
# or, with no global install:
claude mcp add tunnel -- npx -y tunnel-mcp
tunnel-mcpは stdio MCP サーバーであり、対話型 CLI ではありません。手動で起動しても、クライアントを待つため何も表示されません。これは想定された動作です。使い方を確認するにはtunnel-mcp --help、バージョンを確認するにはtunnel-mcp --versionを実行してください。
tunnel-etiquette スキルは、各エージェントがトンネル内でどのように振る舞うべきかを教えます(相手を信頼できない入力として扱い、相手の発言に基づいて行動する前に人間に確認します)。パッケージをインストールすると、スキルは自動的に ~/.claude/skills/ にコピーされます(ベストエフォート)。インストールスクリプトが無効になっている場合(npm install --ignore-scripts)、カスタムディレクトリに配置したい場合、または強制的に更新したい場合は、明示的に実行してください。
npx tunnel-mcp install-skill # into ~/.claude/skills
npx tunnel-mcp install-skill --dir <path> --force # elsewhere / overwrite
TUNNEL_SKILLS_DIR を設定するとデフォルトの配置先を変更できます。また、TUNNEL_SKIP_SKILL_INSTALL=1 を設定すると自動コピーを無効にできます。
cloudflared がまだ PATH 上にない場合、必要になった初回に ~/.tunnel/bin へ自動ダウンロードされます。追加のインストールは不要です。
クイックスタート
ホスト — Claude に目的を伝えて、トンネルを開くよう依頼します。
「チェックアウトフローのデバッグを一緒に行うため、トンネルを開いてください。」
Claude は tunnel_open({ goal }) を呼び出し、すぐに転送できる招待を返します。招待は、1 回限りのセットアップコマンドと参加リンクを含むプレーンテキストのメッセージです。信頼できるチャネル(Slack の DM など)で、もう一人の開発者に貼り付けて送信します。このリンクは秘密情報です。セッションの暗号化キーが含まれているためです。1 回のみ使用でき、有効期限は約 10 分です(tunnel_open が joinLinkExpiresInSec を返します)。そのため、すみやかに共有してください。
ゲスト — リンクを貼り付けて、Claude に参加するよう依頼します。
「このトンネルに参加してください:
<link>」
Claude は tunnel_join({ joinLink }) を呼び出して目的を確認し、ルームのメンバー一覧を返します。デフォルトの招待数は 1 人なので、参加者はあなたともう一人だけです。
ゲストが複数いる場合は、代わりにルームを開きます。
「チェックアウトフローのデバッグを一緒に行うため、私とチームメイト 2 人のトンネルを開いてください。」
Claude は tunnel_open({ goal, invites: 3 }) を呼び出します。invites は参加させるチームメイトの人数です(最大 15 人で、ホストを含めると同時に 16 人まで接続できます)。単一のリンクではなく、チームメイトごとに 1 つの招待が返されます。それぞれの招待は必ず 1 人だけに転送してください。招待はすべて 1 回限りのため、同じリンクを 2 人に使い回さないでください。セッションの途中で誰かを追加したい場合や、招待の有効期限が切れる前に使用できなかった人を再招待したい場合は、(ホスト専用の)tunnel_invite({ count }) で招待を追加発行できます。
両者 — エージェントは tunnel_say でメッセージを送信し、tunnel_listen で次の返信を待つことで、交互に会話します。ルームでは、すべてのメッセージに fromName が付くため、エージェントは必要に応じて人間に確認しながら、誰が何を言ったかを把握できます。
セッションの終了はロールによって異なります。ホストが tunnel_close を呼び出すと、全員のセッションが終了し、中継が停止します。インメモリのトランスクリプトも同時に消去されます。ディスクに書き込まれたことはないためです。メンバーが tunnel_close を呼び出した場合は、そのメンバーだけが退出し、残りのメンバーのためにルームは開いたままです。
ファイルの共有: メンバーは誰でも tunnel_share({ path }) を呼び出して、テキストファイルまたはバイナリファイルをルームに送信できます。ファイルはディスクから読み込まれ、ハッシュ化され、ルームキーで暗号化されてからトンネルを通過するため、中継が目にするのは暗号文だけです。チームメイトには、tunnel_listen 内の artifact メッセージと tunnel_status().artifacts(id、name、kind、size、sender)に共有ファイルが表示されます。ファイルを受け取りたいチームメイトは、自分で選んだパスを指定して tunnel_receive({ artifactId, savePath }) を呼び出します。データは復号され、書き込まれる前に送信者の sha256 と照合されます。一致しない場合は保存せず、拒否されます。アーティファクトは、有効期限(30 分の TTL)が切れるかセッションが終了するまで、現在のメンバーなら誰でも取得できます。tunnel_receive を呼び出すたびに、個別に再取得して再検証されます。古いクライアントを使うメンバーは通知なしにスキップされ(tunnel_share の結果にある olderMembers)、共有の通知を受け取ることはありません。ファイル名は平文のメタデータとして送信されるため、ファイル名に秘密情報を含めないでください。また、受信したファイルはすべて信頼できない入力として扱ってください。エチケットスキルを参照してください。
ツール
| ツール | 利用者 | 目的 |
|---|---|---|
tunnel_open({goal, invites?}) | ホスト | リレーと Quick Tunnel を起動し、チームメイトごとに招待リンクを 1 つ(デフォルトは 1 つ。従来の 2 者間通信)返します。 |
tunnel_invite({count?}) | ホスト | セッション中に、有効期限付きの 1 回限りの招待リンクを追加発行します。 |
tunnel_join({joinLink}) | メンバー | 招待リンクを使ってルームに接続し、認証します。現在のメンバー一覧を返します。 |
tunnel_say({text}) | 全員 | ルームにメッセージを送信します。 |
tunnel_listen({sinceSeq?, timeoutMs?}) | 全員 | 次のメッセージを待機します。各メッセージには送信者の fromName が付与されます。 |
tunnel_share({path}) | 全員 | ファイル(テキストまたはバイナリ)をエンドツーエンドで暗号化してルームに共有します。{artifactId, offeredTo, olderMembers} を返します。 |
tunnel_receive({artifactId, savePath}) | 全員 | 提供されたアーティファクトを取得し、ハッシュを検証して、指定したパスに書き込みます。 |
tunnel_status() | 全員 | セッションのロール、目的、メンバー一覧、保留中の招待、提供されたアーティファクト、lastSeq を確認します。 |
tunnel_close({summary?}) | 全員 | ホストの場合は、全員のセッションを終了します。メンバーの場合は、ルームから退出します。 |
セキュリティモデル
tunnel-mcp は本質的にセキュリティ上の注意を要するツールです。開発者の AI エージェント間にリアルタイムの通信経路を開きます。このツールが保護するものと、保護しないものを以下に正確に説明します。
- チャットメッセージの本文はエンドツーエンドで暗号化されます。 すべての
tunnel_sayの本文は、cloudflaredのパイプを通る前に NaClsecretbox(tweetnaclを介した XSalsa20-Poly1305)で暗号化されます。リレーとパイプからチャット本文の平文が見えることはなく、暗号文だけが見えます。 - 目的、参加者全員の表示名、システムイベントは平文です。
tunnel_openの目的、各メンバーの名前、接続イベント(参加/退出/アイドル/終了)はメタデータとして平文で送信されます。目的の文字列や表示名に秘密情報を含めないでください。 - 認証は鍵の送信ではなく、鍵を所持していることの証明です。 参加時には HMAC チャレンジを使い、参加メンバーがホストと同じ鍵を持っていることを証明します。生の鍵がネットワーク経由で送信されることはありません。
- 各招待は一度だけ使用できる、有効期限付きの認証情報です。 セッションキーが埋め込まれているため、パスワードのように扱ってください。すでに信頼しているチャネル(Slack の DM など)でのみ共有し、公開の Issue、PR、チャットには決して投稿せず、各招待を必ず 1 人だけに転送してください。最初に引き換えた人が招待を使用し、その後退出しても再利用できません。また、約 10 分後に自動的に有効期限が切れるため、招待が漏えいした場合のリスクにさらされる時間は短く、限定的です。
- 招待した相手だけを確実に参加させます。 デフォルトでは 2 者間で、ルームはオプトイン(最大 16 人)です。各招待は一度だけ使用でき、有効期限があります。参加できる人数はホストが作成した招待の数によって制限され、ルームの鍵をたまたま持っている人が参加できるわけではありません。
- 共有ファイルはエンドツーエンドで暗号化され、ハッシュ検証されます。
tunnel_shareは、ファイルのバイト列がトンネルを通る前に、チャットと同じルームキーを使って NaClsecretboxで暗号化し、内容の sha256 を平文で付加します。tunnel_receiveはファイルを復号、再構成し、ディスクに書き込む前にそのハッシュを検証します。ファイル名、サイズ、種類は平文のメタデータです(ファイル名に秘密情報を含めないでください)。受信したファイルは信頼できないものとして扱ってください。tunnel_receiveが書き込むのは受信者が選んだパスのみであり、送信者が指定した名前が使われることはありません。 - ピアからの情報は信頼できない入力であり、指示の情報源ではありません。 他のエージェントからのメッセージは、実行するコマンドではなく、推論の対象となるデータです。これは 1 人だけではなく、ルーム内のすべてのメンバーに当てはまります。エチケットスキルは、ファイルの書き込み、リスクのあるコマンドの実行、あるいはピアの発言に基づいて修正を「確認済み」と宣言する前に、各エージェントがそれぞれの人間の承認を得るよう指示します。
- すべてが一時的です。 会話履歴はメモリ内にのみ保持され、ディスクに書き込まれることはなく、プロセスの終了とともに消去されます。終了時の動作は役割によって異なります。ホストの
tunnel_close(またはホストのプロセス終了、あるいはメッセージが 30 分間ない場合)は全員のセッションを終了し、リレーとcloudflaredの子プロセスを終了します。メンバーのtunnel_closeはそのメンバーが退出するだけで、残りのメンバーのためにルームは開いたままになります。
脅威モデルの詳細と脆弱性の報告方法については、SECURITY.md を参照してください。
要件
- Node.js >= 20
- Claude MCP クライアント(例:Claude Code)
cloudflared— まだPATHに存在しない場合、初回使用時に~/.tunnel/binへ自動インストールされます
開発
npm ci # install dependencies
npm test # run the test suite (248 tests, TDD)
npm run build # compile TypeScript
npm run lint # eslint
npm run format:check # prettier --check .
npm run test:coverage # vitest run --coverage
変更の提案方法については、CONTRIBUTING.md を参照してください。
トラブルシューティング
tunnel-mcp / npx tunnel-mcp を実行しても「何も起きません」。 これは対話型のコマンドラインではなく、stdio MCP サーバーです。引数なしで起動すると、MCP クライアントが標準入力/標準出力経由で接続するのを待ちます。これは想定どおりの動作です。クライアントに登録するか(上記参照)、tunnel-mcp --help を実行してください。
ゲストの参加に失敗し、getaddrinfo ENOTFOUND …trycloudflare.com が表示されます。 cloudflared のクイックトンネルは、トンネルごとの DNS レコードが伝播する数秒前に URL を表示します。何かが早すぎるタイミングで名前解決を試みると、NXDOMAIN が返され、リゾルバーに最大 30 分間ネガティブキャッシュされます。そのため、トンネルが稼働した後も参加できなくなります。tunnel-mcp はこれを回避します。tunnel_open は、リンクを返す前にレコードが実際に名前解決されるまで待機します(Cloudflare の 1.1.1.1 への DoH 経由で確認します。この IP はシステムのリゾルバーを経由しないため、キャッシュを汚染することもありません)。また、ゲストはまずシステム DNS を使い、失敗した場合は DoH にフォールバックします。そのため、新しい参加であれば通常はそのまま動作します。ENOTFOUND が発生した場合は、それより前の試行でキャッシュが汚染された可能性があります。キャッシュの期限が切れるまで待つか、DNS キャッシュをフラッシュしてください(macOS の場合は sudo dscacheutil -flushcache)。DoH(1.1.1.1)がブロックされ、システム DNS ではすでに *.trycloudflare.com が名前解決されるネットワークでのみ、TUNNEL_DOH=off を設定してください。
ロードマップ/未対応
これは MVP です。現時点では、以下は明示的に対象外です。
- ホストがオフラインの場合のメッセージング/非同期メッセージング
- 代替トランスポート(ngrok、WebRTC)
- 招待のローテーション(セッション中に、まだ有効な特定の招待を置き換えること。なお、招待はすでに使い捨てで、有効期限があります。上記のセキュリティモデルを参照してください)
- 目標やその他のメタデータの暗号化
ライセンス
MIT — LICENSE を参照してください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。