Skip to content
DnsLister Forum

Where domain hunters compare notes

tailscale-mcp: an open-source MCP server for Tailscale (186 tools, local CLI + control-plane API, Rust)

I've been building tailscale-mcp, an MCP server that lets an AI agent (Claude Code, Claude Desktop, VS Code, Cursor, Zed, anything that speaks MCP) operate Tailscale. It drives the node it runs on through the tailscale CLI and the whole tailnet through the control-plane REST API. Written in Rust, Apache-2.0.

GitHub: https://github.com/tailscale-mcp/tailscale-mcp

What it does

  • 186 tools, one per verb, with real parameters and honest annotations. Tailscale's own JSON comes back unmodified, so what you know from the docs still applies. Failures come back as a fixed error code plus a hint.
  • Both surfaces are optional: no tailscale binary means the local tools aren't offered, no credential means the tailnet tools aren't. tailscale-mcp diagnose tells you which you have.
  • Nine read-only resources (status, prefs, netcheck, lock state, policy file, devices, DNS, settings), three prompts (diagnose_connectivity, review_policy_change, audit_tailnet_access), argument completions, stdio and Streamable HTTP transports.

Safety model (the part I care most about before pointing an agent at a real tailnet)

  • Two independent dials: the tier (read / write / destructive) caps how dangerous a tool may be, the preset (minimal / core / full) caps how much surface is offered. Read-only is the default. A tool above the permitted tier is not listed, so the model can't be talked into calling something it was never offered.
  • Operations that can cut the server off from its own tailnet (logging the node out, deleting its own device, deploying a policy that locks you out) also require confirm: true.
  • Secrets never reach an argument list, a log line or an error message. A minted auth key or invite URL is returned once and never kept.
  • Prefers an OAuth client over a personal API access token for anything you keep in a config file; the README explains why.

Install

  • npx -y @tailscale-mcp/tailscale-mcp (verifies the release binary against the release's SHA256SUMS before running it)
  • brew trust tailscale-mcp/tap && brew install tailscale-mcp/tap/tailscale-mcp
  • docker run -i --rm -e TAILSCALE_API_KEY ghcr.io/tailscale-mcp/tailscale-mcp
  • cargo install tailscale-mcp
  • an .mcpb bundle from the releases page for Claude Desktop

Then tailscale-mcp setup claude-code (or claude-desktop, vscode, cursor, zed) prints the snippet for your client, with the credential left out on purpose.

There's a capability table in the README comparing it with the three earlier Tailscale MCP servers. It's a strict superset of them, with four deliberate omissions listed there.

Feedback very welcome, especially on the tier/preset split and on what an agent should never be allowed to do to a tailnet even when asked.

Source: r/Tailscale · by /u/s0ulmachine

Leave a Reply

Your email address will not be published. Required fields are marked *