mcpField
T
Tailscale MCP

Tailscale MCP

ローカル
tmhsdigital.github.ioクラウド・インフラ14 日前に更新

Tailscale MCP について

Tailscale MCPは、Agentや開発ツールが認証済みのローカルTailscaleデーモンを確認・操作するstdioサーバーです。tailnetの検出、SSH設定、ポート共有、遅延確認を扱い、構造化エラーと初期状態で無効な公開設定を備えます。

主な機能

  1. 01tailnetの状態とノードの確認
  2. 02SSH設定の生成
  3. 03ServeまたはFunnelによるポート共有
  4. 04ノードの到達性と遅延の確認
  5. 05読み取り専用モードとFunnel権限の制御

活用シーン

  1. 01デプロイ前にオンラインのtailnetノードを検索
  2. 02ノード用のSSHホスト設定を生成
  3. 03tailnetメンバーと開発ポートを共有
  4. 04ノード間の接続が直接か中継かを確認

MCP 対応

stdio経由で、構造化されたTailscaleの状態、SSH設定、共有、pingのツールをMCPクライアントに公開します。ツールのアノテーションと出力スキーマで読み取り専用操作と状態変更操作を示します。

設定

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

mcp.json · 共通設定
{
"mcpServers": {
"tmhsdigital-tailscale": {
"command": "npx",
"args": [
"-y",
"@tmhs/tailscale-mcp"
],
"env": {
"TAILSCALE_MCP_ALLOW_FUNNEL": "<TAILSCALE_MCP_ALLOW_FUNNEL>",
"TAILSCALE_MCP_READONLY": "<TAILSCALE_MCP_READONLY>",
"TAILSCALE_MCP_BIN": "<TAILSCALE_MCP_BIN>",
"TAILSCALE_MCP_TIMEOUT_MS": "<TAILSCALE_MCP_TIMEOUT_MS>"
}
}
}
}
起動コマンドnpx -y @tmhs/tailscale-mcp
設定が必要な環境変数
TAILSCALE_MCP_ALLOW_FUNNELSet to 1 to let share_port expose a port to the open internet with Funnel (off by default)
TAILSCALE_MCP_READONLYSet to 1 for monitoring only: no share tools, and no SSH config writes
TAILSCALE_MCP_BINPath to the tailscale binary if it is not on PATH or in the default install location
TAILSCALE_MCP_TIMEOUT_MSPer-call timeout for tailscale commands in milliseconds (default 10000)

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
npm@tmhs/tailscale-mcp0.4.0

ツール

6

掲載時のツール一覧 · 3 日前に更新

パラメーター型必須説明
onlineOnlybooleanいいえ現在オンラインのピアのみを含めます(デフォルト:false)。

詳細

Tailscale MCP

ローカルの Tailscale デーモンに安全にプログラムからアクセスするための MCP サーバーです。tailnet の検出、SSH 設定の生成、Serve/Funnel によるポート共有、レイテンシーマトリクスに対応します。

ライセンス:CC-BY-NC-ND-4.0 npm バージョン CI


stdio 経由で、エージェントや開発者向けツールにローカルの Tailscale デーモンへの安全で構造化されたアクセス手段を提供します。tailscale CLI を呼び出して実行します(PATH から検索し、見つからない場合は Windows と macOS の既定のインストール先も検索します)。認証キーや tailnet の認証情報は一切扱いません。CLI は、すでに認証済みのローカルデーモンと通信します。

バイナリが見つからない場合、デーモンが停止している場合、またはデバイスでログインが必要な場合、各ツールは例外をスローする代わりに、code と正確な remedy コマンドを含む構造化エラーを返します。

インストール

Cursor に追加 VS Code にインストール Claude Desktop 用にダウンロード

  • Claude Code: claude mcp add tailscale -- npx -y @tmhs/tailscale-mcp
  • Claude Desktop: 最新リリースから tailscale-mcp.mcpb をダウンロードして開きます。インストールダイアログで読み取り専用モードと Funnel を切り替えられます。
  • Cursor / VS Code: 上のボタンを使用します。
  • MCP Registry: 公式 MCP Registry に io.github.TMHSDigital/tailscale-mcp として登録されているため、レジストリに対応したクライアントやカタログから見つけられます。

または、任意の MCP クライアントの設定に手動で追加します。

{
  "mcpServers": {
    "tailscale": {
      "command": "npx",
      "args": ["-y", "@tmhs/tailscale-mcp"]
    }
  }
}

Node 22 以降(アクティブな LTS)と、インストール済みでログイン済みの Tailscale クライアントが必要です。

tailscale CLI の検索

