Tailscale MCP Server
io.github.tailscale-mcp/tailscale-mcp
186 tools to drive a Tailscale node and tailnet through CLI and control-plane API.
What is the Tailscale MCP server?
The Tailscale MCP server exposes 186 tools for managing a Tailscale node and its tailnet. It operates through the tailscale CLI for local node control and the Tailscale control-plane REST API for tailnet-wide administration, with configurable tiers (read, write, destructive) and presets (minimal, core, full) to control what capabilities are offered.
This server lets you manage Tailscale networks programmatically. You can query and configure local node status, manage devices and users across your tailnet, set DNS and policy, handle authentication keys and OAuth clients, manage services and Taildrive, and perform diagnostics—all through a single MCP interface. It's designed for agents that need fine-grained control over Tailscale infrastructure with safety guardrails.
How to install Tailscale
Copy-paste configuration for popular MCP clients.
TAILSCALE_API_KEYsecretA control-plane API access token. One of this, the OAuth client pair, or the OAuth JWT file is needed for the tailnet tools; without any of them only the local tools are offered.
TAILSCALE_OAUTH_CLIENT_IDAn OAuth client id, used with TAILSCALE_OAUTH_CLIENT_SECRET when there is no API access token.
TAILSCALE_OAUTH_CLIENT_SECRETsecretThe OAuth client secret that goes with TAILSCALE_OAUTH_CLIENT_ID.
TAILSCALE_TAILNETThe tailnet the control-plane tools act on. Without it they act on the one the credential belongs to.
TAILSCALE_MCP_PRESETWhich tools are offered: minimal, core or full.
TAILSCALE_MCP_ALLOW_WRITEOffer the tools that change something. Read-only without it.
TAILSCALE_MCP_ALLOW_DESTRUCTIVEOffer the tools that remove or sever something. Implies the write tier.
Tools & capabilities
Tools this server exposes to the agent.
Local status tools— 25 tools for querying node status, IP, version, ping, netcheck, routecheck, DNS queries, and exit node informationLocal preferences tools— 8 tools for managing node preferences, up/down, login/logout, and profilesLocal serve tools— 10 tools for managing Serve and Funnel configurationsLocal files tools— 11 tools for Taildrive, file transfer, certificates, and kubeconfig managementLocal lock tools— 8 tools for Tailnet lock management plus status and logsLocal debug tools— 30 tools exposing Tailscale's diagnostic surfaceTailnet devices tools— 15 tools for listing, authorizing, deleting, expiring, renaming devices, setting IPs, managing routes and tagsTailnet DNS tools— 11 tools for managing nameservers, preferences, search paths, and split DNSTailnet keys tools— 5 tools for managing authentication keysTailnet OAuth apps tools— 5 tools for managing OAuth clientsTailnet users tools— 7 tools for user managementTailnet settings tools— 5 tools for tailnet settings and contactsTailnet webhooks tools— 7 tools for webhook managementTailnet posture tools— 5 tools for posture integrationsTailnet logging tools— 8 tools for audit and network flow logsTailnet invites tools— 11 tools for device and user invitationsTailnet services tools— 7 tools for service managementTailnet organization tools— 3 tools for organization tailnet managementPolicy file tools— Tools for getting, setting, previewing, and validating policy with version identifiersLocal passthrough tool— 1 tool to run arbitrary tailscale subcommands (off by default)
Use cases
- Diagnose and troubleshoot connectivity issues across your tailnet
- Automate device onboarding, authorization, and lifecycle management
- Configure DNS, policy, and security settings programmatically
- Manage authentication keys, OAuth clients, and user access
- Monitor and audit tailnet activity through logs and resources
Tailscale MCP server FAQ
It's an MCP server that exposes 186 tools for managing Tailscale nodes and tailnets. The local tools drive the node via the tailscale CLI; the tailnet tools use the control-plane REST API. Both surfaces are optional—if you lack the tailscale binary or API credential, only the tools you can actually use are offered.
The server itself is open-source. You need a Tailscale account and tailnet to use it; Tailscale's pricing depends on your use case.
Download the .mcpb bundle for your platform from the releases page and open it in your MCP client. Alternatively, use npm: `npx -y @tailscale-mcp/tailscale-mcp`. Run `tailscale-mcp setup claude-desktop` or `tailscale-mcp setup cursor` to get the configuration snippet.
You can use an API access token (tskey-api-...) or an OAuth client (client ID and secret). The README recommends OAuth clients for persistent configurations because they're scoped, don't expire on their own, and don't expose your full account if the config file leaks.
Tiers control danger level: read (always on), write (changes config), destructive (deletes or exposes). Presets control surface area: minimal (37 read tools), core/default (57 read tools), full (68 read tools). You enable them with `--allow-write` and `--allow-destructive` flags.
Yes, via the `local-passthrough` tool, but it's off by default and must be explicitly enabled with `--toolsets +local-passthrough`.
README (reference)
Source of truth, from the repository.
tailscale-mcp
An MCP server for Tailscale. The node it runs on is
driven through the tailscale command-line interface; the tailnet behind it is
driven through the control-plane REST API.
186 tools, one per verb, with real parameters and honest annotations. Tailscale's own JSON comes back unmodified, so anything you learned from Tailscale's documentation still applies. When something fails you get a fixed error code and a hint, not a wall of standard error.
Both surfaces are optional and neither is fatal. No tailscale binary means the
tools that drive this node are not offered; no control-plane credential means the
tools that drive the tailnet are not. tailscale-mcp diagnose says which of the
two this machine has.
On macOS that binary is the tailscale shim the Tailscale application installs
into /usr/local/bin. The executable inside the application bundle is not a
substitute and is not accepted as one: run outside a login shell it starts the
GUI rather than answering, so the local tools would be offered and then fail on
every call.
Install
| Channel | How |
|---|---|
| npm | npx -y @tailscale-mcp/tailscale-mcp — downloads the release binary for your machine and refuses to run it unless the release's own SHA256SUMS vouches for it |
| Container | docker run -i --rm -e TAILSCALE_API_KEY ghcr.io/tailscale-mcp/tailscale-mcp |
| Homebrew | brew trust tailscale-mcp/tap && brew install tailscale-mcp/tap/tailscale-mcp — Homebrew 6 will not load a third-party tap until it is trusted, and reports that as an Invalid formula error once per platform it knows |
| Bundle | Download the .mcpb for your platform from the releases and open it — for MCP clients that install bundles, such as Claude Desktop |
| From source | cargo install tailscale-mcp |
Release archives are on the
releases page with a
SHA256SUMS beside them: macOS and Linux on x86_64 and arm64, and Windows
on x86_64.
Point a client at it
tailscale-mcp setup claude-code
prints the snippet for your client — claude-code, claude-desktop, vscode,
cursor or zed — and says where it goes. It writes nothing: the snippet is
yours to paste, and it leaves the credential out, for the reason in the next
section.
Installed through npm there is nothing to install first, and the client can carry the settings:
{
"mcpServers": {
"tailscale": {
"command": "npx",
"args": ["-y", "@tailscale-mcp/tailscale-mcp"],
"env": {
"TAILSCALE_MCP_ALLOW_WRITE": "true"
}
}
}
}
That much is enough to start it. Without a credential it offers the tools that
drive this node and hides the ones that act on the tailnet, and
tailscale-mcp diagnose says which of the two you have.
Authenticate
setup prints no credential of its own, because the file it prints into is one
people paste into issues and chats without rereading. Adding one is a separate,
deliberate step. Two shapes go in the env block above — an API access token:
"env": {
"TAILSCALE_API_KEY": "tskey-api-…",
"TAILSCALE_MCP_ALLOW_WRITE": "true"
}
or an OAuth client:
"env": {
"TAILSCALE_OAUTH_CLIENT_ID": "k123456CNTRL",
"TAILSCALE_OAUTH_CLIENT_SECRET": "tskey-client-…",
"TAILSCALE_MCP_ALLOW_WRITE": "true"
}
The credentials table has the other shapes, including the JWT file for federated identity. Every tool is offered with either of these: the choice is not about what you can do with the server, which is why it is worth making on other grounds.
Prefer the OAuth client for anything you keep. The reason is what a client configuration is: a file somebody writes once and then forgets, holding a secret for as long as the tool is installed.
An API access token suits that badly on three counts. It belongs to a person and carries everything that person can do, so what leaks with the file is their whole account rather than the tools you turned on. It expires — which in a file nobody has looked at since they wrote it does not present as an expired credential, but as a server that has stopped working for no reason. And it is itself the bearer token, so the thing at rest is the thing that opens the door.
An OAuth client inverts each of those. It belongs to the tailnet, so it outlives whoever set it up and is revoked without touching that person's access. Its scopes narrow it to what the toolsets you enabled actually call. It does not expire on its own, and what sits in the file is not a key but the means of minting one — the token it hands this server lasts an hour, so a copy taken from a backup or a screen share is worth very little by the time it is used.
The API access token is what the control plane offers you first, and is the quicker thing to try this out with. It is worth replacing once the file is one you are going to keep.
Tiers and presets
Two independent dials decide what a session offers.
The tier is how dangerous a tool is allowed to be. Read tools change nothing and are always offered. Write tools change configuration that can be changed back. Destructive tools remove something or expose something in a way that is not simply undone — deleting a device, revoking a key, publishing a service to the internet. Read is always on; write and destructive are off until they are turned on, and a tool above the permitted tier is not listed, not refused when called.
The preset is how much surface area is offered at all. minimal is what an
agent needs to answer questions and fix the common things; core adds the rest
of everyday administration; full adds the tailnet-wide and irreversible
corners. Two toolsets are in no preset and must be asked for by name:
local-debug, which is Tailscale's own diagnostic surface, and
local-passthrough, which is one tool that runs an arbitrary tailscale
subcommand.
| Preset | Read | With --allow-write | With --allow-destructive | Toolsets |
|---|---|---|---|---|
minimal | 37 | 51 | 55 | 4 |
core (default) | 57 | 106 | 126 | 13 |
full | 68 | 126 | 155 | 18 |
Adding --toolsets +local-debug,+local-passthrough to full reaches all 186.
Some destructive tools ask for one more thing: a confirm: true argument. Those
are the ones that affect the whole tailnet, or that can cut this server off from
the node or tailnet it is driving — logging the node out, deleting its own
device, deploying a policy that locks the caller out. The server does not decide
they are wrong; it makes the caller say it meant them.
- docs/tools.md — every tool, its tier and what it does. Generated from the code.
- docs/configuration.md — every environment variable and flag, with defaults.
- docs/errors.md — every error code and what to do about it.
Resources, prompts and completions
Nine resources — eight fixed and one template addressed by device identifier — give a client the local node's status, preferences, netcheck report and tailnet lock state, and the tailnet's policy file, devices, DNS configuration and settings. They are read-only, they appear only when their surface is on, and there are no subscriptions.
Three prompts steer a sequence of tool calls: diagnose_connectivity,
review_policy_change and audit_tailnet_access. They follow the same rule as
the resources: each appears only when the surface it needs is on, and
diagnose_connectivity, which reads from both, stops at the steps the session
can actually take.
Of the four argument slots those two surfaces expose, three are completed, so
a client can offer the values rather than leave them to be guessed: the device
template's identifier, diagnose_connectivity's peer, and
audit_tailnet_access's subject — which offers users, tags and devices, in
that order, so that a tailnet of thousands of devices still shows its handful
of users within the hundred values the protocol sends. The fourth, review_policy_change's goal, is
a sentence about intent, and completing it would be inventing one. Every value offered is one the server will
accept back — a device is offered by its MagicDNS name, never by a hostname two
machines might share — and a source that cannot answer completes to nothing
rather than to an error. The method is rate limited, as the specification asks,
because each keystroke is a request.
Note that the protocol completes a prompt argument and a resource template variable, and nothing else: tool arguments cannot be completed, so this helps the four slots above and none of the 186 tools. Client support is uneven — Claude Code completes resource templates, VS Code completes both, and several clients do neither — so this is an improvement where it is read and inert everywhere else.
Transports
Stdio by default. --http serves Streamable HTTP instead, on
127.0.0.1:8449, behind a bearer token in TAILSCALE_MCP_HTTP_TOKEN, with
host and origin allow-lists, a body limit, a per-address rate limit and an open
health endpoint. Binding anywhere but loopback needs either that token or
--http-no-auth said out loud.
Security
What the tiers do. A tool above the permitted tier is not in the tool list,
so a caller cannot invoke it by guessing its name, and a model cannot be talked
into one that was never offered. The default is read-only. confirm on top of
the destructive tier is a second signal for the operations that are worth one.
Secrets never reach an argument list, a log line or an error message; a minted
key or invite URL is returned once, verbatim, and nothing here keeps a copy.
Every tool result and every error goes through the same redaction on the way
out.
What the tiers do not do. They are not an authorization system, and they are not a sandbox.
- A tier is a property of the server, not of the caller. Everyone talking to one server gets the same tools. If two callers should have different powers, run two servers.
- Permitting a tier permits every tool in it. There is no per-tool switch;
--toolsetsis the coarser dial for narrowing what a session can reach. - The credential is the real boundary. A read-only OAuth client makes the tailnet write tools fail at the control plane whatever this server offers, and that is the boundary to lean on. Scope the credential, and use the tiers to stop honest mistakes.
- The local tools run as whoever runs this server. Tailscale's own operator
check applies — commands refused to a non-operator are refused here, with
needs_operator— but a server run as the operator can do what the operator can do. - Read is not harmless. The read tier returns real network topology: node names, addresses, users, policy. Anything that can read the tool output can read that.
The server never escalates privileges. It does not use sudo, does not ask
for elevation, and does not alter its own permissions or install anything. It
runs the tailscale binary as the user it was started as and sends the
control-plane credential it was given. Where Tailscale refuses because of who is
asking, that refusal is passed through rather than worked around. Four tools do
write files: three of them — a certificate, a Taildrop delivery, a metrics file
— to the path the call names, and tailscale_configure_kubeconfig to the
kubeconfig the client itself would edit. All four write as the user running the
server, and so does tailscale_run, which is in no preset and, once asked for
by name, can reach those same writes and anything else the tailscale binary
does.
Over HTTP the defaults are the cautious ones — loopback, a token required, no browser origin allowed — and each of those is widened by a flag, deliberately.
Compared with the other Tailscale MCP servers
This server is a strict superset of the three that came before it (rtailscale, HexSleeves/tailscale-mcp, YawLabs/tailscale-mcp), with four exceptions listed below the table.
| Capability | rtailscale | HexSleeves | YawLabs | this server |
|---|---|---|---|---|
| Devices: list, get | yes | list only | yes | yes, within tailnet-devices below |
| Devices: authorize, delete, expire, rename, set IP, key expiry | authorize, delete | authorize, delete, expire | yes | yes, 15 tools in all |
| Device routes, tags | routes get | yes | yes | yes, within tailnet-devices below |
| Posture attributes | — | — | yes | yes, within tailnet-devices below |
| Policy file: get, set, preview, validate | get | get, set, validate | yes, with If-Match | yes, with the version identifier on every write |
| DNS: nameservers, preferences, search paths, split DNS | get | yes | 11 tools | 11 tools |
| Auth keys | list | yes | yes | 5 tools |
| OAuth clients | — | — | 4 tools | 5 tools |
| Users | list | — | 7 tools | 7 tools |
| Tailnet settings, contacts | — | partly | 5 tools | 5 tools |
| Webhooks | — | yes | 7 tools | 7 tools |
| Posture integrations | — | — | 5 tools | 5 tools |
| Audit and network flow logs, log streaming | — | — | 9 tools | 8 tools |
| Invites: device and user | — | — | 11 tools | 11 tools |
| Services | — | — | 7 tools | 7 tools |
| Organization tailnets | — | — | 3 tools | 3 tools |
| Local status, IP, whois, whoami, version | — | status, version | 4 tools | 25 tools |
| Ping, netcheck, routecheck, DNS query, exit nodes | — | ping, exit nodes | ping, netcheck | yes, within local-status above |
| Preferences, up, down, login, logout, profiles | — | up, down | — | 8 tools |
| Serve and funnel | — | — | — | 10 tools |
| Taildrive, file transfer, certificates, kubeconfig | — | — | — | 11 tools |
| Tailnet lock | — | stub | — | 8 tools, plus status and log |
| Tailscale's own debug surface | — | — | — | 30 tools |
Arbitrary tailscale subcommand | — | — | — | 1 tool, off by default |
| Resources | 1 | 4 | 4 | 9 |
| Prompts | 1 | 2 | 0 | 3 |
| Transports | stdio, HTTP | stdio, HTTP | stdio | stdio, HTTP |
| Tool count | 1, with 10 actions | 19, one of them a stub | 102 | 186 tools |
One row is lower than YawLabs' and no capability is missing behind it: two of their tools are aggregates over endpoints this server exposes one at a time — one that reads both log types' stream configurations in a single call, and one that authorizes a list of devices in a single call. Both are reachable here as repeated calls to the per-item tool. They are counted in their column and not in this one, which is what makes the logging row read 9 against 8.
Four things the others have and this does not, deliberately:
- No configuration file. rtailscale reads a
config.toml. Everything here is an environment variable or a flag, because that is what an MCP client configuration can set, and a third source of truth is a third place for a setting to hide. - No tool-schema resource. rtailscale serves its own tool schema as a
resource. MCP already has
tools/list; a second copy is one that can disagree with the first. - No OAuth resource-server mode for browser clients, in this release. rtailscale can act as an OAuth resource server so a browser client can authenticate to it. The HTTP transport here takes a bearer token. This is a deferral, not a refusal.
- No extra-enum environment knobs. Several settings in the others accept values outside the documented set, or are read from variables that are not documented at all. Every setting here is in docs/configuration.md, and a value outside the set is a startup error naming the alternatives.
Development
cargo test --workspace --all-targets # the whole suite, offline
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --all --check
The suite needs no tailscale binary, no credential and no network: the
tailscale binary is faked and the control plane is a fake HTTP server. The end-to-end
tests that do want a real node and tailnet are gated on environment variables
and report themselves skipped without them.
docs/tools.md is generated. After adding or changing a tool:
UPDATE_DOCS=1 cargo test -p tailscale-mcp --test docs_are_current
Architecture decisions are in docs/adr/, the vocabulary this
codebase holds itself to is in CONTEXT.md, every judgement call
made while building it is in DECISIONS.md, and how a release
is made is in RELEASING.md.
Licence
Apache-2.0.
Related MCP servers
Dynamic context loading for AI assistants with TDD workflow and AST analysis

Taisly Social Media Posting
Publish videos to TikTok, Instagram Reels, YouTube Shorts, X, and Facebook through AI agents.
MCP cron validator for AI agents; flags impossible schedules and other silent cron bugs.

PlanVortex
Schedule posts, read comments and answer messages across all your social networks.


