Skip to main content
Glama

Tailscale MCP

MCP server for safe programmatic access to the local Tailscale daemon: tailnet discovery, SSH config generation, port sharing via Serve/Funnel, and latency matrices.

License: CC-BY-NC-ND-4.0 npm version CI


Gives agents and developer tools a safe, structured window into the local Tailscale daemon over stdio. It shells out to the tailscale CLI (resolved from PATH, with a Windows fallback to the default install location) and never handles auth keys or tailnet credentials: the CLI talks to the already-authenticated local daemon.

When the binary is missing, the daemon is stopped, or the device needs login, every tool returns a structured error with a code and the exact remedy command instead of throwing.

Installation

npx -y @tmhs/tailscale-mcp

Add to your MCP client configuration (Claude Desktop, Cursor, etc.):

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

Requires Node 20+ and an installed, logged-in Tailscale client.

Related MCP server: mcp-tailscale

Tools

tailnet_status

Trimmed view of tailscale status --json: self node plus peers with hostname, MagicDNS name, Tailscale IPv4/IPv6, OS, online flag, last seen, exit-node flags, and tags. Input: optional onlineOnly.

{
  "backendState": "Running",
  "tailnet": "user@example.com",
  "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

Emits ssh-config Host blocks for tailnet nodes (MagicDNS name preferred, Tailscale IP fallback). Dry-run by default: returns the generated text only. Inputs: write, target, onlineOnly, user.

  • write: true writes the dedicated file ~/.ssh/tailscale_dev_config and returns the Include tailscale_dev_config instruction for ~/.ssh/config (never applied automatically).

  • target: "user_ssh_config" (with write: true) edits ~/.ssh/config directly, idempotently, between # BEGIN tailscale-mcp and # END tailscale-mcp markers. Content outside the markers is never touched.

{
  "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

Shares a local port via Tailscale Serve. Tailnet-only by default. Inputs: port (required), public, path.

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

public: true switches to Funnel and exposes the port to the open internet. See the security notes below.

share_status

Reports active Serve/Funnel sessions: {"active": false, "status": "No serve config"}.

stop_share

Without arguments clears the entire serve/funnel configuration. With httpsPort it turns off one HTTPS endpoint (the serve port shown in share_status, typically 443, not the proxied local port).

ping_all

Concurrent tailscale ping against peers (bounded to 5 in flight, one ping each with a timeout). Inputs: count, timeoutMs, onlineOnly (default true).

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

path distinguishes a direct peer-to-peer connection from a DERP relay, so an agent can tell "works but relayed" from "fast direct path".

Agentic workflow example

An agent asked to "deploy this to my dev VPS and show me the result" can do the whole discovery leg through this server:

  1. tailnet_status {"onlineOnly": true} finds the VPS node and its MagicDNS name (devbox.tail1234.ts.net), with no hardcoded IPs.

  2. generate_ssh_config {"write": true, "user": "deploy"} writes ~/.ssh/tailscale_dev_config; the agent shows the returned one-line Include instruction, and after the user adds it, ssh devbox resolves through the tailnet.

  3. ping_all confirms the node is reachable and whether the path is direct or relayed before starting a large transfer.

  4. After deploying, share_port {"port": 8080} returns a tailnet-only URL teammates on the tailnet can open. Nothing touches the public internet unless the agent is explicitly told to pass public: true.

Security notes on Funnel

  • share_port defaults to tailnet-only Serve. Nothing is reachable from outside your tailnet.

  • public: true uses Tailscale Funnel: the URL is reachable by anyone on the internet, not just your tailnet. The tool description carries this warning so agents surface it before acting.

  • Serve and Funnel must be enabled per-tailnet in the admin console. When they are not, the tool returns a structured SERVE_NOT_ENABLED error containing the exact enablement URL and changes nothing.

  • stop_share (no arguments) is the kill switch: it clears the entire serve/funnel configuration.

  • This server never reads or stores TS_AUTHKEY or any other credential.

Development

npm install
npm run build     # tsc
npm test          # vitest, fully offline (fixture-driven, no live tailnet)
npm run typecheck

Provider adapter pattern: src/providers/types.ts defines the TailscaleProvider interface; CliProvider (the only v0.1 implementation) spawns the CLI through an injectable process runner so tests never launch a real binary. The interface leaves room for a future LocalAPI provider speaking HTTP over the local socket or named pipe.

Project Structure

tailscale-mcp/
  src/                Source code
  src/providers/      TailscaleProvider interface + CliProvider
  src/tools/          MCP tool registrations
  test/fixtures/      Sanitized CLI output captured from a real tailnet
  .github/            CI/CD workflows

Roadmap

See ROADMAP.md for the full project roadmap.

Contributing

See CONTRIBUTING.md for guidelines.

License

CC-BY-NC-ND-4.0 -- see LICENSE for details.


Built by TMHSDigital

Available Tools

6 tools
generate_ssh_configA

Generate ssh-config Host blocks for tailnet nodes (MagicDNS name preferred, Tailscale IP fallback). Dry-run by default: returns the generated config text only and writes nothing. With write=true it writes a dedicated file (~/.ssh/tailscale_dev_config) and returns instructions for adding an Include line to ~/.ssh/config (never applied automatically). Direct editing of ~/.ssh/config itself additionally requires target="user_ssh_config" and is idempotent between managed markers, never touching content outside them.

ParametersJSON Schema
NameRequiredDescriptionDefault
userNoRemote user to set on every Host block
writeNoActually write the config (default: false = dry-run, text only)
targetNoWrite target: "dedicated_file" (default, ~/.ssh/tailscale_dev_config) or "user_ssh_config" (edit ~/.ssh/config between managed markers)
onlineOnlyNoOnly include peers that are currently online (default: false)

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It covers dry-run default, write behavior, target differences, idempotency of user_ssh_config edits, and never touching outside markers. However, it does not detail file overwrite behavior or prerequisites (e.g., tailscale running).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three concise sentences, front-loaded with the main purpose. Every sentence adds essential information without redundancy or verbosity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description explains return values for both dry-run (config text) and write (instructions). It covers all parameters and key behaviors (idempotency, marker boundaries). Minor gaps exist (e.g., config format details, prerequisites), but overall it is well-rounded.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% (baseline 3). The description adds meaningful context beyond the schema, especially for 'write' (explains dry-run vs write) and 'target' (dedicated file vs user_ssh_config with markers). It does not elaborate on 'user' or 'onlineOnly', but the schema descriptions suffice.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it generates SSH config Host blocks for tailnet nodes, with a specific verb ('Generate') and resource ('ssh-config Host blocks'). It distinguishes from sibling tools like ping_all or share_port, which are unrelated. The MagicDNS vs IP fallback adds specificity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for use (generating SSH config for tailnet nodes) and explains the default dry-run, write behavior, and different targets. It does not explicitly list when not to use or compare to siblings, but the purpose is clear enough to avoid misuse.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ping_allA

Ping tailnet peers concurrently (bounded to 5 at a time, one ping each with a timeout) and return a latency matrix: node, latency ms, path (direct vs DERP relay), or unreachable. Defaults to online peers only.

ParametersJSON Schema
NameRequiredDescriptionDefault
countNoPing attempts per peer (default: 1)
timeoutMsNoPer-ping timeout in milliseconds (default: 5000)
onlineOnlyNoOnly ping peers reported online (default: true)

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, but description fully discloses behavioral traits: concurrent pings bounded to 5 at a time, one ping each with timeout, default timeout 5000ms, defaults to online peers only. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, highly efficient. First sentence states action, constraints, and output format. Second adds default scope. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema and no annotations, description provides sufficient context: concurrency, timeout, result structure, default scope. Covers key behavioral aspects for agent invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. Description restates defaults and adds context about concurrency limit but does not significantly enhance parameter meaning beyond schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the tool pings tailnet peers, describes the output as a latency matrix with latency ms, path, and unreachability. It distinguishes from sibling tools like generate_ssh_config and share_port.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Description implies use case for checking latency and connectivity among peers. It notes defaults (online only) but does not explicitly state when to use vs alternatives or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

share_portA

Share a local port over the tailnet via Tailscale Serve (tailnet-only by default). WARNING: setting public=true switches to Funnel and exposes the port to the OPEN INTERNET — anyone with the URL can reach it. Only set public=true when internet exposure is explicitly intended. Returns the resulting URL(s).

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoHTTPS mount path on the serve endpoint (default: "/")
portYesLocal port to share
publicNoExpose to the open internet via Funnel (default: false = tailnet-only Serve). DANGEROUS: public=true makes the port reachable by anyone on the internet.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden. It discloses the critical behavioral trait of public exposure (Funnel) and its dangers. Does not cover authentication or conflict behavior, but the key risk is adequately communicated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three front-loaded sentences with no waste: purpose, warning, return info. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simple tool (3 params, no output schema, no annotations), the description covers essential purpose and warnings. Missing details on return format beyond 'URL(s)' but sufficient for agent invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds value by explaining default behavior for public and warning about dangers, which supplements the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (share a local port), the resource (local port), and the context (over tailnet via Tailscale Serve). It distinguishes from siblings like stop_share or share_status by focusing on the act of sharing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear guidance on when to set public=true vs false with an explicit warning. However, lacks explicit comparison to sibling tools or mention of prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

share_statusA

Report the active Tailscale Serve/Funnel sessions on this node.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description must disclose behavioral traits. It only states the tool reports sessions, but does not mention safety (non-destructive), required permissions, any side effects, or rate limits. Minimal transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, clear sentence with no wasted words. It is front-loaded and efficiently conveys the tool's function.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter tool with no output schema, the description is largely complete. It specifies what the tool reports and on which node. It could mention the return format or relationship to sibling tools, but is adequate for a simple read operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are no parameters; schema coverage is trivially 100%. The description adds meaning by explaining the purpose, which is sufficient since no parameter details are needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool reports active Tailscale Serve/Funnel sessions on the node. It uses a specific verb ('Report') and a well-defined resource, distinguishing it from sibling tools like share_port or tailnet_status.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives such as tailnet_status or share_port. The description does not include exclusions, prerequisites, or context about when this tool is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

stop_shareA

Stop sharing. Without arguments clears the entire serve/funnel configuration; with httpsPort it turns off just that HTTPS serve endpoint (the port shown in share_status, typically 443 — not the local port that was proxied).

ParametersJSON Schema
NameRequiredDescriptionDefault
httpsPortNoHTTPS serve port to turn off (as shown in share_status). Omit to clear everything.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses key behaviors: it clears the serve/funnel configuration, distinguishes between HTTPS port (as shown in share_status) and the local proxied port, and states the effect of omitting the argument. No annotations are provided, so the description carries the full burden, which it does adequately.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise at two sentences, front-loaded with the action, and contains no redundant information. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with one optional parameter and no output schema, the description provides complete guidance on both usage modes and the nature of the parameter. No gaps remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds meaning beyond the schema by explaining that 'httpsPort' is the HTTPS serve port (not the local port) and specifying the effect of omitting it. This clarifies the parameter's purpose and behavior.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: to stop sharing. It distinguishes between two modes (clearing all or turning off a specific HTTPS endpoint), and the context of siblings like 'share_port' and 'share_status' makes it evident that this is the stopping counterpart.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use each mode: without arguments to clear all, with httpsPort to stop a specific endpoint. It implicitly references 'share_status' for the correct port, providing a hint for use. However, it doesn't explicitly state when not to use it or mention alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tailnet_statusA

Report the state of the local tailnet: this node plus all peers with hostname, MagicDNS name, Tailscale IPv4/IPv6, OS, online flag, last seen, exit-node flags, and tags. Returns a structured error with the exact fix command when the tailscale binary is missing, the daemon is stopped, or the device needs login.

ParametersJSON Schema
NameRequiredDescriptionDefault
onlineOnlyNoOnly include peers that are currently online (default: false)

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. It discloses structured error returns with fix commands for common failures (missing binary, stopped daemon, need login), which is helpful behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two focused sentences: first lists output fields, second details error handling. No unnecessary words, front-loaded with purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given one optional parameter and no output schema, the description adequately covers output fields and error conditions, making it complete for a status tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter 'onlineOnly' is fully described in the input schema with a clear description. The tool description adds no further semantic value, meeting but not exceeding baseline expectations.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool reports tailnet state with specific fields (hostname, MagicDNS name, IPs, OS, online flag, etc.), distinguishing it from sibling tools like ping_all or share_port.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implicitly guides usage by listing what it reports and error conditions, but doesn't explicitly state when to use this tool over alternatives. The context from siblings makes it clear enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 6 tool updatesv0.1.0
    • First observedgenerate_ssh_config
    • First observedping_all
    • First observedshare_port
    • First observedshare_status
    • First observedstop_share
    • First observedtailnet_status

TDQS

A4.2/5.0
Disambiguation5/5

Each tool has a clearly distinct purpose: SSH config generation, ping testing, port sharing management, and tailnet status. No overlaps.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern using snake_case (e.g., generate_ssh_config, ping_all, stop_share).

Tool Count5/5

6 tools cover the core functionalities of tailnet management without being excessive or insufficient.

Completeness4/5

Covers SSH config, latency testing, and port sharing comprehensively. Minor gaps like setting exit nodes or managing ACLs, but fits a focused scope.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    F
    maintenance
    An MCP (Model Context Protocol) server for managing Tailscale resources using the official Tailscale Go client library v2. This server provides complete coverage of the Tailscale API with enhanced, self-descriptive tools powered by OpenAPI documentation.
    2
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    An MCP server for managing and monitoring Tailscale networks through natural language. It enables users to list devices, check connection status, monitor for client updates, and retrieve detailed tailnet summaries.
    6
    15
    7
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Production-ready MCP server for Tailscale management with 48 tools across 9 domains: Devices, DNS/Split DNS, ACL policies, Auth Keys, Users, Webhooks, Posture Integrations, Tailnet Settings, and Diagnostics. Supports stdio and SSE transport with Bearer token authentication. Built with TypeScript strict mode, Zod validation, and zero shell execution. AGPL-3.0 + Commercial dual-licensed.
    49
    93
    1
    AGPL 3.0

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TMHSDigital/tailscale-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server