サーバーはまず PATH 上の tailscale を検索し、次にプラットフォームの既定のインストール先を検索します。Windows では C:\Program Files\Tailscale\tailscale.exe、macOS では /Applications/Tailscale.app/Contents/MacOS/Tailscale、/opt/homebrew/bin/tailscale、/usr/local/bin/tailscale を検索します。そのため、Mac App Store 版も追加設定なしで動作します。別のバイナリを使うには、TAILSCALE_MCP_BIN を設定します。

{
  "mcpServers": {
    "tailscale": {
      "command": "npx",
      "args": ["-y", "@tmhs/tailscale-mcp"],
      "env": { "TAILSCALE_MCP_BIN": "/path/to/tailscale" }
    }
  }
}
タイムアウト

すべての tailscale の呼び出しには、既定で 10 秒の制限時間が設定されています。デーモンが応答しない場合、エージェントを停止させるのではなく、構造化された TIMEOUT エラーを返します。低速なマシンや非常に大規模な tailnet で制限時間を延ばすには、TAILSCALE_MCP_TIMEOUT_MS を設定します。share_port は最大 15 秒待機し、ping の制限時間は count と timeoutMs に応じて変わります。ping_all 全体の制限時間は 45 秒です。

設定リファレンス

すべての設定は、サーバーの env ブロックに指定する環境変数です。ブール値フラグには 1/true/yes/on または 0/false/no/off を指定できます。それ以外の値を指定するとサーバーの起動が停止するため、入力ミスによって安全設定が意図せず緩和されることはありません。

変数デフォルト効果
TAILSCALE_MCP_ALLOW_FUNNELoffshare_port {"public": true} を許可し、Funnel 経由でポートをオープンなインターネットに公開します。off の場合、呼び出しは FUNNEL_DISABLED を返し、何も共有されません。
TAILSCALE_MCP_READONLYoff監視専用モードです。share_port と stop_share は登録されず、generate_ssh_config は write: true を拒否します(READ_ONLY)。
TAILSCALE_MCP_BIN(search)tailscale バイナリへのパスです。
TAILSCALE_MCP_TIMEOUT_MS10000呼び出しごとの CLI タイムアウトです。
Linux:Serve/Funnel の権限

Linux では、root または設定されたオペレーターのみが Serve/Funnel の設定を変更できます。share_port または stop_share が PERMISSION_DENIED を返す場合は、一度だけユーザーを許可してください。

sudo tailscale set --operator=$USER

ツール

すべてのツールで MCP アノテーションが宣言されているため、クライアントは読み取り専用のツールを自動承認し、その他のツールは確認を求めることができます。結果は各ツールの outputSchema によって型付けされた structuredContent として返され、古いクライアント向けに同じ JSON がテキストブロックにも含まれます。完全な定義は、サーバーから生成される mcp-tools.json にあります。

ツール読み取り専用破壊的冪等オープンワールド
tailnet_statusはいいいえはいいいえ
share_statusはいいいえはいいいえ
ping_allはいいいえはいいいえ
generate_ssh_configいいえ(write: true の場合のみ書き込み)いいえはいいいえ
share_portいいえいいえはいFunnel が許可されている場合のみ
stop_shareいいえはいはいいいえ
tailnet_status

tailscale status --json の内容を簡潔にしたビューです。自分のノードと、ホスト名、MagicDNS 名、Tailscale IPv4/IPv6、OS、オンラインフラグ、最終確認時刻、出口ノードフラグ、タグを含むピアを返します。入力:省略可能な onlineOnly。

{
  "backendState": "Running",
  "tailnet": "[email protected]",
  "magicDNSSuffix": "tail1234.ts.net",
  "self": {"hostname": "DEVPC", "dnsName": "devpc.tail1234.ts.net", "ipv4": "100.101.1.10"},
  "peerCount": 3,
  "peers": [
    {"hostname": "raspi", "dnsName": "raspi.tail1234.ts.net", "ipv4": "100.101.1.20", "os": "linux", "online": true, "exitNodeOption": true, "tags": []}
  ]
}
generate_ssh_config

