关于 Tailscale MCP
Tailscale MCP 是通过 stdio 让 Agent 和开发工具查看、管理本地已认证 Tailscale 守护进程的 MCP 服务,涵盖 tailnet 发现、SSH 配置、端口共享和延迟检查,并提供结构化错误与默认关闭的公网暴露。
主要功能
- 01查看 tailnet 状态与节点
- 02生成 SSH 配置
- 03通过 Serve 或 Funnel 共享端口
- 04检查节点连通性与延迟
- 05控制只读模式和 Funnel 权限
适用场景
- 01部署前查找在线 tailnet 节点
- 02为节点生成 SSH 主机配置
- 03向 tailnet 成员共享开发端口
- 04判断节点连接是直连还是中继
MCP 相关
通过 stdio 向 MCP 客户端提供结构化的 Tailscale 状态、SSH 配置、共享和 ping 工具。工具注解与输出架构说明只读及状态变更操作。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @tmhs/tailscale-mcpTAILSCALE_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 writesTAILSCALE_MCP_BINPath to the tailscale binary if it is not on PATH or in the default install locationTAILSCALE_MCP_TIMEOUT_MSPer-call timeout for tailscale commands in milliseconds (default 10000)本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
6收录的工具列表 · 更新于 3 天前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| onlineOnly | boolean | 否 | 仅包含当前在线的对等节点(默认值:false) |
详细介绍
Tailscale MCP
用于安全地以编程方式访问本地 Tailscale 守护进程的 MCP 服务:发现 tailnet、生成 SSH 配置、通过 Serve/Funnel 共享端口,以及生成延迟矩阵。
通过 stdio,为 Agent 和开发者工具提供安全、结构化的本地 Tailscale 守护进程访问接口。它会调用 tailscale CLI(从 PATH 查找,也会回退到 Windows 和 macOS 上的默认安装位置),且不会处理身份验证密钥或 tailnet 凭据:CLI 会与已完成身份验证的本地守护进程通信。
如果缺少二进制文件、守护进程已停止,或设备需要登录,每个工具都会返回包含 code 和确切 remedy 命令的结构化错误,而不是抛出异常。
安装
- 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,支持 Registry 的客户端和目录可以找到它。
也可以手动将其添加到任何 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 错误,而不会让 Agent 卡住。对于速度较慢的机器或规模很大的 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_FUNNEL | off | 允许调用 share_port {"public": true},通过 Funnel 将端口暴露给开放互联网。关闭时,调用会返回 FUNNEL_DISABLED,不会共享任何内容。 |
TAILSCALE_MCP_READONLY | off | 仅监控模式:不会注册 share_port 和 stop_share,且 generate_ssh_config 会拒绝 write: true(READ_ONLY)。 |
TAILSCALE_MCP_BIN | (search) | tailscale 二进制文件的路径。 |
TAILSCALE_MCP_TIMEOUT_MS | 10000 | 每次调用的 CLI 超时时间。 |
Linux:Serve/Funnel 权限
仅限 root 或已配置的操作员在 Linux 上更改 Serve/Funnel 设置。如果 share_port 或 stop_share 返回 PERMISSION_DENIED,请为你的用户授权一次:
sudo tailscale set --operator=$USER
工具
每个工具都会声明 MCP 注释,因此客户端可以自动批准只读工具,并对其余工具进行确认。结果以 structuredContent 的形式返回,其类型由各工具的 outputSchema 定义;同时也会在文本块中重复相同的 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、操作系统、在线标志、上次活动时间、出口节点标志和标签的对等节点。输入:可选的 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),若没有则回退到经过净化的操作系统主机名(仅允许[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)会直接编辑~/.ssh/config,在# BEGIN tailscale-mcp和# END tailscale-mcp标记之间以幂等方式更新。标记之外的内容绝不会被修改。如果标记格式错误(孤立、顺序颠倒或重复),工具会返回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
将活动的 Serve/Funnel 会话作为结构化端点报告,数据解析自 tailscale serve status --json。每个端点都有自己的 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
停止共享。必须准确指定一个目标:
httpsPort和/或path会关闭一个挂载。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(通过你的某个节点中继)或 unknown,因此 Agent 可以区分“可用但通过中继”与“快速直连路径”。tailscale ping 会持续 ping,直到建立直连路径,因此 path 和 latencyMs 描述的是最后一次回复,也就是稳定后的路径。整个调用最长持续 45 秒:届时仍未回复的节点会返回 error 和 timedOut: true。
Agentic 工作流示例
如果 Agent 接到“将此部署到我的开发 VPS 并展示结果”的请求,可以通过此服务完成整个发现过程:
tailnet_status {"onlineOnly": true}会找到 VPS 节点及其 MagicDNS 名称(devbox.tail1234.ts.net),无需硬编码 IP。generate_ssh_config {"write": true, "user": "deploy"}会写入~/.ssh/tailscale_dev_config;Agent 会显示返回的单行Include指令,用户添加后,ssh devbox就会通过 tailnet 解析。ping_all会确认节点是否可达,以及路径是直连还是中继,然后再开始大规模传输。- 部署完成后,
share_port {"port": 8080}会返回一个仅限 tailnet 访问的 URL,tailnet 上的队友可以打开。除非你已通过TAILSCALE_MCP_ALLOW_FUNNEL=1启用 Funnel,且明确告知 Agent 传入public: true,否则不会有任何内容暴露到公共互联网。
Funnel 安全说明
share_port默认为仅限 tailnet 的 Serve。tailnet 之外无法访问任何内容。- 除非你主动启用,否则 Funnel 处于关闭状态。
public: true会使用 Tailscale Funnel,使 URL 可被互联网上的任何人访问,而不仅限于你的 tailnet。默认安装会拒绝此操作并返回FUNNEL_DISABLED,因此遭到提示词注入的 Agent 无法自行暴露端口。若要允许此操作,请在客户端配置中设置TAILSCALE_MCP_ALLOW_FUNNEL=1。即便如此,工具描述仍会附带警告,因此 Agent 会在操作前提示用户。 TAILSCALE_MCP_READONLY=1会完全移除共享工具,适用于只能观察的 Agent。- 必须在管理控制台中为每个 tailnet 启用 Serve 和 Funnel。未启用时,工具会返回结构化的
SERVE_NOT_ENABLED错误,其中包含准确的启用 URL,且不会进行任何更改。 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 构建
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。