Skip to main content
Glama
YawLabs

@yawlabs/tailscale-mcp

by YawLabs

@yawlabs/tailscale-mcp

Add to Yaw MCP

One click adds this to your local Yaw MCP config so it's available in every Yaw Terminal session. Or install manually below.

npm version License: MIT GitHub stars Release

Ask your agent questions about your tailnet and have it act on the answers. 97 admin-API tools + 6 optional local-CLI diagnostics + 1 always-on catalog tool + 4 resources spanning the Tailscale v2 API — devices, ACLs, DNS, keys and trust credentials, users, invites, webhooks, log streaming, posture, services, and organization tailnets. Backed by 1900+ unit tests and an opt-in live-tailnet integration suite.

Built and maintained by Yaw Labs.

What's the point if the API already exists?

You could curl the Tailscale API. The point isn't replacing curl — it's letting an agent compose multi-endpoint workflows in one turn without writing a script:

  • "Which devices haven't checked in for 30 days and have key expiry disabled?" — lists devices, filters by lastSeen (online devices carry none), filters by keyExpiryDisabled, returns a table. Three endpoints, one question.

  • "Someone broke DNS at 2am — who changed what in the last 24 hours?" — pulls the audit log, filters by DNS-related actors and endpoints, reads each change's before/after, summarizes in English.

  • "Draft an ACL change that lets tag:mobile reach tag:dashboard but not tag:db, preserving my comments" — reads the current HuJSON, proposes a minimal diff, validates it against the API, returns the diff for you to apply.

  • "Rotate every auth key older than 90 days and print the new ones" — iterates, creates new keys with matching tags, revokes the old ones.

  • "Create an OAuth client for our CI pipeline scoped to devices:core:read and dns:read" — creates a trust credential via tailscale_create_key with keyType=client, returns the credentials once (save them immediately).

A curl can do each step. The agent composes them. That's where the lift is, and that's what the tool surface is designed for — every read endpoint is first-class so the agent can synthesize, and every write endpoint is tagged destructiveHint or idempotentHint so your MCP client can gate mutations the way you configured it.

If all you need is one endpoint in a CI job, use curl — we even have a CLI subcommand for the common ACL-from-git case. The MCP is for the interactive, exploratory, "I don't know what I need yet" work.

Related MCP server: mcp-tailscale

Why MCP vs. a skill or the tailscale CLI?

Reasonable question. Both have their place. Where this MCP is better:

  • Broad admin API coverage. The tailscale CLI is scoped to the node it runs on. Admin concerns — ACLs, users, invites, webhooks, log streaming, posture integrations, auth keys, OAuth clients, and federated identities — live in the v2 HTTP API. You'd be shelling out to curl anyway.

  • Typed tool surface, not string parsing. Every tool has a Zod-validated input schema and a structured response. No brittle tailscale status --json | jq pipelines that break when the schema evolves.

  • Cross-client, and updates arrive as a version bump. An MCP server works in Claude Code, Claude Desktop, Cursor, Windsurf, VS Code, and anything else that speaks MCP; a skill written to the Agent Skills standard travels between agents too, but it is prose you maintain. Version bumps ship through npx — nobody rewrites a skill's instructions when Tailscale adds an endpoint.

  • Safe-by-default writes. Every tool declares readOnlyHint / destructiveHint / idempotentHint so clients can skip confirmation on reads and require it on mutations. A skill that shells out to the CLI can't express that.

  • Real tests. 1900+ unit tests covering every tool's input validation, API shape, and error handling. Plus an opt-in live-tailnet integration suite (RUN_INTEGRATION_TESTS=1 + a tailnet API key) for shape-drift detection. Most skills are short markdown prompts without their own test layer — if the vendor changes output format, nothing catches it for you.

If you already have a skill that covers your 10% of Tailscale workflows, great — keep it. The MCP is for the other 90%.

What about Tailscale's own MCP endpoints and skill? As of 2026-09-19 they solve different problems, and nothing here duplicates them. Tailscale's official MCP tools are two alpha built-in connectors inside Aperture: Tailnet, whose Tailnet_provision_node returns a single-use auth key so an agent can join one new node after a person approves it, and Tailscale SSH, whose TailnetSSH_list_machines and TailnetSSH_run_command discover SSH-enabled machines and run one command on one of them. They require Aperture. tailscale/tailscale-skill is an alpha, knowledge-only skill — reference material that teaches an agent to curl the v2 API, with no server of its own. Neither exposes the admin API as typed tools, so the overlap with this server is close to nil. Nor can Aperture front this one today: this server speaks stdio, and Aperture proxies only URL-addressable Streamable-HTTP or SSE servers. Both of those products are alpha, so treat the date on this paragraph as its expiry.

Trust signals

Fair critique from Reddit: a new repo claiming "actively maintained" with no visible tests is worth exactly zero trust. Here's what's actually verifiable:

  • 1900+ tests (node --test) covering every tool's input validation, API shape, and error handling. Run npm test to see them pass locally.

  • Local release flow via release.sh: lint + test + bump + tag + push + npm publish + MCP Registry publish, all from the workstation. No CI workflow to babysit.

  • Dependabot alerts surface on this repo and get fixed, not ignored.

  • Every tool verified against the live API. If it's in the tool list, it calls a real endpoint that exists in the current v2 API. No placeholder 404 tools.

Issues and PRs are triaged. File one if something is off — github.com/YawLabs/tailscale-mcp/issues.

Quick start

1. Set your API key

Get an API key from Tailscale Admin Console > Settings > Keys and set it where your MCP client will see it. The .mcp.json env block in step 2 works identically on every platform and is the option to prefer; to export it from a shell profile instead (~/.bashrc, ~/.zshrc, ~/.config/fish/config.fish):

macOS / Linux / WSL (bash, zsh):

export TAILSCALE_API_KEY="tskey-api-..."

fish:

set -Ux TAILSCALE_API_KEY tskey-api-...

Windows (PowerShell 5.1 and 7) — [Environment]::SetEnvironmentVariable persists it for the user, where $env: alone lasts only for the session:

[Environment]::SetEnvironmentVariable('TAILSCALE_API_KEY', 'tskey-api-...', 'User')

2. Create .mcp.json in your project root

macOS / Linux / WSL:

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

Windows:

{
  "mcpServers": {
    "tailscale": {
      "command": "cmd",
      "args": ["/c", "npx", "-y", "@yawlabs/tailscale-mcp@latest"]
    }
  }
}

Why the extra step on Windows? On Windows, npx is a .cmd file, and Node 20+ refuses to spawn .cmd files directly. Wrapping with cmd /c is the standard workaround.

3. Restart and approve

Restart Claude Code (or your MCP client) and approve the Tailscale MCP server when prompted.

That's it. Now ask your agent:

"List my Tailscale devices that haven't been seen in the last 7 days"

"Summarize every ACL change in the audit log from yesterday"

"Draft an ACL rule that lets tag:ci reach tag:registry on port 5000 only"

Too many tools? Subset them.

97 tools is a lot. If you've already got a dozen MCP servers and your client is feeling heavy, trim what this one exposes. Three knobs, combinable:

The env blocks below show only the variable under discussion. Your credentials come from the environment, as set in Quick start — keep them in your shell profile rather than in the client's JSON config, which is world-readable on most systems and easy to commit by accident.

Option 1: TAILSCALE_PROFILE (preset, easiest)

{
  "env": {
    "TAILSCALE_PROFILE": "core"
  }
}
  • minimal (20 tools) — status, devices, audit. Observe the tailnet, read the audit log.

  • core (52 tools) — adds acl, dns, keys, users. The day-to-day admin surface.

  • full (97 tools, default) — everything. Same as omitting the env var.

Option 2: TAILSCALE_TOOLS (explicit group list)

{
  "env": {
    "TAILSCALE_TOOLS": "devices,acl,dns,audit"
  }
}

Comma-separated group names. Overrides TAILSCALE_PROFILE when both are set — use this when the presets aren't quite right.

Valid group names: status, devices, acl, dns, keys, users, tailnet, webhooks, posture, audit, invites, services, log-streaming. The local-cli group is also available, but only when TAILSCALE_LOCAL_CLI=1 is set — see Local CLI integration.

Option 3: TAILSCALE_READONLY (drop mutations)

{
  "env": {
    "TAILSCALE_PROFILE": "core",
    "TAILSCALE_READONLY": "1"
  }
}

Set to 1 or true to drop every tool without readOnlyHint: true. Stacks with TAILSCALE_PROFILE or TAILSCALE_TOOLS as an intersection — combine for maximum minimalism.

Confirming what loaded

The server logs the active filter to stderr on startup:

@yawlabs/tailscale-mcp v0.12.0 ready (20 tools, profile=minimal, readonly)

When both TAILSCALE_PROFILE and TAILSCALE_TOOLS are set, TAILSCALE_TOOLS wins. The banner marks the profile as overridden so the precedence is obvious at a glance — no need to guess which filter actually applied:

@yawlabs/tailscale-mcp v0.12.0 ready (22 tools, profile=core (overridden by TAILSCALE_TOOLS), groups=devices,acl)

The "(overridden)" marker only fires for substantive profiles (minimal / core); profile=full is a no-op preset, so it's shown without the marker when TAILSCALE_TOOLS is also set.

If you don't set any filter, startup prints a tip pointing you at the profiles.

And how the agent knows

Everything above is stderr -- your MCP client's log. The model never sees it, so a withheld tool and a tool that was never built look identical from the agent's side. That is how an agent ends up working around a restriction instead of reporting it.

tailscale_tool_groups closes that gap. It is always registered, whatever the filters say, and answers the question in-band:

> "Why can't you delete that device?"

  tailscale_tool_groups({ toolName: "tailscale_delete_device" })

  {
    "tool": "tailscale_delete_device",
    "available": false,
    "group": "devices",
    "kind": "write",
    "reason": "TAILSCALE_WRITE_GROUPS is set to \"dns\", which does not grant writes here",
    "toEnable": "add \"devices\" to TAILSCALE_WRITE_GROUPS (e.g. \"dns,devices\")"
  }

It separates the three cases an agent otherwise cannot tell apart:

Case

What the agent should do

No such tool exists, under any configuration

Find another approach -- no setting will produce it

Exists, but its group is not loaded

Report toEnable to you; do not work around it

Exists and loaded, but writes are withheld there

Same -- the fix is yours, not a workaround

Called with no arguments it lists every group with its availability and, for anything withheld, the exact environment change that would restore it. It reads no network and needs no credentials, so it works even when the server is misconfigured.

Scoping writes to areas

TAILSCALE_WRITE_GROUPS names the areas an agent may write to. Everything else stays readable:

{
  "env": {
    "TAILSCALE_WRITE_GROUPS": "devices,keys"
  }
}

That serves all 41 read tools plus the 18 writes in devices and keys, and withholds the other 38 writes — the ACL, DNS, users, tailnet, webhooks, posture, services, invites, org-tailnets and log-streaming writes are simply not registered. Unset means no write gate, which is the shipped default.

Read this first: this filters the tool list, not your API token. The server still holds one credential with full tailnet authority in every configuration. An agent that also has a shell can curl api.tailscale.com with that same token and do everything this knob withheld. Scope the Tailscale OAuth client itself to the areas you actually need (scopes per tool group) — that bound survives outside this process; this one does not. TAILSCALE_WRITE_GROUPS is the low-friction complement to credential scoping, not a replacement for it.

What a grant actually contains

Group names are the same ones TAILSCALE_TOOLS uses. Writes per group:

Group

Writes

Group

Writes

devices

13

webhooks

5

invites

7

posture

3

dns

6

services

3

keys

5

tailnet

3

users

5

log-streaming

3

org-tailnets

2

acl

1

status, audit and the opt-in local-cli group contain no writes at all, so granting them does nothing.

devices is the widest grant, and the one most likely to be set. In a compose file write=devices reads like "device admin", but it hands over delete_device, set_devices_authorized, expire_device, deauthorize_device, set_device_routes, set_device_tags and update_device_key alongside rename_device. There is no finer setting: an honest "safe subset" of devices is rename_device alone, and a knob whose useful value is one tool is not a knob.

Three grants are tailnet-admin-equivalent

keys, users and acl are not blocked — CI key rotation legitimately needs keys — but grant them knowing:

  • keys — tailscale_create_key mints an OAuth client with whatever scopes the caller asks for, including policy_file and all. That credential outlives the agent's session and is not subject to this or any other setting here.

  • users — tailscale_update_user_role accepts owner.

  • acl — tailscale_update_acl rewrites policy for every principal in the tailnet.

The server prints this on startup when your grant includes one of them.

What it does and does not bound

It bounds where an agent may write. It does not bound severity within a granted area: inside a granted group, writes run unattended, including the grant-direction ones. Pair it with TAILSCALE_REQUIRE_APPROVAL=1 when a human is at the keyboard — but understand that for an unattended agent that pairing contributes nothing, because a never-prompt client denies those calls rather than prompting.

Precedence, and what happens when you get it wrong

Situation

Result

Unset, empty, whitespace, or commas-only

No write gate. -e VAR with no value must not silently revoke every write.

TAILSCALE_READONLY=1 also set

Readonly wins; banner says readonly (TAILSCALE_WRITE_GROUPS ignored).

A name is misspelled (devises)

Grants nothing and names the typo. Unlike TAILSCALE_TOOLS, there is no fallback — a typo'd write grant that fell back would hand over all 56 writes at the moment you were restricting them.

Partly misspelled (devices,dnss)

Grants the valid half, warns about the rest.

A granted group is not loaded by TAILSCALE_TOOLS / TAILSCALE_PROFILE

The grant has no effect; a separate warning says so, since the name is not a typo.

none, all, off, *

Not reserved words — they are unknown group names, so they grant nothing. Use TAILSCALE_READONLY=1 for no writes, or leave this unset for all writes. The server points you at the right spelling.

Names are case-sensitive, matching TAILSCALE_TOOLS.

The upgrade contract: upgrading this package can never widen the set of areas an agent may write to. A new group is in nobody's grant until a human types its name. It can, however, add tools inside an area you already granted — a pinned test makes that a reviewed line in the diff rather than a silent change.

The startup banner shows what applied:

@yawlabs/tailscale-mcp v0.19.0 ready (59 tools, write=devices,keys)

Requiring approval on irreversible tools

readOnlyHint / destructiveHint are advisory — the MCP spec says clients MUST treat annotations as untrusted, and most don't gate on them. TAILSCALE_REQUIRE_APPROVAL=1 adds a stronger signal that supported clients enforce:

{
  "env": {
    "TAILSCALE_REQUIRE_APPROVAL": "1"
  }
}

Nine tools are then advertised with _meta["anthropic/requiresUserInteraction"], which forces a confirmation prompt even when an allow-rule would otherwise auto-approve the call:

Tool

Why it's on the list

tailscale_update_acl

Can lock every device out of the tailnet; the previous HuJSON (comments included) is gone unless you captured it

tailscale_delete_device

The device must re-enroll

tailscale_delete_user

No undelete

tailscale_delete_tailnet

Destroys an entire tailnet

tailscale_delete_key

The secret is never returned again

tailscale_delete_oauth_app

Same

tailscale_delete_webhook

Same

tailscale_delete_log_stream_config

Same

tailscale_delete_posture_integration

Same

The line drawn is "this server cannot undo it with information you still hold", which is narrower than the 23 tools annotated destructiveHint: true. tailscale_suspend_user is deliberately excluded — tailscale_restore_user reverses it. So are tailscale_deauthorize_device (reversed by tailscale_authorize_device) and the replace-all setters, which all have a get_* counterpart you can read before writing.

Opt-in on purpose, and read this before turning it on. In a client mode that never prompts (an unattended agent, a CI run), the flag causes those calls to be denied rather than run. That is the right default when a human is at the keyboard and the wrong one when nobody is, so it stays off unless you set it.

Requires a client that honors the annotation; Claude Code added support in v2.1.199. Clients that don't recognize it ignore it, so setting the variable is never worse than leaving it off.

Separately and always on, the tools whose response size scales with the tailnet rather than with the request — tailscale_list_devices, tailscale_list_users, tailscale_get_acl, tailscale_diff_acl_access, tailscale_get_audit_log, tailscale_get_network_flow_logs, tailscale_local_status — declare _meta["anthropic/maxResultSizeChars"], so a large-but-legitimate result stays inline instead of being truncated into a file reference the agent has to read back mid-task. The last of those is the one entry behind an opt-in: it declares the cap whenever TAILSCALE_LOCAL_CLI=1 registers it, and is absent entirely otherwise.

Using with mcp.hosting / mcph

If you run this server through mcp.hosting (via the @yawlabs/mcph local agent), the two filtering layers compose cleanly:

  1. Server-side — TAILSCALE_PROFILE / TAILSCALE_TOOLS / TAILSCALE_READONLY reduce the tool surface before mcph sees it. The unloaded tools aren't registered at all.

  2. Client-side — mcph's mcp_connect_activate({ tools: [...] }) filters further for what appears in tools/list. Tools not in that list stay reachable via mcp_connect_dispatch, so you don't lose capability.

Recommended pattern for mcph users: set TAILSCALE_PROFILE=core (or narrower) in your mcp.hosting server config, then let mcph handle per-conversation activation on top. The server stays lean by default, and mcp_connect_dispatch covers the long-tail tools for ad-hoc needs.

Authentication

API key (simplest): Set TAILSCALE_API_KEY in your shell or MCP config.

OAuth (scoped access): For fine-grained permissions, set TAILSCALE_OAUTH_CLIENT_ID and TAILSCALE_OAUTH_CLIENT_SECRET instead. Create an OAuth client at Tailscale Admin Console > Settings > Trust credentials, with the scopes listed below for the tool groups you load.

The server checks for an API key first, then falls back to OAuth. If neither is set, tools return a clear error telling you what to configure — the server still starts, so your MCP client doesn't loop restarting.

Tailnet: Uses the credential's own tailnet (-) automatically, which is what most setups want. To name one explicitly, set TAILSCALE_TAILNET to the Tailnet ID shown under Settings > General in the admin console — it looks like T1234CNTRL. Tailnets created before October 2025 can still use their legacy organization name; newer ones have no such name to use. Per the OpenAPI spec, the Tailnet ID is the preferred identifier either way.

TAILSCALE_OAUTH_TAILNET — target an API-only tailnet (one created by tailscale_create_org_tailnet). Those tailnets are not reachable with a plain client-credentials exchange: you authenticate with an OAuth client belonging to the creating tailnet (all scope) and the target rides on the token request. Set this to the new tailnet's id. Deliberately separate from TAILSCALE_TAILNET so the default token exchange is unchanged for everyone else. If you set this, leave TAILSCALE_TAILNET unset (or -) so tool requests follow the token — pointing the two at different tailnets makes every tailnet-scoped tool return 403, and the server warns about it at startup.

OAuth scopes by tool group

The scopes an OAuth client needs for each TAILSCALE_TOOLS group. Grant the Read column for the groups you load, and add the Write column for the ones you let it change; Notes lists what a group needs beyond that. all:read (every read scope) and all (everything) are the broadest grants there are.

Group

Read

Write

Notes

status

devices:core:read, feature_settings:read

none

Reads the device list and the tailnet settings, and still returns one when the other is refused.

devices

devices:core:read, devices:routes:read, devices:posture_attributes:read

devices:core, devices:routes, devices:posture_attributes

The route tools use the devices:routes pair and the posture-attribute tools the devices:posture_attributes pair; the rest use devices:core. A credential holding devices:core must be created with at least one tag.

acl

policy_file:read, devices:core:read, devices:posture_attributes:read

policy_file, devices:posture_attributes

Tailscale requires the device scopes alongside policy_file:read and policy_file. tailscale_diff_acl_access also needs users:read when you omit principals and it lists the users itself.

dns

dns:read

dns

Unverified. The OpenAPI spec names no scope on any DNS operation, and the trust credentials doc these come from does not list /dns/configuration, the endpoint behind tailscale_get_dns_configuration and tailscale_set_dns_configuration.

keys

auth_keys:read, oauth_keys:read, federated_keys:read, api_access_tokens:read, oauth_apps:read

auth_keys, oauth_keys, federated_keys, api_access_tokens, oauth_apps

Key scopes go by key type: auth_keys for auth keys, oauth_keys for OAuth clients, federated_keys for federated identities, api_access_tokens for personal API access tokens (read and delete only). Grant only the types you manage; only all:read and all can list every access token in the tailnet. The OAuth-app tools use oauth_apps, and tailscale_create_oauth_app also needs devices:posture_attributes when it sends allowedNodeAttributes.

users

users:read

users

tailnet

feature_settings:read, account_settings:read

feature_settings, account_settings

Settings are split by field: network flow logging needs logs:network:read / logs:network, HTTPS certificates networking_settings:read / networking_settings, and the two externally-managed-ACL fields policy_file:read / policy_file; feature_settings covers the rest. The contacts tools use account_settings.

org-tailnets

tailnets:read

tailnets

tailscale_delete_tailnet needs all (see TAILSCALE_OAUTH_TAILNET above).

webhooks

webhooks:read

webhooks

posture

feature_settings:read

feature_settings

The same scope governs most tailnet settings, so a client that can manage posture integrations can change those too.

audit

logs:configuration:read, logs:network:read

none

tailscale_get_audit_log uses the first, tailscale_get_network_flow_logs the second.

invites

device_invites:read

device_invites (delete only)

Creating, resending and accepting a device invite (tailscale_create_device_invite, tailscale_resend_device_invite, tailscale_accept_device_invite) cannot be done with a token from an OAuth client at all, and creating, deleting and resending a user invite (tailscale_create_user_invite, tailscale_delete_user_invite, tailscale_resend_user_invite) is permitted only with a user-owned key. Use TAILSCALE_API_KEY for those. The spec names no scope for reading user invites.

services

services:read

services

tailscale_list_service_hosts, tailscale_get_service_device_approval and tailscale_set_service_device_approval need both services and devices:core, so the two reads among them do not work on a read-only client.

log-streaming

log_streaming:read

log_streaming

Streaming to a private endpoint also needs device_invites and policy_file. tailscale_create_aws_external_id and tailscale_validate_aws_trust_policy both need log_streaming, although the second is a read.

local-cli

none

none

Runs the local tailscale binary and makes no admin-API call.

Scopes are taken from Tailscale's OpenAPI spec as of 2026-09-19. The DNS row, which the spec omits, and the device scopes in the acl row come from the trust credentials doc. All of it is read from the documentation, not observed against a tailnet.

Reliability and debugging

429 and gateway-error retry (built-in). HTTP 429, 502, 503 and 504 are retried up to 3 times on the idempotent methods (GET, PUT, DELETE), honoring the Retry-After header (both seconds-integer and HTTP-date forms). Falls back to exponential backoff with jitter, capped at 30s per wait. No env var needed — this is on by default. Workflows like "rotate every key older than 90 days" no longer fail mid-loop on Tailscale's per-tenant rate limits, and a gateway blip no longer fails a whole tool call: per the OpenAPI spec, 504 is documented on every device and service operation with the message "request took too long to process, please try again later", and 502 on the log reads. HTTP 500 is not retried — it means the server failed to process the request, not that something in front of it gave up. POST and PATCH are never retried, on any status. A DELETE that retried past a gateway error and then got a 404 says so in its error, because the attempt that timed out may already have deleted the resource.

TAILSCALE_DEBUG=1 — log every HTTP method, URL, status, and elapsed time to stderr. Authorization headers are never logged. Use this when a tool returns an unexpected error and you want to see the actual request that went out. Example:

[tailscale-mcp] GET https://api.tailscale.com/api/v2/tailnet/-/devices
[tailscale-mcp]   <- 200 (148ms)