tailnet ノードの ssh-config Host ブロックを出力します(MagicDNS 名を優先し、利用できない場合は Tailscale IP を使用します)。デフォルトではドライランです。生成されたテキストのみを返します。入力:write、target、onlineOnly、includeShared、user。

  • 各 Host エイリアスには、ノードの最初の MagicDNS ラベル(raspi.tail1234.ts.net → raspi)を使用します。利用できない場合は、無害化した OS ホスト名([a-z0-9-] のみ)を使用します。エイリアスが重複する場合は数値の接尾辞が付けられ、renamed に一覧表示されます。Mullvad の出口ノードと、共有相手のユーザーのノード(includeShared: true の場合を除く)は除外され、skipped に一覧表示されます。
  • write: true を指定すると、専用ファイル ~/.ssh/tailscale_dev_config に書き込み、~/.ssh/config に追加する Include tailscale_dev_config の指示を返します(自動適用はされません)。
  • target: "user_ssh_config"(write: true の場合)を指定すると、# BEGIN tailscale-mcp と # END tailscale-mcp のマーカーの間にある ~/.ssh/config を直接、冪等に編集します。マーカー外の内容には一切触れません。マーカーが不正な場合(対応するマーカーがない、順序が逆、または重複)、ツールは SSH_CONFIG_MARKERS_CORRUPT を返し、何も書き込みません。
  • 書き込みはアトミックに行われます(一時ファイルの作成後に名前を変更)。以前の ~/.ssh/config は config.tailscale-mcp.bak として保持され、新しいファイルは 0600 で作成されます(既存ファイルのパーミッションは保持されます)。シンボリックリンクされた設定ファイルは置き換えず、そのリンク先に書き込みます。
{
  "dryRun": true,
  "hostCount": 2,
  "configText": "# BEGIN tailscale-mcp\nHost raspi\n    HostName raspi.tail1234.ts.net\n\nHost devbox\n    HostName devbox.tail1234.ts.net\n# END tailscale-mcp"
}
share_port

Tailscale Serve を介してローカルポートを共有します。**デフォルトでは tailnet 内のみで共有されます。**入力:port(必須)、public、path。

{"port": 3000, "public": false, "scope": "tailnet-only (Serve)", "urls": ["https://devpc.tail1234.ts.net/"]}

public: true を指定すると Funnel に切り替わり、ポートがオープンなインターネットに公開されます。TAILSCALE_MCP_ALLOW_FUNNEL=1 が設定されていない場合は拒否されます。詳しくは以下のセキュリティに関する注意事項をご覧ください。

share_status

tailscale serve status --json から解析した、アクティブな Serve/Funnel セッションを構造化エンドポイントとして報告します。各エンドポイントには独自の public フラグがあり、Funnel によってインターネットに公開されている場合は true になります。また、何かが公開されている場合、publicExposure は true になります。

{
  "active": true,
  "publicExposure": true,
  "endpoints": [
    {"url": "https://devpc.tail1234.ts.net/", "host": "devpc.tail1234.ts.net", "httpsPort": 443, "scheme": "https", "path": "/", "target": "http://127.0.0.1:3000", "targetType": "proxy", "public": true, "foreground": false}
  ]
}

生の TCP 転送は tcpForwards の下に表示されます。--json に対応していない古い CLI では、テキスト形式のステータスが status の下に返され、publicExposure は null になります。

stop_share

共有を停止します。対象を 1 つだけ指定してください。

  • httpsPort および/または path を指定すると、1 つのマウントを停止します。httpsPort は share_status に表示される Serve ポート(デフォルトは 443 で、プロキシ先のローカルポートではありません)で、path は share_port に指定したマウントパス(デフォルトは /)です。たとえば、{"path": "/api"} は share_port {"port": 3000, "path": "/api"} を取り消します。
  • mine: true を指定すると、このサーバーセッション中に share_port が作成した共有だけを停止します。
  • all: true を指定すると、このサーバーの外部で設定した共有も含めて、Serve/Funnel の設定全体を消去します。

引数を指定しない場合、何も停止されません。このツールは TARGET_REQUIRED を返し、アクティブなエンドポイントを一覧表示します。成功した呼び出しはすべて、removed(停止したエンドポイント)と remaining(その後の share_status の表示)を返します。

マウントパスは / で始まり、英字、数字、および . _ ~ - / のみを使用し、. または .. のセグメントを含めてはいけません。末尾のスラッシュは削除されます。

ping_all

ピアに対して tailscale ping を並行して実行します(同時実行数は最大 5 件、各 ping にタイムアウトを設定)。入力項目は count、timeoutMs、onlineOnly(デフォルトは true)です。

{
  "pinged": 2,
  "reachable": 1,
  "timedOut": false,
  "matrix": [
    {"hostname": "raspi", "target": "100.101.1.20", "reachable": true, "latencyMs": 3, "path": "direct", "via": "192.168.1.20:41641", "attempts": 3, "replies": 3},
    {"hostname": "exitbox", "target": "100.101.1.40", "reachable": false, "latencyMs": null, "path": null, "via": null, "attempts": 1, "replies": 0}
  ]
}

