Rust MCP server and CLI for Tailscale devices, users, keys, policies, and auth.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
We haven't yet run this listing's install command through our automated sandbox check. This isn't a red flag β we're steadily working through the catalog.
π‘ Paste into ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows)
Tailscale device, route, DNS, key, user, and ACL management over MCP and CLI.
It exposes one MCP tool, tailscale, plus the rtailscale CLI. Agents can
list devices, inspect routes, read API keys, ACL policy, DNS settings, and
users, authorize devices, and delete devices when the destructive gate is
explicitly enabled.
30-second path: set TAILSCALE_API_KEY, then run
npx -y @dinglebear/rtailscale devices --json -> start loopback HTTP with
TAILSCALE_MCP_HOST=127.0.0.1 npx -y @dinglebear/rtailscale serve -> call tools/call
with {"action":"devices"}.
Status: operational RMCP upstream-client server. Write-capable for device
authorization; destructive device deletion requires both server opt-in and
caller confirmation. HTTP MCP supports loopback dev mode, static bearer tokens,
and Google OAuth through lab-auth.
Not for: replacing the Tailscale admin console, bypassing Tailscale account permissions, operating multiple unrelated tailnets from one trust boundary, storing API keys for callers, arbitrary WireGuard control, or passing Tailscale API keys through MCP tool arguments.
| Surface | This repo |
|---|---|
| Repository | tailscale-rmcp |
| Rust crate | tailscale-rmcp |
| Binary / CLI | rtailscale |
| npm package | @dinglebear/rtailscale |
| npm binary aliases | tailscale-rmcp, rtailscale |
| MCP tool | tailscale |
| Config home | ~/.tailscale-mcp on hosts, /data in containers |
| Env prefixes | TAILSCALE_*, TAILSCALE_MCP_*, TAILSCALE_RMCP_* for npm launcher controls |
The repo, crate, and npm package use the RMCP family name. The shipped binary is
rtailscale to avoid shadowing the official tailscale CLI.
TAILSCALE_ALLOW_DESTRUCTIVE=true and the caller
also passes explicit confirmation.| This repo owns | Tailscale owns | Explicitly out of scope |
|---|---|---|
| MCP/CLI projection, request validation, HTTP MCP auth policy, response shaping, setup checks, and destructive gates. | Tailnet state, device identities, ACL semantics, DNS behavior, API key issuance, user membership, and upstream authorization. | Replacing the admin console, storing caller credentials, multi-tailnet tenancy, arbitrary WireGuard control, policy editing beyond exposed actions, and local Tailscale daemon management. |
| Path | Command | Best for | Notes |
|---|---|---|---|
| npm / npx | npx -y @dinglebear/rtailscale --help | Local MCP clients and quick trials. | Downloads the matching rtailscale binary from GitHub Releases. |
| Release installer | curl -fsSL https://raw.githubusercontent.com/dinglebear-ai/rtailscale/main/scripts/install.sh | bash | Host installs without Node. | Installs rtailscale for the current Linux host. |
| Docker / Compose | docker compose up -d | Shared HTTP MCP deployments. | Reads .env and exposes container port 40040. |
| Build from source | cargo build --release | Development and audits. | Produces target/release/rtailscale. |
| Plugin | claude plugin install plugins/tailscale | Claude Code local plugin setup from this checkout. | Ships the skill, .mcp.json, and a bundled binary. No hooks β run rtailscale setup check yourself if you want the environment verified. |
Run the stdio MCP server or CLI without a manual binary install:
The npm package downloads rtailscale during postinstall. Override download
behavior only when testing packaging:
| Variable | Purpose |
|---|---|
TAILSCALE_RMCP_SKIP_DOWNLOAD=1 | Skip postinstall binary download. |
TAILSCALE_RMCP_VERSION or TAILSCALE_RMCP_BINARY_VERSION | Select the GitHub Release tag. |
TAILSCALE_RMCP_REPO | Select the GitHub repo used for release downloads. |
TAILSCALE_RMCP_RELEASE_BASE_URL | Select a custom release base URL. |
Minimum supported Rust version: 1.86.
Create an API key at https://login.tailscale.com/admin/settings/keys. Use the minimum capability needed for the actions you plan to expose.
Every Tailscale account belongs to a tailnet. TAILSCALE_TAILNET=- targets the
default personal tailnet; organization tailnets usually use the org domain.
In another shell:
Register Tailscale through Labby as an HTTP upstream when sharing one long-running server, or run it directly as stdio for local-only use.
Do not put TAILSCALE_API_KEY, OAuth secrets, passwords, SSH keys, or upstream
bearer tokens in MCP tool arguments. Use env, config files, or the MCP client's
secret storage. MCP callers never provide credentials, tokens, keys, or secrets
as action arguments.
| Surface | Status | Entry point | Purpose |
|---|---|---|---|
| MCP stdio | Supported | rtailscale mcp, npx -y @dinglebear/rtailscale mcp | Local child-process MCP clients. |
| MCP HTTP | Supported | rtailscale serve, POST /mcp | Streamable HTTP MCP for local or shared server deployments. |
| CLI | Supported | rtailscale <command> | Scriptable parity and debugging. |
| REST API | Not shipped | N/A | Tailscale already owns the REST API. |
| Web UI | Not shipped | N/A | Tailscale already owns the admin console. |
One MCP tool is exposed: tailscale. Pass the required action argument to
select the operation.
| Action | Description | Required params | Optional params |
|---|---|---|---|
devices | List all devices in the tailnet. | none | none |
device | Return one device. | id | none |
device_routes | Return subnet routes for one device. | id | none |
keys | List API keys in the tailnet. | none | none |
acl | Return ACL policy JSON. | none | none |
dns | Return DNS nameservers, search paths, and MagicDNS preferences. | none | none |
users | List tailnet users. | none | none |
help | Return built-in action documentation. | none | none |
| Action | Description | Required params | Optional params |
|---|---|---|---|
authorize_device | Approve a device for the tailnet. | id | none |
| Action | Description | Required params | Optional params |
|---|---|---|---|
delete_device | Permanently remove a device. | id, confirm=true | none |
Device IDs may be stable node IDs such as n1234abc or legacy numeric device
IDs. Use action=devices first to discover IDs.
The binary calls the same service layer as the MCP tool:
All commands currently print JSON. --json is accepted for parity with the rest
of the RMCP family.
Host installs read ~/.tailscale-mcp/.env before loading config. Containers
read /data/.env. Process environment overrides both.
| Variable | Default | Purpose |
|---|---|---|
TAILSCALE_API_KEY | unset | Tailscale API key. |
TAILSCALE_TAILNET | - | Tailnet: org domain or - for personal. |
TAILSCALE_ALLOW_DESTRUCTIVE | false | Enable delete_device server-side. |
TAILSCALE_MCP_HOST | 0.0.0.0 | HTTP bind host. |
TAILSCALE_MCP_PORT | 40040 | HTTP bind port. |
TAILSCALE_MCP_SERVER_NAME | tailscale-rmcp | Advertised MCP server name. |
TAILSCALE_MCP_NO_AUTH | false | Disable auth only for loopback development. |
TAILSCALE_MCP_TOKEN | unset | Static bearer token for HTTP MCP. |
TAILSCALE_NOAUTH | false | Trust an upstream gateway to enforce auth. |
TAILSCALE_MCP_AUTH_MODE | bearer | bearer or oauth. |
TAILSCALE_MCP_PUBLIC_URL | unset | Public URL for OAuth discovery. |
TAILSCALE_MCP_GOOGLE_CLIENT_ID | unset | Google OAuth client ID. |
TAILSCALE_MCP_GOOGLE_CLIENT_SECRET | unset | Google OAuth client secret. |
TAILSCALE_MCP_AUTH_ADMIN_EMAIL | unset | Admin email for OAuth bootstrap. |
TAILSCALE_MCP_ALLOWED_HOSTS | unset | Extra accepted Host header values. |
TAILSCALE_MCP_ALLOWED_ORIGINS | unset | Extra accepted CORS origins. |
TAILSCALE_MCP_HOME | platform appdata | Override the config/log home used by setup and file logging. |
The Tailscale API base URL is not configurable; it is fixed at
https://api.tailscale.com/api/v2 in src/tailscale.rs.
Stdio MCP runs as a local trusted child process and does not use HTTP auth.
HTTP MCP auth policy:
| State | Condition | Behavior |
|---|---|---|
| Loopback dev | TAILSCALE_MCP_HOST starts with 127. or auth is explicitly disabled on loopback | Local unauthenticated development is allowed. |
| Mounted bearer | Non-loopback with TAILSCALE_MCP_TOKEN | Requires Authorization: Bearer <token> and action scopes. |
| Mounted OAuth | TAILSCALE_MCP_AUTH_MODE=oauth | Uses Google OAuth/JWT through lab-auth. |
| Trusted gateway | TAILSCALE_NOAUTH=true | Assumes a reverse proxy or gateway already enforced auth. |
Non-loopback HTTP startup is rejected unless bearer auth, OAuth, or
TAILSCALE_NOAUTH=true is configured.
delete_device has a two-key interlock:
TAILSCALE_ALLOW_DESTRUCTIVE=true on the server and caller-provided
confirm=true.Cargo.toml, Cargo.lock, packages/tailscale-rmcp/package.json,
.release-please-manifest.json, and server.json must agree on the released
version.rtailscale binary consumed by the npm launcher.@dinglebear/rtailscale; binary aliases are
tailscale-rmcp and rtailscale.ghcr.io/dinglebear-ai/rtailscale:<version> (see
docker-compose.prod.yml). The image path still uses the pre-transfer owner
namespace even though the repo now lives at dinglebear-ai/rtailscale.plugins/tailscale/.mcp.json must launch npx -y @dinglebear/rtailscale mcp so
stdio clients start the MCP transport rather than the HTTP server.plugins/tailscale/ ships no Claude Code hooks; scripts/validate-plugin-layout.sh
fails if a hooks/ directory reappears.src/, plus the package, plugin, and registry manifests.Runtime smoke:
HTTP smoke:
Use loopback for local development:
Use Docker Compose for shared HTTP deployment:
When binding to a non-loopback address, configure TAILSCALE_MCP_TOKEN,
TAILSCALE_MCP_AUTH_MODE=oauth, or TAILSCALE_NOAUTH=true behind an
authenticated gateway.
| Symptom | Check |
|---|---|
TAILSCALE_API_KEY is missing | Set it in env or ~/.tailscale-mcp/.env. |
| Device calls return unauthorized | Refresh the API key in Tailscale admin settings. |
HTTP /mcp returns unauthorized | Set TAILSCALE_MCP_TOKEN and send Authorization: Bearer <token>. |
| Stdio client hangs or logs JSON errors | Ensure client config runs tailscale-rmcp mcp, not the default HTTP server mode. |
delete_device is rejected | Set TAILSCALE_ALLOW_DESTRUCTIVE=true server-side and pass confirm=true after verifying the target. |
| Port conflict | Set TAILSCALE_MCP_PORT or stop the process already using 40040. |
unraid-rs/ is the GraphQL bridge for NAS and server management.CLAUDE.md is the curated local operating guide for contributors and agents.docs/SETUP.md is curated plugin/setup guidance.docs/OAUTH.md is curated OAuth setup guidance.plugins/tailscale/skills/tailscale/SKILL.md is the agent usage guide.src/ is the source of truth for current actions, config defaults, auth
behavior, and CLI parsing.Original Dinglebear-authored portions of this project are licensed under AGPL-3.0-only. Separate commercial licensing is available for organizations that need terms outside the AGPL. Third-party material remains under its original license. See LICENSING.md.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/tailscale-rmcp-2)<a href="https://allmcps.com/mcp/tailscale-rmcp-2"><img src="https://allmcps.com/api/badge/tailscale-rmcp-2?style=directory" alt="Tailscale RMCP on AllMCPs" /></a>