Tailscale MCP server for AI agents

Live

BEARER TOKEN

NETWORK ACCESS

Developer Tools

Tailscale gives your agent network access control for your tailnet: list and authorize devices, manage users and invites, edit and test the access control policy, configure DNS, and create auth keys.

  • Per-user credentials: each call uses the actual user's access token, never a shared bot.
  • Encrypted per-tenant vault: AES-256, resolved at request time, never in LLM context.
  • Scoped before every call: pre-call scope check, 90-day SIEM-exportable audit chain.
Tailscale
agent · Acme Q3
Run
Which devices haven't been seen in the last 30 days?
S
tailscale_list_devices
93ms
Network ops agent
9 of 84 devices have not been seen in 30 days. 6 run macOS and 3 are tagged tag:ci.
Sources: tailnet, 84 devices
tailscale
9 devices
18:29
Message Claude...

Tools your network ops agent reaches for on Tailscale, scoped per user.

CALL ANY TOOL
41 tools for network access on Tailscale: list, authorize, tag, and remove devices, manage users and invites, read, test, and update the access control policy, configure DNS, read audit and flow logs, and manage auth keys.
tailscale_authorize_device
Authorize device
Authorize or deauthorize a device on a tailnet that has device approval enabled. Returns an empty JSON object on success. Use authorize_device to approve a pending device or revoke access. Only meaningful when device approval is turned on in the tailnet settings.
Parameters
Name
Type
Required
Description
authorized
boolean
Required
Set to true to authorize the device or false to deauthorize it.
device_id
string
Required
ID of the device. The preferred form is the node ID returned as nodeId by the list devices tool (for example 'nABC123CNTRL'); the legacy numeric id (for example '12345') also works.
tailscale_create_auth_key
Create auth key
tailscale_delete_device
Delete device
tailscale_delete_key
Delete key
tailscale_expire_device_key
Expire device key
tailscale_get_configuration_audit_logs
Get configuration audit logs
tailscale_get_contacts
Get contacts
tailscale_get_device
Get device
tailscale_get_dns_configuration
Get dns configuration
tailscale_get_dns_nameservers
Get dns nameservers
tailscale_get_dns_preferences
Get dns preferences
tailscale_get_key
Get key
tailscale_get_network_flow_logs
Get network flow logs
tailscale_get_policy_file
Get policy file
tailscale_get_tailnet_settings
Get tailnet settings
tailscale_get_user
Get user
tailscale_list_devices
List devices
tailscale_list_keys
List keys
tailscale_list_user_invites
List user invites
tailscale_preview_policy_rule_matches
Preview policy rule matches
tailscale_rename_device
Rename device
tailscale_run_policy_tests
Run policy tests
tailscale_set_device_key
Set device key
tailscale_set_device_routes
Set device routes
tailscale_set_dns_nameservers
Set dns nameservers
tailscale_set_dns_preferences
Set dns preferences
tailscale_set_dns_search_paths
Set dns search paths
tailscale_update_contact
Update contact
tailscale_update_policy_file
Update policy file
tailscale_update_split_dns
Update split dns

For more tools, view docs.

Build your Agent
Same auth pattern across LangChain, OpenAI, Anthropic, and Google ADK.
Python · LlamaIndex
import { ScalekitClient } from "@scalekit-sdk/node";
import { createReactAgent } from "@langchain/langgraph/prebuilt";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);

// Tailscale tools scoped to this user
const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["tailscale"], toolNames: [
    "tailscale_list_devices",
    "tailscale_authorize_device",
    "tailscale_run_policy_tests"] },
  pageSize: 100,
});

const agent = createReactAgent({ llm, tools });
await agent.invoke({ messages: [{ role: "user", content: "List devices that have not been seen in the last 30 days" }] });
import OpenAI from "openai";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);
const openai = new OpenAI();

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["tailscale"] }, pageSize: 100,
});

const res = await openai.chat.completions.create({
  model: "gpt-5",
  messages: [{ role: "user", content: "List devices that have not been seen in the last 30 days" }],
  tools,
});

// Execute the tool call with the user's vaulted Tailscale access token
await sk.tools.executeTool(res.choices[0].message.tool_calls[0], "user_123");
import Anthropic from "@anthropic-ai/sdk";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);
const anthropic = new Anthropic();

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["tailscale"] }, pageSize: 100,
});

const msg = await anthropic.messages.create({
  model: "claude-sonnet-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "List devices that have not been seen in the last 30 days" }],
  tools,
});

// Tool call runs with the user's vaulted Tailscale access token
await sk.tools.executeTool(msg.content, "user_123");
import { Agent } from "@google/adk/agents";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["tailscale"] }, pageSize: 100,
});

const agent = new Agent({
  name: "network_ops_agent",
  model: "gemini-2.5-pro",
  instruction: "Tailscale tools scoped to this user",
  tools,
});