path は direct(ピア間の直接接続)、derp(Tailscale DERP サーバー経由の中継)、peer-relay(自分のノードの 1 つを経由した中継)、または unknown です。これにより、エージェントは「接続できるが中継経由」と「高速な直接接続」を見分けられます。tailscale ping は直接接続が確立するまで ping を続けるため、path と latencyMs は最後の応答、つまり確立後の接続経路を示します。呼び出し全体は最大 45 秒です。その時点までに応答していないピアは、error と timedOut: true を伴って返されます。

エージェント型ワークフローの例

「これを開発用 VPS にデプロイして、結果を見せて」と依頼されたエージェントは、このサーバーを通じて探索段階のすべてを実行できます。

  1. tailnet_status {"onlineOnly": true} で VPS ノードとその MagicDNS 名(devbox.tail1234.ts.net)を見つけます。IP アドレスをハードコードする必要はありません。
  2. generate_ssh_config {"write": true, "user": "deploy"} で ~/.ssh/tailscale_dev_config に書き込みます。エージェントは返された 1 行の Include 指示を表示し、ユーザーがそれを追加すると、ssh devbox で tailnet 経由の接続先が解決されます。
  3. ping_all でノードに到達できること、および大容量の転送を開始する前に経路が直接接続か中継経由かを確認します。
  4. デプロイ後、share_port {"port": 8080} は、tailnet 上のチームメイトが開ける tailnet 限定 URL を返します。TAILSCALE_MCP_ALLOW_FUNNEL=1 で Funnel を有効にし、エージェントに public: true を渡すよう明示的に指示しない限り、インターネットには何も公開されません。

Funnel に関するセキュリティ上の注意

  • share_port はデフォルトで tailnet 限定の Serve を使用します。tailnet の外部からアクセスできるものはありません。
  • Funnel は有効にしない限りオフです。 public: true は Tailscale Funnel を使用し、tailnet 上のユーザーだけでなく、インターネット上の誰でも URL にアクセスできるようにします。デフォルトのインストールでは FUNNEL_DISABLED を返して拒否されるため、プロンプトインジェクションを受けたエージェントが単独でポートを公開することはできません。有効にするには、クライアント設定で TAILSCALE_MCP_ALLOW_FUNNEL=1 を設定してください。その場合もツールの説明には警告が含まれるため、エージェントは操作前に警告を提示します。
  • TAILSCALE_MCP_READONLY=1 を設定すると共有ツールが完全に削除され、参照のみを行うエージェントに適した状態になります。
  • Serve と Funnel は、管理コンソールで tailnet ごとに有効にする必要があります。有効になっていない場合、ツールは有効化用の URL を正確に含む構造化エラー SERVE_NOT_ENABLED を返し、設定は変更しません。
  • stop_share {"all": true} は緊急停止手段です。Serve/Funnel の設定全体を消去します。引数なしで呼び出しても、何も削除されません。
  • このサーバーが TS_AUTHKEY やその他の認証情報を読み取ったり保存したりすることはありません。

開発

npm install
npm run build      # tsc
npm test           # vitest, fully offline (fixture-driven, no live tailnet)
npm run typecheck  # src and tests
npm run gen:tools  # regenerate mcp-tools.json after changing a tool

独自の tailnet でビルドを試すには、MCP Inspector で実行してください。

npm run build
npx @modelcontextprotocol/inspector node dist/index.js

プロバイダーアダプターパターン:src/providers/types.ts では TailscaleProvider インターフェースを定義しています。唯一の実装である CliProvider は、注入可能なプロセスランナーを介して CLI を起動するため、テストで実際のバイナリが実行されることはありません。このインターフェースは、ローカルソケットまたは名前付きパイプを介して HTTP 通信する将来の LocalAPI プロバイダーにも対応できるようになっています。

プロジェクト構成

tailscale-mcp/
  src/index.ts        stdio entry point
  src/config.ts       Environment variable parsing
  src/providers/      TailscaleProvider interface + CliProvider
  src/tools/          MCP tool registrations and output schemas
  src/sshconfig.ts    Pure ssh-config rendering and managed-block editing
  src/__tests__/      vitest suites (offline, mocked CLI runner)
  test/fixtures/      Sanitized CLI output used by the tests
  mcp-tools.json      Generated tool definitions (npm run gen:tools)
  docs/               GitHub Pages site
  .github/            CI/CD workflows

ロードマップ

プロジェクトのロードマップ全体については、ROADMAP.md を参照してください。

コントリビューション

ガイドラインについては、CONTRIBUTING.md を参照してください。

ライセンス

CC-BY-NC-ND-4.0 -- 詳細は LICENSE を参照してください。


TMHSDigital が開発

コメント

MCP は初めてですか?

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

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