TAILSCALE_MAX_CONCURRENT=N — cap in-flight API requests at N. Default is unlimited (no behavior change for users who don't opt in). Useful when an agent fans out aggressively against a tailnet that has stricter limits than the per-call retry can absorb.

TAILSCALE_REQUEST_BUDGET_MS=N — total wall-clock budget per request, including retries and their sleeps. Default 90000 (90s). When the next retry's predicted wall time would exceed the budget, the call surfaces the error immediately instead of holding the line. For a gateway 5xx that prediction also charges the duration of the attempt that just failed: a 504 arrives only after the gateway has already waited, so the retry most likely costs the same again, and spending the rest of the budget on it would leave your client with silence instead of the 504. A call that retries past a gateway 5xx is also held to half this budget from that point on — 45s by default, under the 60s low end of the usual MCP client timeout — since those attempts cost gateway wait time rather than backoff, and a chain of them can outlast the client while a 429 chain cannot. Raising this value raises that ceiling with it; a 429 chain keeps the whole budget either way. Tune lower if your MCP client has a tighter outer timeout. Non-idempotent methods (POST, PATCH) are never retried — those return immediately regardless of budget.

TAILSCALE_RETRY_BASE_DELAY_MS=N — base delay for the exponential backoff between retries; attempt N waits base * 2^N (capped at 30s, plus jitter). Default 1000 (1s), so a fully-exhausted retry chain spends roughly 1s + 2s + 4s sleeping. Pairs with TAILSCALE_REQUEST_BUDGET_MS: lowering the budget on its own doesn't get you more retries, it just makes the default backoff exhaust the budget sooner and give up. Shrink both if you want "retry hard, fail fast". A server-supplied Retry-After header always wins over this value.

TAILSCALE_EXTRA_WEBHOOK_EVENTS=eventA,eventB — opt-in escape hatch for webhook event types Tailscale ships after the latest release of this package. The webhook tools validate subscriptions against a strict static catalog so typos and stale event names fail fast with a clear error; if you need a brand-new event before the catalog catches up, list it here (comma-separated) and the schema will accept it. The two category subscriptions (categoryTailnetManagement, categoryDeviceMisconfigurations) are in the catalog, so they need no entry here. Please also open an issue so the static list catches up.

TAILSCALE_EXTRA_POSTURE_PROVIDERS=providerA,providerB — the same escape hatch for device-posture integration providers. tailscale_create_posture_integration validates provider against a static list (falcon, fleet, huntress, intune, jamfpro, kandji, kolide, sentinelone); if Tailscale adds one before this package catches up, list it here rather than waiting for a release. This field used to be a closed enum, which made a newly-supported provider uncreatable rather than merely unvalidated.

Friendlier error messages. JSON error bodies of the form {"message":"..."} or {"error":"..."} are unwrapped before display, so you see the prose explanation instead of raw JSON. When the body also carries a data array — which the ACL endpoints use to report a failing policy test — it is rendered under the message, so a rejected policy says which user and which assertion failed instead of just test(s) failed. 401s still get the full multi-line auth-error formatter (with the Windows env-var hint when applicable).

Local CLI integration (opt-in)

Most tools talk to the Tailscale v2 admin API — they describe the tailnet. Sometimes you want to ask about this machine's view: is it actually connected? What DERP region is it on? How far is my-laptop from here? Those answers come from the local tailscale binary, not the admin API.

Set TAILSCALE_LOCAL_CLI=1 (in your shell or .mcp.json env block) to add 6 read-only diagnostic tools:

Tool

Equivalent CLI command

Use it for

tailscale_local_status

tailscale status --json [--peers=false] [--active]

This machine's connection state + peers it can see; peers: false and activeOnly: true narrow the peer map

tailscale_ping

tailscale ping <target>

Latency probe to another tailnet node (direct vs DERP-relayed)

tailscale_netcheck

tailscale netcheck --format=json

NAT type, DERP latency map, IPv4/IPv6 support

tailscale_local_version

tailscale version

Which client version is actually running

tailscale_local_whoami

tailscale whoami

Which user and device this machine is authenticated as (needs tailscale >= 1.102.1)

tailscale_local_service_list

tailscale service list

Tailscale Services visible to this node (needs tailscale >= 1.102.1)

Requirements: the tailscale binary has to be findable. It's looked up on PATH first, then at the default install paths below, and TAILSCALE_BINARY overrides both with an absolute path of your choosing.

Platform

Where it looks beyond PATH

Notes

macOS

/Applications/Tailscale.app/Contents/MacOS/Tailscale, /opt/homebrew/bin/tailscale, /usr/local/bin/tailscale

The standard install keeps the CLI inside the app bundle and adds nothing to PATH. An MCP client launched from the Dock or Spotlight also inherits a minimal PATH, not your shell's — so a bare lookup can fail even when tailscale works in your terminal.

Linux

/usr/bin/tailscale, /snap/bin/tailscale

The snap wrapper is outside some minimal PATHs.

Windows

—

The installer puts tailscale.exe on the machine PATH. If you set TAILSCALE_BINARY, use a Windows path (C:/Program Files/Tailscale/tailscale.exe), not a Git Bash one (/c/...) — that spelling is translated when you type it at an MSYS prompt, but not when it's read from a JSON config or a .env.

WSL

/usr/bin/tailscale, /snap/bin/tailscale

These tools report the Linux node, and need Tailscale installed inside the distro with tailscaled running there. In a fresh WSL install the only tailscale in reach is the Windows one; a Linux process can't exec tailscale.exe, and pointing TAILSCALE_BINARY at /mnt/c/.../tailscale.exe would report the Windows host's Self, peers, whoami identity and netcheck results while every tool here says "this machine's". tailscale.exe is deliberately never picked up automatically.

The MCP server doesn't need root to run these — they're all diagnostic, not state-mutating. Operations that would need elevation (tailscale up, set --advertise-routes, lock sign) are deliberately not exposed.

When opt-in is on, the startup banner reflects it: @yawlabs/tailscale-mcp v0.13.3 ready (103 tools, local-cli=on) — the 6 local CLI tools are additive on top of the default 97.

Resources (4)

MCP Resources expose read-only data clients can browse without a tool call.

Resource

URI

Description

Tailnet Status

tailscale://tailnet/status

Device count and tailnet settings

Devices

tailscale://tailnet/devices

All devices with status and IPs

ACL Policy

tailscale://tailnet/acl

Full ACL policy (HuJSON preserved)

DNS Config

tailscale://tailnet/dns

Nameservers, search paths, split DNS, MagicDNS

Tools (97 + 6 opt-in)

Tool

Description

tailscale_status

Verify API connection, see tailnet info and device count

Tool

Description

tailscale_list_devices

List devices (default field subset; fields: "all" adds routes, connectivity, SSH, distro, posture identity). lastSeen is absent while a device is online

tailscale_get_device

Get one device (fields: "all" for the full record)

tailscale_authorize_device

Authorize a pending device

tailscale_deauthorize_device

Deauthorize a device

tailscale_set_devices_authorized

Authorize/deauthorize many devices in one call (parallel, per-id error reporting)

tailscale_delete_device

Remove a device from the tailnet

tailscale_rename_device

Rename a device (FQDN or base name; empty string resets to the OS hostname)

tailscale_expire_device

Expire a device's key, forcing re-authentication

tailscale_get_device_routes

Get advertised and enabled subnet routes

tailscale_set_device_routes

Enable or disable subnet routes

tailscale_get_device_posture_attributes

Get all posture attributes for a device

tailscale_set_device_posture_attribute

Set a custom posture attribute (optional expiry and audit-log comment)

tailscale_delete_device_posture_attribute

Delete a custom posture attribute

tailscale_set_device_tags

Set ACL tags on a device

tailscale_set_device_ip

Set a device's Tailscale IPv4 address

tailscale_update_device_key

Update device key settings (e.g. disable key expiry)

tailscale_batch_update_posture_attributes

Batch update custom posture attributes across devices

Tool

Description

tailscale_get_acl

Get ACL policy with formatting preserved (HuJSON) + ETag

tailscale_update_acl

Update ACL policy (requires ETag for safe concurrent edits; ts-default for a first write)

tailscale_validate_acl

Validate a policy without applying it

tailscale_preview_acl

Preview rules that would apply to a user or IP

tailscale_diff_acl_access

Compare a proposed policy against the live one — who gains and loses access

Tool

Description

tailscale_get_nameservers

Get DNS nameservers

tailscale_set_nameservers

Set DNS nameservers

tailscale_get_search_paths

Get DNS search paths

tailscale_set_search_paths

Set DNS search paths

tailscale_get_split_dns

Get split DNS configuration

tailscale_set_split_dns

Set split DNS configuration (full replace; null clears a domain)

tailscale_update_split_dns

Update split DNS configuration (partial merge; null removes a domain)

tailscale_get_dns_preferences

Get DNS preferences (MagicDNS)

tailscale_set_dns_preferences

Set DNS preferences (MagicDNS)

tailscale_get_dns_configuration

Get unified DNS configuration (all settings in one call)

tailscale_set_dns_configuration

Set unified DNS configuration (all settings in one call)

Tool

Description

tailscale_list_keys

List keys (default set depends on the credential; all=true for tailnet-wide: auth keys, API access tokens, OAuth clients, federated identities)

tailscale_get_key

Get details for a key of any type

tailscale_create_key

Create an auth key, OAuth client (keyType=client), or federated identity (keyType=federated)

tailscale_delete_key

Delete a key of any type, including the API access token this server runs on

tailscale_update_key

Update a key's description, scopes, tags, or federated claim settings

tailscale_create_oauth_app

Create an OAuth App for third-party device provisioning (Tailscale alpha)

tailscale_get_oauth_app

Get an OAuth App's name, redirect URIs, and scopes

tailscale_list_oauth_apps

List every OAuth App registered in the tailnet

tailscale_delete_oauth_app

Delete an OAuth App, revoking its ability to provision devices

Tool

Description

tailscale_list_users

List all users in the tailnet

tailscale_get_user

Get details for a specific user

tailscale_approve_user

Approve a pending user

tailscale_suspend_user

Suspend a user, revoking access

tailscale_restore_user

Restore a suspended user

tailscale_update_user_role

Update a user's role (owner, admin, member, etc.)

tailscale_delete_user

Delete a user and all their devices

Tool

Description

tailscale_get_tailnet_settings

Get tailnet settings (HTTPS, device approval, key expiry, etc.)

tailscale_update_tailnet_settings

Update tailnet settings (HTTPS certificates, approval, auto-updates, key expiry, posture, regional routing, network flow logging, external ACL management)

tailscale_get_contacts

Get tailnet contacts

tailscale_set_contacts

Set tailnet contacts

tailscale_resend_contact_verification

Resend verification email for a contact

Tool

Description

tailscale_list_webhooks

List webhooks

tailscale_get_webhook

Get a specific webhook

tailscale_create_webhook

Create a webhook (raw JSON, or formatted for Slack / Mattermost / Google Chat / Discord via providerType)

tailscale_update_webhook

Update a webhook's endpoint URL and/or subscriptions

tailscale_delete_webhook

Delete a webhook

tailscale_rotate_webhook_secret

Rotate a webhook's secret

tailscale_test_webhook

Send a test event to verify webhook delivery

Tool

Description

tailscale_list_posture_integrations

List posture integrations

tailscale_get_posture_integration

Get a posture integration

tailscale_create_posture_integration

Create a posture integration

tailscale_update_posture_integration

Update a posture integration

tailscale_delete_posture_integration

Delete a posture integration

Tool

Description

tailscale_list_services

List all Tailscale Services in your tailnet

tailscale_get_service

Get details for a specific service

tailscale_update_service

Update a service's configuration

tailscale_delete_service

Delete a service

tailscale_list_service_hosts

List devices hosting a service

tailscale_get_service_device_approval

Get approval status of a device for a service

tailscale_set_service_device_approval

Approve or reject a device to host a service

Create and tear down whole tailnets programmatically — useful for per-agent sandboxes, per-tenant isolation, and ephemeral CI environments. Organizations get 10 tailnets including the original by default. Unlike every other group here these endpoints live under /organizations, authenticate only with an OAuth client (the tailnets scope to create, all to then reach the tailnet), and produce tailnets that are not managed in the admin console. Set TAILSCALE_OAUTH_TAILNET to operate on one.

Tool

Description

tailscale_list_org_tailnets

List the organization's tailnets (paginated via limit / cursor)

tailscale_create_org_tailnet

Create an API-only tailnet; returns its OAuth client secret once

tailscale_delete_tailnet

Delete a tailnet (the configured one, or an explicit tailnet) — irreversible; requires confirmTailnet to match

Tool

Description

tailscale_list_log_stream_configs

List log streaming configurations (both audit and network)

tailscale_get_log_stream_config

Get log streaming config for a log type

tailscale_set_log_stream_config

Set where logs are sent (Axiom, Datadog, Splunk, etc.)

tailscale_delete_log_stream_config

Delete a log streaming configuration

tailscale_get_log_stream_status

Check if log streaming is delivering successfully

tailscale_create_aws_external_id

Create/get the AWS external ID for S3 role-based log streaming (reusable, default true, returns the same ID until it is linked)

tailscale_validate_aws_trust_policy

Validate AWS IAM role trust policy for S3 log streaming

Tool

Description

tailscale_list_device_invites

List device invites for a specific device

tailscale_create_device_invite

Create a device invite

tailscale_get_device_invite

Get a device invite

tailscale_delete_device_invite

Delete a device invite

tailscale_accept_device_invite

Accept a device share invitation

tailscale_resend_device_invite

Resend a device invite email

Tool

Description

tailscale_list_user_invites

List open (not yet accepted) user invites

tailscale_create_user_invite

Create a user invite

tailscale_get_user_invite

Get a user invite

tailscale_delete_user_invite

Delete a user invite

tailscale_resend_user_invite

Resend a user invite email

Tool

Description

tailscale_get_audit_log

Get configuration audit log (who changed what, when); optional server-side actor / target / event filter

tailscale_get_network_flow_logs

Get network traffic flow logs between devices

Tool

Description

tailscale_local_status

This machine's view of the tailnet (own connection state, peers, DERP region); narrow with peers: false or activeOnly: true

tailscale_ping

Latency probe to another tailnet node from this machine

tailscale_netcheck

NAT type, DERP latency map, IPv4/IPv6 support diagnostics

tailscale_local_version

Local tailscale binary version

tailscale_local_whoami

Which user and device this machine is authenticated as (needs tailscale >= 1.102.1)

tailscale_local_service_list

Tailscale Services visible to this node (needs tailscale >= 1.102.1)

GitOps: deploy ACLs from CI

For the simple "deploy ACL from git on merge" workflow, you don't need an MCP server or an agent — use the built-in CLI:

# PR check: validate the proposed policy without touching the tailnet
npx -y @yawlabs/tailscale-mcp@latest validate-acl tailscale/acl.json

# On merge: ETag fetch + validate + deploy with If-Match, fail-closed at every step
npx -y @yawlabs/tailscale-mcp@latest deploy-acl tailscale/acl.json

Works in any CI system. Set TAILSCALE_API_KEY as an env var; TAILSCALE_TAILNET is optional — leave it unset to act on the key's own tailnet, or set it to the Tailnet ID to name one explicitly. Both commands exit non-zero on any failure; deploy-acl refuses to deploy without an ETag (so a concurrent Admin Console edit can never be silently clobbered) and reports a 412 as a concurrent-edit conflict you resolve by re-running.

When validation reports a failing policy test, the CI log names the user and the assertion (For user user1@example.com: / Errors found:), the same detail upstream's gitops-pusher prints. Validation warnings — a SCIM group that is not syncing, for instance — fail the run too, matching gitops-pusher and Tailscale's own Go client; their text is printed alongside so you can see what was flagged.

A complete GitHub Actions workflow — validate on PR, deploy on merge:

name: tailscale-acl
on:
  pull_request:
    paths: ["tailscale/acl.json"]
  push:
    branches: [main]
    paths: ["tailscale/acl.json"]

jobs:
  acl:
    runs-on: ubuntu-latest
    env:
      TAILSCALE_API_KEY: ${{ secrets.TAILSCALE_API_KEY }}
      TAILSCALE_TAILNET: T1234CNTRL # Tailnet ID from Settings > General; or omit: defaults to the key's tailnet
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - name: Validate ACL
        if: github.event_name == 'pull_request'
        run: npx -y @yawlabs/tailscale-mcp@latest validate-acl tailscale/acl.json
      - name: Deploy ACL
        if: github.event_name == 'push'
        run: npx -y @yawlabs/tailscale-mcp@latest deploy-acl tailscale/acl.json

For reproducible deploys, replace @latest with a pinned version.

If you hand-roll this with curl instead: Tailscale's ACL endpoint only returns the ETag header on GET, not HEAD. A curl -I (HEAD) ETag fetch silently yields an empty value — and an empty If-Match either deploys unguarded (clobbering concurrent edits) or trips your guard and fails the deploy. Fetch the ETag with a GET (curl -fsS -D - -o /dev/null ...), and fail the job if it comes back empty. The CLI above does all of this for you.

Optional: Lock the Admin Console to prevent manual edits that drift from git. Ask your agent:

"Set aclsExternallyManagedOn to true and aclsExternalLink to our repo URL"

This shows a read-only banner in the Tailscale Admin Console pointing to your repo. Use the MCP for reads and investigations, and let CI handle the deploy.

Requirements

  • Node.js 20.11+ to run the server (22+ to develop — the test script passes a glob to node --test, supported from Node 21)

  • A Tailscale API key or OAuth client credentials

Running on oam.js (optional)

oam.js runs this server unmodified, and the tailscale-mcp command only ever uses the latest oam release, currently 0.15.2. Verified against oam 0.15.2: full MCP handshake, all 97 admin-API tools plus tailscale_tool_groups, all 4 resources, identical error responses, and a clean stdout protocol stream — from the shipped bundle and straight from the TypeScript source with no build step.

oam 0.15.2 is the minimum. A floor matters here: releases before 0.9.0 ran child_process.execFile arguments through a shell, re-splitting them on whitespace and executing shell metacharacters inside an argument, and this server shells out to the tailscale binary across its local-CLI tools, so that was a reachable bug rather than a theoretical one.

How the tailscale-mcp command (bin/tailscale-mcp.mjs) picks a runtime:

  • TAILSCALE_MCP_RUNTIME=auto (the default) — if a client already launched it with oam run on oam 0.15.2 or newer, the server runs in that process. Otherwise it uses OAM_BIN when that is 0.15.2 or newer, else asks every oam binary it can find — %LOCALAPPDATA%\oam\bin then ~/.oam/bin on Windows, ~/.oam/bin elsewhere, then PATH — for its version and uses the newest at or above the floor (on a tie the installed copy wins). With none, it runs on Node. An oam host older than 0.15.2 never serves the server itself: it hands off to the newest usable oam, or to Node on PATH, or exits with an error when there is neither. Whenever it looks for an oam, stderr names an OAM_BIN that was passed over and why; the oam binaries it found and passed over are named, each with its reason, only when no usable oam turns up.

  • TAILSCALE_MCP_RUNTIME=oam — the same, but exit with an error instead of falling back to Node.

  • TAILSCALE_MCP_RUNTIME=node — always Node: in-process under npx, handed off to Node on PATH when a client launches the command with oam run.

The value is case-insensitive; anything else is warned about on stderr and treated as auto. On Windows only oam.exe counts: an oam.cmd / oam.bat shim is never run, and it is named on stderr only when no usable oam turns up.

Sandboxing (opt-in)

Set TAILSCALE_MCP_SANDBOX=1 to run under oam's --permission model: network restricted to api.tailscale.com -- the only host the bundle contacts, including the OAuth token exchange -- and filesystem denied. Child-process stays granted because the local-CLI tools shell out to the tailscale binary, which is also why PATH remains in the environment allow-list.

It is opt-in rather than default because a wrong grant does not fail loudly. oam denies a non-granted environment variable by making it absent from process.env rather than throwing, so an under-granted TAILSCALE_API_KEY reads as "unauthenticated" rather than "denied". The env allow-list in the launcher is derived from what the shipped bundle actually reads -- if you add a new process.env lookup, extend that list with it.

The sandbox is applied by the tailscale-mcp command, which spawns a fresh oam for it -- even when a client launched the command with oam run -- because --permission is a process-level flag. If it finds no usable oam to spawn, TAILSCALE_MCP_RUNTIME=auto still starts the server, without the sandbox; set TAILSCALE_MCP_RUNTIME=oam to make that an error. TAILSCALE_MCP_RUNTIME=node runs on Node, so it never applies the sandbox.

{
  "mcpServers": {
    "tailscale": {
      "command": "oam",
      "args": ["run", "/path/to/tailscale-mcp/dist/index.js"]
    }
  }
}

Measure startup on your own hardware. An MCP client cold-starts this server once per session, so startup is the cost that actually gets paid, and on the machine this was measured on node won it — 437ms vs 1554ms for oam run over 10 warmed runs (an earlier 5-run round showed 326ms vs 427ms; the box was busy, so treat the magnitude as noisy and the direction as the finding). Those runs used an oam that predates the 0.15.2 floor and have not been repeated since, so do not read them as a current ranking.

The published tailscale-mcp command prefers the newest usable oam it finds (see above). Without oam that costs almost nothing: discovery is file-existence checks only, never a subprocess, and the fallback runs the server inside the Node process npm already started. With oam installed, though, the command boots Node, runs --version on every oam binary it found to pick the newest, and only then boots oam, so it is always slower than pointing your client at a runtime directly — the config above for oam, node /path/to/tailscale-mcp/dist/index.js for Node. TAILSCALE_MCP_RUNTIME=node skips oam entirely.

Two places oam does win for this repo, both opt-in and neither touching the npm package:

  • npm run check:oam — type-checks via oam check (tsgo, TypeScript 7 native). Measured 4015ms against 7680ms for tsc --noEmit, same clean result. npx tsc --noEmit remains the portable default.

  • npm run build:binary:oam — builds the standalone binary via oam compile instead of Node SEA. Measured ~57.7 MB against ~73.6 MB for the Node SEA carrier before its blob is injected. Writes to the same bin/<platform>-<arch>/ path as npm run build:binary, so the release staging script consumes either unchanged — run one or the other. If you redistribute that binary it embeds oam's runtime, so ship oam's LICENSE, NOTICE and THIRD_PARTY_LICENSES.md with it.

The source stays runtime-agnostic on purpose: no oam: imports anywhere, and tests stay on node:test. That is what keeps the Node fallback real rather than nominal. Note that any oam invocation writes a bytecode cache to oam/ in the working directory — already in .gitignore.

Contributing

Contributions welcome. See CONTRIBUTING.md for the PR workflow and AI-agent guidelines. Please open an issue to discuss before a PR for anything beyond a typo fix.

git clone https://github.com/YawLabs/tailscale-mcp.git
cd tailscale-mcp
npm install
npm run lint       # Biome check
npm run lint:fix   # Auto-fix
npm run build      # tsc + esbuild bundle
npm test           # node --test (full suite)

For integration testing against your own tailnet: set TAILSCALE_API_KEY and run node dist/index.js.

Security

Found a vulnerability? See SECURITY.md — please use GitHub's private vulnerability reporting, not a public issue.

License

MIT

Follow @YawLabs on X

Available Tools

98 tools
tailscale_accept_device_inviteAccept device inviteB
Idempotent

Accept a device share invitation using the invite URL or code.

ParametersJSON Schema
NameRequiredDescriptionDefault
inviteYesThe device invite URL or invite code

TDQS

B3.3/5.0
Behavior2/5

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

Annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=true, and openWorldHint=true, so the safety profile is covered. The description adds no behavioral context of its own — no mention of permissions needed, what the acceptance does to the tailnet/device, or that it is idempotent.

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?

A single front-loaded sentence with zero filler. Nothing is padded or restated.

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

Completeness3/5

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

For a one-parameter, no-output-schema tool with rich annotations, the description is minimally sufficient to call it correctly. It omits any note about the post-acceptance effect or required privileges, leaving a modest gap for a mutation 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?

Schema coverage is 100% and the single parameter 'invite' is documented as 'The device invite URL or invite code'. The description merely repeats that wording, adding no format or syntax detail beyond the schema; baseline 3 is appropriate.

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

Purpose4/5

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

States a specific verb ('Accept') and resource ('device share invitation'), which cleanly distinguishes it from the sibling invite tools (create/get/list/delete/resend device invite). It does not explicitly name an alternative, but the action is unambiguous.

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

Usage Guidelines3/5

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

The phrase 'using the invite URL or code' implies the prerequisite (you must already hold an invite) but never states when to use this versus resending, deleting, or listing device invites. Usage is inferable but not spelled out.

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

tailscale_approve_userApprove userA
Idempotent

Approve a pending user, granting them access to the tailnet.

ParametersJSON Schema
NameRequiredDescriptionDefault
userIdYesThe user ID to approve

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare the safety profile (not read-only, idempotent, non-destructive, open-world), lowering the bar. The description adds the meaningful effect 'granting them access to the tailnet,' but says nothing about permissions required, reversibility, or what happens to already-approved users.

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?

A single front-loaded sentence with the action first and the effect second; no filler or redundancy.

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 one-parameter, non-destructive, idempotent operation with no output schema, the description conveys both purpose and outcome, which is close to sufficient. Only the precondition detail (how a user becomes 'pending') and any auth requirement are left unstated.

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?

With a single parameter and 100% schema description coverage, the schema fully documents userId. The description adds no format, source, or constraint detail beyond what the schema already provides, so the baseline 3 applies.

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

Purpose4/5

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

States a specific verb (approve) and resource (user) with a qualifying scope (pending) and the resulting effect (tailnet access). It implicitly separates itself from restore_user/suspend_user via the 'pending' state, but never names an alternative, so it stops short of full sibling differentiation.

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

Usage Guidelines3/5

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

The word 'pending' implies the precondition (the user must be in a pending state) and thus gives a hint of when the tool applies. However, no explicit when-to-use guidance, prerequisites, or alternatives (e.g., restore_user, authorize_device) are provided.

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

tailscale_authorize_deviceAuthorize deviceA
Idempotent

Authorize a device that is pending authorization.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceIdYesThe device ID to authorize. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.

TDQS

A4/5.0
Behavior3/5

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

Annotations already convey that the operation is not read-only, is not destructive, and is idempotent. The description adds the useful constraint that only pending-authorization devices are relevant, but does not disclose consequences beyond that, such as what authorization enables for the device.

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, focused sentence with no filler. The action and the prerequisite condition are front-loaded and immediately actionable.

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?

This is a simple single-parameter tool with no output schema, and annotations cover idempotency and safety. The description adequately states the action and condition; a small gap is the lack of any note about authorization effects or alternatives, but nothing critical is missing for calling the 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?

Schema description coverage is 100%, and the deviceId parameter is well documented with an example and a warning not to use the nodeKey. The description itself adds no parameter-level detail, so the baseline score of 3 applies.

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 states a specific verb ('Authorize') applied to a specific resource ('a device') with a clear precondition ('pending authorization'). This clearly distinguishes a single-device authorization action from siblings like tailscale_deauthorize_device or tailscale_set_devices_authorized.

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 gives a clear usage context: use this tool for devices that are pending authorization. It does not explicitly name alternatives or exclusions, such as batch authorization via tailscale_set_devices_authorized, so it stops short of full routing guidance.

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

tailscale_batch_update_posture_attributesBatch update posture attributesA
Idempotent

Batch update custom posture attributes across multiple devices. Each attribute key must start with 'custom:'. Uses JSON Merge Patch semantics — pass null as the attribute config to delete.

ParametersJSON Schema
NameRequiredDescriptionDefault
nodesYesMap of device ID to attribute config map (e.g. { "nPM2KNuedB21DEVEL": { "custom:compliant": { "value": "true" } }, "nPpz3VEKzX11DEVEL": { "custom:compliant": { "value": false, "expiry": "2026-12-01T00:00:00Z" } } }). Keys are device IDs, nodeIds preferred. Pass null as the config to delete an attribute.
commentNoOptional comment added to the audit log explaining why attributes are being set (max 200 chars)

TDQS

A3.8/5.0
Behavior1/5

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

Description contradicts annotations: it explicitly states 'pass null as the attribute config to delete', a destructive operation, while annotations declare destructiveHint=false. This is a serious inconsistency that misleads agents about the tool's side effects. Per rule, score is 1 when contradiction exists.

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 sentences, zero waste. Purpose is front-loaded, and the additional constraints (key prefix, merge patch, null deletion) are presented concisely. Ideal length for the tool's complexity.

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?

The description covers the essential behavioral aspects: batch scope, custom: prefix, merge patch semantics, and deletion via null. The nested schema covers parameter structure fully. However, the destructiveHint annotation conflict undermines completeness, and no mention of response format (though no output schema exists) is a minor gap. Overall, still quite complete for the complexity level.

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 value by explicitly stating the 'custom:' key prefix requirement and clarifying JSON Merge Patch semantics, which are not fully captured in the schema's parameter descriptions. The null-deletion behavior is repeated from the schema but the additional constraint justifies a 4.

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 states a specific verb ('batch update'), resource ('custom posture attributes'), and scope ('across multiple devices'). It clearly distinguishes itself from sibling tools like tailscale_set_device_posture_attribute and tailscale_delete_device_posture_attribute by emphasizing batch, multi-device operation.

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 clearly implies use for batch updates across multiple devices. It doesn't explicitly mention alternatives or when not to use this tool, but the 'batch' wording gives clear context. No exclusions are stated, so it fits the 'clear context, no exclusions' level.

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

tailscale_create_aws_external_idCreate AWS external IDA

Create or get the AWS external ID Tailscale presents when assuming your IAM role for S3 log streaming. Put it in the role trust policy's sts:ExternalId condition, then check it with tailscale_validate_aws_trust_policy.

ParametersJSON Schema
NameRequiredDescriptionDefault
reusableNoDefault true: Tailscale returns the SAME external ID on repeat calls until that ID has been linked to an AWS account, so asking again does not invalidate the ID already pasted into an IAM trust policy. Set false to force a fresh ID (what Tailscale's Terraform provider does, one ID per resource).

TDQS

A4/5.0
Behavior3/5

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

Annotations already indicate readOnlyHint=false and idempotentHint=false, so the tool is expected to have side effects and not be idempotent. The description adds that it 'creates or gets' an ID and the intended downstream use, but it does not disclose specifics about state changes, auth requirements, or rate limits. It doesn't contradict annotations, but it also doesn't enrich them significantly.

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 two sentences, front-loaded with the core purpose, and immediately directs the agent to the next action. Every word earns its place; there is no filler or redundancy.

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 tool with one well-documented parameter, clear annotations, and no output schema, the description provides sufficient context: it states what it does, why it is needed, and how to integrate it with the validation tool. It could explicitly mention that the tool returns the external ID, but that is strongly implied by 'Create or get' and the usage instructions. Overall, nothing critical is missing.

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 schema description coverage is 100% for the single parameter 'reusable', which is thoroughly explained (default behavior, what false means). Per the rubric, a high coverage baseline of 3 applies. The tool description itself adds no extra parameter context, so the schema carries the weight.

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 uses a specific verb ('Create or get') and identifies the resource ('AWS external ID') with its purpose ('for S3 log streaming'). It clearly distinguishes this tool from siblings by naming the exact object and context, and it references the companion validation tool, making its role unambiguous.

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 gives a clear workflow: obtain the ID, place it in the trust policy, then validate with tailscale_validate_aws_trust_policy. It implies when to use this tool (as a prerequisite to validation) but does not explicitly state when not to use it or mention alternative approaches. The 'reusable' parameter behavior is covered in the schema, not the description.

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

tailscale_create_device_inviteCreate device inviteA

Create a device share invitation that allows an external user to access a specific device in your tailnet.

ParametersJSON Schema
NameRequiredDescriptionDefault
emailNoEmail address to send the invite to
deviceIdYesThe device ID to create an invite for. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.
multiUseNoWhether the invite can be used more than once (default: false)
allowExitNodeNoWhether the invited device can be used as an exit node (default: false)

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already indicate this is a non-read-only, non-idempotent, non-destructive mutation. The description adds context that it creates an invitation, but does not disclose side effects such as email sending or the return format. It does not contradict annotations.

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 that front-loads the primary action and purpose. No extraneous words.

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

Completeness3/5

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

Given the tool's simplicity and the complete parameter documentation in the schema, the description is adequate but lacks information about expected response or any prerequisites. It does not mention that the device must exist or that an email may be sent, which could be relevant for an agent.

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 input schema has 100% coverage of all four parameters, including descriptions for email, deviceId, multiUse, and allowExitNode. The description itself adds no parameter-specific information beyond what the schema provides, so it relies on the schema's documentation.

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 a specific verb 'Create' and resource 'device share invitation', and explains its purpose of allowing an external user to access a specific device. This distinguishes it from user invites and other device operations.

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?

The description does not provide any guidance on when to use this tool versus alternatives such as tailscale_create_user_invite or other invite-related tools. It simply states what it does, leaving the agent to infer usage from the name and context.

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

tailscale_create_keyCreate keyA

Create a new key in your tailnet. Supports auth keys (for adding devices), OAuth clients (for programmatic API access), and federated identities (for OIDC-based CI/CD access). Returns the key value -- save it immediately, as it cannot be retrieved again.

SECURITY: the response body contains a long-lived credential verbatim. MCP clients commonly persist tool responses to logs and conversation transcripts; treat this response as sensitive (do not commit it, avoid re-sharing it in unrelated chat history).

Examples:

  • Auth key: {keyType:'auth', reusable:true, tags:['tag:ci']}

  • OAuth client: {keyType:'client', scopes:['devices:core:read','dns:read']}

  • Federated (GitHub Actions): {keyType:'federated', scopes:['devices:core:read'], issuer:'https://token.actions.githubusercontent.com', subject:'repo:my-org/my-repo:*'}

ParametersJSON Schema
NameRequiredDescriptionDefault
tagsNoACL tags (must start with 'tag:'). Required for client/federated if scopes include 'devices:core' or 'auth_keys'
issuerNo(federated only) OIDC issuer URL (e.g. 'https://token.actions.githubusercontent.com')
scopesNo(client/federated) OAuth scopes to grant (e.g. ['devices:core:read', 'dns:read']). Use the current scope names listed at https://tailscale.com/kb/1623/trust-credentials#scopes; the pre-2024 names such as 'devices:read' and 'acl' are legacy.
keyTypeNoKey type: 'auth' (default) for device auth keys, 'client' for OAuth clients, 'federated' for OIDC federation
subjectNo(federated only) Expected subject claim, supports * wildcards
audienceNo(federated only) Expected audience claim
reusableNo(auth only) Whether the key can be used more than once (default: false)
ephemeralNo(auth only) Whether devices using this key are ephemeral (default: false)
descriptionNoDescription for this key (max 50 chars, alphanumeric/hyphens/spaces)
expirySecondsNo(auth only) Key expiry in seconds (default: 90 days)
preauthorizedNo(auth only) Whether devices are pre-authorized (default: false)
customClaimRulesNo(federated only) Custom claim mapping rules

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already carry the mutation/idempotency hints, and the description adds meaningful behavior: the key value is shown only once and must be saved immediately. The explicit SECURITY warning that the response contains a long-lived credential that may be persisted by MCP clients is valuable context beyond any structured field. It does not cover error conditions or permission requirements, but that is a minor gap for this operation.

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 front-loaded with the core purpose and one-time retrieval behavior, then uses a clearly labeled SECURITY callout and three compact examples. Despite its length, each section earns its place and the structure makes it scannable for an agent.

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 12-parameter creation tool with no output schema, the description covers return behavior, security handling, all three supported key types, and representative parameter combinations. It omits error cases, authorization prerequisites, and explicit warnings about creating duplicate keys, but the combination of schema and description is largely sufficient.

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?

With 100% schema coverage, the schema already documents every parameter, so the baseline is 3. The description adds value with concrete example objects that show how tags, scopes, issuer, subject, and keyType compose for each of the three key types, helping an agent assemble valid parameter sets.

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

Purpose4/5

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

The description opens with a specific verb and resource ('Create a new key in your tailnet') and enumerates the three supported key types, which clearly distinguishes it from key lifecycle siblings like list_keys, get_key, update_key, and delete_key. It does not explicitly differentiate from the sibling tailscale_create_oauth_app, which also handles OAuth client creation, so it stops short of a perfect 5.

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

Usage Guidelines3/5

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

The description gives context for when each key type is appropriate (auth for adding devices, OAuth for API access, federated for OIDC CI/CD) and supplies example payloads. However, it never says when not to use this tool or names alternatives such as tailscale_create_oauth_app or tailscale_update_key, leaving routing between siblings to inference.

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

tailscale_create_oauth_appCreate OAuth appA

Create an OAuth App for device provisioning (Tailscale alpha). Lets a third-party application enroll a device into your tailnet via the authorization-code flow, after a user consents. Returns the app's client secret -- save it immediately, it cannot be retrieved again.

SECURITY: the response body contains a long-lived credential verbatim. MCP clients commonly persist tool responses to logs and conversation transcripts; treat this response as sensitive.

Use scope 'auth_keys:create:once' (one auth key per authorization, no refresh token) -- the scope Tailscale's device-provisioning guide documents. The API reference's example shows 'auth_keys:create'; this tool does not restrict the value. Distinct from tailscale_create_key with keyType='client', which mints a machine-to-machine OAuth client instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesHuman-readable name for the OAuth app, shown on the consent screen
scopesYesScopes to grant. Use 'auth_keys:create:once', the scope the device-provisioning guide documents; the API reference's example shows 'auth_keys:create'. Not restricted here.
redirectUrisYesAllowed redirect URIs for the authorization-code flow (e.g. ['https://example.com/callback'])
allowedNodeAttributesNoOptional node attributes the app may request when provisioning a device

TDQS

A4.9/5.0
Behavior5/5

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

Adds important behavior beyond annotations: the response contains a long-lived credential that cannot be retrieved again, and MCP clients may persist it in logs. The security warning and alpha status give the agent operational context that readOnlyHint/idempotentHint/destructiveHint do not convey.

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 front-loaded with the core function and flow, then handles security, scope guidance, and sibling differentiation. Every paragraph serves a distinct purpose and no sentence is wasted.

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 the moderate complexity and lack of an output schema, the description covers purpose, flow, required parameters, secret handling, and the key sibling alternative. The agent has enough information to invoke the tool correctly and handle its response safely.

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 the baseline is 3. The description adds value by explaining the recommended scope's semantics ('one auth key per authorization, no refresh token') and clarifying that the tool does not restrict the scope value despite the API reference's example.

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?

States it creates an OAuth app for device provisioning, describes the authorization-code flow and user consent, and notes it returns the client secret. It also distinguishes itself from tailscale_create_key, making the purpose unambiguous.

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

Usage Guidelines5/5

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

Explicitly names tailscale_create_key with keyType='client' as the alternative for machine-to-machine OAuth clients, and frames this tool as the one for third-party device enrollment after user consent. It also recommends the exact scope to use, leaving little room for incorrect selection.

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

tailscale_create_org_tailnetCreate organization tailnetA

Create a new API-only tailnet in your organization. Returns the tailnet (id, displayName, orgId, dnsName, createdAt) AND a freshly-minted OAuth client for it.

SECURITY: the response body contains that OAuth client's secret verbatim, and it cannot be retrieved again. MCP clients commonly persist tool responses to logs and conversation transcripts; treat this response as sensitive.

Requires an OAuth client with the 'tailnets' scope -- an API key will not work. To then operate on the new tailnet, set TAILSCALE_OAUTH_TAILNET to its id and use an OAuth client with the 'all' scope.

Organizations are limited to 10 tailnets including the original unless Tailscale sales has raised the limit.

The response may include alreadyExists: true; Tailscale's spec ALSO documents a 400 for a name already in use and neither has been observed, so after a timeout call tailscale_list_org_tailnets before retrying rather than assuming either.

ParametersJSON Schema
NameRequiredDescriptionDefault
displayNameYesHuman-readable name for the new tailnet. May contain letters, numbers, spaces, apostrophes and hyphens, and must be unique within the organization.
organizationNoOrganization ID. Defaults to '-' (the organization owning the calling credentials).

TDQS

A4.5/5.0
Behavior5/5

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

The description goes well beyond the annotations by disclosing that the response contains a one-time OAuth client secret, that MCP clients may persist responses, that creation requires specific credentials, that there is a 10-tailnet limit, and that duplicate-name behavior is ambiguous between alreadyExists and a 400. This is exactly the kind of behavioral context an agent needs and is not inferable from annotations or schema.

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?

Although the description is longer than typical, every section earns its place: the core purpose and return value are front-loaded, followed by security, auth, quota, and duplicate-handling guidance. The formatting with labeled sections makes it scannable despite the density of information.

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 create operation with unusual security and idempotency implications and no output schema, the description is remarkably complete. It covers return values, secret sensitivity, credential prerequisites, quota limits, and ambiguous failure modes, leaving an agent well-equipped to call the tool correctly and handle results appropriately.

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 description coverage is 100%, and both parameters (displayName and organization) already have descriptive text including uniqueness and default behavior. The description adds no additional parameter-level details beyond what the schema provides, so the baseline score of 3 is appropriate.

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 opens with a specific action and resource: 'Create a new API-only tailnet in your organization.' It also clarifies what is returned (the tailnet plus an OAuth client), which distinguishes it from sibling create operations like create_oauth_app or create_webhook. The purpose is unambiguous and not a tautology.

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 gives clear context for when to use the tool: it requires an OAuth client with the 'tailnets' scope, explains that an API key will not work, and describes follow-up actions after creation. It also tells the agent to call tailscale_list_org_tailnets before retrying after a timeout. It does not explicitly enumerate when not to use it, but for a create operation this is reasonable context.

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

tailscale_create_posture_integrationCreate posture integrationB

Create a new device posture integration.

ParametersJSON Schema
NameRequiredDescriptionDefault
cloudIdNoIdentifies which of the provider's clouds to integrate with. Falcon: us-1|us-2|eu-1|us-gov; Intune: global|us-gov; Jamf Pro/Kandji/Sentinel One: FQDN of your subdomain; Kolide: leave blank. Fleet/Huntress: undocumented upstream (see clientId).
clientIdNoClient ID for the provider (Intune: application UUID; Falcon/Jamf Pro: client id; Kandji/Kolide/Sentinel One: leave blank). Fleet and Huntress: Tailscale does not document how their credentials map onto these API fields -- the admin console asks for a Fleet URL + API token (Fleet) and an API key + API secret, plus an optional organization ID (Huntress). Do not assume this can be left blank; confirm the mapping first.
providerYesThe posture provider slug: falcon (CrowdStrike Falcon), fleet, huntress, intune (Microsoft Intune), jamfpro (Jamf Pro), kandji (Iru, formerly Kandji), kolide (1Password XAM, formerly Kolide), sentinelone
tenantIdNoMicrosoft Intune directory (tenant) ID. Other providers leave blank. Fleet/Huntress: undocumented upstream (see clientId).
clientSecretYesThe secret (auth key, token, etc.) used to authenticate with the provider. SENSITIVE: passed straight to Tailscale and not echoed back, but MCP clients may log the input value you supply.

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already indicate it's a write operation (readOnlyHint=false) and not idempotent. The description adds no additional behavioral context, such as side effects, authentication needs, or failure modes. It neither contradicts annotations nor adds significant value beyond what is already declared.

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, concise sentence that is front-loaded with the essential action and resource. It contains no fluff and is appropriately sized for the tool's simplicity.

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

Completeness2/5

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

Given the tool's complexity (5 parameters, provider-specific quirks, a sensitive secret), the description is too minimal. It does not mention the provider-specific nature of the operation, what happens on success, or any prerequisites. With no output schema, the agent has no indication of the return value, making this a significant gap.

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 description coverage is 100%, with detailed per-parameter documentation including provider-specific mappings and sensitivity warnings. The tool description adds no parameter information beyond what the schema provides, so the baseline of 3 applies.

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 ('Create') and the resource ('device posture integration'). It differentiates from sibling tools like get, update, delete, and list posture integrations by indicating a create operation. No ambiguity about the tool's purpose.

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?

The description provides no guidance on when to use this tool versus updating or deleting an integration, nor does it mention prerequisites like provider credentials or that it is intended only for new integrations. No alternatives or exclusions are mentioned.

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

tailscale_create_user_inviteCreate user inviteC

Create a new user invite that allows someone to join your tailnet.

ParametersJSON Schema
NameRequiredDescriptionDefault
roleNoRole to assign to the invited user (default: member)
emailNoEmail address to send the invite to

TDQS

C2.9/5.0
Behavior2/5

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

Annotations already declare readOnlyHint=false, non-idempotent, openWorld, non-destructive, so the safety profile is covered. The description adds only that the invite lets someone join the tailnet; it omits whether an email is dispatched, invite expiry, rate limits, or required privileges. For a mutation that contacts an external party, that leaves meaningful gaps.

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

Conciseness4/5

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

A single short sentence, front-loaded with the verb and resource, with no filler. It is efficient, though borderline under-specified rather than maximally informative.

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

Completeness3/5

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

For a simple two-parameter creation tool with no output schema and annotations covering the safety profile, the description is minimally adequate. It nonetheless leaves out the delivery mechanism, invite lifecycle, and permission requirements that an agent would need to call this correctly.

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% and the schema itself explains both the email target and the role enum with its default of 'member'. The description adds nothing about parameter behavior, so the baseline 3 for schema-complete tools applies.

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

Purpose4/5

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

States a specific verb+resource ('Create a new user invite') with a brief note on its effect ('allows someone to join your tailnet'). However, it never distinguishes itself from the numerous sibling invite tools (tailscale_create_device_invite, resend_user_invite, list/get/delete_user_invite), so the agent must infer scope from the name alone.

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 when-to-use guidance, no prerequisites (e.g., admin role required, seat availability), and no mention of the alternatives such as device invites or resending an existing invite. An agent gets no routing help from this text.

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

tailscale_create_webhookCreate webhookA

Create a new webhook. The response includes the webhook's signing secret -- this is the only opportunity to capture it; save it immediately. Set providerType when the endpoint is a Slack, Mattermost, Google Chat or Discord incoming-webhook URL, so the events arrive in the format that provider renders.

SECURITY: the response body contains the secret verbatim. MCP clients commonly persist tool responses to logs and conversation transcripts; treat this response as sensitive.

ParametersJSON Schema
NameRequiredDescriptionDefault
endpointUrlYesThe HTTPS URL to send webhook events to
providerTypeNoFormat deliveries for a chat provider's incoming-webhook URL. Omit for raw Tailscale JSON -- the default, and what a custom receiver verifying signatures wants. Set once: it cannot be changed after creation.
subscriptionsYesEvent types to subscribe to (at least one). 'categoryTailnetManagement' and 'categoryDeviceMisconfigurations' subscribe to a whole category, including events Tailscale adds to it later.

TDQS

A4.3/5.0
Behavior5/5

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

The description discloses the most important behavioral trait: the signing secret appears only once in the response and must be saved immediately. It also adds a security warning that MCP clients may persist responses to logs, which is valuable context beyond the annotations. The annotations already indicate this is a non-read, non-idempotent, non-destructive operation, and the description complements them with the one-time-secret and providerType-immutability details.

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 compact and front-loaded: the one-time secret warning appears in the first sentence, followed by providerType guidance and a security note. Every sentence earns its place, and the SECURITY section is clearly separated. No filler or repetition of schema content.

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 create operation with no output schema, the description covers the critical response behavior (one-time secret), the key parameter decision (providerType), and the security implications. It doesn't describe the full response shape or error cases, but the essential information an agent needs to call this correctly and handle the result is present.

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 the schema already documents all three parameters. The description adds value by explaining the consequence of providerType (format deliveries for chat providers, cannot be changed after creation) and the consequence of subscriptions (category subscriptions include future events). This goes beyond the schema's basic descriptions, though it doesn't add syntax details for endpointUrl.

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

Purpose4/5

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

The description states a specific verb and resource ('Create a new webhook') and adds the critical detail that the response contains a one-time signing secret. It doesn't explicitly differentiate from sibling tools like tailscale_update_webhook or tailscale_test_webhook, but the create semantics are clear enough that an agent can distinguish it from list/get/delete/update siblings.

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 gives clear context on when to set providerType (when the endpoint is a Slack, Mattermost, Google Chat or Discord incoming-webhook URL) and when to omit it (raw Tailscale JSON for custom receivers verifying signatures). It doesn't explicitly say 'use tailscale_update_webhook to modify later' or 'use tailscale_test_webhook to test', but the create-vs-alternative distinction is reasonably inferable from the sibling names and the description's focus on creation-time constraints.

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

tailscale_deauthorize_deviceDeauthorize deviceA
DestructiveIdempotent

Deauthorize a device, immediately removing its access to the tailnet. The device will need to be re-authorized to reconnect.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceIdYesThe device ID to deauthorize. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.

TDQS

A4.1/5.0
Behavior5/5

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

The annotations already mark the action destructive and non-read-only; the description adds that access is removed immediately and that the device can reconnect only after being re-authorized. This clearly communicates the consequence and recovery path, going beyond the annotation flags.

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 short sentences front-load the action and consequence, with no filler or repetition of the title. Every clause contributes meaning.

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 one-parameter mutation with annotations and a fully documented schema, the description is complete: it states the effect, the immediacy, and the recovery condition. No missing information prevents an agent from invoking it correctly.

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 schema description covers 100% of the parameter, including an example and a caution that the nodeKey is not accepted. The tool description adds no parameter detail, so the schema carries the full burden; baseline 3 applies.

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

Purpose4/5

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

The description opens with the verb 'Deauthorize' and the resource 'device,' and specifies the immediate effect of removing tailnet access. It is clearly a revocation action and distinguishable from siblings like tailscale_authorize_device, though it does not explicitly name alternative tools.

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

Usage Guidelines3/5

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

The description implies the tool is for revoking a single device's tailnet access, but it offers no explicit guidance on when to choose it over related siblings such as tailscale_expire_device, tailscale_set_devices_authorized, or tailscale_delete_device. The re-authorization note hints at reversibility but does not provide selection criteria.

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

tailscale_delete_deviceDelete deviceA
DestructiveIdempotent

Permanently remove a device from the tailnet. This is irreversible — the device must re-authenticate to rejoin.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceIdYesThe device ID to delete. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so the destructive nature is known. The description adds beyond annotations by specifying the consequence: the device must re-authenticate to rejoin. This is valuable context that the annotations do not convey. There is no contradiction with annotations.

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 two sentences, front-loaded with the core purpose, and contains no redundant words. The irreversibility note is concise and directly relevant to usage decisions.

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?

The tool is simple (one parameter, no output schema) and the annotations provide the destructive hint. The description covers the key behavioral detail (re-authentication requirement) and the purpose. It does not mention return codes or error handling, but for a delete operation this is often implicit and not necessary for correct invocation. Overall it is complete for an agent to use effectively.

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 input schema provides 100% coverage with a detailed description of the deviceId parameter (including examples and clarifications about nodeId vs nodeKey). The tool description itself adds no additional parameter information, so the baseline of 3 applies since the schema already carries the semantic load.

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 a specific verb ('remove') and resource ('device'), and adds the qualifier 'permanently' which distinguishes it from temporary actions like expire or deauthorize. It also notes the irreversible nature, making the tool's purpose unambiguous.

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 that this is for permanent removal, and the irreversibility statement implies that it should not be used for temporary or reversible actions. However, it does not explicitly name alternative tools (e.g., tailscale_expire_device) or state 'use this when...', so guidance is implied rather than explicit.

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

tailscale_delete_device_inviteDelete device inviteA
DestructiveIdempotent

Delete a device invite. This is irreversible — the invite link will stop working.

ParametersJSON Schema
NameRequiredDescriptionDefault
inviteIdYesThe device invite ID to delete

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and idempotentHint=true, but the description adds concrete consequence detail beyond them: the deletion is irreversible and the invite link stops working. That is genuinely useful behavioral context (no undo). It does not cover error behavior for an unknown inviteId, but the annotations supply the safety profile.

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 short sentences, front-loaded with the operation and immediately followed by the irreversibility warning. Zero filler and every clause 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?

For a one-parameter, no-output-schema mutation tool, noting the irreversible effect and the invite-link consequence is close to sufficient. Missing only edge-case behavior (e.g. what happens if inviteId does not exist), which is minor.

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 description coverage is 100% and the single inviteId parameter is already documented in the schema as 'The device invite ID to delete'. The description adds no format, sourcing, or lookup guidance beyond that, so the baseline 3 applies.

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

Purpose4/5

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

States a specific verb (Delete) and resource (device invite) that mirrors the tool name, so the agent knows exactly what operation it performs. It does not, however, distinguish itself from near-name siblings such as tailscale_delete_user_invite, tailscale_delete_device, or the create/accept/resend device-invite family.

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?

The description never states when to use this tool versus alternatives — e.g. when to delete an invite instead of resending it (tailscale_resend_device_invite), accepting it (tailscale_accept_device_invite), or deleting the underlying device (tailscale_delete_device). No prerequisites or context are given.

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

tailscale_delete_device_posture_attributeDelete device posture attributeA
DestructiveIdempotent

Delete a custom posture attribute from a device. This is irreversible.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceIdYesThe device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.
attributeKeyYesThe attribute key to delete (e.g. 'custom:lastAuditDate')

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, and the description adds the more specific context that deletion is irreversible. This is meaningful beyond the generic destructive flag, and nothing contradicts the annotations.

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 short sentences with no filler: the first states the operation, the second adds the critical warning. The information is front-loaded and every word 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?

For a simple two-parameter delete with destructive annotations and rich parameter descriptions, the description covers the essential behavior including irreversibility. It omits explicit alternative guidance and response/error details, but those are secondary given the schema and annotations.

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%, with both deviceId and attributeKey already well-documented through concrete examples and exclusions (e.g., not the nodeKey). The description adds no additional parameter-level meaning, so the baseline of 3 applies.

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 uses a specific verb ('Delete') and identifies the resource ('custom posture attribute from a device'), clearly distinguishing this from sibling tools like tailscale_delete_posture_integration. It is direct and unambiguous about the operation and scope.

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 over related tools such as tailscale_set_device_posture_attribute or tailscale_batch_update_posture_attributes. The only additional sentence warns about irreversibility, which is behavioral rather than usage guidance.

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

tailscale_delete_keyDelete keyA
DestructiveIdempotent

Delete a key (auth key, API access token, OAuth client, or federated identity). This is irreversible. For auth keys, devices already authenticated are unaffected but no new devices can use it. For OAuth clients and federated identities, any integrations using them lose access immediately. API access tokens are deletable here too: if keyId is the token this server authenticates with -- it shows up in tailscale_list_keys under API-key auth -- the server revokes its own credential and every later call fails with 401 until it is reconfigured.

ParametersJSON Schema
NameRequiredDescriptionDefault
keyIdYesThe key ID to delete (auth key, API access token, OAuth client, or federated identity)

TDQS

A4.5/5.0
Behavior5/5

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

The description goes far beyond the annotations' destructiveHint=true by disclosing irreversibility, the differing impact on auth keys versus OAuth clients/federated identities, and the self-revocation edge case where the server's own credential is deleted and later calls fail with 401. This is rich, actionable 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?

The description is compact and front-loaded: it opens with the action and resource, then states irreversibility, and then covers per-type behavior. Every sentence adds distinct information, and nothing repeats the schema or annotations.

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 one-parameter destructive tool with no output schema, the description covers the required scope, irreversibility, per-key-type consequences, and the notable self-revocation failure mode. Combined with annotations that already declare destructive and idempotent hints, nothing essential is missing for correct 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?

The schema already documents keyId at 100% coverage, so the baseline is 3. The description adds genuine semantic value by clarifying that keyId may be an API access token itself and explaining the special self-authentication case. It stops short of explaining how to obtain or format key IDs, so it is not a 5.

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 states a specific verb ('Delete') and a well-scoped resource ('a key'), then enumerates the four key types: auth key, API access token, OAuth client, and federated identity. This clearly distinguishes it from sibling tools like tailscale_delete_oauth_app or tailscale_delete_device.

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

Usage Guidelines3/5

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

The description gives clear context about consequences for each key type, but it never explicitly names alternatives or states when to prefer this tool over siblings such as tailscale_delete_oauth_app. Usage is implied by resource type rather than explicitly prescribed, so an agent must infer the selection logic.

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

tailscale_delete_log_stream_configDelete log stream configA
DestructiveIdempotent

Delete a log streaming configuration. Logs will stop being sent to the configured destination.

ParametersJSON Schema
NameRequiredDescriptionDefault
logTypeYesThe log type to stop streaming: 'configuration' or 'network'

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and idempotentHint=true, and the description adds useful context that deleting the configuration stops logs from being sent to the destination. It does not cover auth requirements or recovery options, but for a simple destructive delete with annotations, this is a meaningful addition.

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 short sentences, front-loaded with the action and followed by the consequence. No filler; 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?

For a one-parameter destructive delete with rich annotations and no output schema, the description is complete enough for correct invocation. It omits usage routing but covers purpose and consequence.

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 description coverage is 100%, with logType fully documented and enum values explained. The description adds no parameter meaning beyond the schema, so baseline 3 applies.

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

Purpose4/5

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

States a specific verb and resource ('Delete a log streaming configuration'), making clear what the tool does. It does not name sibling tools or explain how it differs from get/set/list log stream config tools, so sibling differentiation is left to the tool name.

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?

Provides no explicit guidance about when to use this tool versus alternatives such as tailscale_set_log_stream_config or other delete tools. The operation is implied by the verb, but there are no prerequisites or exclusions stated.

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

tailscale_delete_oauth_appDelete OAuth appA
DestructiveIdempotent

Delete an OAuth App (Tailscale alpha). This is irreversible: the app's client secret stops working immediately and any integration using it loses its device-enrollment path, so no further device can be authorized through it. Devices already enrolled stay in the tailnet, exactly as they do when the auth key that added them is deleted. Use tailscale_list_oauth_apps to find the id.

ParametersJSON Schema
NameRequiredDescriptionDefault
appIdYesThe OAuth app ID to delete (see tailscale_list_oauth_apps)

TDQS

A4.2/5.0
Behavior5/5

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

Annotations already declare destructiveHint=true and idempotentHint=true, so the safety profile is known, but the description goes well beyond that: it explains the client secret dies immediately, integrations lose their device-enrollment path, and already-enrolled devices survive. This is exactly the side-effect disclosure an agent needs for a destructive operation.

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

Conciseness4/5

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

Front-loaded with the action and the word 'irreversible' before the consequences, and the routing sentence lands last. Three sentences all earn their place, though the alpha parenthetical is slightly incidental.

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 one-parameter destructive tool with no output schema, the description covers irreversibility, the exact blast radius (secret invalidated, no new device authorization), what is NOT destroyed (enrolled devices), and how to source the id. Nothing an agent needs to call this safely is missing.

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 description coverage is 100%, so appId is already documented, and the description's only added semantics is pointing at tailscale_list_oauth_apps for the value. Baseline 3 applies when the schema carries the parameter documentation.

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?

States a specific verb and resource (delete an OAuth App), names the object precisely, and flags its alpha status. An agent can distinguish it from siblings like tailscale_delete_key or tailscale_delete_device without opening any schema.

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

Usage Guidelines3/5

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

The description points to tailscale_list_oauth_apps as the way to obtain the id, which is useful routing. However, it offers no guidance on when deletion is appropriate versus alternatives such as rotating the client secret or leaving the app in place, so usage context is only implied.

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

tailscale_delete_posture_integrationDelete posture integrationB
DestructiveIdempotent

Delete a posture integration. This is irreversible.

ParametersJSON Schema
NameRequiredDescriptionDefault
integrationIdYesThe posture integration ID to delete

TDQS

B3.3/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true, readOnlyHint=false and idempotentHint=true, so the safety profile is covered structurally. The description reinforces this with 'irreversible', which is useful emphasis, but adds nothing about cascading effects (e.g., devices relying on the integration), auth requirements, or error behavior.

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 short sentences, verb-resource front-loaded and the hazard warning placed immediately after. Nothing redundant or padded.

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

Completeness3/5

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

For a one-parameter destructive tool with full schema coverage and explicit annotations, the description covers the essentials and needs no output schema explanation. However, it omits any note on dependencies or what breaks after deletion, which would matter for an irreversible operation.

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% for the single integrationId parameter and its description already explains it is the ID to delete. The description adds no format, prefix, or sourcing detail beyond the schema, so the baseline 3 applies.

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

Purpose4/5

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

States a specific verb (Delete) and resource (posture integration) in the first sentence, so an agent can immediately distinguish it from the create/update/get/list posture-integration siblings. It stops short of explicitly naming those alternatives, but the action is unambiguous.

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?

There is no guidance on when to use this versus the sibling update_posture_integration or get_posture_integration, and no prerequisites such as required permissions. 'This is irreversible' is a warning, not usage direction.

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

tailscale_delete_serviceDelete serviceA
DestructiveIdempotent

Delete a Tailscale Service. This is irreversible — the service's MagicDNS name and virtual IP will be released.

ParametersJSON Schema
NameRequiredDescriptionDefault
serviceNameYesThe service name to delete

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, so the safety profile is covered. The description adds real value beyond them by spelling out the concrete consequences: irreversibility and release of the MagicDNS name and virtual IP. It stops short of noting permission/auth requirements.

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 short sentences, zero filler, with the action stated first and the irreversible consequence immediately after. Every clause 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?

For a one-parameter destructive tool with full annotation coverage and no output schema, the description supplies the key missing piece (side effects of deletion). It is nearly complete, lacking only auth/permission expectations that an agent might otherwise assume.

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 description coverage is 100% for the single serviceName parameter, so the schema already carries the semantics. The description adds nothing about name format or scoping (tailnet-level uniqueness), leaving this at the baseline for high-coverage schemas.

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

Purpose4/5

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

The description states a specific verb ('Delete') and resource ('Tailscale Service'), which cleanly separates it from sibling operations like tailscale_get_service, tailscale_update_service, and tailscale_list_services. It is clear without needing to name a sibling, though it does not explicitly justify itself against delete-adjacent tools such as tailscale_delete_device.

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?

There is no guidance on when to use this over alternatives (e.g., update_service, or deauthorizing hosts via list_service_hosts), nor any stated prerequisites or confirmation conventions. Usage is only implied by the tool name, which is the minimum bar.

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

tailscale_delete_tailnetDelete tailnetA
DestructiveIdempotent

Permanently delete a tailnet. This is IRREVERSIBLE and removes every device, user, ACL, and key in it.

By default it acts on the tailnet the current credentials point at (TAILSCALE_TAILNET, or TAILSCALE_OAUTH_TAILNET when targeting an API-only tailnet). Pass tailnet to name a different one -- e.g. an id returned by tailscale_list_org_tailnets -- which requires credentials scoped to reach it; UNVERIFIED against a live tailnet, so expect a 403/404 if your token cannot. You must always pass confirmTailnet matching the effective target exactly; the call is refused locally otherwise. That check is a typo guard, not an authorization gate: when you also pass tailnet you are supplying both halves of the comparison, so it proves only that they agree -- it is a genuine second look only on the omit-tailnet path, where the value has to match the operator's environment. Restricting who may delete at all is TAILSCALE_READONLY / TAILSCALE_TOOLS, which drop this tool from the server entirely. Intended for tearing down API-only tailnets created by tailscale_create_org_tailnet.

ParametersJSON Schema
NameRequiredDescriptionDefault
tailnetNoTailnet to delete (e.g. an id from tailscale_list_org_tailnets). Omit to target the configured tailnet. Requires credentials scoped to reach it.
confirmTailnetYesMust exactly match the effective target -- `tailnet` when given, otherwise the configured tailnet (TAILSCALE_TAILNET / TAILSCALE_OAUTH_TAILNET). A typo guard, not an authorization gate: on the explicit-`tailnet` path the caller writes both halves of the comparison, so it proves only self-agreement. It is a real second look only when `tailnet` is omitted and the value has to match the operator's environment.

TDQS

A4.9/5.0
Behavior5/5

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

Beyond the annotations, the description discloses that deletion is irreversible and removes every device, user, ACL, and key. It explains default targeting, credential requirements for alternate tailnets, local `confirmTailnet` refusal behavior, and that the confirmation is a typo guard rather than an authorization gate.

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

Conciseness4/5

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

The description is long, but it is front-loaded and organized around the destructive operation, target selection, confirmation semantics, and restrictions. Some details repeat the schema descriptions, but the length is largely justified for an irreversible operation.

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 the irreversible destructive behavior, no output schema, and two parameters, the description provides unusually complete context: effects, default and alternate targeting, credential constraints, confirmation semantics, and server-side tool restrictions.

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

Parameters5/5

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

Both parameters are fully described in the schema and expanded in the description. `tailnet` is explained as an optional alternate target, and `confirmTailnet` is described as a required exact-match guard whose semantics differ depending on whether `tailnet` is supplied.

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 states a specific verb and resource: 'Permanently delete a tailnet.' It immediately distinguishes the operation's scope by listing everything removed and identifies the intended use case: tearing down API-only tailnets created by tailscale_create_org_tailnet.

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

Usage Guidelines5/5

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

The description provides explicit usage context: it defaults to the credential-associated tailnet, supports naming another via `tailnet`, and says it is intended for tearing down API-only tailnets created by tailscale_create_org_tailnet. It also explains credential and environment-variable restrictions that drop the tool from the server.

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

tailscale_delete_userDelete userA
DestructiveIdempotent

Delete a user from the tailnet. This is irreversible — the user and all their devices will be removed.

ParametersJSON Schema
NameRequiredDescriptionDefault
userIdYesThe user ID to delete

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, idempotentHint=true, and openWorldHint=true, so the safety profile is covered structurally. The description earns credit for adding what those hints cannot: the operation is irreversible and the removal cascades to all of the user's devices. It stops short of noting permission requirements or whether dependent resources (keys, invites) are also affected.

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 short sentences with zero filler, and the irreversible consequence is front-loaded right after the action statement. Nothing needs trimming and nothing is buried.

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 destructive, single-parameter mutation with annotations carrying the safety hints and no output schema, the description covers action, scope, and consequence. The remaining gap is preconditions such as required privileges or confirmation expectations, which a delete operation of this severity would benefit from stating.

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?

There is a single parameter with 100% schema description coverage ('The user ID to delete'), so the schema fully documents the input. The description adds no format hints (e.g., numeric ID vs email), which is the correct baseline for a fully covered single-param schema.

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?

States a specific verb and resource ('Delete a user from the tailnet') and immediately clarifies the blast radius ('the user and all their devices will be removed'). This clearly separates it from softer siblings like tailscale_suspend_user, tailscale_restore_user, and tailscale_delete_user_invite without the agent needing to open schemas.

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?

The description gives no when-to-use guidance relative to alternatives. With close siblings such as tailscale_suspend_user and tailscale_deauthorize_device available, an agent gets no signal on when deletion is preferred over suspension or why the user must be removed rather than disabled. Usage is only implied by the verb.

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

tailscale_delete_user_inviteDelete user inviteA
DestructiveIdempotent

Delete a user invite. This is irreversible — the invite link will stop working.

ParametersJSON Schema
NameRequiredDescriptionDefault
inviteIdYesThe user invite ID to delete

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, so the mutation profile is known. The description adds concrete consequence detail beyond the annotations: the deletion is irreversible and the invite link stops working, which tells the agent exactly what is destroyed. It stops short of noting error behavior for an unknown inviteId.

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 short sentences, front-loaded with the action and immediately followed by the consequence. Every clause earns its place and there is no filler.

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 single-parameter mutation with no output schema and annotations covering the safety profile, this is nearly complete: the action, its irreversibility, and the effect on the invite link are all stated. Only minor gaps remain (behavior on a stale/already-deleted ID, permission requirements).

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 description coverage is 100% for the single inviteId parameter, so the schema fully documents it. The description adds nothing about the parameter format or source (e.g., from list_user_invites), so the baseline 3 applies.

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

Purpose4/5

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

States a specific verb and resource (delete a user invite) so an agent immediately knows the operation. It does not, however, distinguish itself from the near-identical sibling tailscale_delete_device_invite, which the agent must disambiguate by name alone.

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?

The description gives no when-to-use guidance, no prerequisites, and never mentions the alternatives (list_user_invites, get_user_invite, resend_user_invite) that would precede or replace this call. Only the warning about irreversibility hints at caution.

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

tailscale_delete_webhookDelete webhookA
DestructiveIdempotent

Delete a webhook. This is irreversible — the webhook secret cannot be recovered.

ParametersJSON Schema
NameRequiredDescriptionDefault
webhookIdYesThe webhook ID to delete

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, so the description's real contribution is the concrete consequence: the webhook secret cannot be recovered. That is a genuine addition beyond the hint flags. It is not a contradiction with idempotentHint — repeated deletes yield the same end state, which is separate from reversibility.

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 short sentences with the downside front-loaded immediately after the action. No filler, no restated name, nothing to trim.

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 one-parameter delete with no output schema and destructive annotations already present, the irreversible-secret note is the key missing piece and it is supplied. Only minor gaps remain, such as behavior when the webhook ID does not exist.

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 description coverage is 100% and there is a single required webhookId, so the schema carries the parameter meaning. The description adds nothing about format, source, or lookup (e.g., where to obtain the ID), making baseline 3 appropriate.

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

Purpose4/5

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

States a specific verb and resource ('Delete a webhook'), so the operation is unambiguous. It doesn't differentiate from sibling deletion tools or name adjacent webhook operations, but the resource is distinctive enough that no confusion arises.

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?

There is no when-to-use guidance and no mention of alternatives such as tailscale_rotate_webhook_secret, which is the non-destructive way to address a compromised secret. The agent gets no routing help, only a warning about the outcome.

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

tailscale_diff_acl_accessDiff ACL accessA
Read-onlyIdempotent

Answer 'who loses access?' before applying an ACL change. Compares the CURRENT policy against a proposed one and reports, per user, which destinations they gain and lose. Run this before tailscale_update_acl -- validate_acl only checks syntax and the policy's own tests block, so a policy with no tests validates clean while revoking everyone. LIMITS, all reported in the response rather than left to be discovered. It compares USER principals only, so a revocation that runs through a tag or group can show a clean diff, and an empty result is never proof a change is safe. Posture DEFINITION changes ARE detected: posture names are resolved to their rules, so tightening posture:corp shows as a change -- except when a preview omits the definitions map, where it falls back to comparing names. It costs two preview requests per user, so it checks the first 25 by default and stops after 60 seconds regardless; either way it sets truncated, reports how many were skipped, and says which limit stopped it. Users whose preview fails are listed in failed and excluded from the compared count -- a failure is never reported as lost access, and if nothing could be compared the call fails rather than returning an empty diff.

ParametersJSON Schema
NameRequiredDescriptionDefault
policyYesThe proposed ACL policy text to compare against the current live policy
principalsNoPrincipals to check, as they appear in `loginName` from tailscale_list_users. That is often an email, but on a GitHub or SSO tailnet it is not (e.g. 'alice@github') -- pass the loginName verbatim rather than an address you assume. Omit to enumerate the tailnet's users automatically. Pass an explicit list to bound the request count, or to check specific users beyond the cap.
maxPrincipalsNoMaximum users to check (default 25). Each costs two preview requests. Raising this on a large tailnet can be slow and may hit rate limits.

TDQS

A4.6/5.0
Behavior5/5

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

While annotations cover the safety profile (readOnly, idempotent, non-destructive), the description adds substantial behavioral context annotations cannot: cost model (two preview requests per user), a 25-user/60-second cap that sets `truncated`, a `failed` list excluded from the comparison, user-only principal coverage that can hide tag/group revocations, posture-definition resolution behavior, and a hard failure when nothing can be compared. This is exactly the kind of context that goes beyond structured fields.

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

Conciseness4/5

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

Purpose and routing to the sibling are front-loaded, and every sentence carries information (limits, caveats, failure handling) with no filler. It is dense and runs long, but nothing is padding.

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?

With no output schema, the description carries the burden of explaining returns and does so: gain/loss per user, the `truncated` flag, the skip count, the stopping limit, and the `failed` list. An agent knows both the input contract and what the response will tell it.

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 description coverage is 100%, so all three parameters are already well documented, including the loginName caveat and the maxPrincipals rate-limit warning. The description reinforces the 25-user default but adds no syntax or format detail beyond the schema, so the baseline 3 applies.

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?

Names a specific verb (compares/diffs) and resource (ACL policy access), and frames the exact question it answers ('who loses access?'). It distinguishes itself from siblings by name (tailscale_update_acl, validate_acl), so an agent can select it without opening any schema.

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

Usage Guidelines5/5

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

Explicitly states when to use it ('Run this before tailscale_update_acl') and why the alternative is insufficient ('validate_acl only checks syntax... a policy with no tests validates clean while revoking everyone'). The when-not condition is spelled out, leaving nothing to inference.

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

tailscale_expire_deviceExpire device keyA
DestructiveIdempotent

Expire a device's key, forcing it to re-authenticate.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceIdYesThe device ID to expire. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already mark the tool as destructive and idempotent; the description adds the key consequence that the device must re-authenticate, which clarifies the real-world effect of the action. It does not cover immediate availability or permissions, but given annotation coverage this is adequate.

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?

One short sentence ('Expire a device's key, forcing it to re-authenticate.') delivers the essential action and consequence with zero padding. This is ideal for a one-parameter tool.

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 single-parameter destructive action with a fully self-documenting schema and safety annotations, the description plus schema provides sufficient information for correct invocation. It does not mention preconditions like admin rights, but that is a minor gap for a tool this simple.

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 deviceId is fully documented in the schema with an example and an explicit warning against using nodeKey. The description text adds no additional parameter semantics, so it relies entirely on the schema, matching the baseline for 100% coverage.

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 states a specific verb ('Expire'), a resource ('a device's key'), and the effect ('forcing it to re-authenticate'). This clearly distinguishes it from siblings like tailscale_delete_device or tailscale_update_device_key.

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?

The description provides no guidance on when to use this tool versus alternatives such as tailscale_update_device_key or tailscale_deauthorize_device. It only states what the tool does, leaving the selection decision entirely to the agent.

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

tailscale_get_aclGet ACL policyA
Read-onlyIdempotent

Get the current ACL policy for your tailnet. Returns the raw policy text with original formatting preserved, including comments and trailing commas (HuJSON). Also returns an ETag — you must pass it to tailscale_update_acl to safely update the policy.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare read-only, idempotent, non-destructive, open-world behavior, so safety is covered. The description adds genuinely useful context beyond them: the return is raw HuJSON text with comments and trailing commas preserved, plus an ETag for concurrency-safe updates. It doesn't discuss auth/permission requirements, but it adds real behavioral value.

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 tight sentences, front-loaded with the purpose and followed by the most decision-relevant detail (format preservation and the ETag dependency). No filler.

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?

No output schema exists, so the description carries the return-value burden itself, and it does: raw HuJSON preservation and the ETag. Combined with annotations covering safety, an agent has everything needed to call it and use the result correctly.

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?

Zero parameters, so there is nothing to disambiguate; baseline 4 applies. The description correctly implies a no-argument, tailnet-scoped call.

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?

States a specific verb (Get) and resource (current ACL policy for your tailnet), cleanly separating it from the write/validate/preview siblings (update_acl, validate_acl, preview_acl). An agent can identify the tool's job without opening the schema.

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?

Gives clear workflow context: the returned ETag 'must' be passed to tailscale_update_acl to update safely, effectively explaining the read-before-write relationship. It does not, however, address when to prefer this over validate_acl/preview_acl/diff_acl_access, so it stops short of explicit alternatives/exclusions.

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

tailscale_get_audit_logGet audit logA
Read-onlyIdempotent

Get the tailnet audit/configuration log. Shows who changed what and when -- useful for troubleshooting and compliance. Optional actor, target and event filters narrow the query server-side, so a targeted question doesn't have to pull the whole window.

ParametersJSON Schema
NameRequiredDescriptionDefault
endNoEnd time in RFC3339 format. Optional: when omitted the tool sends the current time, which Tailscale's API requires.
actorNoServer-side filter: one exact actor ID, or '~text' to wildcard-match a login or display name (e.g. '~bob'). One value per call -- how the API reads a repeated filter key is not verified yet.
eventNoServer-side filter: one event type from Tailscale's audit event list, e.g. 'TAILNET.UPDATE.ACL', 'TAILNET.UPDATE.DNS_CONFIG', 'NODE.CREATE', 'NODE.DELETE', 'API_KEY.CREATE', 'USER.UPDATE.USER_ROLE', 'WEBHOOK_ENDPOINT.CREATE'. Not a closed set -- the list keeps growing. One value per call, as for actor.
startYesStart time in RFC3339 format (e.g. '2026-04-01T00:00:00Z'). Required.
targetNoServer-side filter: one string, matched against any part of any of an entry's targets (ID or name). One value per call, as for actor.

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering safety. The description adds behavioral context by explaining that filters operate server-side and that the log shows change history, which is useful for selecting the tool. It doesn't mention pagination or response format, but the annotation coverage lowers the bar, and the added context earns a 4.

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 two sentences, front-loads the core purpose, and adds a concise note about filters. Every sentence earns its place with no redundancy or fluff.

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 read-only get operation with a rich input schema and safety annotations, the description covers the main purpose, content, and filter behavior. It doesn't describe the return format, but the absence of an output schema and the tool's straightforward nature make this acceptable. Overall, it's complete enough for an agent to call correctly.

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 description coverage is 100%, with each parameter (start, end, actor, event, target) having detailed descriptions. The description only reiterates that filters exist and narrow queries server-side, adding marginal value over the schema. Baseline of 3 is appropriate for high coverage.

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

Purpose4/5

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

The description clearly states the tool retrieves the tailnet audit/configuration log and explains what it shows ('who changed what and when'). It's a specific verb+resource, and the purpose is unambiguous. It doesn't explicitly differentiate from siblings like tailscale_get_network_flow_logs, but the resource is distinct enough that the intent is clear.

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

Usage Guidelines3/5

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

The description provides context on when to use the tool (troubleshooting, compliance) and hints at using filters for targeted queries. However, it doesn't explicitly state when not to use it or mention alternatives like network flow logs. Usage guidance is implied rather than explicit.

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

tailscale_get_contactsGet contactsA
Read-onlyIdempotent

Get the tailnet contact information (security, support, admin emails).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=true, and destructiveHint=false, so the safety profile is covered. The description adds the specific contact fields returned, which is useful context, but does not disclose auth requirements, rate limits, or response format beyond the annotations.

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, front-loaded sentence that names the action, resource, and returned data with no wasted words.

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 no-parameter, read-only getter without an output schema, the description adequately conveys what the tool returns. It could optionally mention response shape or required permissions, but it is complete enough for correct 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?

The tool takes zero parameters, so there are no parameter semantics to document. Per calibration, a parameterless tool receives a baseline score of 4 for this dimension.

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

Purpose4/5

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

The description states a specific verb ('Get') and resource ('tailnet contact information') and clarifies the returned contact types with '(security, support, admin emails)'. It does not explicitly differentiate itself from the sibling set_contacts or from broader settings tools, but the resource is clear enough for an agent to identify the operation.

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

Usage Guidelines3/5

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

There is no explicit when-to-use or when-not-to-use guidance, nor are alternatives named. However, the verb 'Get' combined with the specific resource implies this should be used when retrieving tailnet contact information, which is adequate for a simple read-only getter.

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

tailscale_get_deviceGet deviceA
Read-onlyIdempotent

Get detailed information about a specific device by its ID. Returns the default field subset unless fields: 'all'. 'lastSeen' is omitted while a device is connected (connectedToControl: true) and for devices that have never been online -- on a connected device a missing lastSeen means online now, not never seen.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsNoWhich device fields to return. Tailscale documents exactly two values. 'default' (also what you get when this is omitted) is the limited set: addresses, id, nodeId, user, name, hostname, clientVersion, updateAvailable, os, created, connectedToControl, lastSeen, keyExpiryDisabled, expires, authorized, isExternal, machineKey, nodeKey, blocksIncomingConnections, tailnetLockKey, tailnetLockError, tags, isEphemeral. 'all' adds advertisedRoutes, enabledRoutes, clientConnectivity (endpoints, DERP latency), sshEnabled, distro, multipleConnections and postureIdentity (serial numbers and, where a posture integration collects them, hardware/MAC addresses). Omitting it does NOT return everything.
deviceIdYesThe device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.

TDQS

A4.5/5.0
Behavior5/5

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

Annotations already declare readOnlyHint and idempotentHint, so the safety profile is covered. The description adds valuable behavioral nuance about lastSeen omission: that a missing lastSeen on a connected device means 'online now', not 'never seen'. This is non-obvious and critical for correct interpretation, going beyond what annotations or schema provide.

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 two sentences long, with the core purpose front-loaded and a specific caveat appended. Every sentence earns its place: the first states the action, the second explains a subtle behavior. There is no fluff or redundancy, making it efficient for an agent to parse.

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?

The description provides all necessary context for correct invocation: it explains the field selection, the default return subset, and the lastSeen edge case. Since there is no output schema, the description adequately conveys the return semantics without needing to enumerate all fields. The tool's complexity is well-handled within this concise description.

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 description coverage is 100%, with both fields and deviceId having detailed descriptions. The tool description repeats some of this (e.g., default vs. all) but adds no new meaning beyond the schema. Since the schema already explains parameter values and effects, the description does not need to compensate, so a baseline score of 3 is appropriate.

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: retrieving detailed information for a specific device by its ID. It distinguishes itself from sibling tools like tailscale_list_devices by specifying 'a specific device', making its scope unambiguous. The mention of field subsets (default vs. all) further clarifies what the tool returns.

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 signals when to use this tool: when you need details about one device rather than a list. It does not explicitly name alternatives, but the distinction from list_devices is evident from the description's focus on a single device. It also explains the fields parameter's effect, which guides selection of output detail. However, it lacks explicit exclusion guidance, such as 'use this instead of get_device_routes for routing info'.

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

tailscale_get_device_inviteGet device inviteC
Read-onlyIdempotent

Get details for a specific device invite.

ParametersJSON Schema
NameRequiredDescriptionDefault
inviteIdYesThe device invite ID

TDQS

C2.9/5.0
Behavior2/5

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

The rich annotations (readOnlyHint, idempotentHint, destructiveHint, openWorldHint) already declare the full safety and idempotency profile, and the description adds no behavioral context beyond restating the purpose. No mention of auth requirements, permissions, or what 'details' are returned.

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

Conciseness4/5

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

A single short, front-loaded sentence with zero filler. It is efficient, though extremely terse given the surrounding tool set.

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

Completeness3/5

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

For a simple single-parameter read tool with full annotation coverage, the description is minimally adequate. With no output schema, it could say more about what an invite's details contain, but the low complexity makes the omission tolerable.

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 description coverage is 100%, so inviteId is fully documented in the schema. The description adds no syntax, format, or example meaning beyond what the schema provides, so the baseline 3 applies.

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

Purpose4/5

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

States a specific verb ('Get') and resource ('device invite') with a singular scope, which distinguishes it from list_device_invites in the sibling set. However, it never names or contrasts an alternative, so the differentiation is only implicit.

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 when-to-use or when-not-to-use guidance is given. An agent must infer that this fetches one invite by ID rather than listing, creating, or deleting invites, with no explicit routing to the many related siblings.

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

tailscale_get_device_posture_attributesGet device posture attributesA
Read-onlyIdempotent

Get all posture attributes for a device, including custom and system-managed attributes.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceIdYesThe device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.

TDQS

A3.8/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the description does not need to restate safety. It adds minor context by noting the response includes both custom and system-managed attributes, but it does not disclose any further behavioral traits such as auth requirements or error behavior.

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?

A single, front-loaded sentence that states the action, target, and scope with no filler or redundancy. Every phrase 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?

For a simple single-parameter read-only tool with strong annotationsasi and full schema coverage, the description is nearly complete. It does not explain the return shape, but the absence of an output schema and the simplicity of the operation make that a minor gap.

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 description coverage is 100%, and the deviceId parameter is fully documented in the schema with an example and clarification about nodeId vs nodeKey. The description adds no additional parameter meaning, which is acceptable since the schema already carries the burden.

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 states a specific verb ('Get') and resource ('posture attributes for a device'), and adds the clarifying scope 'including custom and system-managed attributes.' This distinguishes it from sibling mutation tools like tailscale_set_device_posture_attribute and tailscale_delete_device_posture_attribute.

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

Usage Guidelines3/5

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

The description implies a read-only retrieval use case, but it does not explicitly say when to use this tool versus the set/delete/batch posture attribute siblings. No when/when-not guidance or alternatives are named, though the tool name and readOnlyHint make the intent reasonably clear.

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

tailscale_get_device_routesGet device routesA
Read-onlyIdempotent

Get the subnet routes a device advertises and which are enabled.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceIdYesThe device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.

TDQS

A4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds a small domain nuance — advertised vs enabled routes — but says nothing about authentication requirements, empty results, or how disabled routes are represented.

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?

One compact sentence that is front-loaded with the operation and resource, with no filler or redundant restatement of the title.

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 one-parameter read-only getter, the description covers the resource, the input requirement, and the output scope in one sentence. No output schema exists, but the description states what is returned (advertised and enabled subnet routes); a minor gap is that it does not hint at the response shape or possible absence of disabled routes.

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% and the deviceId parameter is already well described with an example and a warning that nodeKey must not be used. The description contributes no parameter-level meaning beyond the schema, so baseline 3 applies.

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 names the exact operation — retrieving subnet routes for a device — and adds two useful distinctions: routes the device advertises and routes that are enabled. This differentiates it from related siblings like tailscale_set_device_routes and tailscale_get_device.

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 verb and object make the read-only retrieval context clear, and the description scopes the operation to routes specifically, which an agent can infer is for inspection rather than modification. However, it does not explicitly mention when not to use it or name tailscale_set_device_routes as the write alternative.

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

tailscale_get_dns_configurationGet DNS configuration (unified)A
Read-onlyIdempotent

Get the unified DNS configuration for your tailnet, including nameservers, search paths, split DNS, and MagicDNS preference in a single call.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so safety and idempotency are covered without the description. The description adds the useful scoping note that the response is the unified view spanning four sub-configs. It doesn't describe return shape or the openWorldHint implication, so it adds moderate value.

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?

A single sentence that front-loads the verb+resource and packs the payload contents in compactly. No filler, nothing redundant.

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 no-parameter read tool with full annotation coverage, the description is essentially complete: the agent knows what it returns and that it is a safe unified read. There's no output schema, but the description enumerates the top-level contents, which largely compensates.

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?

Zero parameters, so the schema imposes no documentation burden and the baseline of 4 applies. The description correctly never invents parameters, staying consistent with the empty input schema.

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?

Specific verb (Get) plus a precise resource (unified DNS configuration for your tailnet), and it enumerates exactly what the unified payload contains: nameservers, search paths, split DNS, and MagicDNS preference. This distinguishes it clearly from siblings like tailscale_get_nameservers, tailscale_get_split_dns, and tailscale_get_dns_preferences.

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 phrase 'in a single call' implicitly signals when to prefer this over the granular getters (get_nameservers, get_split_dns, get_dns_preferences), giving the agent a clear selection rationale. It doesn't explicitly state exclusions or prerequisites, so it stops short of a 5.

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

tailscale_get_dns_preferencesGet DNS preferencesB
Read-onlyIdempotent

Get DNS preferences for your tailnet, including whether MagicDNS is enabled.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is fully covered without the description. The description's only added value is naming MagicDNS as part of the returned state, which is modest but real 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?

A single front-loaded sentence with no filler, stating scope first and the notable returned field second. Nothing is wasted and nothing needs reordering.

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

Completeness3/5

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

For a zero-param read there is little to explain, and annotations cover the safety profile. But with no output schema, the description could enumerate what 'preferences' includes beyond MagicDNS, and it never disambiguates this tool from the several sibling getters of related DNS state — leaving a real selection gap.

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?

The tool takes zero parameters, so per the baseline this scores 4. There is no parameter behavior for the description to explain, and it correctly implies the call is scoped to the caller's tailnet.

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

Purpose4/5

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

States a specific verb (Get) and resource (DNS preferences) scoped to 'your tailnet', and even names the key field returned (MagicDNS). It does not, however, distinguish itself from closely named siblings like tailscale_get_dns_configuration, tailscale_get_split_dns, or tailscale_get_search_paths, which an agent would otherwise confuse it with.

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?

There is no when-to-use guidance at all — no mention of when to call this versus tailscale_get_dns_configuration, tailscale_get_split_dns, or tailscale_get_nameservers. The agent must infer usage purely from the name.

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

tailscale_get_keyGet keyA
Read-onlyIdempotent

Get details for a specific key (auth key, API access token, OAuth client, or federated identity). A revoked or expired key is still returned, with invalid: true.

ParametersJSON Schema
NameRequiredDescriptionDefault
keyIdYesThe key ID (auth key, API access token, OAuth client, or federated identity)

TDQS

A4.2/5.0
Behavior4/5

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

The annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering safety. The description adds a non-obvious behavior: that revoked or expired keys are still returned with 'invalid: true'. This is valuable context beyond annotations, but it does not elaborate on other response traits (e.g., pagination or field structure), which are minor given the tool's simplicity.

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 two sentences with no superfluous words. The main purpose is stated first, and the additional invalid-key behavior is added as a concise second sentence. It is front-loaded and 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?

With a single well-documented parameter and annotations covering the safety profile, the description is largely complete. It mentions the invalid-key flag, which is a key detail for handling results. It does not enumerate all possible return fields, but for a simple 'get details' tool, that is acceptable, especially since no output schema exists and the description gives enough context to call the tool correctly.

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 schema description for keyId already covers the parameter's meaning, including the list of key types. The description essentially repeats this information without adding new semantic detail (e.g., how to obtain the keyId or any format constraints). Since schema coverage is 100%, the baseline is 3, and no extra value is provided.

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 states a specific verb ('Get details') and resource ('a specific key'), and enumerates the key types (auth key, API access token, OAuth client, or federated identity), which clearly distinguishes it from sibling tools like tailscale_list_keys or tailscale_create_key. It also adds a behavioral detail about revoked/expired keys, further clarifying the tool's exact function.

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 gives clear context that this tool is for retrieving details of a single key, implying it should be used when a specific keyId is known rather than listing all keys. However, it does not explicitly mention alternatives like tailscale_list_keys or state when not to use this tool, so it lacks explicit exclusions but provides enough context for an agent to infer correct usage.

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

tailscale_get_log_stream_configGet log stream configB
Read-onlyIdempotent

Get the log streaming configuration for a specific log type.

ParametersJSON Schema
NameRequiredDescriptionDefault
logTypeYesThe log type: 'configuration' for audit logs, 'network' for network flow logs

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, so the safety profile is covered. The description adds no behavioral context beyond that (no auth requirements, rate limits, or error behavior), which is acceptable but minimal for a read tool.

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

Conciseness4/5

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

A single efficient sentence with the resource and scope front-loaded. Nothing extraneous, though it is on the terse side.

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

Completeness3/5

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

For a simple one-parameter read with annotations covering safety and no output schema required, the description is adequate but thin — it leaves all context to the schema and annotations.

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% and the enum (configuration/network) is fully documented in the schema itself. The description only restates that the config is keyed by log type, adding no meaning beyond the schema — baseline 3 applies.

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

Purpose4/5

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

States a specific verb (Get) and resource (log streaming configuration) with a scoping qualifier (for a specific log type). This distinguishes it from list_log_stream_configs and get_log_stream_status, though it doesn't name those siblings explicitly.

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

Usage Guidelines3/5

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

The phrase 'for a specific log type' implicitly differentiates a single-config read from the list_ sibling, but there is no explicit when-to-use guidance, no exclusions, and no named alternative.

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

tailscale_get_log_stream_statusGet log stream statusA
Read-onlyIdempotent

Get the status of log streaming for a specific log type. Shows whether logs are being delivered successfully.

ParametersJSON Schema
NameRequiredDescriptionDefault
logTypeYesThe log type: 'configuration' for audit logs, 'network' for network flow logs

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, so the safety profile is covered. The description adds useful semantic context about what 'status' means (successful delivery), but does not disclose anything further about rate limits, auth requirements, or response detail, so it is adequate but not rich.

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

Conciseness4/5

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

Two sentences, front-loaded with the core verb+resource and zero wasted preamble. The second sentence slightly restates 'status' but usefully specifies that it concerns delivery success, so it mostly 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?

With one fully documented parameter, comprehensive safety annotations, and no output schema, the description is nearly complete for a simple read-status tool. It could be slightly more informative about what the status payload includes, but nothing essential for correct invocation is missing.

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 logType parameter has 100% schema description coverage, including enum values and their meanings, so the schema carries the full parameter burden. The description only restates 'for a specific log type' and adds no format or constraint details beyond the schema, making the baseline 3 appropriate.

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

Purpose4/5

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

States a specific verb and resource ('Get the status of log streaming') and clarifies that it reports delivery health, which distinguishes it from the sibling config tools (get_log_stream_config, set_log_stream_config). However, it does not explicitly name or contrast those alternatives, so it falls short of a 5.

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

Usage Guidelines3/5

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

The description implies usage by defining what the tool reports ('whether logs are being delivered successfully'), giving an agent enough context to infer when to call it. But it offers no explicit when-to-use guidance, no exclusions, and no mention of the config-oriented siblings, so it remains implied rather than stated.

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

tailscale_get_nameserversGet nameserversB
Read-onlyIdempotent

Get the DNS nameservers configured for your tailnet.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.4/5.0
Behavior3/5

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

The annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is fully covered without the description. The description adds only the scoping detail 'configured for your tailnet' and says nothing about return shape or whether the list can be empty, which is a modest addition over the structured data.

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?

A single front-loaded sentence with no filler. Every word (DNS, nameservers, tailnet) carries meaning and nothing is redundant.

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

Completeness3/5

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

For a zero-argument getter with no output schema, the description is minimally sufficient but does not describe what the response contains (e.g., a list of nameserver IPs) or how it relates to DNS preference/split-DNS config. It is adequate but leaves a clear gap for an agent working among many DNS-related siblings.

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?

The tool takes zero parameters, so there is no parameter surface for the description to explain. Baseline 4 applies; no parameter information is missing or needed.

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

Purpose4/5

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

States a specific verb (Get) and resource (DNS nameservers) scoped to the tailnet, so the operation itself is unambiguous. However, it does not distinguish itself from nearby siblings like tailscale_get_dns_preferences, tailscale_get_split_dns, or tailscale_get_dns_configuration, which an agent could easily conflate with this tool.

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?

There is no guidance on when to use this tool versus the multiple DNS-related getters in the sibling list. The description gives no prerequisites, no conditions, and no alternatives, leaving routing entirely to inference from the name.

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

tailscale_get_network_flow_logsGet network flow logsA
Read-onlyIdempotent

Get network traffic flow logs showing connections between devices. Shows source/destination nodes, timestamps, and traffic metadata — useful for security monitoring and debugging connectivity.

ParametersJSON Schema
NameRequiredDescriptionDefault
endNoEnd time in RFC3339 format. Optional: when omitted the tool sends the current time, which Tailscale's API requires.
startYesStart time in RFC3339 format (e.g. '2026-04-01T00:00:00Z'). Required.

TDQS

A3.9/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds context about the content of the logs but does not disclose additional behavioral traits such as pagination limits, auth requirements, or scope of data returned.

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

Conciseness4/5

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

The description is two sentences, front-loaded with the primary verb and resource, and adds relevant content and use cases without fluff. It is concise but not overly terse.

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 simple read-only tool with two well-documented parameters and strong annotations, the description adequately covers the data returned (source/destination nodes, timestamps, traffic metadata) and the use cases. It does not mention pagination or output schema, but that is acceptable given the tool's simplicity.

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 input schema already describes both parameters fully (100% coverage) with RFC3339 format and the behavior of the optional end parameter. The description does not add additional meaning about how to choose start/end beyond what the schema provides, so the baseline of 3 is appropriate.

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 uses a specific verb and resource ('Get network traffic flow logs') and elaborates with content ('source/destination nodes, timestamps, and traffic metadata') and use cases ('security monitoring and debugging connectivity'), clearly distinguishing it from sibling tools like audit logs or log stream configs.

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 usage context ('useful for security monitoring and debugging connectivity') which implies when to use the tool, but it does not explicitly name alternatives or state when not to use it. This is clear context without exclusions.

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

tailscale_get_oauth_appGet OAuth appA
Read-onlyIdempotent

Get an OAuth App's configuration (name, redirect URIs, scopes) by its app ID. Use this to verify an app was registered as intended. The client secret is not returned -- it is only available at creation time.

ParametersJSON Schema
NameRequiredDescriptionDefault
appIdYesThe OAuth app ID returned by tailscale_create_oauth_app

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare read-only, idempotent, non-destructive, open-world behavior, so safety is covered. The description adds meaningful context beyond that: the client secret is never returned and only exists at creation time, which prevents an agent from expecting it and explains an important output limitation.

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 tight sentences with the core action and returned fields front-loaded, followed by purpose and then the important output caveat. No filler or redundancy.

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?

With no output schema, the description compensates by naming what is returned (name, redirect URIs, scopes) and what is excluded (client secret). For a simple single-parameter read tool with full annotations, nothing an agent needs to call it correctly is missing.

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% and the single appId parameter is fully documented there, including its origin from create_oauth_app. The description only echoes 'by its app ID', adding no format or syntax detail beyond the schema, so the baseline of 3 applies.

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?

States a specific verb and resource ('Get an OAuth App's configuration') and even enumerates the returned fields (name, redirect URIs, scopes). It is clearly distinct from the sibling create/list/delete OAuth app tools.

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?

Explicitly gives a use case ('Use this to verify an app was registered as intended'), which tells the agent the intent behind the call. However, it does not explicitly route away from siblings like tailscale_list_oauth_apps for broader discovery, so it stops short of naming alternatives.

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

tailscale_get_posture_integrationGet posture integrationA
Read-onlyIdempotent

Get details for a specific device posture integration.

ParametersJSON Schema
NameRequiredDescriptionDefault
integrationIdYesThe posture integration ID

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is fully covered by structured data. The description adds no behavioral context beyond that — no return shape, no note on unknown IDs — so it earns only the baseline.

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?

A single front-loaded sentence with zero filler; the verb and resource lead and nothing is redundant.

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 one-parameter read tool fully covered by the schema and safety annotations, the definition is essentially complete. The only minor gap is that with no output schema, it doesn't hint at what 'details' the integration returns.

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% and the single integrationId parameter is documented ('The posture integration ID'). The description only restates that a specific integration is fetched and adds no format or sourcing guidance, so the schema does the work.

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

Purpose4/5

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

Clear verb+resource ('Get details for a specific device posture integration'), and the singular 'a specific' distinguishes it from the sibling list_posture_integrations. It does not name the sibling explicitly, but the singular/plural contrast makes the scope inferable.

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

Usage Guidelines3/5

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

Requiring a 'specific' integration implies you must already have an integrationId and are not enumerating, which hints at when to use this over list_posture_integrations. However, there is no explicit when-to-use/when-not statement or named alternative.

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

tailscale_get_search_pathsGet DNS search pathsA
Read-onlyIdempotent

Get the DNS search paths configured for your tailnet.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is fully covered by structured data. The description only adds the tailnet scoping context, with no mention of return format, caching, or freshness; against this annotation coverage a 3 is appropriate.

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?

A single front-loaded sentence with no filler; the resource and scope appear immediately. Nothing is wasted and nothing relevant is buried.

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 read-only getter with no output schema and annotations that already carry the safety semantics, the description is nearly sufficient. It stops short of describing what a search path entry looks like or how results are ordered, but for this tool's complexity that omission is minor.

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?

The tool takes zero parameters, so per the rubric the baseline is 4. Schema coverage is 100% and there is nothing further for the description to clarify about inputs.

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

Purpose4/5

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

States a specific verb and resource ('Get the DNS search paths') and scopes it to 'your tailnet', which is clear and unambiguous. However, it does not differentiate itself from adjacent DNS tools such as tailscale_get_split_dns, tailscale_get_dns_preferences, or its mutation counterpart tailscale_set_search_paths.

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?

The description offers no guidance on when to use this tool versus the many other DNS getters in the sibling list, and no prerequisites or conditions are stated. The agent must infer usage purely from the name.

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

tailscale_get_serviceGet serviceB
Read-onlyIdempotent

Get details for a specific Tailscale Service, including its MagicDNS name, virtual IP, and configuration.

ParametersJSON Schema
NameRequiredDescriptionDefault
serviceNameYesThe service name

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint, so the safety profile is fully covered without description help. The description adds what the response contains (MagicDNS name, virtual IP, configuration), which is useful but no deeper behavioral context such as error handling for an unknown service name.

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

Conciseness4/5

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

A single front-loaded sentence with no filler; the returned-fields clause earns its place. It is efficiently sized, though very terse for a tool with a large sibling set.

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 simple read-only getter with one required param and full annotation coverage, the description is nearly sufficient. With no output schema present, the brief enumeration of returned fields (MagicDNS name, virtual IP, configuration) is a meaningful partial substitute, leaving only error/not-found behavior unaddressed.

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?

There is one parameter with 100% schema description coverage, so the schema already documents serviceName. The description adds nothing about the parameter's format (hostname vs. fully qualified name vs. tag), so the baseline of 3 applies.

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

Purpose4/5

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

States a specific verb and resource (get details for a specific Tailscale Service) and names the returned content. The word "specific" implicitly distinguishes it from tailscale_list_services, but no sibling is named explicitly, so it stops short of a 5.

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?

The description gives no when-to-use guidance, no prerequisites, and never points to the obvious alternatives (tailscale_list_services to discover names, tailscale_update_service / tailscale_delete_service for mutations). Usage can only be inferred from the required serviceName parameter.

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

tailscale_get_service_device_approvalGet service device approvalB
Read-onlyIdempotent

Get the approval status of a specific device for a Tailscale Service.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceIdYesThe device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.
serviceNameYesThe service name

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, covering the safety profile. The description adds no behavioral context beyond that, such as what the approval status looks like or potential errors. Since annotations handle the core transparency, a 3 is fair; it neither contradicts nor enriches them.

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?

A single, grammatically correct sentence that is front-loaded with the verb and resource. No unnecessary words or repetition; it is concise and to the point.

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 simple read-only operation with no output schema, the description adequately conveys the tool's purpose. The two required parameters are well-documented in the schema, and annotations cover safety. It could hint at the return type (e.g., a boolean or status string), but the name and description are sufficient for an agent to call it correctly.

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 description coverage is 100%, so both parameters (serviceName, deviceId) are fully described in the schema, including the deviceId note about nodeId vs nodeKey. The description adds no extra parameter semantics, aligning with the baseline for high schema coverage.

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

Purpose4/5

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

The description clearly states the action (get), the resource (approval status of a specific device for a Tailscale Service), and is distinct from siblings like tailscale_set_service_device_approval (which mutates) and tailscale_get_service (which gets service details). It is specific but doesn't explicitly contrast with alternatives, hence a 4 rather than 5.

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 on when to use this tool versus other get tools or the set counterpart. It doesn't state prerequisites (e.g., the device must exist) or when a different tool would be more appropriate. The description is purely a purpose statement without usage context.

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

tailscale_get_split_dnsGet split DNSB
Read-onlyIdempotent

Get the split DNS configuration for your tailnet.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.1/5.0
Behavior2/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so the safety profile is fully covered. The description adds essentially nothing beyond that and the name — only the 'your tailnet' scope — and says nothing about the shape or size of the returned configuration.

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

Conciseness4/5

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

A single front-loaded sentence with no filler or repetition. It is appropriately sized, though its brevity reflects missing information rather than tight editing.

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

Completeness3/5

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

For a zero-parameter read tool the call mechanics are trivially complete, and annotations cover safety. But with no output schema present, the description does nothing to convey what a split DNS configuration contains, leaving the agent to guess at the return value.

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?

The tool takes zero parameters, so per the rubric the baseline is 4. There is no parameter semantics for the description to illuminate or omit.

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

Purpose4/5

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

States a specific verb (Get) and resource (split DNS configuration) scoped to 'your tailnet', which is clear enough to act on. It does not, however, distinguish itself from close siblings like tailscale_get_dns_configuration or tailscale_get_dns_preferences, which an agent could easily confuse it with.

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?

There is no when-to-use guidance, no mention of the related read siblings (get_dns_configuration, get_dns_preferences, get_search_paths), and no indication of when this tool is preferable to them. The agent must infer selection purely from the name.

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

tailscale_get_tailnet_settingsGet tailnet settingsA
Read-onlyIdempotent

Get your tailnet settings (device approval, key expiry, HTTPS certificates, etc.).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior3/5

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

The annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is fully covered by structured data. The description's only added context is the enumeration of setting categories, which helps but does not disclose auth scope, return shape, or caching behavior.

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

Conciseness4/5

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

A single front-loaded sentence with no filler, which is appropriate for a no-argument read tool. The trailing 'etc.' slightly weakens precision by leaving the scope of returned settings open-ended.

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 zero-parameter, read-only getter with no output schema, the description gives the agent enough: it names the resource and sketches what comes back. Nothing required to call it correctly is missing.

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?

The tool takes zero parameters, so the schema leaves nothing to document and the description has no parameter burden to carry. Baseline of 4 applies; there is no syntax or format detail it could add.

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

Purpose4/5

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

States a specific verb ('Get') and resource ('your tailnet settings') and enumerates the categories of settings returned (device approval, key expiry, HTTPS certificates), which lets an agent distinguish it from the sibling tailscale_update_tailnet_settings. It does not explicitly call out that sibling, but the get/update distinction is unambiguous.

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

Usage Guidelines3/5

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

Usage is implied by the read-only 'get' framing and the parenthetical list of settings, so an agent can infer when to reach for it. However, there is no explicit when-to-use, no note on prerequisites or permissions, and no routing to alternatives such as tailscale_get_dns_preferences or tailscale_status for adjacent configuration reads.

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

tailscale_get_userGet userB
Read-onlyIdempotent

Get details for a specific user.

ParametersJSON Schema
NameRequiredDescriptionDefault
userIdYesThe user ID

TDQS

B3.1/5.0
Behavior2/5

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

The annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is fully covered without the description. The description contributes no additional behavioral context (no lookup semantics, no error behavior for unknown IDs, no auth requirements).

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?

A single front-loaded sentence with zero filler; nothing is wasted and the action is immediately clear.

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

Completeness3/5

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

For a simple one-parameter read tool whose annotations carry the safety profile, the definition is minimally adequate. With no output schema, it leaves the shape of the returned 'details' unspecified, which is the main remaining gap.

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 description coverage is 100% for the single userId parameter, so the schema already documents it. The description adds no format, source, or example information beyond the schema, making the baseline 3 appropriate.

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

Purpose4/5

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

States a specific verb (Get) and resource (user) with scope ('a specific user'), so the operation is unmistakable. It does not, however, distinguish itself from near-neighbors like tailscale_list_users or the user-invite tools, which the agent must infer on its own.

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?

There is no guidance on when to call this versus tailscale_list_users or the other user-related siblings, nor any stated prerequisites or context. Usage is only implied by the name and description.

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

tailscale_get_user_inviteGet user inviteB
Read-onlyIdempotent

Get details for a specific user invite.

ParametersJSON Schema
NameRequiredDescriptionDefault
inviteIdYesThe user invite ID

TDQS

B3.1/5.0
Behavior2/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is fully covered. The description adds nothing beyond that — no note on auth requirements, rate limits, or what 'details' includes — so it earns little credit against the lower annotated bar.

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

Conciseness4/5

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

A single front-loaded sentence with zero filler — appropriately sized for a one-parameter read tool, though it is so terse that it borders on under-specification rather than exemplary structure.

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 simple read-only lookup with one fully documented parameter, complete annotations, and no output schema, the description covers what an agent needs to invoke it. The only gap is that nothing hints at the returned detail set, which is minor at this complexity.

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 description coverage is 100%, so inviteId is fully documented in the schema itself. The description adds no meaning about the ID's format, source, or where to obtain it, so the baseline 3 applies.

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

Purpose4/5

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

States a specific verb ('Get') and resource ('user invite') with a scope qualifier ('a specific'). It does not differentiate from the near-identical sibling tailscale_get_device_invite, but the resource is unambiguous enough that an agent can pick it over list/create/delete/resend.

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?

There is no explicit when-to-use guidance, no mention of the sibling tailscale_list_user_invites, and no stated prerequisite beyond the existence of an invite ID. The only implied usage is 'call this when you already have an invite ID', which the agent must infer.

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

tailscale_get_webhookGet webhookB
Read-onlyIdempotent

Get details for a specific webhook.

ParametersJSON Schema
NameRequiredDescriptionDefault
webhookIdYesThe webhook ID

TDQS

B3.2/5.0
Behavior2/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is fully covered. The description adds nothing beyond that: no return format, no note on error behavior for a missing/invalid ID, and no pagination or auth context. With annotations carrying the load it is not a 1, but the description contributes no behavioral value.

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

Conciseness4/5

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

One front-loaded sentence with zero filler. It is efficient, though it borders on under-specification for a tool an agent must route correctly among many webhook siblings.

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

Completeness3/5

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

For a simple single-parameter read tool with full annotation coverage, the essentials are present. But with no output schema, the description does not tell the agent what details are returned, which is a modest gap.

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 description coverage is 100% with a single parameter, so the schema already explains webhookId as 'The webhook ID'. The description adds no syntax, format, or sourcing guidance for the ID beyond what the schema provides, which is the baseline 3 case.

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

Purpose4/5

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

States a specific verb ('Get') and resource ('webhook') with a clear singular scope, which distinguishes it from the plural list_webhooks sibling. However, it does not explicitly name or contrast against related siblings like tailscale_list_webhooks or tailscale_test_webhook.

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

Usage Guidelines3/5

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

Usage is only implied: the singular 'specific webhook' plus the required webhookId suggests retrieval by identifier. There is no explicit statement of when to use this versus list_webhooks or get_webhook-adjacent tools, and no prerequisites or exclusions are given.

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

tailscale_list_device_invitesList device invitesA
Read-onlyIdempotent

List all device invites for a specific device.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceIdYesThe device ID to list invites for. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds the scoping constraint (per-device) but doesn't disclose return format, pagination, or ordering. With annotations covering the safety profile, a 3 is appropriate.

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

Conciseness4/5

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

The description is a single clear sentence that front-loads the action and resource. The parameter description is also concise and informative. No wasted words.

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

Completeness3/5

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

For a simple read-only list tool with one well-documented parameter and annotations covering safety, the description is mostly complete. However, it doesn't mention what the response contains (e.g., invite details, status) or whether there are any pagination/limit considerations, which an agent might need to know.

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 description coverage is 100%, so the schema already documents the deviceId parameter. The description adds value by clarifying the deviceId format (nodeId from tailscale_list_devices, numeric id ok, not the nodeKey), which goes beyond the schema's basic type definition.

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

Purpose4/5

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

The description states a specific verb ('List') and resource ('device invites for a specific device'), which clearly distinguishes it from sibling tools like tailscale_list_user_invites and tailscale_get_device_invite. It doesn't explicitly name the sibling it is not, but the scope is clear enough.

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

Usage Guidelines3/5

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

The description implies usage context: it lists invites for a specific device, and the parameter description clarifies the deviceId format. However, it doesn't explicitly state when to use this tool versus alternatives like tailscale_get_device_invite (single invite) or tailscale_list_user_invites (user invites).

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

tailscale_list_devicesList devicesA
Read-onlyIdempotent

List all devices in your tailnet with their status, IP addresses, OS, and last seen time. 'lastSeen' is omitted while a device is connected (connectedToControl: true) and for devices that have never been online -- on a connected device a missing lastSeen means online now, not never seen.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsNoWhich device fields to return. Tailscale documents exactly two values. 'default' (also what you get when this is omitted) is the limited set: addresses, id, nodeId, user, name, hostname, clientVersion, updateAvailable, os, created, connectedToControl, lastSeen, keyExpiryDisabled, expires, authorized, isExternal, machineKey, nodeKey, blocksIncomingConnections, tailnetLockKey, tailnetLockError, tags, isEphemeral. 'all' adds advertisedRoutes, enabledRoutes, clientConnectivity (endpoints, DERP latency), sshEnabled, distro, multipleConnections and postureIdentity (serial numbers and, where a posture integration collects them, hardware/MAC addresses). Omitting it does NOT return everything. Any other value is forwarded unvalidated; Tailscale documents none.
filtersNoServer-side filters on top-level device properties, exact match only (e.g. { isEphemeral: 'true', os: 'linux' }). All filters are ANDed. Pass an array to repeat a key: { tags: ['tag:prod', 'tag:subnetrouter'] } sends tags=..&tags=.. and matches devices whose tags contain BOTH. Properties that are complex objects (e.g. clientConnectivity) cannot be filtered; repeating a key on a non-list property is undocumented upstream.

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint false, so safety is covered. The description adds valuable nuance: the lastSeen omission semantics for connected/never-online devices, and the critical gotcha that omitting 'fields' does not return all fields. This goes beyond annotations.

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

Conciseness4/5

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

The description is dense but efficient, front-loading the core purpose and then adding the critical lastSeen nuance and parameter gotchas. No wasted words, though it is longer than typical.

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 read-only list tool with two optional parameters and no output schema, the description covers the key behaviors: field selection, filter semantics, and a subtle timing detail. It omits pagination and rate limits, which are less critical for a simple list operation.

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

Parameters5/5

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

Both parameters have full schema coverage, but the description significantly enriches them. It explains the exact two valid values for 'fields', the default behavior, and that omitting it does not mean 'all'. For 'filters', it clarifies exact-match-only, AND semantics, and how to repeat keys for list properties. This is far more than the schema provides.

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 lists all devices in the tailnet with specific attributes (status, IP, OS, lastSeen), and it is distinct from the singular tailscale_get_device sibling. The scope is unambiguous and action-oriented.

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

Usage Guidelines3/5

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

The description implies a listing use-case but does not explicitly contrast with tailscale_get_device or other device-specific tools. There is no 'use this when' or 'use get_device for a single device' guidance, leaving the agent to infer the right selection.

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

tailscale_list_keysList keysA
Read-onlyIdempotent

List keys in your tailnet: auth keys, API access tokens, OAuth clients and federated identities. Without 'all', what comes back depends on the credential this server runs on -- a user-owned API key sees only that user's keys (including the API access token the server itself is using, keyType 'api'); an OAuth-client token sees the tailnet's OAuth clients; a federated-identity token sees its federated identities. Set 'all' to true for the tailnet-wide list (needs the matching :read scopes; only 'all:read' and 'all' return every API access token).

ParametersJSON Schema
NameRequiredDescriptionDefault
allNoWhen true, list keys tailnet-wide instead of the credential-dependent default set. Default: false

TDQS

A4.5/5.0
Behavior5/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds substantial non-obvious behavior beyond that: results are credential-dependent, a user-owned API key sees the server's own access token (keyType 'api'), and only 'all:read'/'all' scopes return every API access token. These are surprising behavioral traits an agent could not infer from the annotations alone.

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

Conciseness4/5

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

The purpose is front-loaded and each of the three sentences earns its place: scope enumeration, credential-dependent default behavior, and 'all' semantics with permissions. It loses a point only for the dense dash-nested parenthetical ('including the API access token the server itself is using, keyType api'), which packs several ideas into one clause and slightly reduces parseability.

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?

Everything needed to invoke the tool correctly is covered: the default credential-dependent behavior, what 'all' does, and the scope constraints. However, with no output schema, the description leaves the shape of returned key objects unspecified — for a list operation with four distinct key types, some hint at the return record structure would complete the picture.

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% (the single 'all' parameter has its own description), so the baseline is 3. The tool description adds value above the schema by disclosing the permission requirement ('needs the matching :read scopes') and the nuance that only 'all:read' and 'all' return every API access token — details absent from the schema's parameter description.

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 opens with a specific verb+resource ('List keys in your tailnet') and enumerates the four key categories (auth keys, API access tokens, OAuth clients, federated identities), leaving no ambiguity about scope. This enumeration also differentiates it from siblings like tailscale_get_key, tailscale_create_key, and tailscale_list_oauth_apps without needing to open their schemas.

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 operational context: it explains that default results depend on the credential the server runs under and instructs when to set 'all' for a tailnet-wide list, including the required :read scopes. It does not, however, explicitly name sibling alternatives (e.g., when to prefer tailscale_get_key for a single key) or state when not to use this tool, so it stops short of a 5.

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

tailscale_list_log_stream_configsList log stream configsA
Read-onlyIdempotent

List all log streaming configurations for your tailnet. Fetches both 'configuration' (audit) and 'network' (flow) log stream configs. Log streaming sends logs to external destinations like Axiom, Datadog, Splunk, Elasticsearch, or S3.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, openWorld, and non-destructive, so the safety profile is covered. The description adds genuine context beyond that: it discloses that a single call returns both audit and network config types, which is a behavioral fact an agent could not infer from the schema or annotations.

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

Conciseness4/5

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

Front-loaded with the core verb and scope, then the subtype disclosure. The final sentence about external destinations (Axiom, Datadog, Splunk) is partially tangential to calling the tool, keeping it short of a 5.

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 parameterless read-only list tool with annotations covering safety and no output schema, the description supplies everything needed: what is listed, its scope, and the two config categories returned. Nothing required to invoke it correctly is missing.

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 zero parameters, so the baseline is 4. The description correctly implies an unfiltered full-list call and introduces no parameter assumptions that need reconciling with the empty schema.

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?

States a specific verb (List) and resource (log streaming configurations) with explicit scope: 'all' configs for the tailnet, and it names both subtypes it returns ('configuration'/audit and 'network'/flow). This distinguishes it from the singular sibling tailscale_get_log_stream_config, which returns one config type.

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

Usage Guidelines3/5

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

Usage is implied by 'List all ... for your tailnet,' which signals the enumeration case, but the description never states when to use this over tailscale_get_log_stream_config or the set/delete siblings, nor any prerequisites or exclusions. The alternative tool is left to inference.

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

tailscale_list_oauth_appsList OAuth appsA
Read-onlyIdempotent

List the OAuth Apps registered in your tailnet (Tailscale alpha). Returns an oauthApps array describing each app (id, name, redirect URIs, scopes). Client secrets are NOT included -- a secret is only returned once, by tailscale_create_oauth_app at creation time. This is how you recover the id of an app you did not record; pass that id to tailscale_delete_oauth_app to revoke it.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, open-world), so the description's real added value is the disclosure that client secrets are never returned here and exist only once at creation via tailscale_create_oauth_app. That is meaningful data-sensitivity context, though pagination and rate-limit behavior are unmentioned.

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 sentences, each carrying distinct information: what is listed, what the response contains, and the secret caveat plus the id-recovery workflow. Front-loaded with no filler.

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?

With no input parameters and no output schema, the description fully compensates by describing the returned array, its fields, and the omission of secrets. An agent has everything needed to call and interpret this tool.

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?

The tool takes zero parameters, so the baseline is 4. The description instead characterizes the response shape, which is useful but not required for invocation.

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?

States a specific verb and resource (list OAuth Apps), scopes it to your tailnet, and enumerates the returned fields (id, name, redirect URIs, scopes). It also flags the alpha status and distinguishes itself from tailscale_get_oauth_app's id-based lookup by emphasizing enumeration and id recovery.

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?

Gives a concrete use case: recovering the id of an app you did not record, and routes that id onward to tailscale_delete_oauth_app. It stops short of explicitly contrasting with tailscale_get_oauth_app for the case where the id is already known, but the context is strong.

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

tailscale_list_org_tailnetsList organization tailnetsA
Read-onlyIdempotent

List the tailnets in your organization, including API-only tailnets created via the API. Paginated: returns at most limit results (Tailscale defaults to 100) plus a cursor. Pass that cursor back to fetch the next page; an empty cursor in the response means you have reached the end. Requires OAuth authentication.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax tailnets to return in this page. Omit to use Tailscale's default of 100.
cursorNoPagination cursor from a previous response. Omit for the first page.
organizationNoOrganization ID. Defaults to '-' (the organization owning the calling credentials).

TDQS

A3.7/5.0
Behavior4/5

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

Annotations already cover safety (readOnly, idempotent, non-destructive), so credit is for the extra context: the pagination contract (at most `limit` results, cursor returned, empty cursor means end) and the OAuth authentication requirement. The auth prerequisite is a genuinely useful behavioral disclosure not present in the annotations.

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

Conciseness4/5

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

Purpose is front-loaded and the pagination explanation is compact and non-redundant. The auth note is a short final sentence that earns its place, though the definition is slightly longer than strictly necessary given the schema already documents cursor and limit.

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?

No output schema exists, and the description compensates by explaining the pagination envelope (results plus cursor) and terminating condition. Scope, auth, and pagination are all covered; only the shape of individual tailnet records is left unstated, which is acceptable for a list 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?

Schema description coverage is 100%, so all three parameters (limit, cursor, organization) are already documented in the schema. The description restates the limit default and cursor round-trip but adds nothing the schema does not already provide, which is the baseline 3.

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

Purpose4/5

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

States a specific verb (List) and resource (tailnets in your organization), and adds a scope distinction: it includes API-only tailnets created via the API, which a bare 'list' would leave ambiguous. It does not explicitly differentiate itself from siblings like tailscale_create_org_tailnet or tailscale_delete_tailnet, so it lands just short of a 5.

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

Usage Guidelines3/5

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

Usage is implied by the verb and the pagination instructions, and it names no alternatives or when-not conditions. An agent can infer this is the read path for org tailnets versus the create/delete siblings, but the description never makes that routing explicit.

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

tailscale_list_posture_integrationsList posture integrationsA
Read-onlyIdempotent

List all device posture integrations configured for your tailnet.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=true, and destructiveHint=false, so the safety profile is fully covered. The description adds only the tailnet scoping context; it discloses nothing about pagination, result size, or ordering behavior.

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?

A single front-loaded sentence with zero filler. Every word earns its place and identifies verb, resource, and scope immediately.

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 simple no-param read-only list operation with no output schema, the description is largely sufficient. It could note pagination or result handling, but nothing essential to correct invocation is missing.

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?

The tool takes zero parameters, so there is nothing to document and the baseline for a no-param tool applies. The schema is trivially complete and the description adds no parameter detail, which is appropriate here.

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

Purpose4/5

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

States a specific verb ('List') and resource ('device posture integrations') scoped to 'your tailnet'. An agent can distinguish it from get_posture_integration (singular) and the create/update/delete siblings, though no sibling is named explicitly.

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

Usage Guidelines3/5

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

The 'list all' phrasing implies an enumeration use case, but there is no explicit when-to-use guidance, no mention of the single-item get_posture_integration alternative, and no conditions or prerequisites. Usage is only implied.

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

tailscale_list_service_hostsList service hostsA
Read-onlyIdempotent

List devices hosting a specific Tailscale Service.

ParametersJSON Schema
NameRequiredDescriptionDefault
serviceNameYesThe service name

TDQS

A3.5/5.0
Behavior3/5

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

Annotations declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is covered. The description adds little beyond the action itself: no details on return format, pagination, or whether results might be filtered by approval status. With annotations carrying the safety burden, a 3 is appropriate – it adds some scoping context but not rich behavioral nuance.

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?

A single, efficient sentence that front-loads the action and resource. No waste.

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

Completeness3/5

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

For a read-only list tool with full annotation coverage and a simple single-parameter schema, the description is minimally sufficient. However, it lacks any guidance on when to use this tool versus other service-related tools, and provides no information about the expected output or any filtering behavior, leaving a clear gap.

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 description coverage is 100%, so the single parameter 'serviceName' is fully documented in the schema. The description does not add any syntax, format, or constraint details beyond what the schema provides. Baseline 3 when schema does the heavy lifting.

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

Purpose4/5

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

States a specific verb+resource: 'List devices hosting a specific Tailscale Service.' This is clear and distinct from siblings like tailscale_list_services (lists services) and tailscale_list_devices (lists all devices). However, it doesn't explicitly differentiate from tailscale_get_service or tailscale_get_service_device_approval, which an agent might confuse when looking for service-related device information.

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

Usage Guidelines3/5

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

The description implies usage (list devices for a given service) but provides no explicit when-to-use guidance, no alternatives, and no prerequisites or context about when this tool is appropriate versus others. Adequate but with clear gaps.

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

tailscale_list_servicesList servicesA
Read-onlyIdempotent

List all Tailscale Services in your tailnet. Services provide stable MagicDNS names and virtual IPs, decoupled from individual devices. Note: services are created implicitly when a node first advertises one (tailscale up --advertise-services=svc:name); there is no API endpoint to create a service from this MCP. Use the update/delete/approval tools here once the service exists.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint, destructiveHint=false, so the safety profile is covered. The description adds non-obvious context: that services are created implicitly via node advertisement and that creation is unsupported here. It does not mention pagination or result shape, but with strong annotations a 4 is warranted for the extra provisioning context.

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

Conciseness4/5

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

Three sentences, all earning their place: purpose first, definition second, creation/limitation third. Slightly longer than a minimal list tool needs, but the sentences are dense and front-loaded with no filler.

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 zero-parameter read-only list tool with annotations covering safety, the definition is complete: it explains the resource, its lifecycle, and the boundaries of the MCP. No output schema exists, and the description appropriately does not promise one.

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?

Parameter count is 0, so the baseline of 4 applies; there is nothing for the description to compensate for and no misleading param guidance.

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?

States a specific verb+resource ("List all Tailscale Services in your tailnet") and distinguishes from siblings by explaining what a Service is (stable MagicDNS names, virtual IPs, decoupled from devices) and naming the update/delete/approval tools rather than get_service. An agent can select this over siblings without opening other schemas.

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

Usage Guidelines5/5

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

Explicitly tells the agent when services exist (created implicitly on advertise) and explicitly excludes what this MCP cannot do (no create API endpoint), redirecting to update/delete/approval tools. When-to-use and when-not-to-use are both present.

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

tailscale_list_user_invitesList user invitesA
Read-onlyIdempotent

List the open (not yet accepted) user invites for your tailnet. Accepted invites are not returned.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior3/5

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

Annotations already declare readOnlyHint: true, idempotentHint: true, and destructiveHint: false, covering the safety profile. The description adds the meaningful behavioral detail that accepted invites are not returned, but does not disclose pagination, ordering, or response structure. This matches the expected baseline when annotations already provide safety 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?

The description is two short sentences with no filler. The primary action and scope are front-loaded, and the second sentence reinforces the key behavioral constraint without unnecessary detail.

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 read-only, zero-parameter list operation, the description is complete. It identifies exactly what is returned (open user invites) and what is excluded (accepted invites). No additional invocation guidance is needed, and the annotations cover safety.

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?

The tool has zero parameters, so the schema provides no additional semantics to clarify. The description is sufficient, and the baseline of 4 applies because there is nothing about parameters that could add confusion.

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 states a specific verb ('List'), a precise resource ('open ... user invites for your tailnet'), and explicitly excludes accepted invites. This clearly differentiates it from sibling tools like tailscale_list_device_invites by specifying 'user invites'.

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 gives clear context for when to use the tool: when listing open, not-yet-accepted user invites. It does not explicitly name alternatives such as tailscale_get_user_invite or tailscale_list_device_invites, but the scope is clear enough that an agent can select it correctly.

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

tailscale_list_usersList usersB
Read-onlyIdempotent

List all users in your tailnet.

ParametersJSON Schema
NameRequiredDescriptionDefault
roleNoFilter by user role
typeNoFilter by user type: 'member' (direct members), 'shared' (shared-in users), or 'all' (default)

TDQS

B3.1/5.0
Behavior2/5

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

The annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=true, giving the agent the full safety profile. The description adds only the scope phrase 'in your tailnet', which is effectively implied by openWorldHint, so it contributes almost nothing beyond the structured metadata.

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

Conciseness4/5

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

A single short sentence with no waste, front-loaded with the verb and resource. Slightly imperfect only because 'all users' conflicts with the available role/type filters, making the brevity a touch ambiguous.

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-required-parameter list tool with full schema coverage, complete annotations, and no output schema, the description is sufficient to call it correctly. It omits any note about pagination or result shape, which is a minor gap given no output schema is declared.

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 description coverage is 100% — both role and type have enum values plus inline descriptions — so the schema carries the parameter semantics. The description adds nothing about the filters and its phrase 'all users' arguably understates the filtering the tool supports, but the baseline for full schema coverage is 3.

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

Purpose4/5

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

States a specific verb (List) and resource (users) with scope (your tailnet), so an agent can immediately tell what it does. It does not, however, differentiate itself from adjacent siblings like tailscale_get_user, tailscale_list_user_invites, or tailscale_list_devices, relying on the name alone for that.

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?

There is no when-to-use guidance, no prerequisites, and no named alternative. The description never hints that tailscale_get_user exists for a single user or that role/type filtering is possible, so routing decisions are left entirely to inference.

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

tailscale_list_webhooksList webhooksA
Read-onlyIdempotent

List all webhooks configured for your tailnet.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=true, so the safety and idempotency profile is fully covered without the description. The description adds the tailnet scoping of the result set but says nothing about return shape, ordering, or whether pagination applies, which is the remaining context a caller would want.

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?

A single front-loaded sentence with the resource and scope stated up front and no filler. Nothing could be trimmed without losing the tailnet scoping qualifier.

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 simple, annotation-backed list tool with no parameters and no output schema, the description covers what the caller needs to select it. It could be marginally more complete with a note on return format, but that is a minor omission given the trivial surface area.

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?

The tool takes zero parameters, which is the baseline-4 case – there are no argument semantics for the description to clarify. No meaningful gap exists here.

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

Purpose4/5

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

The description states a specific verb ('List') and resource ('webhooks') scoped to the tailnet, which clearly distinguishes it from the create/get/update/delete webhook siblings. It stops just short of explicitly contrasting itself with tailscale_get_webhook (single vs. all), so it isn't a textbook 5.

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

Usage Guidelines3/5

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

Using this to enumerate webhooks is strongly implied by 'List all', but there is no explicit when/when-not guidance and no named alternative (e.g. get_webhook for a single record). For a zero-parameter list tool the intended use is obvious, making this minimally adequate rather than rich.

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

tailscale_preview_aclPreview ACL rulesA
Read-onlyIdempotent

Preview the ACL rules that would apply to a specific user or IP address if a proposed policy were applied.

ParametersJSON Schema
NameRequiredDescriptionDefault
typeYesPreview type: 'user' to see rules for a user, 'ipport' to see rules for an IP
policyYesThe proposed ACL policy text to preview
previewForYesThe user email (for type 'user') or IP:port (for type 'ipport') to preview rules for

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is fully covered. The description does add one meaningful behavioral fact — that nothing is actually applied, the result is a hypothetical preview — but says nothing about required permissions or what the preview returns.

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?

A single sentence with zero filler, and the key framing (hypothetical preview) is front-loaded. Nothing could be cut without losing meaning.

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

Completeness3/5

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

For a preview/analysis tool the return value is the entire deliverable, yet there is no output schema and the description does not indicate what the preview contains (e.g., matched rules, allow/deny verdicts). What is present is accurate and sufficient to invoke the tool, but thin on outcome.

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 description coverage is 100% and the enum values for 'type' are already documented in the schema, so the description's mention of 'a specific user or IP address' only restates the schema's two modes. Baseline 3 is appropriate when the schema carries the parameter burden.

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

Purpose4/5

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

The description states a specific verb ('Preview') and resource ('ACL rules'), plus the exact scope: results for a given user or IP under a proposed policy. It is clearly distinguishable from get_acl (current state) and validate_acl (syntax check) by implication, though it never names those siblings outright.

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

Usage Guidelines3/5

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

The hypothetical framing ('if a proposed policy were applied') implies when you'd reach for this tool, but there is no explicit guidance on when to use it versus tailscale_validate_acl or tailscale_diff_acl_access, which are the nearest alternatives. Usage is inferable rather than stated.

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

tailscale_rename_deviceRename deviceA
Idempotent

Set the name of a device in the tailnet, or reset it to its OS hostname.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesNew device name: the FQDN (e.g. 'nodename.your-tailnet.ts.net') or just the base name (e.g. 'nodename'). Pass an empty string to reset the name to one generated from the OS hostname (per Tailscale's API spec).
deviceIdYesThe device ID to rename. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=true, openWorldHint=true. The description adds the reset-to-OS-hostname behavior and the empty-string convention, which is beyond the annotations. It doesn't mention permissions or side effects, but the idempotent and non-destructive hints cover the main safety profile.

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 sentence that states the primary action and the reset alternative. It is front-loaded with the main verb and resource, and every word earns its place. No fluff.

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 simple two-parameter tool with a rich schema and clear annotations, the description is nearly complete. It explains the reset behavior, which is the main non-obvious aspect. It doesn't describe the return value, but there is no output schema and the tool is a simple rename operation, so that is acceptable.

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 description coverage is 100%, so the schema already documents both parameters well. The description adds the reset behavior tied to the name parameter, which complements the schema. It doesn't add much beyond the schema, but the schema is already rich, so a baseline of 3-4 is appropriate; the reset context gives it a 4.

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 ('Set the name of a device in the tailnet') and the resource (device in the tailnet), and also covers the reset behavior. It distinguishes itself from sibling tools like tailscale_get_device or tailscale_delete_device by focusing specifically on renaming.

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 implies when to use this tool: when you need to set or reset a device's name. It doesn't explicitly state when not to use it or name alternatives, but the context of renaming is clear. The schema adds guidance on the name format, which helps usage.

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

tailscale_resend_contact_verificationResend contact verificationC

Resend the verification email for a tailnet contact.

ParametersJSON Schema
NameRequiredDescriptionDefault
contactTypeYesThe contact type to resend verification for

TDQS

C2.9/5.0
Behavior2/5

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

Annotations already declare non-read-only, non-idempotent, open-world behavior, and the description is consistent with them. However, it adds no behavioral context beyond the title—nothing about rate limits, whether it changes verification state, or what the caller sees on success. With annotations carrying the safety profile, the description contributes almost nothing.

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

Conciseness4/5

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

A single front-loaded sentence with no filler, which is appropriately sized. It is near-optimal for conciseness, though it is arguably terse given the missing usage context.

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

Completeness3/5

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

For a one-parameter action tool with no output schema, the description is minimally adequate, but it omits what the tool actually does to state (sends an email), expected outcome, and any rate-limit or eligibility preconditions an agent would need.

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 description coverage is 100% with a single enum parameter (account/support/security), so the schema fully documents the input. The description only says 'a tailnet contact' and does not enrich the meaning of contactType, so the baseline 3 applies.

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

Purpose4/5

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

The description names a specific verb (resend) and resource (verification email for a tailnet contact), which lets an agent distinguish it from the similarly-named resend_device_invite and resend_user_invite siblings. It stops short of explicitly contrasting those siblings, so it is clear but not maximally differentiated.

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?

There is no guidance on when to use this tool: no prerequisites (e.g., the contact must exist and be unverified), no mention of the alternatives (get_contacts, set_contacts), and no exclusions. The single clause only restates the action.

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

tailscale_resend_device_inviteResend device inviteC

Resend a device invite email.

ParametersJSON Schema
NameRequiredDescriptionDefault
inviteIdYesThe device invite ID to resend

TDQS

C2.9/5.0
Behavior2/5

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

Annotations already declare readOnlyHint=false, idempotentHint=false, destructiveHint=false, and openWorldHint=true, so the safety/state profile is covered structurally. The description adds nothing beyond that: it does not say whether the previous invite/link is invalidated, whether a new expiry is issued, or whether the operation can fail for already-accepted invites — notably the non-idempotent hint goes unexplained.

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

Conciseness4/5

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

A single short sentence with the action front-loaded and no filler. It is efficient, though arguably under-specified rather than optimally terse.

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

Completeness3/5

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

With one fully documented parameter and no output schema, the mechanical surface is covered. However, for a state-changing, non-idempotent operation the description omits side effects and return expectations, leaving the minimal viable picture rather than a complete one.

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 description coverage is 100% (inviteId documented as 'The device invite ID to resend'), and there is only one parameter. The description adds no format, sourcing, or validation detail beyond the schema, so the baseline of 3 applies.

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

Purpose4/5

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

The description states a specific verb ('resend') and resource ('device invite email'), so an agent immediately knows the operation. It implicitly distinguishes itself from sibling resend tools like tailscale_resend_user_invite and tailscale_resend_contact_verification by naming 'device invite', though it never explicitly contrasts them.

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?

There is no guidance on when to use this versus alternatives, nor any precondition such as the invite needing to be pending or unexpired. The agent must infer the trigger condition (an invite that was not received or expired) entirely on its own.

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

tailscale_resend_user_inviteResend user inviteB

Resend a user invite email.

ParametersJSON Schema
NameRequiredDescriptionDefault
inviteIdYesThe user invite ID to resend

TDQS

B3.2/5.0
Behavior2/5

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

Annotations already declare readOnlyHint=false, idempotentHint=false, and destructiveHint=false, and the description adds nothing beyond restating the title. It omits the practically important behavior for a resend (whether the prior invite/link is invalidated, regeneration of the token, and any rate limiting), which matters precisely because idempotentHint=false hints at side effects.

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

Conciseness4/5

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

A single short sentence with the action front-loaded and zero filler. It is efficient, though the brevity borders on under-specification rather than tight editing.

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

Completeness3/5

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

For a one-parameter, non-destructive-by-annotation tool with full schema coverage and no output schema, this is minimally sufficient. However, since the operation sends an email and is flagged non-idempotent, some note on re-send consequences or failure modes would round it out.

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 description coverage is 100% with a single documented parameter (inviteId), so the schema already carries the semantics. The description adds no format, sourcing, or constraints beyond it, which is the expected baseline for full coverage.

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

Purpose4/5

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

States a specific verb ('Resend') and resource ('user invite email'), which is clear and matches the title. It does not distinguish itself from the near-identical sibling tailscale_resend_device_invite, but the resource noun 'user' does most of the work.

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

Usage Guidelines3/5

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

Usage is only implied: an agent can infer it should be called when an invitee needs a new invite email, but the description gives no explicit when-to-use, when-not-to-use, or alternative (e.g., delete + recreate invite, or the device-invite variant).

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

tailscale_restore_userRestore userA
Idempotent

Restore a previously suspended user, re-granting them access to the tailnet.

ParametersJSON Schema
NameRequiredDescriptionDefault
userIdYesThe user ID to restore

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, idempotentHint=true and destructiveHint=false, so the safety profile is covered. The description adds the actual effect ('re-granting them access to the tailnet'), which is useful for a mutation, but says nothing about required permissions or what happens if the user is not suspended.

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?

One sentence, front-loaded with the verb and the key precondition, with zero filler. Every word 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?

For a single-parameter mutation whose annotations already cover idempotency and destructiveness, the description conveys the precondition and the outcome. Missing only edge-case behavior (user not suspended, nonexistent ID), which is minor at this complexity.

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 description coverage is 100% with a single documented userId parameter, so the schema already carries the parameter meaning. The description adds no format, ID-source, or lookup guidance beyond it, making the baseline 3 appropriate.

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

Purpose4/5

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

States a specific verb (Restore) and resource (user) plus the precondition (previously suspended), which cleanly separates it from siblings like tailscale_suspend_user and tailscale_delete_user. It stops short of explicitly naming the reverse-operation sibling, so it is clear but not maximally differentiated.

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

Usage Guidelines3/5

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

The phrase 'previously suspended user' implies when to use it, i.e. to undo a suspension. However, it never states when NOT to use it (e.g. for a deleted user, use a different tool) or names an alternative, leaving the routing inference to the agent.

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

tailscale_rotate_webhook_secretRotate webhook secretA

Rotate a webhook's secret. Returns the new secret — save it immediately, as it cannot be retrieved again. The old secret is immediately invalidated.

SECURITY: the response body contains the secret verbatim. MCP clients commonly persist tool responses to logs and conversation transcripts; treat this response as sensitive.

ParametersJSON Schema
NameRequiredDescriptionDefault
webhookIdYesThe webhook ID whose secret to rotate

TDQS

A4.3/5.0
Behavior5/5

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

Annotations only supply the generic safety flags (readOnlyHint=false, idempotentHint=false, destructiveHint=false, openWorldHint=true). The description goes well beyond them by disclosing the one-time retrieval constraint, the immediate invalidation of the old secret, and a security note about clients persisting responses to logs and transcripts. This is exactly the behavioral context annotations cannot convey.

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 short sentences plus a labeled SECURITY note; the critical 'save it immediately' warning is front-loaded and every sentence carries unique information. No padding or repetition of the title.

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?

With no output schema, the description correctly compensates by explaining what is returned (the new secret, verbatim) and that it cannot be retrieved again. For a one-parameter mutation tool, an agent has everything needed to call it and handle the result safely.

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?

There is a single parameter (webhookId) with 100% schema description coverage, so the schema fully documents it. The description adds no format, sourcing, or lookup guidance for the ID, so the baseline of 3 applies.

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?

States a specific verb and resource ('Rotate a webhook's secret') and clearly distinguishes itself from siblings like tailscale_update_webhook or tailscale_create_webhook by naming the exact mutation being performed on the secret. An agent can select this tool without opening the schema.

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

Usage Guidelines3/5

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

The description implies the usage context (you need a fresh secret, so rotate) and warns about the immediate invalidation of the old secret, but it never explicitly says when to choose this over tailscale_update_webhook or why a rotation would be needed. Usage is inferable but not stated or contrasted against alternatives.

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

tailscale_set_contactsSet contactsA
Idempotent

Update tailnet contact information. Each provided contact type (account/support/security) is PATCHed in parallel; per-type errors are returned alongside the successes so a partial failure doesn't lose the work that succeeded. On partial failure the response is data: { applied, failed } -- inspect data.failed for per-type error details.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountNoAccount contact email
supportNoSupport contact email
securityNoSecurity contact email

TDQS

A3.7/5.0
Behavior5/5

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

Annotations declare the safety profile (readOnlyHint=false, idempotentHint=true, destructiveHint=false), but the description goes well beyond them: it discloses PATCH semantics per contact type, parallel execution, per-type error isolation, and the exact partial-failure response shape (data: { applied, failed }) with instructions to inspect data.failed. This is non-obvious behavior an agent could not infer from structured fields.

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 tight sentences, front-loaded with the action and then the failure-mode contract. No filler, and the most decision-relevant fact (partial failures are preserved) is stated before the response details.

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?

With no output schema, the description correctly documents the failure response, which is the highest-value gap to fill. It omits the success-path response shape and any note on omitted contact types being left unchanged, but it is otherwise sufficient for a 3-optional-param mutation 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?

Schema description coverage is 100% and each nested property already documents its email and validation pattern, so the schema carries the parameter burden. The description only restates the three contact type names, adding no format or merge/replace detail beyond the schema — the expected baseline of 3.

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

Purpose4/5

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

States a specific verb and resource: 'Update tailnet contact information', and names the three contact types (account/support/security) that can be set. It is clear what the tool does, but it never distinguishes itself from siblings like tailscale_get_contacts or tailscale_resend_contact_verification, so an agent gets no explicit routing signal.

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?

There is no when-to-use or when-not-to-use guidance, and no mention of the read-side sibling (tailscale_get_contacts) or prerequisites such as admin/tailnet-owner scope. Usage is only implied by the verb 'Update'.

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

tailscale_set_device_ipSet device IPA
Idempotent

Set the Tailscale IPv4 address for a device.

ParametersJSON Schema
NameRequiredDescriptionDefault
ipv4YesThe new Tailscale IPv4 address for the device (e.g. '100.64.0.1')
deviceIdYesThe device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, destructiveHint=false, and idempotentHint=true, covering the basic safety profile. The description adds no additional behavioral context (e.g., potential disconnection of the device, permission requirements, or side effects). It is consistent with annotations but doesn't enrich the agent's understanding beyond them.

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 concise sentence that immediately conveys the core action. There is no fluff or redundant wording, and it is front-loaded with the verb and resource.

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

Completeness3/5

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

Given the simplicity of the tool (two required parameters, well-documented schema, no output schema), the description is minimally sufficient but lacks contextual details like the implications of changing an IP address or when this should be used. It doesn't mention any constraints or edge cases, but for a straightforward set operation it is adequate.

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 input schema has 100% coverage with detailed descriptions for both parameters: deviceId explains the source and format (nodeId from tailscale_list_devices, not nodeKey), and ipv4 gives an example. The tool description itself adds no parameter-specific information, but the schema already handles semantics well, so a baseline 3 is appropriate.

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 ('Set') and the resource ('Tailscale IPv4 address for a device'), which is specific and distinct from sibling tools like tailscale_set_device_routes or tailscale_set_device_tags. An agent can immediately understand what this tool does without ambiguity.

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?

The description provides no guidance on when to use this tool versus alternatives. There are many sibling tools that modify devices (e.g., rename, expire, set routes), but no context is given about selecting this one over them. It simply states the action without any usage conditions or exclusions.

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

tailscale_set_device_posture_attributeSet device posture attributeB
Idempotent

Set a custom posture attribute on a device. Creates or updates the attribute. Attribute keys must start with 'custom:'. Useful for compliance tracking, JIT access, and custom security policies.

ParametersJSON Schema
NameRequiredDescriptionDefault
valueYesThe attribute value: a string (max 50 characters, letters, numbers, underscores and periods only), an integer number (JSON-safe, up to 2^53-1), or a boolean. The type is fixed by the first value written for a key -- every device's value for that key must then be the same type.
expiryNoOptional expiry time in RFC3339 format (e.g. '2026-12-01T00:00:00Z'). Attribute is automatically removed after expiry.
commentNoOptional comment added to the audit log explaining why the attribute is being set (max 200 chars)
deviceIdYesThe device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.
attributeKeyYesThe attribute key (must start with 'custom:', e.g. 'custom:lastAuditDate'). Max 128 characters including the prefix; letters, numbers, underscores and colons only. Keys are case-sensitive but are checked for uniqueness case-insensitively, so 'custom:MyAttribute' and 'custom:myattribute' cannot both exist in one tailnet.

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, idempotentHint=true, destructiveHint=false. The description adds the key-prefix constraint (also in schema) and 'Creates or updates' which aligns with idempotency, but no new behavioral disclosure beyond annotations.

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 concise sentences, front-loaded with the core purpose and the critical key constraint. No wasted words.

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 straightforward mutation tool with fully documented parameters and annotations, the description provides adequate purpose and constraints. It doesn't cover response format, but there's no output schema, so that's acceptable.

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 the baseline is 3. The description does not add parameter-level meaning beyond what the schema provides (e.g., value types, expiry, comment). It only reiterates the key prefix rule.

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

Purpose4/5

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

The description clearly states the verb ('Set') and resource ('custom posture attribute on a device'), and clarifies that it creates or updates. This distinguishes it from get/delete operations, though it doesn't explicitly mention the batch variant sibling.

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 explicit guidance on when to use this tool versus alternatives like tailscale_batch_update_posture_attributes. The 'useful for compliance tracking...' phrase is about general purpose, not tool selection.

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

tailscale_set_device_routesSet device routesA
DestructiveIdempotent

Set the enabled subnet routes for a device. Replaces all currently enabled routes — pass the full list of routes you want enabled.

ParametersJSON Schema
NameRequiredDescriptionDefault
routesYesFull list of CIDR routes to enable (e.g. ['10.0.0.0/24', '192.168.1.0/24']). Replaces existing enabled routes.
deviceIdYesThe device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.

TDQS

A4.5/5.0
Behavior5/5

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

The description adds significant behavioral context beyond the annotations: it discloses that the operation is a full replacement ('Replaces all currently enabled routes') and instructs the agent to pass the complete desired list. This aligns with and reinforces the destructiveHint and idempotentHint annotations without contradicting them.

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 two sentences with no filler. The primary action is front-loaded, and the critical replacement behavior is stated immediately after, making the most important information easy to spot.

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 two-parameter mutation tool with no output schema, the description is complete: it states the action, the resource, and the critical destructive/replacement behavior. The schema covers parameter formats (including device ID provenance), and annotations cover safety flags, so nothing needed for correct invocation is missing.

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 description coverage is 100%, with both deviceId and routes already documented in detail. The description reinforces the routes semantics ('pass the full list of routes you want enabled') but does not add meaning beyond what the schema already provides, so the baseline of 3 is appropriate.

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 states a precise action ('Set the enabled subnet routes for a device') with an explicit resource and scope, and clarifies that it replaces all currently enabled routes. This clearly distinguishes it from sibling get_* tools like tailscale_get_device_routes and other set_* tools operating on different resources.

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 makes the usage context clear: use it to configure the full list of enabled routes for a device. The explicit warning to pass the full list is valuable operational guidance. However, it does not explicitly name tailscale_get_device_routes as the read alternative or state when not to use this tool, though sibling names make this relatively obvious.

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

tailscale_set_devices_authorizedSet devices authorized (bulk)A
DestructiveIdempotent

Authorize or deauthorize multiple devices in one call. Each device's POST runs in parallel; per-device errors are returned alongside the successes so a partial failure doesn't lose the work that succeeded. On partial failure the call still returns success (ok) with data: { authorized, succeeded, failed } -- inspect data.failed for the per-device errors. Common use: authorize a batch of newly-enrolled CI hosts, or deauthorize a group of devices flagged by a security review.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceIdsYesDevice IDs to update (nodeIds preferred; legacy numeric ids also work)
authorizedYestrue to authorize, false to deauthorize

TDQS

A4.4/5.0
Behavior5/5

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

The description goes well beyond annotations by revealing parallel POST execution, partial-failure handling, and the response shape on failure with data.failed. It also clarifies that a partially failed call still returns success (ok), which is critical behavioral context. No contradiction with readOnlyHint or destructiveHint.

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?

Four focused sentences front-load the core action, then explain failure semantics, then give concrete usage examples. No filler or redundancy; every sentence contributes distinct useful information.

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?

With no output schema, the description compensates by explaining the partial-failure response structure and how to inspect per-device errors. Combined with the fully documented parameters and annotations, this is sufficient for correct invocation and interpretation, though a fully specified success response shape is not provided.

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%, with both deviceIds and authorized already described in the input schema. The description adds no additional parameter-level detail; its extra information is behavioral rather than semantic, so the baseline score applies.

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?

Clearly states the tool authorizes or deauthorizes multiple devices in one call. The verb plus 'multiple devices' and 'bulk' title differentiate it from the single-device tailscale_authorize_device and tailscale_deauthorize_device siblings without ambiguity.

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 explicit common use cases: authorizing a batch of newly-enrolled CI hosts or deauthorizing security-flagged devices. It does not explicitly name the single-device alternatives or say when not to use this tool, but the batch context is clear.

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

tailscale_set_device_tagsSet device tagsA
DestructiveIdempotent

Set ACL tags on a device. Replaces all existing tags — pass the full list of tags you want applied.

ParametersJSON Schema
NameRequiredDescriptionDefault
tagsYesFull list of ACL tags (e.g. ['tag:server', 'tag:production']). Replaces all existing tags.
deviceIdYesThe device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and idempotentHint=true. The description adds valuable behavioral context beyond those flags by specifying that all existing tags are replaced and the caller must pass the full list. This directly addresses the destructive nature in a way that guides correct invocation.

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 two sentences with zero filler. The primary action is stated first, immediately followed by the most important behavioral caution. Every word earns its place.

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 two-parameter mutation with detailed schema descriptions and annotations covering safety (destructive, idempotent, read-only), the description fully covers the non-obvious behavior—replace-all—and needs no additional context for an agent to call it correctly.

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%, and both parameters already have rich descriptions including examples, format constraints, and the 'replaces all existing tags' note. The description does not add further parameter-level meaning, so the baseline 3 is appropriate.

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 states a specific verb ('Set'), resource ('ACL tags'), and target ('a device'), which clearly separates it from sibling set-* tools like tailscale_set_device_routes and tailscale_set_device_ip. No ambiguity remains about what the tool does.

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

Usage Guidelines3/5

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

The description provides no explicit when-to-use or alternative comparison. It gives critical caveat about replacing all tags, but does not name sibling tools or exclusion conditions. The usage context is implied by the tool name rather than stated.

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

tailscale_set_dns_configurationSet DNS configuration (unified)A
DestructiveIdempotent

Set the unified DNS configuration for your tailnet in a single call. Replaces all DNS settings (nameservers, search paths, split DNS, MagicDNS preference).

ParametersJSON Schema
NameRequiredDescriptionDefault
dnsNoList of DNS server IP addresses
magicDNSNoWhether to enable MagicDNS
splitDnsNoMap of domain to nameserver list for split DNS
searchPathsNoList of DNS search domains

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, idempotentHint=true, and openWorldHint=true. The description adds specific scope by naming exactly what gets replaced (nameservers, search paths, split DNS, MagicDNS preference), which is valuable context beyond the annotation flags.

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, front-loaded with the action and the critical replacement behavior. Every sentence earns its place with no redundancy.

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?

Combined with fully described parameters and rich annotations covering safety semantics, the description makes the tool's full-replacement nature and scope explicit. An agent has everything needed to invoke it correctly.

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 description coverage is 100%, with each parameter documented in the schema. The description lists the four configurable areas by name but adds no syntax, format, or edge-case guidance beyond what the schema already provides. Baseline 3 is appropriate.

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?

States a specific verb (Set), resource (unified DNS configuration), and scope (tailnet, single call). The phrase 'unified' and 'Replaces all DNS settings' clearly distinguishes it from the granular DNS siblings like set_nameservers and set_search_paths.

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 conveys when to use it: for replacing all DNS settings in a single call. It does not explicitly name granular alternatives or state when not to use it, but the context is clear and actionable.

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

tailscale_set_dns_preferencesSet DNS preferencesA
Idempotent

Set DNS preferences for your tailnet, such as enabling or disabling MagicDNS. The API reference says enabling can fail when the tailnet has no nameservers; if it does, add one with tailscale_set_nameservers first.

ParametersJSON Schema
NameRequiredDescriptionDefault
magicDNSYesWhether to enable MagicDNS

TDQS

A4/5.0
Behavior4/5

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

Discloses a non-obvious failure mode and ordering dependency (enabling MagicDNS fails without nameservers) that annotations do not convey. Annotations already cover readOnly=false, idempotent=true, and destructive=false, so the description adds meaningful behavioral context beyond those structured hints.

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 with no filler: the first defines the operation, the second provides a targeted fallback instruction. The important operation is front-loaded, and the caveat is placed where it is most useful.

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 single-parameter tool with idempotent and non-destructive annotationsasi, the description covers the operation, the parameter meaning, and a real-world failure scenario with remediation. It does not describe return values, but no output schema is present and the operation itself is simple enough that this is a minor gap.

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%, and the schema already documents magicDNS as a boolean. The description reinforces that the boolean enables or disables MagicDNS and hints at the enabling side effect, but it does not substantially go beyond the schema for the single parameter.

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

Purpose4/5

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

States a specific verb and resource ('Set DNS preferences for your tailnet') and gives a concrete example (enabling/disabling MagicDNS). It is clearly distinct from get_dns_preferences by the set/get contrast, though it does not explicitly disambiguate from set_dns_configuration or set_nameservers.

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 a concrete usage caveat: enabling can fail when no nameservers exist, and directs the agent to call tailscale_set_nameservers first in that case. This is an explicit conditional alternative, though it does not broadly discuss when to prefer this over set_dns_configuration or when to check get_dns_preferences.

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

tailscale_set_log_stream_configSet log stream configA
Idempotent

Set the log streaming configuration for a specific log type. Configures where logs are sent (e.g. Axiom, Datadog, Splunk, Elasticsearch, S3).

Per-destination required fields:

  • splunk / elastic / panther / cribl / datadog / axiom: url + token (user optional)

  • s3: s3Bucket + s3Region + s3AuthenticationType, plus either (s3AccessKeyId + s3SecretAccessKey) for 'accesskey' auth or s3RoleArn for 'rolearn' auth. Call tailscale_create_aws_external_id first when using 'rolearn'.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoDestination URL (required for non-s3 destinations)
userNoUsername for the destination (if required)
tokenNoAuthentication token or API key for the destination. SENSITIVE: passed straight to Tailscale and not echoed back, but MCP clients may log the input value you supply.
logTypeYesThe log type: 'configuration' for audit logs, 'network' for network flow logs
s3BucketNo(s3 only) S3 bucket name. Required when destinationType is 's3'.
s3RegionNo(s3 only) AWS region of the S3 bucket. Required when destinationType is 's3'.
s3RoleArnNo(s3 only) IAM role ARN that Tailscale will assume. Required when s3AuthenticationType is 'rolearn'.
s3KeyPrefixNo(s3 only) Optional prefix prepended to the auto-generated S3 object key.
s3AccessKeyIdNo(s3 only) AWS access key id. Required when s3AuthenticationType is 'accesskey'.
destinationTypeYesThe log streaming destination type
compressionFormatNoCompression algorithm for log uploads. Defaults to 'none'.
s3SecretAccessKeyNo(s3 only) AWS secret access key. Required when s3AuthenticationType is 'accesskey'. SENSITIVE: see the token field's note about MCP client logging.
uploadPeriodMinutesNoMinutes to wait between uploads (1-1440). Optional.
s3AuthenticationTypeNo(s3 only) Authentication mode. Required when destinationType is 's3'. Tailscale recommends 'rolearn'.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=false, openWorldHint=true, idempotentHint=true, and destructiveHint=false, so safety posture is covered. The description adds valuable behavioral context about per-destination required fields and the two-step rolearn workflow, though it doesn't describe rate limits, error handling, or how existing configs are replaced.

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

Conciseness4/5

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

The description is front-loaded with the core action, then uses a compact bulleted breakdown of per-destination requirements. It is efficient for a 14-parameter tool, though the nested bullet could be slightly tightened.

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 high schema coverage and no output schema, the description covers the key conditional parameter combinations and the external-id dependency. It is nearly complete, though it could mention what happens to an existing config when this is called.

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 the baseline is 3, but the description adds meaningful cross-field constraints (which combinations of url/token/s3Bucket/s3Region/s3AuthenticationType/s3RoleArn are required per destinationType) that the schema only partially encodes in individual field notes.

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 states a specific verb (Set) and resource (log streaming configuration) scoped by log type, and it names the destination categories (Axiom, Datadog, Splunk, Elasticsearch, S3). It is clearly distinguishable from sibling tools like tailscale_set_log_stream_config vs. tailscale_get_log_stream_config or tailscale_list_log_stream_configs.

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 gives concrete per-destination requirements and explicitly routes the agent to tailscale_create_aws_external_id for rolearn auth. It does not, however, state when this tool should be preferred over alternatives or what prerequisites exist before calling it (e.g. whether the destination must already exist).

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

tailscale_set_nameserversSet nameserversA
DestructiveIdempotent

Set the DNS nameservers for your tailnet. Replaces all existing nameservers. Removing every nameserver may also change MagicDNS: the API reference says it is switched off, while Tailscale's current MagicDNS docs say a nameserver is no longer required -- check magicDNS in the response.

ParametersJSON Schema
NameRequiredDescriptionDefault
dnsYesList of DNS server IP addresses (e.g. ['8.8.8.8', '1.1.1.1'])

TDQS

A4.5/5.0
Behavior5/5

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

The description adds significant behavioral detail beyond annotations: it warns that all existing nameservers are replaced, explains that removing all nameservers may affect MagicDNS, flags a documentation discrepancy, and tells the agent to inspect `magicDNS` in the response. This is exactly the kind of context that prevents incorrect invocation.

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 sentences, each earning its place: purpose and scope first, destructive replacement warning second, and the subtle MagicDNS edge case third. There is no fluff or restatement of schema or annotation data.

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 one-parameter mutation with strong annotations (destructive, idempotent, not read-only) and a fully documented schema, the description covers the core behavior, the edge case, and what to check in the response. Nothing essential is missing for an agent to call it correctly.

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?

The schema already fully documents the `dns` parameter with an example, so the baseline is 3. The description adds meaningful semantic value by indicating that an empty array is a valid and consequential input, which the schema does not explicitly state. It does not add syntax-level detail, so a 4 is appropriate.

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 states a specific verb ('Set'), a specific resource ('DNS nameservers'), and a clear scope ('your tailnet'). It also clarifies the full-replacement semantics, making it easy to distinguish from read-style siblings like tailscale_get_nameservers.

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

Usage Guidelines3/5

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

The description implies the tool is used to replace tailnet nameservers, but it does not explicitly say when to choose it over related siblings such as tailscale_set_dns_configuration or tailscale_set_dns_preferences. There is no when/when-not guidance, only an implied use case.

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

tailscale_set_search_pathsSet DNS search pathsA
DestructiveIdempotent

Set the DNS search paths for your tailnet. Replaces all existing search paths.

ParametersJSON Schema
NameRequiredDescriptionDefault
searchPathsYesList of DNS search domains (e.g. ['example.com', 'internal.corp'])

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, idempotentHint=true and openWorldHint=true, but the description adds the crucial specifics of what gets destroyed: ALL existing search paths are replaced rather than merged. It does not cover auth/permission requirements or rate limits, so it is additive but not exhaustive.

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 short sentences, front-loaded with the action and resource, with the destructive replacement caveat immediately following. Every sentence earns its place and nothing is padded.

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 one-parameter setter with no output schema and full schema description coverage, the description plus annotations give the agent everything needed: what it configures, the overwrite behavior, and the safety profile. No material 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% and the schema already documents searchPaths as a list of DNS search domains with examples. The description adds meaning beyond that by making clear the supplied array is the complete, replacement set rather than an append, which changes how the caller should construct the parameter.

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

Purpose4/5

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

The description gives a specific verb+resource ('Set the DNS search paths') scoped to 'your tailnet', so an agent immediately knows what the tool does and that it is the write counterpart to tailscale_get_search_paths. It stops short of naming that sibling explicitly, so it is clear rather than maximally differentiating.

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

Usage Guidelines3/5

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

Usage is implied: it is a configuration setter, and 'Replaces all existing search paths' hints that this is a full-overwrite operation. There is no explicit statement of when to prefer this over tailscale_get_search_paths or tailscale_set_dns_preferences, and no stated preconditions or warnings about the overwrite.

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

tailscale_set_service_device_approvalSet service device approvalB
Idempotent

Approve or reject a device to host a Tailscale Service.

ParametersJSON Schema
NameRequiredDescriptionDefault
approvedYesWhether to approve (true) or reject (false) the device
deviceIdYesThe device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.
serviceNameYesThe service name

TDQS

B3.3/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds the domain context of approving a device for a service, but does not disclose side effects, reversibility, or permission requirements. Given the annotations, the description provides minimal additional behavioral insight.

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?

A single sentence that states the action and target resource with zero fluff. It is front-loaded with the verb and immediately clear. No wasted words.

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

Completeness3/5

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

For a simple write operation with three fully documented parameters and annotations covering safety, the description is minimally sufficient. However, it lacks any note about prerequisites, post-condition effects, or when this tool is preferred over similar authorization tools. Given the simplicity, it is adequate but not comprehensive.

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 description coverage is 100%, so all three parameters are documented in the schema. The deviceId description is notably rich (source, example, exclusions). The tool description itself adds no parameter-level meaning beyond what the schema already provides, so baseline 3 is appropriate.

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

Purpose4/5

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

The description uses a specific verb 'Approve or reject' and a clear resource 'a device to host a Tailscale Service.' It is unambiguous about the action. However, it does not explicitly differentiate from sibling tools like tailscale_authorize_device or tailscale_set_devices_authorized, which could be confused with this service-specific approval.

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. There is no mention of context (e.g., 'use this for service-level approval, not device authorization') or exclusions. The agent must infer its purpose from the name and schema.

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

tailscale_set_split_dnsSet split DNSA
DestructiveIdempotent

Set split DNS configuration. Maps domains to specific nameservers. Replaces the entire split DNS configuration: a domain you leave out is removed, and an empty object clears every domain. Per the API reference, setting a domain to null clears that domain's nameservers.

ParametersJSON Schema
NameRequiredDescriptionDefault
splitDnsYesMap of domain to nameserver list, or to null to clear that domain (e.g. { "corp.example.com": ["10.0.0.1"], "old.example.com": null })

TDQS

A4.8/5.0
Behavior5/5

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

Even though destructiveHint and idempotentHint are already present in annotations, the description goes further by explaining exactly what gets destroyed: the entire split DNS configuration, omitted domains, and empty-object clearing behavior. It also discloses that setting a domain to null clears that domain's nameservers, which is valuable behavioral context beyond the structured annotations.

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 concise sentences, each carrying essential information. The core purpose is front-loaded, and the destructive/clearing semantics follow logically. No filler or repetition of the schema's example.

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 one-parameter mutation tool with no output schema, the description covers everything needed to call it correctly: what it does, the full-replacement semantics, the clearing behavior, and the null convention. The annotations cover idempotency and destructiveness, so no critical behavioral information is missing.

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

Parameters5/5

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

The schema already documents the splitDns parameter well and provides an example, so baseline is high. The description adds substantial extra meaning beyond the schema: omitted domains are removed, an empty object clears every domain, and null clears a single domain's nameservers. These are exactly the nontrivial semantics an agent needs to invoke the parameter correctly.

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 names a specific verb and resource ('Set split DNS configuration') and immediately defines the distinguishing behavior: it replaces the entire split DNS configuration, not just the supplied entries. This makes it clearly distinct from get_split_dns and from a partial-update sibling such as tailscale_update_split_dns.

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 gives clear context for when to use the tool: when you want to set split DNS with full-replacement semantics. It also explains consequences ('a domain you leave out is removed, and an empty object clears every domain'), which is important usage guidance. It does not explicitly name alternatives or state 'use X for partial updates,' but the replacement wording already implies the boundary.

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

tailscale_statusCheck API statusA
Read-onlyIdempotent

Check that the Tailscale API connection is working. Returns your tailnet name, device count, and confirms authentication is valid. Use this to verify setup.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive), so the bar is lower, yet the description still adds value by stating what the call verifies (auth validity) and what it returns. It does not mention error behavior on a failed connection, but the gap is minor.

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 short sentences, front-loaded with the core action, then return values, then the use case. No filler and nothing repeated from the annotations or schema.

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?

With no parameters and no output schema, the description correctly compensates by describing what the call returns and what it validates. An agent has everything needed to invoke and interpret it, though a note on failure/timeout behavior would make it fully self-contained.

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?

The tool takes zero parameters, so the baseline is 4 per the rubric. There is nothing for the description to clarify beyond confirming there is no input required.

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 names a specific operation (checking the Tailscale API connection) and enumerates the concrete outputs (tailnet name, device count, authentication validity). This distinguishes it cleanly from every data-mutating sibling in the list.

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?

"Use this to verify setup" gives a clear use context, so the agent knows this is a connectivity/auth diagnostic rather than a data-retrieval tool. It names no explicit exclusions or alternatives, but no sibling tool competes for this role.

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

tailscale_suspend_userSuspend userA
DestructiveIdempotent

Suspend a user, immediately revoking their access to the tailnet. Their devices will be disconnected. Can be reversed with tailscale_restore_user.

ParametersJSON Schema
NameRequiredDescriptionDefault
userIdYesThe user ID to suspend

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false. The description adds concrete consequences beyond the flags: immediate access revocation, device disconnection, and reversibility via a named restore tool. This is meaningful context on top of the annotation envelope, though it doesn't mention auth requirements or any propagation delay.

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 short sentences, no padding, consequences front-loaded before the reversal note. Every sentence earns its place.

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 single-param destructive mutation, the description covers effect scope (tailnet access revocation), side effects (device disconnect), and reversibility. No output schema exists, and the return isn't needed to call it correctly; nothing material is missing.

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 description coverage is 100%, so the userId parameter is already documented as 'The user ID to suspend.' The description adds no format or sourcing guidance for the ID, so this is baseline 3 – schema carries it.

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?

States a specific verb (suspend) and resource (user), and adds scope detail that distinguishes it: immediate access revocation and device disconnection. Names the sibling tailscale_restore_user, making the pair unambiguous.

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?

Explicitly names the reversal path (tailscale_restore_user), which tells the agent when this is undoable. But it doesn't contrast with other user-state tools in the large sibling set, like tailscale_delete_user or tailscale_approve_user, so the 'when not to use' is only partially covered.

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

tailscale_test_webhookTest webhookA

Send a test event to a webhook endpoint to verify it is configured correctly and receiving events.

ParametersJSON Schema
NameRequiredDescriptionDefault
webhookIdYesThe webhook ID to test

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, openWorldHint=true, idempotentHint=false, and destructiveHint=false, so the agent knows this is a non-destructive, non-idempotent outbound action. The description adds that it dispatches a test event to an external endpoint, which is useful context, but says nothing about the payload sent, whether delivery attempts are logged, or whether repeated calls trigger repeated deliveries.

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?

A single well-formed sentence that front-loads the action and resource with no redundant or filler content.

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 one-parameter diagnostic tool with no output schema, the description is nearly sufficient; annotations cover the safety profile. A brief note on what the test produces (e.g., success/failure indication) would make it complete.

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 description coverage is 100% and there is only one parameter, so the schema already documents webhookId. The description adds no syntax, format, or meaning beyond what is in the schema, which is the expected baseline here.

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

Purpose4/5

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

States a specific verb ('send') plus resource ('test event to a webhook endpoint') and the goal (verify configuration). An agent can distinguish it from sibling mutation tools like tailscale_create_webhook or tailscale_update_webhook, though it does not name them explicitly.

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

Usage Guidelines3/5

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

The phrase 'to verify it is configured correctly and receiving events' implies the diagnostic use case, but there is no explicit when-to-use guidance, no when-not-to-use, and no mention of alternatives or prerequisites (e.g., webhook must already exist).

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

tailscale_tool_groupsExplain available toolsA
Read-onlyIdempotent

Explain which of this server's tools are available and why. Call this FIRST when a Tailscale tool you expected is missing, instead of assuming the capability does not exist -- tools can be withheld by configuration, and the fix is usually one environment variable. Pass toolName to ask about one specific tool (e.g. 'tailscale_delete_device'): the answer distinguishes 'no such tool exists' -- where you should find another approach -- from 'it exists but its group is not loaded' and 'it exists and loaded but writes are withheld there', both of which the operator can enable and neither of which you should work around. With no arguments it lists every group with its availability and, where something is withheld, the exact environment change that would restore it. Always available regardless of filters.

ParametersJSON Schema
NameRequiredDescriptionDefault
toolNameNoA specific tool to ask about, e.g. 'tailscale_delete_device'. Omit to list every group.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, non-destructive, closed-world, so the safety profile is covered. The description adds genuine behavioral context beyond that: tools can be withheld by configuration, the fix is usually an environment variable, and it is 'always available regardless of filters.' It stops short of describing output shape, but that is largely implicit in the outcome enumeration.

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

Conciseness4/5

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

Front-loaded with the core directive ('Call this FIRST when...') before the parameter and no-argument behaviors. Dense and mostly waste-free, though the middle clause is somewhat run-on and could be tightened.

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?

There is no output schema, so the description must convey what comes back; it does so by enumerating the three distinguishable outcomes and the no-argument group listing with environment-change details. For a single-optional-param introspection tool, nothing an agent needs to call it correctly is missing.

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% and the parameter is already documented, so baseline is 3. The description goes further by explaining what the answer to `toolName` actually distinguishes (no such tool vs. group not loaded vs. writes withheld), adding semantic meaning beyond the schema's 'omit to list every group.'

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?

States a specific verb and object ('Explain which of this server's tools are available and why'), a capability that is clearly distinct from every sibling, which are all Tailscale API operations. An agent can immediately tell this is a meta/introspection tool rather than an API call.

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

Usage Guidelines5/5

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

Explicitly states when to call it: 'Call this FIRST when a Tailscale tool you expected is missing, instead of assuming the capability does not exist.' It also gives the fallback reasoning for each outcome (find another approach vs. ask the operator to enable), covering both when-to-use and when-not-to-work-around.

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

tailscale_update_aclUpdate ACL policyA
DestructiveIdempotent

Update the ACL policy for your tailnet. Accepts the full policy as a string to preserve formatting, comments, and trailing commas (HuJSON). You MUST pass the ETag from tailscale_get_acl to prevent overwriting concurrent changes, or ts-default for the first write to a tailnet nobody has edited yet. Always get the current ACL first, make targeted edits to the text, and pass the full modified text back.

ParametersJSON Schema
NameRequiredDescriptionDefault
etagYesThe ETag from tailscale_get_acl (quotes optional -- they are normalized). Required to prevent concurrent edit conflicts. For the FIRST write to a fresh tailnet you may pass `ts-default` instead: the update then succeeds only if the policy file is still Tailscale's untouched default.
policyYesThe full ACL policy text. Preserve existing formatting, comments, and structure. Only modify the specific parts that need to change.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already indicate destructive/idempotent write behavior; the description adds critical context about preserving HuJSON formatting, preventing concurrent overwrites via ETag, and the first-write ts-default path. No contradiction with annotations.

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 sentences with the core purpose front-loaded, followed by essential procedural constraints. Every sentence earns its place with no redundancy or filler.

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?

Together, the description and input schema fully cover the preconditions, the required parameters, and the expected payload format. With no output schema, return-value details are not necessary for an agent to invoke the tool correctly.

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?

Input schema coverage is 100% and both parameters are thoroughly described, including ETag normalization and ts-default semantics. The description reinforces the workflow and parameter usage but does not add new parameter-level details beyond the schema.

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?

States a specific verb ('Update') and resource ('the ACL policy for your tailnet'), and clarifies the payload as the full policy string. This cleanly distinguishes it from sibling tools like tailscale_get_acl, tailscale_validate_acl, and tailscale_preview_acl.

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

Usage Guidelines5/5

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

Explicitly instructs the agent to always fetch the current ACL first, make targeted edits, and pass the full modified text back. It also names the required ETag and the ts-default exception for first writes, leaving no ambiguity about when and how to invoke the tool.

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

tailscale_update_device_keyUpdate device keyA
Idempotent

Update a device's key settings, such as disabling key expiry. Useful for servers that should never need to re-authenticate.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceIdYesThe device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey.
keyExpiryDisabledYesWhether to disable key expiry for this device

TDQS

A4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, destructiveHint=false, and idempotentHint=true, so the mutation and safety profile are covered. The description adds the practical effect (disabling key expiry for servers) but does not disclose potential side effects, permission requirements, or impact on existing connections. With annotations providing the core safety traits, this is adequate but not rich.

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 efficient sentences with zero redundancy. The primary action and use case are front-loaded, and the description avoids unnecessary detail. It earns its place without wasting tokens.

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 simple 2-parameter mutation tool with no output schema and moderate annotations, the description covers the essential purpose and a canonical use case. It does not explain return values or error conditions, but those are less critical for a straightforward update operation. The tool's scope is clear and sufficient for correct 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 description coverage is 100%, with both parameters well-documented (deviceId explains the format and clarifies it's not the nodeKey; keyExpiryDisabled is self-explanatory). The description adds no additional parameter detail beyond the schema, so the baseline of 3 applies.

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?

States a clear verb (update) and resource (device's key settings), provides a concrete example (disabling key expiry), and identifies a specific use case (servers that should never re-authenticate). This distinguishes it from siblings like tailscale_expire_device (which expires keys) and tailscale_update_key (which manages API keys).

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?

Gives a clear usage scenario ('Useful for servers that should never need to re-authenticate') that helps an agent decide when to apply this tool. It doesn't explicitly name alternatives or when NOT to use it, but the context is strong enough for typical selection. Sibling differentiation is implicit through the specific focus on key expiry settings.

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

tailscale_update_keyUpdate keyA
Idempotent

Update an existing key. Supported fields depend on the key type: all key types accept 'description'; OAuth clients and federated identities additionally accept 'scopes' and 'tags'; federated identities additionally accept 'issuer', 'subject', 'audience', and 'customClaimRules'. For auth keys, pass only 'description' — the Tailscale API will reject other fields.

ParametersJSON Schema
NameRequiredDescriptionDefault
tagsNoUpdated ACL tags (must start with 'tag:')
keyIdYesThe key ID to update
issuerNo(federated only) Updated OIDC issuer URL
scopesNo(client/federated) Updated OAuth scopes
subjectNo(federated only) Updated subject claim pattern
audienceNo(federated only) Updated audience claim
descriptionNoUpdated description (max 50 chars, alphanumeric/hyphens/spaces)
customClaimRulesNo(federated only) Updated custom claim rules

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare the safety profile (readOnly=false, destructive=false, idempotent=true), so the bar is lower. The description adds real behavioral value the annotations cannot: field support varies by key type and the API will reject out-of-type fields, preventing a failed call. It stops short of describing reversibility or response behavior.

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 dense sentences, front-loaded with the core action, then the conditional field matrix, then the failure-mode warning. No filler and each sentence carries distinct information.

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 an 8-parameter mutation tool with a nested object and no output schema, the description covers the key risk (wrong fields for the key type) and lets the schema carry per-parameter formats. Minor gap: nothing about return value shape, though no output schema exists to cover it.

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 the baseline is 3, but the schema only tags each field with a parenthetical like '(federated only)'. The description consolidates those tags into a coherent key-type-to-field mapping and adds the auth-key rejection rule, which adds meaning beyond the schema.

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

Purpose4/5

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

States a specific verb ('Update') and resource ('existing key'), cleanly separating it from create_key, delete_key, and get_key siblings. It does not explicitly name an alternative tool, so it lands at clear-but-not-sibling-differentiating.

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?

Gives explicit conditional guidance keyed on key type — which fields are valid for auth keys, OAuth clients, and federated identities — including a hard when-not: auth keys must receive only 'description' or the API rejects the call. It does not discuss when to reach for this tool over siblings, but the field-eligibility rules are concrete usage instruction.

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

tailscale_update_posture_integrationUpdate posture integrationC
Idempotent

Update an existing posture integration's credentials or configuration.

ParametersJSON Schema
NameRequiredDescriptionDefault
cloudIdNoUpdated cloud identifier (e.g. 'us-1', 'global', or provider FQDN)
clientIdNoUpdated client ID for the provider
tenantIdNoUpdated tenant ID
clientSecretNoUpdated client secret for the provider (omit to retain the existing secret). SENSITIVE: passed straight to Tailscale and not echoed back, but MCP clients may log the input value you supply.
integrationIdYesThe posture integration ID to update

TDQS

C2.9/5.0
Behavior2/5

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

Annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=true and openWorldHint=true, so the safety and replay profile is covered. The description adds nothing beyond that: it does not say whether unmentioned fields are preserved (partial vs full replacement), whether the call is a full overwrite, or what authorization is required for credential changes.

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

Conciseness4/5

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

A single front-loaded sentence with no filler; the verb and resource lead. It is slightly under-powered rather than padded, so conciseness is not the problem.

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

Completeness3/5

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

There is no output schema and no annotations gap on safety, so the definition is minimally viable. However, for a mutation with four optional fields, the description never states that omitted fields retain existing values or that only integrationId is required, leaving the partial-update semantics to be reconstructed from the schema.

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 description coverage is 100% and the schema already documents each field well, including that the secret is sensitive and omitted secrets are retained. The description's 'credentials or configuration' is a loose grouping of those parameters and adds no format or constraint detail beyond the schema. Baseline 3 applies.

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

Purpose4/5

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

The description names a specific verb (update) and resource (posture integration) and narrows the scope to credentials or configuration, so an agent can distinguish it from create/delete/get posture integration siblings by name alone. It stops short of explicitly naming those siblings or stating what is not touched.

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?

The phrase 'an existing posture integration' implies the integration must already exist, but there is no explicit when-to-use, no prerequisites, and no routing to alternatives such as tailscale_create_posture_integration or tailscale_get_posture_integration. The agent must infer everything about invocation context.

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

tailscale_update_serviceUpdate serviceC
Idempotent

Update a Tailscale Service's configuration.

ParametersJSON Schema
NameRequiredDescriptionDefault
tagsNoACL tags for the service
portsNoPorts the service listens on
serviceNameYesThe service name to update
autoApproveHostsNoWhether to auto-approve devices that want to host this service

TDQS

C2.9/5.0
Behavior2/5

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

Annotations already declare the safety profile (idempotent, non-destructive, open-world), so the description is not the sole bearer of that. Still, it adds no behavioral context: nothing about whether omitted fields are preserved or reset, what permissions are required, or how conflicts between ports/tags are handled. For a mutation tool, the description contributes essentially nothing beyond the title.

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

Conciseness4/5

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

A single front-loaded sentence with zero filler, which is efficiently sized for what it says. It is under-specified rather than verbose, but there is no wasted text to penalize structurally.

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

Completeness2/5

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

For a 4-parameter mutation tool with no output schema, the description omits the most important semantic detail: whether this replaces the configuration or merges into it. Annotations cover safety, but the merge/replace ambiguity and the required-serviceName precondition leave an agent guessing.

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 description coverage is 100%, so all four parameters (serviceName, tags, ports, autoApproveHosts) are already documented in the schema with types, bounds, and enum for protocol. The description adds no meaning beyond that, so the baseline of 3 applies.

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

Purpose4/5

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

States a specific verb (update) and resource (Tailscale Service's configuration), which is clearer than the bare name alone. However, it offers no differentiation from siblings such as tailscale_get_service or tailscale_delete_service, nor from other update_* tools, so an agent gets no routing signal beyond the noun.

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?

The description gives no when-to-use guidance, no prerequisites (e.g., the service must already exist), and no named alternatives. It never says whether this is a partial or full-replace update, which is the central usage question for an update call.

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

tailscale_update_split_dnsUpdate split DNS (partial)A
Idempotent

Partially update split DNS configuration. Merges the provided domains with the existing config -- only the specified domains are changed, others are untouched. To remove a domain, set it to null: that is the idiom the API reference documents. An empty array is also accepted and forwarded as-is -- it is what Tailscale's Terraform provider sends.

ParametersJSON Schema
NameRequiredDescriptionDefault
splitDnsYesMap of domain to nameserver list to merge, or to null to remove that domain (e.g. { "new.example.com": ["10.0.0.3"], "old.example.com": null }). Only specified domains are changed.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations establish that this is a mutating, idempotent call, but the description adds the key behavioral details: it merges with existing config, only specified domains change, null removes a domain, and an empty array is forwarded as-is rather than interpreted as a clear operation. These details explain what changes and what does not, and they do not contradict the annotations.

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 sentences, and each one earns its place: the first defines the operation and merge semantics, the second covers removal, and the third addresses the empty-array edge case. The core partial-update idea is front-loaded, and the Terraform-provider reference is a compact way to signal the intended semantics.

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 single-parameter tool with thorough schema documentation and useful annotations, the description leaves no gap an agent needs to invoke it correctly. It states the operation, scope, merge behavior, removal semantics, and the empty-array edge case. The lack of an output schema is not a problem because invocation is fully specified.

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?

The schema already documents the splitDns map, the null-to-remove idiom, and the fact that only specified domains change, so the baseline is solid. The description adds extra value by explaining that an empty array is accepted and forwarded as-is, which prevents misinterpretation. This goes beyond the schema's basic type constraints.

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 opens with 'Partially update split DNS configuration', giving a specific verb, resource, and scope. It then explains the merge behavior ('only the specified domains are changed, others are untouched'), which clearly distinguishes it from full-replacement operations. The removal via null and empty-array handling make the tool's exact purpose unambiguous.

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 clearly conveys that this tool is for partial updates to split DNS, where only specified domains are merged into the existing config. It also documents the removal idiom (set to null) and the empty-array case. However, it does not explicitly point to set_split_dns as the alternative for full replacement, leaving the when-not contrast mostly implicit.

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

tailscale_update_tailnet_settingsUpdate tailnet settingsB
Idempotent

Update tailnet settings (device approval, auto-updates, key expiry, HTTPS certificates, network flow logging, regional routing, posture identity collection).

ParametersJSON Schema
NameRequiredDescriptionDefault
httpsEnabledNoWhether HTTPS certificates are enabled (for tailscale serve/funnel)
usersApprovalOnNoWhether user approval is required
aclsExternalLinkNoURL to the external ACL management system (shown in the admin console)
devicesApprovalOnNoWhether device approval is required
regionalRoutingOnNoWhether regional routing is enabled
devicesAutoUpdatesOnNoWhether auto-updates are enabled
networkFlowLoggingOnNoWhether network flow logging is enabled
devicesKeyDurationDaysNoKey expiry duration in days
aclsExternallyManagedOnNoWhether ACLs are externally managed (e.g. via GitOps)
postureIdentityCollectionOnNoWhether posture identity collection is enabled
usersRoleAllowedToJoinExternalTailnetsNoWhich user roles can join external tailnets

TDQS

B3.1/5.0
Behavior3/5

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

Annotations already declare the safety profile (readOnlyHint=false, idempotentHint=true, destructiveHint=false, openWorldHint=true), so the agent knows this is a safe, repeatable mutation. The description adds no behavioral context beyond the field list — notably it never states whether this is a partial merge (only supplied fields change) or a full replacement, which is the single most consequential behavior for an all-optional 11-param update.

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

Conciseness4/5

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

A single front-loaded sentence with the verb+resource first and the affected areas second; efficient and skimmable. The parenthetical enumeration is somewhat redundant against a 100%-covered schema, costing it the top score.

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

Completeness2/5

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

For an 11-parameter, zero-required mutation tool with no output schema, the description omits the crucial partial-update semantics (are omitted fields left unchanged or reset?) and any authorization requirement. An agent could call it correctly only by guessing at the merge behavior.

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 description coverage is 100%, so the schema already documents every parameter and the baseline is 3. The parenthetical list of setting categories is largely redundant with the schema's own descriptions and does not add format, defaulting, or interaction semantics.

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

Purpose4/5

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

Specific verb+resource ('Update tailnet settings') with an enumerated list of the setting categories affected, which cleanly separates it from the read-only sibling tailscale_get_tailnet_settings. It stops short of naming that sibling explicitly, so it is clear but not sibling-differentiating.

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 when-to-use guidance, no prerequisites (e.g. admin/owner permissions), and no mention of the paired tailscale_get_tailnet_settings for reading current values before mutating. The usage context is left entirely to inference from the name.

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

tailscale_update_user_roleUpdate user roleB
Idempotent

Update a user's role in the tailnet.

ParametersJSON Schema
NameRequiredDescriptionDefault
roleYesThe new role to assign
userIdYesThe user ID

TDQS

B3.1/5.0
Behavior2/5

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

Annotations declare readOnlyHint=false, openWorldHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds no behavioral context beyond the annotations, such as permission requirements (e.g., needing owner/admin privileges) or the effect of changing a role.

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, efficient sentence with no wasted words and is front-loaded with the action and resource.

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

Completeness3/5

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

Given the tool's moderate complexity (2 required parameters, one enum, no output schema) and the presence of annotations covering safety, the description is minimally adequate. It lacks guidance on usage context and behavioral nuances like permission requirements, which would be helpful for an agent.

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 description coverage is 100%, with role having an enum of 7 values and userId described. The description adds no parameter meaning beyond what the schema provides, so the baseline score of 3 applies.

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

Purpose4/5

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

The description states a specific verb and resource: 'Update a user's role in the tailnet.' This clearly distinguishes it from related user-management siblings like tailscale_suspend_user, tailscale_approve_user, and tailscale_delete_user. However, it doesn't explicitly name or differentiate itself from those alternatives.

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?

There is no guidance on when to use this tool versus alternatives such as tailscale_approve_user or tailscale_suspend_user, nor any prerequisites or exclusions. The agent is left to infer usage from the tool name and description.

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

tailscale_update_webhookUpdate webhookA
Idempotent

Update an existing webhook's endpoint URL and/or subscriptions.

ParametersJSON Schema
NameRequiredDescriptionDefault
webhookIdYesThe webhook ID to update
endpointUrlNoNew HTTPS URL to send webhook events to
subscriptionsNoUpdated list of event types to subscribe to (at least one). 'categoryTailnetManagement' and 'categoryDeviceMisconfigurations' subscribe to a whole category, including events Tailscale adds to it later.

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already convey that this is not read-only, is idempotent, and is not destructive, so the description does not need to restate those facts. It adds only a weak hint of partial update via 'and/or' and does not explain whether omitted fields are preserved or what the response looks like, though the annotations lower the burden here.

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 sentence, front-loaded with the action and resource, and contains no filler or redundant information. Every word contributes to understanding what the tool does.

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

Completeness3/5

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

For a simple three-parameter update tool with annotations covering safety, the definition is mostly adequate. However, it does not clarify partial-update behavior when only webhookId is provided, and with no output schema the agent cannot anticipate the return shape.

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 description coverage is 100%, and the schema already documents webhookId, endpointUrl, and subscriptions thoroughly. The description's mention of 'endpoint URL and/or subscriptions' adds no meaning beyond what the schema provides, so the baseline score of 3 is appropriate.

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

Purpose4/5

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

The description clearly states the action ('Update'), the resource ('existing webhook'), and the exact fields in scope ('endpoint URL and/or subscriptions'). It is distinct from create/delete by saying 'existing', though it does not explicitly name sibling tools to differentiate from.

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

Usage Guidelines3/5

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

The verb and resource imply this tool is for modifying an existing webhook rather than creating, listing, testing, or rotating one. However, it provides no explicit when-to-use/when-not-to-use guidance and does not reference alternatives like tailscale_create_webhook or tailscale_delete_webhook.

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

tailscale_validate_aclValidate ACL policyA
Read-onlyIdempotent

Validate an ACL policy without applying it. Returns any errors found, or confirms the policy is valid.

ParametersJSON Schema
NameRequiredDescriptionDefault
policyYesThe full ACL policy text to validate

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds value by disclosing the return behavior (errors found or valid confirmation), which matters since no output schema exists, though it does not say whether validation is syntactic only or checked against live tailnet state.

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 short sentences with zero filler; the non-mutating scope is front-loaded before the return-value statement. Nothing can be trimmed without losing meaning.

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 one-parameter, read-only validation tool with annotations covering safety and a description covering the return outcome, this is nearly complete. The only gap is not clarifying whether validation is purely syntactic or evaluated against current tailnet configuration.

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 description coverage is 100% and the single 'policy' parameter is documented as 'The full ACL policy text to validate'. The description adds nothing beyond the schema, so the baseline 3 applies for a fully documented single-parameter tool.

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?

States a specific verb (validate) and resource (ACL policy) and adds the critical scope qualifier 'without applying it', which separates it from the mutating siblings tailscale_update_acl and tailscale_set_* tools. An agent can tell this is a non-mutating check without opening the schema.

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

Usage Guidelines3/5

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

The phrase 'without applying it' implies the intended use case (check a policy before committing it), but there is no explicit when-to-use guidance or routing against close siblings such as tailscale_preview_acl, tailscale_diff_acl_access, or tailscale_get_acl. Usage is inferable rather than stated.

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

tailscale_validate_aws_trust_policyValidate AWS trust policyA
Read-onlyIdempotent

Validate that an AWS IAM role trust policy is correctly configured with the Tailscale external ID. Use this after setting up the IAM role for S3 log streaming.

ParametersJSON Schema
NameRequiredDescriptionDefault
roleArnYesThe AWS IAM role ARN to validate against
externalIdYesThe AWS external ID to validate

TDQS

A3.8/5.0
Behavior3/5

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

Annotations already declare this as a read-only, idempotent, non-destructive, open-world operation, so the safety profile is covered. The description adds useful workflow context by tying it to the S3 log streaming setup, but omits what the validation actually returns (pass/fail, error detail) and any auth prerequisites.

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 tightly written sentences: purpose first, usage trigger second. Nothing is redundant and the key information is front-loaded.

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 simple two-parameter read-only validation tool with full schema coverage and clear annotations, the description is nearly complete. The only mild gap is that it doesn't hint at the shape of the validation result, though no output schema exists.

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 description coverage is 100% – both roleArn and externalId are documented in the schema itself. The description adds no syntax or format detail beyond that, so the baseline of 3 applies.

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

Purpose4/5

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

States a specific verb (Validate) and a specific resource (AWS IAM role trust policy), plus the exact thing being checked (correct configuration with the Tailscale external ID). It's clear, though it doesn't explicitly differentiate itself from the adjacent tailscale_create_aws_external_id sibling.

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?

'Use this after setting up the IAM role for S3 log streaming' gives a concrete lifecycle trigger for when to invoke it. It stops short of naming alternatives or stating when not to use it, so it's clear context without full exclusion guidance.

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.

  1. 36 tool updatesv0.21.0
    • Changedtailscale_authorize_device1 field changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID to authorize"New value: +"The device ID to authorize. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
    • Changedtailscale_batch_update_posture_attributes1 field changed
      • changedInput schema / properties / nodes / description
        Previous value: -"Map of device ID to attribute config map (e.g. { \"12345\": { \"custom:compliant\": { \"value\": \"true\" } }, \"67890\": { \"custom:compliant\": { \"value\": false, \"expiry\": \"2026-12-01T00:00:00Z\" } } }). Pass null as the config to delete an attribute."New value: +"Map of device ID to attribute config map (e.g. { \"nPM2KNuedB21DEVEL\": { \"custom:compliant\": { \"value\": \"true\" } }, \"nPpz3VEKzX11DEVEL\": { \"custom:compliant\": { \"value\": false, \"expiry\": \"2026-12-01T00:00:00Z\" } } }). Keys are device IDs, nodeIds preferred. Pass null as the config to delete an attribute."
    • Changedtailscale_create_aws_external_id1 field changed
      • addedInput schema / properties / reusable
        Added value: +{
        +  "description": "Default true: Tailscale returns the SAME external ID on repeat calls until that ID has been linked to an AWS account, so asking again does not invalidate the ID already pasted into an IAM trust policy. Set false to force a fresh ID (what Tailscale's Terraform provider does, one ID per resource).",
        +  "type": "boolean"
        +}
    • Changedtailscale_create_device_invite1 field changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID to create an invite for"New value: +"The device ID to create an invite for. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
    • Changedtailscale_create_key1 field changed
      • changedInput schema / properties / scopes / description
        Previous value: -"(client/federated) OAuth scopes to grant (e.g. ['devices:read', 'dns', 'acl'])"New value: +"(client/federated) OAuth scopes to grant (e.g. ['devices:core:read', 'dns:read']). Use the current scope names listed at https://tailscale.com/kb/1623/trust-credentials#scopes; the pre-2024 names such as 'devices:read' and 'acl' are legacy."
    • Changedtailscale_create_oauth_app1 field changed
      • changedInput schema / properties / scopes / description
        Previous value: -"Scopes to grant. Currently 'auth_keys:create:once' is the supported value."New value: +"Scopes to grant. Use 'auth_keys:create:once', the scope the device-provisioning guide documents; the API reference's example shows 'auth_keys:create'. Not restricted here."
    • Changedtailscale_create_org_tailnet1 field changed
      • changedInput schema / properties / displayName / description
        Previous value: -"Human-readable name for the new tailnet"New value: +"Human-readable name for the new tailnet. May contain letters, numbers, spaces, apostrophes and hyphens, and must be unique within the organization."
    • Changedtailscale_create_posture_integration3 fields changed
      • changedInput schema / properties / clientId / description
        Previous value: -"Client ID for the provider (Intune: application UUID; Falcon/Jamf Pro: client id; Fleet/Huntress/Kandji/Kolide/Sentinel One: leave blank)"New value: +"Client ID for the provider (Intune: application UUID; Falcon/Jamf Pro: client id; Kandji/Kolide/Sentinel One: leave blank). Fleet and Huntress: Tailscale does not document how their credentials map onto these API fields -- the admin console asks for a Fleet URL + API token (Fleet) and an API key + API secret, plus an optional organization ID (Huntress). Do not assume this can be left blank; confirm the mapping first."
      • changedInput schema / properties / cloudId / description
        Previous value: -"Identifies which of the provider's clouds to integrate with. Falcon: us-1|us-2|eu-1|us-gov; Intune: global|us-gov; Jamf Pro/Kandji/Sentinel One: FQDN of your subdomain; Kolide: leave blank."New value: +"Identifies which of the provider's clouds to integrate with. Falcon: us-1|us-2|eu-1|us-gov; Intune: global|us-gov; Jamf Pro/Kandji/Sentinel One: FQDN of your subdomain; Kolide: leave blank. Fleet/Huntress: undocumented upstream (see clientId)."
      • changedInput schema / properties / tenantId / description
        Previous value: -"Microsoft Intune directory (tenant) ID. Other providers leave blank."New value: +"Microsoft Intune directory (tenant) ID. Other providers leave blank. Fleet/Huntress: undocumented upstream (see clientId)."
    • Changedtailscale_create_webhook3 fields changed
      • addedInput schema / properties / providerType
        Added value: +{
        +  "description": "Format deliveries for a chat provider's incoming-webhook URL. Omit for raw Tailscale JSON -- the default, and what a custom receiver verifying signatures wants. Set once: it cannot be changed after creation.",
        +  "enum": [
        +    "slack",
        +    "mattermost",
        +    "googlechat",
        +    "discord"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / subscriptions / description
        Previous value: -"Event types to subscribe to (at least one)"New value: +"Event types to subscribe to (at least one). 'categoryTailnetManagement' and 'categoryDeviceMisconfigurations' subscribe to a whole category, including events Tailscale adds to it later."
      • changedInput schema / properties / subscriptions / items / enum
        Previous value: -[
        -  "exitNodeIPForwardingNotEnabled",
        -  "nodeApproved",
        -  "nodeCreated",
        -  "nodeDeleted",
        -  "nodeKeyExpired",
        -  "nodeKeyExpiringInOneDay",
        -  "nodeNeedsApproval",
        -  "nodeNeedsSignature",
        -  "nodeSigned",
        -  "policyUpdate",
        -  "subnetIPForwardingNotEnabled",
        -  "userApproved",
        -  "userCreated",
        -  "userDeleted",
        -  "userNeedsApproval",
        -  "userRestored",
        -  "userRoleUpdated",
        -  "userSuspended"
        -]New value: +[
        +  "categoryDeviceMisconfigurations",
        +  "categoryTailnetManagement",
        +  "exitNodeIPForwardingNotEnabled",
        +  "nodeApproved",
        +  "nodeCreated",
        +  "nodeDeleted",
        +  "nodeKeyExpired",
        +  "nodeKeyExpiringInOneDay",
        +  "nodeNeedsApproval",
        +  "nodeNeedsSignature",
        +  "nodeSigned",
        +  "policyUpdate",
        +  "subnetIPForwardingNotEnabled",
        +  "userApproved",
        +  "userCreated",
        +  "userDeleted",
        +  "userNeedsApproval",
        +  "userRestored",
        +  "userRoleUpdated",
        +  "userSuspended"
        +]
    • Changedtailscale_deauthorize_device1 field changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID to deauthorize"New value: +"The device ID to deauthorize. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
    • Changedtailscale_delete_device1 field changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID to delete"New value: +"The device ID to delete. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
    • Changedtailscale_delete_device_posture_attribute1 field changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID"New value: +"The device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
    • Changedtailscale_delete_key1 field changed
      • changedInput schema / properties / keyId / description
        Previous value: -"The key ID to delete (auth key, OAuth client, or federated identity)"New value: +"The key ID to delete (auth key, API access token, OAuth client, or federated identity)"
    • Changedtailscale_expire_device1 field changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID to expire"New value: +"The device ID to expire. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
    • Changedtailscale_get_audit_log4 fields changed
      • addedInput schema / properties / actor
        Added value: +{
        +  "description": "Server-side filter: one exact actor ID, or '~text' to wildcard-match a login or display name (e.g. '~bob'). One value per call -- how the API reads a repeated filter key is not verified yet.",
        +  "items": {
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 1,
        +  "type": "array"
        +}
      • changedInput schema / properties / end / description
        Previous value: -"End time in RFC3339 format. Defaults to now."New value: +"End time in RFC3339 format. Optional: when omitted the tool sends the current time, which Tailscale's API requires."
      • addedInput schema / properties / event
        Added value: +{
        +  "description": "Server-side filter: one event type from Tailscale's audit event list, e.g. 'TAILNET.UPDATE.ACL', 'TAILNET.UPDATE.DNS_CONFIG', 'NODE.CREATE', 'NODE.DELETE', 'API_KEY.CREATE', 'USER.UPDATE.USER_ROLE', 'WEBHOOK_ENDPOINT.CREATE'. Not a closed set -- the list keeps growing. One value per call, as for actor.",
        +  "items": {
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 1,
        +  "type": "array"
        +}
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "Server-side filter: one string, matched against any part of any of an entry's targets (ID or name). One value per call, as for actor.",
        +  "items": {
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 1,
        +  "type": "array"
        +}
    • Changedtailscale_get_device2 fields changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID (numeric id or nodeId, NOT the nodeKey)"New value: +"The device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
      • addedInput schema / properties / fields
        Added value: +{
        +  "description": "Which device fields to return. Tailscale documents exactly two values. 'default' (also what you get when this is omitted) is the limited set: addresses, id, nodeId, user, name, hostname, clientVersion, updateAvailable, os, created, connectedToControl, lastSeen, keyExpiryDisabled, expires, authorized, isExternal, machineKey, nodeKey, blocksIncomingConnections, tailnetLockKey, tailnetLockError, tags, isEphemeral. 'all' adds advertisedRoutes, enabledRoutes, clientConnectivity (endpoints, DERP latency), sshEnabled, distro, multipleConnections and postureIdentity (serial numbers and, where a posture integration collects them, hardware/MAC addresses). Omitting it does NOT return everything.",
        +  "enum": [
        +    "all",
        +    "default"
        +  ],
        +  "type": "string"
        +}
    • Changedtailscale_get_device_posture_attributes1 field changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID"New value: +"The device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
    • Changedtailscale_get_device_routes1 field changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID"New value: +"The device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
    • Changedtailscale_get_key1 field changed
      • changedInput schema / properties / keyId / description
        Previous value: -"The key ID (auth key, OAuth client, or federated identity)"New value: +"The key ID (auth key, API access token, OAuth client, or federated identity)"
    • Changedtailscale_get_network_flow_logs1 field changed
      • changedInput schema / properties / end / description
        Previous value: -"End time in RFC3339 format. Defaults to now."New value: +"End time in RFC3339 format. Optional: when omitted the tool sends the current time, which Tailscale's API requires."
    • Changedtailscale_get_service_device_approval1 field changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID"New value: +"The device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
    • Changedtailscale_list_device_invites1 field changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID to list invites for"New value: +"The device ID to list invites for. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
    • Changedtailscale_list_devices4 fields changed
      • changedInput schema / properties / fields / description
        Previous value: -"Comma-separated list of fields to include. Omit for all fields. Valid fields: addresses, advertisedRoutes, authorized, blocksIncomingConnections, clientConnectivity, clientVersion, connectedToControl, created, distro, enabledRoutes, expires, hostname, id, isExternal, keyExpiryDisabled, lastSeen, machineKey, name, nodeId, nodeKey, os, sshEnabled, tags, tailnetLockError, tailnetLockKey, updateAvailable, user. Use 'all' for every field."New value: +"Which device fields to return. Tailscale documents exactly two values. 'default' (also what you get when this is omitted) is the limited set: addresses, id, nodeId, user, name, hostname, clientVersion, updateAvailable, os, created, connectedToControl, lastSeen, keyExpiryDisabled, expires, authorized, isExternal, machineKey, nodeKey, blocksIncomingConnections, tailnetLockKey, tailnetLockError, tags, isEphemeral. 'all' adds advertisedRoutes, enabledRoutes, clientConnectivity (endpoints, DERP latency), sshEnabled, distro, multipleConnections and postureIdentity (serial numbers and, where a posture integration collects them, hardware/MAC addresses). Omitting it does NOT return everything. Any other value is forwarded unvalidated; Tailscale documents none."
      • addedInput schema / properties / filters / additionalProperties / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "items": {
        +      "type": "string"
        +    },
        +    "minItems": 1,
        +    "type": "array"
        +  }
        +]
      • removedInput schema / properties / filters / additionalProperties / type
        Removed value: -"string"
      • changedInput schema / properties / filters / description
        Previous value: -"Server-side filters as key-value pairs. Filter by any top-level device property (e.g. { isEphemeral: 'true', os: 'linux', tags: 'tag:prod' }). Multiple filters are ANDed together."New value: +"Server-side filters on top-level device properties, exact match only (e.g. { isEphemeral: 'true', os: 'linux' }). All filters are ANDed. Pass an array to repeat a key: { tags: ['tag:prod', 'tag:subnetrouter'] } sends tags=..&tags=.. and matches devices whose tags contain BOTH. Properties that are complex objects (e.g. clientConnectivity) cannot be filtered; repeating a key on a non-list property is undocumented upstream."
    • Changedtailscale_list_keys1 field changed
      • changedInput schema / properties / all / description
        Previous value: -"When true, returns all key types (auth keys, OAuth clients, federated identities). Default: false"New value: +"When true, list keys tailnet-wide instead of the credential-dependent default set. Default: false"
    • Changedtailscale_rename_device2 fields changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID to rename"New value: +"The device ID to rename. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
      • changedInput schema / properties / name / description
        Previous value: -"The new name for the device (FQDN within your tailnet)"New value: +"New device name: the FQDN (e.g. 'nodename.your-tailnet.ts.net') or just the base name (e.g. 'nodename'). Pass an empty string to reset the name to one generated from the OS hostname (per Tailscale's API spec)."
    • Changedtailscale_set_device_ip1 field changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID"New value: +"The device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
    • Changedtailscale_set_device_posture_attribute4 fields changed
      • changedInput schema / properties / attributeKey / description
        Previous value: -"The attribute key (must start with 'custom:', e.g. 'custom:lastAuditDate')"New value: +"The attribute key (must start with 'custom:', e.g. 'custom:lastAuditDate'). Max 128 characters including the prefix; letters, numbers, underscores and colons only. Keys are case-sensitive but are checked for uniqueness case-insensitively, so 'custom:MyAttribute' and 'custom:myattribute' cannot both exist in one tailnet."
      • addedInput schema / properties / comment
        Added value: +{
        +  "description": "Optional comment added to the audit log explaining why the attribute is being set (max 200 chars)",
        +  "maxLength": 200,
        +  "type": "string"
        +}
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID"New value: +"The device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
      • changedInput schema / properties / value / description
        Previous value: -"The attribute value (string, number, or boolean)"New value: +"The attribute value: a string (max 50 characters, letters, numbers, underscores and periods only), an integer number (JSON-safe, up to 2^53-1), or a boolean. The type is fixed by the first value written for a key -- every device's value for that key must then be the same type."
    • Changedtailscale_set_device_routes1 field changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID"New value: +"The device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
    • Changedtailscale_set_device_tags1 field changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID"New value: +"The device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
    • Changedtailscale_set_devices_authorized1 field changed
      • changedInput schema / properties / deviceIds / description
        Previous value: -"Device IDs to update"New value: +"Device IDs to update (nodeIds preferred; legacy numeric ids also work)"
    • Changedtailscale_set_service_device_approval1 field changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID"New value: +"The device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
    • Changedtailscale_set_split_dns4 fields changed
      • addedInput schema / properties / splitDns / additionalProperties / anyOf
        Added value: +[
        +  {
        +    "items": {
        +      "type": "string"
        +    },
        +    "type": "array"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedInput schema / properties / splitDns / additionalProperties / items
        Removed value: -{
        -  "type": "string"
        -}
      • removedInput schema / properties / splitDns / additionalProperties / type
        Removed value: -"array"
      • changedInput schema / properties / splitDns / description
        Previous value: -"Map of domain to nameserver list (e.g. { \"corp.example.com\": [\"10.0.0.1\"], \"internal.dev\": [\"10.0.0.2\"] })"New value: +"Map of domain to nameserver list, or to null to clear that domain (e.g. { \"corp.example.com\": [\"10.0.0.1\"], \"old.example.com\": null })"
    • Changedtailscale_update_acl1 field changed
      • changedInput schema / properties / etag / description
        Previous value: -"The ETag from tailscale_get_acl. Required to prevent concurrent edit conflicts."New value: +"The ETag from tailscale_get_acl (quotes optional -- they are normalized). Required to prevent concurrent edit conflicts. For the FIRST write to a fresh tailnet you may pass `ts-default` instead: the update then succeeds only if the policy file is still Tailscale's untouched default."
    • Changedtailscale_update_device_key1 field changed
      • changedInput schema / properties / deviceId / description
        Previous value: -"The device ID"New value: +"The device ID. nodeId from tailscale_list_devices (e.g. nPM2KNuedB21DEVEL); numeric id ok; not the nodeKey."
    • Changedtailscale_update_split_dns4 fields changed
      • addedInput schema / properties / splitDns / additionalProperties / anyOf
        Added value: +[
        +  {
        +    "items": {
        +      "type": "string"
        +    },
        +    "type": "array"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedInput schema / properties / splitDns / additionalProperties / items
        Removed value: -{
        -  "type": "string"
        -}
      • removedInput schema / properties / splitDns / additionalProperties / type
        Removed value: -"array"
      • changedInput schema / properties / splitDns / description
        Previous value: -"Map of domain to nameserver list to merge (e.g. { \"new.example.com\": [\"10.0.0.3\"] }). Only specified domains are changed."New value: +"Map of domain to nameserver list to merge, or to null to remove that domain (e.g. { \"new.example.com\": [\"10.0.0.3\"], \"old.example.com\": null }). Only specified domains are changed."
    • Changedtailscale_update_webhook2 fields changed
      • changedInput schema / properties / subscriptions / description
        Previous value: -"Updated list of event types to subscribe to (at least one)"New value: +"Updated list of event types to subscribe to (at least one). 'categoryTailnetManagement' and 'categoryDeviceMisconfigurations' subscribe to a whole category, including events Tailscale adds to it later."
      • changedInput schema / properties / subscriptions / items / enum
        Previous value: -[
        -  "exitNodeIPForwardingNotEnabled",
        -  "nodeApproved",
        -  "nodeCreated",
        -  "nodeDeleted",
        -  "nodeKeyExpired",
        -  "nodeKeyExpiringInOneDay",
        -  "nodeNeedsApproval",
        -  "nodeNeedsSignature",
        -  "nodeSigned",
        -  "policyUpdate",
        -  "subnetIPForwardingNotEnabled",
        -  "userApproved",
        -  "userCreated",
        -  "userDeleted",
        -  "userNeedsApproval",
        -  "userRestored",
        -  "userRoleUpdated",
        -  "userSuspended"
        -]New value: +[
        +  "categoryDeviceMisconfigurations",
        +  "categoryTailnetManagement",
        +  "exitNodeIPForwardingNotEnabled",
        +  "nodeApproved",
        +  "nodeCreated",
        +  "nodeDeleted",
        +  "nodeKeyExpired",
        +  "nodeKeyExpiringInOneDay",
        +  "nodeNeedsApproval",
        +  "nodeNeedsSignature",
        +  "nodeSigned",
        +  "policyUpdate",
        +  "subnetIPForwardingNotEnabled",
        +  "userApproved",
        +  "userCreated",
        +  "userDeleted",
        +  "userNeedsApproval",
        +  "userRestored",
        +  "userRoleUpdated",
        +  "userSuspended"
        +]
  2. 5 tool updatesv0.19.1
    • Changedtailscale_create_device_invite1 field changed
      • changedInput schema / properties / email / pattern
        Previous value: -"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"New value: +"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
    • Changedtailscale_create_user_invite1 field changed
      • changedInput schema / properties / email / pattern
        Previous value: -"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"New value: +"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
    • Addedtailscale_diff_acl_access
    • Changedtailscale_set_contacts3 fields changed
      • changedInput schema / properties / account / properties / email / pattern
        Previous value: -"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"New value: +"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
      • changedInput schema / properties / security / properties / email / pattern
        Previous value: -"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"New value: +"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
      • changedInput schema / properties / support / properties / email / pattern
        Previous value: -"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"New value: +"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
    • Addedtailscale_tool_groups
  3. 6 tool updatesv0.18.0
    • Changedtailscale_batch_update_posture_attributes1 field changed
      • changedInput schema / properties / nodes / additionalProperties / additionalProperties / anyOf
        Previous value: -[
        -  {
        -    "properties": {
        -      "expiry": {
        -        "type": "string"
        -      },
        -      "value": {
        -        "anyOf": [
        -          {
        -            "type": "string"
        -          },
        -          {
        -            "type": "number"
        -          },
        -          {
        -            "type": "boolean"
        -          }
        -        ]
        -      }
        -    },
        -    "required": [
        -      "value"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "properties": {
        +      "expiry": {
        +        "type": "string"
        +      },
        +      "value": {
        +        "type": [
        +          "string",
        +          "number",
        +          "boolean"
        +        ]
        +      }
        +    },
        +    "required": [
        +      "value"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Addedtailscale_delete_oauth_app
    • Changedtailscale_delete_tailnet1 field changed
      • changedInput schema / properties / confirmTailnet / description
        Previous value: -"Must exactly match the effective target -- `tailnet` when given, otherwise the configured tailnet (TAILSCALE_TAILNET / TAILSCALE_OAUTH_TAILNET). A deliberate second look before an irreversible org-wide delete."New value: +"Must exactly match the effective target -- `tailnet` when given, otherwise the configured tailnet (TAILSCALE_TAILNET / TAILSCALE_OAUTH_TAILNET). A typo guard, not an authorization gate: on the explicit-`tailnet` path the caller writes both halves of the comparison, so it proves only self-agreement. It is a real second look only when `tailnet` is omitted and the value has to match the operator's environment."
    • Addedtailscale_list_oauth_apps
    • Changedtailscale_set_device_posture_attribute2 fields changed
      • removedInput schema / properties / value / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  }
        -]
      • addedInput schema / properties / value / type
        Added value: +[
        +  "string",
        +  "number",
        +  "boolean"
        +]
    • Changedtailscale_update_acl1 field changed
      • addedInput schema / properties / etag / minLength
        Added value: +1
  4. 8 tool updatesv0.17.1
    • Addedtailscale_create_oauth_app
    • Addedtailscale_create_org_tailnet
    • Changedtailscale_create_posture_integration3 fields changed
      • changedInput schema / properties / clientId / description
        Previous value: -"Client ID for the provider (Intune: application UUID; Falcon/Jamf Pro: client id; Kandji/Kolide/Sentinel One: leave blank)"New value: +"Client ID for the provider (Intune: application UUID; Falcon/Jamf Pro: client id; Fleet/Huntress/Kandji/Kolide/Sentinel One: leave blank)"
      • changedInput schema / properties / provider / description
        Previous value: -"The posture provider"New value: +"The posture provider slug: falcon (CrowdStrike Falcon), fleet, huntress, intune (Microsoft Intune), jamfpro (Jamf Pro), kandji (Iru, formerly Kandji), kolide (1Password XAM, formerly Kolide), sentinelone"
      • changedInput schema / properties / provider / enum
        Previous value: -[
        -  "falcon",
        -  "intune",
        -  "jamfpro",
        -  "kandji",
        -  "kolide",
        -  "sentinelone"
        -]New value: +[
        +  "falcon",
        +  "fleet",
        +  "huntress",
        +  "intune",
        +  "jamfpro",
        +  "kandji",
        +  "kolide",
        +  "sentinelone"
        +]
    • Changedtailscale_create_webhook1 field changed
      • addedInput schema / properties / subscriptions / items / enum
        Added value: +[
        +  "exitNodeIPForwardingNotEnabled",
        +  "nodeApproved",
        +  "nodeCreated",
        +  "nodeDeleted",
        +  "nodeKeyExpired",
        +  "nodeKeyExpiringInOneDay",
        +  "nodeNeedsApproval",
        +  "nodeNeedsSignature",
        +  "nodeSigned",
        +  "policyUpdate",
        +  "subnetIPForwardingNotEnabled",
        +  "userApproved",
        +  "userCreated",
        +  "userDeleted",
        +  "userNeedsApproval",
        +  "userRestored",
        +  "userRoleUpdated",
        +  "userSuspended"
        +]
    • Addedtailscale_delete_tailnet
    • Addedtailscale_get_oauth_app
    • Addedtailscale_list_org_tailnets
    • Changedtailscale_update_webhook1 field changed
      • addedInput schema / properties / subscriptions / items / enum
        Added value: +[
        +  "exitNodeIPForwardingNotEnabled",
        +  "nodeApproved",
        +  "nodeCreated",
        +  "nodeDeleted",
        +  "nodeKeyExpired",
        +  "nodeKeyExpiringInOneDay",
        +  "nodeNeedsApproval",
        +  "nodeNeedsSignature",
        +  "nodeSigned",
        +  "policyUpdate",
        +  "subnetIPForwardingNotEnabled",
        +  "userApproved",
        +  "userCreated",
        +  "userDeleted",
        +  "userNeedsApproval",
        +  "userRestored",
        +  "userRoleUpdated",
        +  "userSuspended"
        +]
  5. 89 tool updatesv0.13.3
    • First observedtailscale_accept_device_invite
    • First observedtailscale_approve_user
    • First observedtailscale_authorize_device
    • First observedtailscale_batch_update_posture_attributes
    • First observedtailscale_create_aws_external_id
    • First observedtailscale_create_device_invite
    • First observedtailscale_create_key
    • First observedtailscale_create_posture_integration
    • First observedtailscale_create_user_invite
    • First observedtailscale_create_webhook
    • First observedtailscale_deauthorize_device
    • First observedtailscale_delete_device
    • First observedtailscale_delete_device_invite
    • First observedtailscale_delete_device_posture_attribute
    • First observedtailscale_delete_key
    • First observedtailscale_delete_log_stream_config
    • First observedtailscale_delete_posture_integration
    • First observedtailscale_delete_service
    • First observedtailscale_delete_user
    • First observedtailscale_delete_user_invite
    • First observedtailscale_delete_webhook
    • First observedtailscale_expire_device
    • First observedtailscale_get_acl
    • First observedtailscale_get_audit_log
    • First observedtailscale_get_contacts
    • First observedtailscale_get_device
    • First observedtailscale_get_device_invite
    • First observedtailscale_get_device_posture_attributes
    • First observedtailscale_get_device_routes
    • First observedtailscale_get_dns_configuration
    • First observedtailscale_get_dns_preferences
    • First observedtailscale_get_key
    • First observedtailscale_get_log_stream_config
    • First observedtailscale_get_log_stream_status
    • First observedtailscale_get_nameservers
    • First observedtailscale_get_network_flow_logs
    • First observedtailscale_get_posture_integration
    • First observedtailscale_get_search_paths
    • First observedtailscale_get_service
    • First observedtailscale_get_service_device_approval
    • First observedtailscale_get_split_dns
    • First observedtailscale_get_tailnet_settings
    • First observedtailscale_get_user
    • First observedtailscale_get_user_invite
    • First observedtailscale_get_webhook
    • First observedtailscale_list_device_invites
    • First observedtailscale_list_devices
    • First observedtailscale_list_keys
    • First observedtailscale_list_log_stream_configs
    • First observedtailscale_list_posture_integrations
    • First observedtailscale_list_service_hosts
    • First observedtailscale_list_services
    • First observedtailscale_list_user_invites
    • First observedtailscale_list_users
    • First observedtailscale_list_webhooks
    • First observedtailscale_preview_acl
    • First observedtailscale_rename_device
    • First observedtailscale_resend_contact_verification
    • First observedtailscale_resend_device_invite
    • First observedtailscale_resend_user_invite
    • First observedtailscale_restore_user
    • First observedtailscale_rotate_webhook_secret
    • First observedtailscale_set_contacts
    • First observedtailscale_set_device_ip
    • First observedtailscale_set_device_posture_attribute
    • First observedtailscale_set_device_routes
    • First observedtailscale_set_device_tags
    • First observedtailscale_set_devices_authorized
    • First observedtailscale_set_dns_configuration
    • First observedtailscale_set_dns_preferences
    • First observedtailscale_set_log_stream_config
    • First observedtailscale_set_nameservers
    • First observedtailscale_set_search_paths
    • First observedtailscale_set_service_device_approval
    • First observedtailscale_set_split_dns
    • First observedtailscale_status
    • First observedtailscale_suspend_user
    • First observedtailscale_test_webhook
    • First observedtailscale_update_acl
    • First observedtailscale_update_device_key
    • First observedtailscale_update_key
    • First observedtailscale_update_posture_integration
    • First observedtailscale_update_service
    • First observedtailscale_update_split_dns
    • First observedtailscale_update_tailnet_settings
    • First observedtailscale_update_user_role
    • First observedtailscale_update_webhook
    • First observedtailscale_validate_acl
    • First observedtailscale_validate_aws_trust_policy

TDQS

A3.5/5.0

Scored across 98 tools

Disambiguation4/5

Most tools are clearly separated by resource and action (devices, users, ACL, DNS, services, webhooks, keys, etc.), so an agent can usually tell them apart. Some overlap exists between the unified DNS getter/setter and the individual DNS tools, and between single-device and batch operations, but the descriptions explain the distinctions. With 98 tools, a few pairs still risk misselection.

Naming Consistency4/5

Almost all tools follow the tailscale_verb_noun pattern (list_devices, create_webhook, delete_device, update_acl), which is highly consistent. Minor exceptions like tailscale_status and tailscale_tool_groups break the verb_noun pattern, and a few singular/plural mismatches (set_device_posture_attribute vs get_device_posture_attributes) keep it from being perfect.

Tool Count2/5

98 tools is far beyond the well-scoped range and even the heavy 25+ threshold. While Tailscale's API is broad, this is too many tools for one MCP server; agents will struggle to navigate the surface. Many tools could be consolidated (e.g., unified DNS vs individual DNS setters) or split into domain-specific servers.

Completeness5/5

The tool set covers essentially the full Tailscale management surface: devices, users, invites, keys, ACL, DNS, services, posture integrations, webhooks, log streaming, OAuth apps, tailnet settings, contacts, audit logs, and network flow logs. CRUD/lifecycle operations are present for each resource, and destructive operations are paired with getters/listers, leaving no obvious dead ends.

Maintenance

ActivityActive
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers

  • 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
    5 npm
    7
    MIT

Appeared in Searches