await agent.run("List devices that have not been seen in the last 30 days");
Try these prompts
Copy any prompt into your agent. Each maps directly to a Tailscale tool. Click to copy, paste into your agent, done.
Devices
Copy the prompt
Copied
List devices that are waiting for approval.
Copy the prompt
Copied
Authorize the device named build-runner-04.
Copy the prompt
Copied
Set the tags on db-proxy to tag:prod and tag:db.
Policy and DNS
Copy the prompt
Copied
Run the policy tests against our current tailnet policy.
Copy the prompt
Copied
Which policy rules apply to sam@acme.com?
Copy the prompt
Copied
Turn on MagicDNS for our tailnet.
Users and audit
Copy the prompt
Copied
Invite sam@acme.com to the tailnet as a member.
Copy the prompt
Copied
Show configuration audit log entries from the last 24 hours.
Copy the prompt
Copied
List auth keys that expire this month.
SEE HOW AUTH WORKS
Each user connects their own Tailscale access token once, and Scalekit sends it with every call. Tokens stay vaulted, every call is scope checked, and every action is logged.
1
Authorize
Your user connects
Tailscale
once. We tie it to their identity and the meetings they approved — no shared bot account, no org-wide access
Who:
user ‘A’
when:
Once per user
access:
Limited to user
2
Store
Their
Tailscale
token lives in a vault scoped to them. User A's meetings are never reachable by an agent acting for user B, even on the same connection
vault:
encrypted
scope:
per-user
tokens:
auto-refreshed
3
Resolve
When your agent calls a
Tailscale
tool, we fetch the right token server-side. It never touches your agent, never appears in the LLM context, never shows up in your logs
speed:
~40ms
check:
before every call
seen by:
nobody
4
Audit
Every
Tailscale
tool call is logged — who triggered it, which meeting was fetched, what came back. 90 days of history, tied to the user who authorized it
history:
90 days
export:
SIEM-ready
logged:
every call
Test other agents
See the same per-user auth pattern across other developer tools and monitoring connectors.
Engineering Teams
DevOps assistant agent
Polls GitHub for failing checks and stale PRs, opens Linear issues for the ones that need work, and posts a daily digest to Slack. It acts as the engineer, not a shared service account.
Test other agents
See the same per-user auth pattern across other developer tools and monitoring connectors.
ENGINEERING
DevOps assistant agent
Poll GitHub for failing checks and stale pull requests, open Linear issues for the ones that need work, and digest to Slack.
Why Scalekit
Secure your agent's access. Connectors ship in minutes
01.
Shared tokens break per-user analytics
A shared Tailscale access token looks fine in a demo. In production every device approval looks like one service account, and you cannot tell which user triggered it. Scalekit resolves the credential of the actual user who triggered the agent, never a shared bot.
// shared token
audit → bot_service_account

// scalekit
audit → user_abc ✓
02.
Authentication is not authorization
03.
Multi-tenancy is architectural
04.
Tailscale today. Ten connectors tomorrow.
“Our agents act across Salesforce, Gong, Google Drive, and more, on behalf of every customer. Scalekit behind the scenes meant we can keep adding tools without ever rebuilding how credentials or tool calling work.”
Venu Madhav Kattagoni
Head of Engineering / Von
FAQs
Frequently Asked Questions
Does the agent access Tailscale as the user or through a shared access token?
As the user. Each user connects their own Tailscale access token once, and Scalekit sends it with every call. Device approvals, policy edits, and key changes the agent makes are attributed to that user in your audit trail, not a shared service account.
Where is the Tailscale access token stored?
In Scalekit's managed AES-256 token vault, namespaced per tenant. To rotate it, the user reconnects with a new access token. Revocation is a single dashboard action. Credentials never appear in prompts, logs, or LLM context.
Can I limit what the agent does in Tailscale?
Yes. Filter by tool name in listScopedTools to expose only what you want, for example device and policy read tools without tailscale_update_policy_file, which replaces the entire policy file, and tailscale_delete_device. Scalekit also enforces scope checks before every API call.
What happens when a user revokes Tailscale access?
The connection is invalidated on the next tool call. Subsequent requests for that user fail closed with a clear error. Other users in the tenant remain unaffected. The event is logged for audit.
Can the agent change who can reach what on the tailnet?
Only if you expose tailscale_update_policy_file, which replaces the whole access control policy. tailscale_validate_policy_file and tailscale_run_policy_tests check a policy without saving it. Leave the update tool out of listScopedTools to keep the agent to reading and testing policy.
Start in your coding agent
Up and running in one command
Install the Scalekit skill in your editor of choice. Connector, auth, tools, prompt, all wired up
Claude Code REPL
/plugin marketplace add scalekit-inc/claude-code-authstack
/plugin install agentkit@scalekit-auth-stack
Cursor Code REPL
# ~/.cursor/mcp.json
{
""mcpServers"": {
""tailscale"": {
""url"": ""https://mcp.scalekit.com/tailscale"",
""headers"": { ""Authorization"": ""Bearer $SCALEKIT_TOKEN"" }
}
}
}
Codex Code REPL
# ~/.codex/config.toml
[mcp_servers.tailscale]
url = ""https://mcp.scalekit.com/tailscale""
auth_env = ""SCALEKIT_TOKEN""
Copilot Code REPL
# .vscode/mcp.json
{
""servers"": {
""tailscale"": {
""url"": ""https://mcp.scalekit.com/tailscale"",
""type"": ""http""
}
}
}