diff --git a/ROADMAP.md b/ROADMAP.md index 0b79861..ac8ca18 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -2,26 +2,70 @@ # Roadmap -**Current:** v0.1.0 +**Current:** v0.1.2 (published to npm) -## Tailscale MCP +Direction: stay the *safe, structured window into Tailscale* — dry-run defaults, explicit opt-in for anything dangerous, structured errors with remedies. Every new tool is judged against that bar before it ships. -### v0.1.x -- Foundation +Informed by [docs/research/Tailscale MCP Landscape Research.md](docs/research/Tailscale%20MCP%20Landscape%20Research.md) (July 2026). Two findings anchor the plan: the competitive field splits into local-only CLI wrappers and Admin-API-only enterprise engines — **nobody bridges both**; and **no server offers stateful dry-run pre-flights** (ACL validate/preview) even though that's exactly what agents need. Both gaps are this project's identity. -- [x] Core provider adapters -- [x] Initial tool surface +## v0.1.x — Foundation (shipped) + +- [x] `TailscaleProvider` interface + `CliProvider` (injectable process runner, offline fixture-driven tests) +- [x] Error taxonomy with remedies (`BINARY_NOT_FOUND`, `DAEMON_NOT_RUNNING`, `NEEDS_LOGIN`, `SERVE_NOT_ENABLED`, `CLI_ERROR`) +- [x] Tool surface: `tailnet_status`, `generate_ssh_config`, `share_port`, `share_status`, `stop_share`, `ping_all` - [x] stdio transport -- [ ] CI/CD workflows -- [ ] GitHub Pages documentation site +- [x] CI/CD: build+test matrix (Node 20/22), tag-and-release, npm publish with provenance +- [x] GitHub Pages documentation site, community files, issue/PR templates, security policy + +## v0.2.0 — Annotations + local surface expansion + +No new credentials, no new trust boundary. Highest value-per-effort items first. + +- [ ] **Tool annotations on every tool** (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`). The spec treats unannotated tools as destructive/non-idempotent, and Claude Code uses `readOnlyHint` as a concurrency signal — today our read-only tools are being serialized and over-confirmed for no reason. Cheap, immediate, ships first. +- [ ] **LocalAPI provider — narrow scope**: `/localapi/v0/status` and `/localapi/v0/whois` only. These are the two high-stability endpoints (the CLI and GUIs depend on them); the LocalAPI as a whole is officially unstable, so `CliProvider` remains the default for everything else and the fallback for these. Platform IPC handled natively: Unix socket (Linux), ACL'd named pipe (Windows), sameuserproof (macOS). +- [ ] **`whois` tool** — resolve a tailnet IP to node + user identity ("who is hitting my shared port"); also the building block for identity-gated tools in v0.4 +- [ ] **`exit_node` tools** — list advertised exit nodes; set/clear the active exit node (mutating: structured before/after state in the response) +- [ ] **`netcheck`** — DERP region latency, preferred relay, NAT detail; complements `ping_all` for "why is this path relayed" +- [ ] **`dns_status`** — MagicDNS config, resolvers, search domains +- [ ] Serve improvements: TCP forwarding mode, multiple simultaneous shares, `share_port` idempotency (re-share same port updates instead of erroring) +- [ ] Taildrop `send_file` via CLI (`tailscale file cp`); receive deferred — the `file-put` LocalAPI path is medium-stability and sandbox-entangled + +## v0.3.0 — Admin API bridge (opt-in) + +A new trust boundary: the Admin API needs OAuth client credentials. Everything here is **off unless credentials are provided via env** (`TS_API_CLIENT_ID`/`TS_API_CLIENT_SECRET`), scoped least-privilege, never logged or echoed. This is the "unified local + Admin API" gap no competitor fills. + +- [ ] **`AdminApiProvider`** with documented least-privilege scope recipes per use case (read-only monitoring: `devices:core:read` + `dns:read`; GitOps validation: `policy_file:read`; provisioning: `auth_keys` with tag-locked OAuth client) +- [ ] Rate-limit resilience: honor `429`/`Retry-After` with exponential backoff + jitter; `TAILSCALE_MAX_CONCURRENT` cap +- [ ] Device management tools: list all tailnet devices (not just peers), authorize, rename, set tags, key-expiry status +- [ ] **ACL dry-run pre-flight tools** — `acl_validate` / `acl_preview`: review a proposed policy change and see which connections it would affect, *before* any human applies it. No server in the landscape offers this; it is the flagship v0.3 feature. Still no blind ACL writes — ever. +- [ ] Scoped auth-key creation (ephemeral, preauthorized, tag-inheriting via tag-locked OAuth client) +- [ ] Permission tiers via env: `TAILSCALE_MCP_READONLY=1`, `TAILSCALE_MCP_ALLOW_FUNNEL=0`, risk-level gate checked before every mutating tool + +## v0.4.0 — Agentic ergonomics + identity-gated execution + +- [ ] **Capability-grant authorization**: resolve the caller's identity via `whois` and check application capability grants in the tailnet ACL policy before executing privileged tools — the published mitigation for the confused-deputy problem (unprivileged user driving a privileged agent) +- [ ] MCP **resources**: `tailnet://status`, `tailnet://peers/` (Claude Desktop and Claude Code both render these fully) +- [ ] MCP **prompts**: canned workflows ("diagnose connectivity to ", "share this dev server with the team") +- [ ] Progress notifications for long ops (`ping_all` over large tailnets) — Claude Code renders text tickers; other clients ignore them, so this is progressive enhancement only + +## v1.0.0 — Stable + distribution + +- [ ] Full test coverage incl. Windows + macOS CI runners (named pipe vs unix socket vs sameuserproof paths) +- [ ] Integration-test harness: fixture capture tooling against a real tailnet, sanitizer included +- [ ] Complete docs site: per-tool reference, security model page, provider architecture +- [ ] Semver commitment; documented tool-schema stability policy +- [ ] **Distribution beyond npm**: signed Docker image with SBOM (Docker MCP Catalog requirement), Smithery listing, mcp.so, standalone binaries for Windows/macOS/Linux, one-click configs for Claude Desktop / Claude Code / Cursor -### v0.2.0 -- Expansion +## Deliberately skipped or deferred -- [ ] Additional provider adapters -- [ ] Richer tooling -- [ ] Streaming support +- **Streamable HTTP transport** — deferred. Claude Desktop and Cursor don't support it (stdio remains the universal transport); `jaxxstorm/tailscale-mcp-proxy` already bridges stdio→HTTP for those who need remote deployment. Revisit when client support lands (also a Smithery hosting prerequisite). +- **OAuth authorization-server metadata / PRM discovery** — wait; mainstream clients don't render these flows yet. +- **Elicitation** — no meaningful client support. +- **Custom dashboards/visualization** — out of lane; effort belongs in the tool execution plane. -### v1.0.0 -- Stable Release +## Explicitly out of scope -- [ ] Broader provider coverage -- [ ] Full test coverage -- [ ] Complete documentation +- Handling `TS_AUTHKEY` or any node credential — the daemon owns auth +- ACL **writes** — validate/preview only; too much blast radius for an agent tool +- Anything that silently widens exposure (Funnel stays opt-in with warnings, forever) +- Competing on tool count (one competitor ships 89+ Admin API tools) — the differentiator is safety architecture, not surface area diff --git a/docs/research/Tailscale MCP Landscape Research.md b/docs/research/Tailscale MCP Landscape Research.md new file mode 100644 index 0000000..bbbb1dd --- /dev/null +++ b/docs/research/Tailscale MCP Landscape Research.md @@ -0,0 +1,371 @@ +# **Architectural and Landscape Analysis: Tailscale Model Context Protocol Integration** + +The rapid evolution of the Model Context Protocol (MCP) as an open standard for connecting large language models to secure computational environments has introduced new paradigms for infrastructure automation1. For integrations interfacing directly with enterprise virtual private networks, such as those powered by the Tailscale daemon, the architectural requirements have shifted from simple local command-line execution interfaces to robust, identity-aware systems3. This report provides a detailed, production-grade landscape analysis and technical assessment to guide the development of @tmhs/tailscale-mcp from its initial CLI-wrapping design toward a highly secure, enterprise-ready 1.0 architecture3. + +## **Executive Summary: Strategic Directives** + +* **The Transition from CLI to REST-Based Client Libraries:** Competitors have moved beyond executing shell commands, adopting full coverage of the Tailscale Admin API via typed Go and TypeScript SDKs3. Continuing to wrap the local tailscale CLI exposes a project to breaking changes in string output and limits execution to a single local machine3. +* **Decoupled Multi-Platform Network Access:** Rather than restricting the integration to a local machine's tailscaled instance, mature implementations deploy as containerized network sidecars or remote services4. This shift leverages Tailscale's cryptographic identity layer to authorize requests without exposing raw API keys to developer environments8. +* **Operating System Isolation and Platform Sockets:** Directly interfacing with the local daemon requires handling fragmented IPC mechanisms across operating systems10. Unix sockets on Linux10, ACL-restricted named pipes on Windows12, and sandboxed basic authentication challenges on macOS must be handled natively to avoid security and execution failures13. +* **Performance Optimization via Concurrency Annotations:** Modern MCP hosts, particularly Claude Code, do not treat tool metadata merely as optional text14. The host uses the readOnlyHint property as a strict concurrency signal, parallelizing read operations while sequentially executing any tools where the hint is omitted14. +* **Identity-Driven Tool Permissions:** Security boundaries are shifting toward checking permissions directly against the centralized tailnet Access Control List (ACL) policy using application capability grants16. This pattern mitigates the confused-deputy problem by checking if a user has permission to execute a specific tool before running the request16. + +## **1\. Competitive Landscape** + +The competitive landscape of Tailscale-specific Model Context Protocol implementations is defined by a clear divide between local, single-user diagnostic utilities and highly integrated, enterprise-scale management engines3. The table below outlines the actively maintained implementations discovered across registries and source code platforms, detailing their tool coverage, underlying integration mechanisms, security models, and adoption statistics. + +### **Competitive Matrix** + +| Implementation Name | Target Environment | Integration Interface | Tool Surface Area | Authentication Model | Star & Download Traction | Last Release & Status | License | +| :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | +| **@yawlabs/tailscale-mcp** \[cite: 3\] | Enterprise Tailnets & Multi-Client3 | Admin API v2 & Local CLI3 | 89+ Admin-API tools, 4 opt-in CLI diagnostics, 4 resources3 | OAuth Client Credentials & API Keys; Rate-Limit Retry3 | Active; 24 stars18 | Mid-2026; Highly Active18 | MIT18 | +| **pnocera/tailscale-mcp-server** \[cite: 4\] | Dockerized Infrastructure4 | Official Go Client v24 | 42 comprehensive tools4 | API Key or OAuth Client Credentials with fallback4 | Emerging; 2 stars4 | Mid-2026; Active4 | MIT4 | +| **jaxxstorm/tailscale-mcp** \[cite: 16\] | Stdio/HTTP Developers16 | Admin API v2 Client16 | Devices, policy files, and tailnet settings16 | API Key with Tailscale ACL OAuth Grant validation16 | Stable fork19 | Late 2025; Stable | Open Source | +| **aplaceforallmystuff/mcp-tailscale** \[cite: 20\] | Claude Code / CLI Users20 | Read-Only REST API20 | 6 Read-only device & update status tools20 | Static API Key20 | Small; 6 stars20 | Mid-2026; Active20 | MIT20 | +| **sandraschi/tailscale-mcp** \[cite: 21, 22\] | Python FastMCP Pipelines21 | FastMCP & Admin API21 | Portmanteau operations & agentic workflows21 | Static API Key with Prometheus monitoring21 | Specialized21 | Mid-2026; Experimental22 | Open Source | +| **paulsmith/tailscale-mcp-server** \[cite: 5, 24\] | Local Desktop Clients5 | CLI Binary Wrapping5 | 8 Safe local CLI subcommands & 3 prompts5 | Implicit; relies on local active account permissions5 | Small; Draft status5 | Late 2025; Maintenance | Open Source | + +The architectural trend highlights that premium tools have moved away from local command wrapping3. They now favor typed, Zod-validated schemas that map directly to the Tailscale OpenAPI spec, avoiding the fragility of parsing CLI stdout3. + +### **Gap and Commoditization Analysis** + +Integrating an LLM with secure networks has progressed past basic diagnostics, turning many early features into standard, commoditized expectations. + +| Commoditized Capabilities (Standard Baseline) | Gaps in Current Offerings (High-Value Opportunities) | +| :---- | :---- | +| **Basic Device and IP Discovery:** Listing online nodes is a universal feature5. | **Stateful Dry-Run Pre-flights:** No server leverages Tailscale's /acl/validate or /acl/preview endpoints25 to let users review proposed ACL changes before applying them. | +| **Standard Netcheck Diagnostics:** Running basic latency checks is commoditized3. | **Bounded Capabilities via Tailnet Grants:** Implementations rarely parse the central ACL file16 to restrict which tools a specific user is authorized to run. | +| **Basic Exit Node Management:** Exposing exit-node status is a common capability5. | **Unified Local Socket/Admin API Fallback:** Servers are split, either using only local socket APIs5 or only the Admin API3, failing to bridge both. | +| **Static Webhook Auditing:** Subscribing to basic webhooks is universally supported3. | **Built-in Workload Identity Federation:** No server supports passwordless OIDC token exchange for GitOps and container deployments26. | + +## **2\. Tailscale LocalAPI** + +The Tailscale LocalAPI is an unauthenticated HTTP service run by the local daemon (tailscaled on Unix systems and Windows service wrappers)27. This interface is responsible for local configuration and status queries, serving as the communication backend for the tailscale CLI itself27. + +### **Endpoint Inventory and Stability Assessment** + +The LocalAPI operates under the /localapi/v0/ prefix29. Tailscale explicitly states that this is not a public or stable API30. The Go Client package LocalClient serves as the primary code reference for this interface30. + +| Endpoint URI | HTTP Method | Capability & Action | Stability | Churn Risk and Release History | +| :---- | :---- | :---- | :---- | :---- | +| /localapi/v0/status | GET | Returns complete node state, active peers, and active connections11. | **High** | High backwards compatibility due to CLI and GUI reliance30. | +| /localapi/v0/whois | GET | Resolves a client IP address to a Tailscale identity (UserProfile)10. | **High** | Stable core endpoint; used to authorize third-party platforms10. | +| /localapi/v0/reload-config | POST | Dynamically reloads the local daemon configuration file without restart33. | **Medium** | Added in late 1.9x builds to support declarative file-based setups33. | +| /localapi/v0/service-prefs | GET / POST | Reads or writes local desktop application preferences34. | **Low** | Introduced in v1.99 to persist desktop client preferences34. | +| /localapi/v0/file-put | PUT | Handles peer-to-peer file staging for Taildrop file transfers28. | **Medium** | Governed by OS and platform sandboxing rules37. | +| /localapi/v0/debug | POST | Exposes internal diagnostics (such as current wireguard netmap state)39. | **Low** | Internal only; changed in v1.98 to reduce container logging spam39. | + +### **Platform Authentication and Isolation Models** + +Because the LocalAPI does not use traditional HTTP tokens, it relies entirely on the host operating system's process isolation and socket security descriptors to enforce permissions10. + +#### **Linux and Unix Sockets** + +By default, the API binds to /var/run/tailscale/tailscaled.sock10. Permission check logic validates the caller's peer credentials (UID/GID) on connection13. Standard users are granted read-only status (PermitRead \= true), while mutating endpoints (PermitWrite \= true) require the caller to be root or a user in the configured operator group13. + +#### **Windows Named Pipe Security** + +To mitigate loopback TCP redirection and DNS rebinding attacks on Windows, Tailscale moved its interface from local TCP loops to a secure Named Pipe30: + +\\\\. \\pipe\\ProtectedPrefix\\Administrators\\Tailscale\\tailscaled + +Access is secured using Windows Security Descriptors, restricting connections to processes running within the administrative context12. Non-privileged processes attempting to open this pipe will receive an Access is denied or file-not-found error12. + +#### **macOS Sandboxing and the sameuserproof Protocol** + +On macOS, the App Store and Standalone system extension builds run in highly restricted application sandboxes, preventing them from opening unauthenticated Unix sockets in shared system paths27. To establish a secure channel with unprivileged user processes, the macOS extension opens a loopback TCP port secured by the sameuserproof authentication flow13. Clients must locate a dynamically generated password from a user-specific sandbox-safe directory and include it as an HTTP Basic Authentication header to unlock the connection13. + +### **Architectural Contrast: LocalAPI vs. PeerAPI** + +It is critical to distinguish the localapi from the peerapi when designing an MCP provider. + +* **localapi:** Runs on localhost and is accessed by local front-ends and tools to control the daemon28. +* **peerapi:** Listens on the node's Tailscale IP interface, reachable by other verified nodes in the encrypted tailnet28. This interface handles peer-to-peer features like Taildrop file storage28 and diagnostic node-to-node pings36. + +### **Known Breakage History across Client Versions** + +1. **Loopback Port Removal (v1.34.1):** Tailscale deprecated loopback TCP socket listeners on Windows (historically on port 41112\)30. This broke all third-party integrations that connected directly over loopback HTTP30. +2. **NetworkMap Schema Shifts (v1.94.1):** Structural changes in the daemon's internal NetworkMap struct caused marshaling failures in custom consumer clients, resulting in empty responses on the status bus31. +3. **LocalAPI /debug Logging Redesign (v1.98.3):** Rapid, repeating status checks (such as those from container boot scripts) against the local debug netmap endpoints created massive log bloat39. This forced a structural update to route peer status tracking through the IPN event bus stream instead of the debug endpoint39. +4. **Serve Socket Path Proxy Escapes (TS-2026-005):** A privilege escalation vulnerability was discovered where non-root operators could configure Tailscale Serve to target privileged root Unix sockets (e.g., the Docker daemon)41. This bypass was addressed in version 1.98.9 by enforcing strict validation to ensure only root can configure Unix socket targets26. + +## **3\. Tailscale Admin API (api.tailscale.com)** + +The Admin API (v2) is Tailscale's centralized REST interface, used to manage tailnets, configure access rules, register nodes, and generate API keys or authentication credentials3. + +### **Capability Inventory** + +The Admin API supports deep automation of tailnet infrastructure: + +* **Device Management:** Rest endpoints support listing devices, expiring node keys, updating machine names, modifying tags, and deleting inactive instances25. +* **Access Control Lists (ACLs):** Allows developers to retrieve the current ACL policy, validate syntax changes, preview rules against specific targets, and deploy new configurations using JSON or HuJSON25. +* **Key Operations:** Programs can programmatically create or delete pre-authorized authentication keys46. Keys can be customized with properties like ephemeral, reusable, and tags46. +* **Split-DNS Configuration:** Provides endpoints to configure MagicDNS, search paths, and fallback nameservers25. +* **Webhooks:** Supports registering endpoints and rotating signing keys to monitor tailnet modifications48. +* **Device Posture and Logging:** Allows automated agents to evaluate device compliance status and audit logging streams48. + +### **Least-Privilege Credential Best Practices** + +Automated agents should use scoped OAuth 2.0 Client Credentials rather than global API keys to limit access to sensitive resources3. + +┌────────────────────────────────────────────────────────┐ +│ OAuth 2.0 Scope Isolation │ +├──────────────────────────┬─────────────────────────────┤ +│ Policy Modification │ dns (dns:read) │ +│ (policy\_file) │ devices (devices:core:read) │ +└───────────────┬──────────┴───────────┬─────────────────┘ + │ │ + v v +┌──────────────────────────┐ ┌──────────────────────────┐ +│ Write Scopes │ │ Read-Only Scopes │ +│ (Restricted to Admins) │ │ (Granted to Agents) │ +└──────────────────────────┘ └──────────────────────────┘ + +When setting up an OAuth client for an MCP agent, scopes should be restricted to the bare minimum required for the task47: + +* **ReadOnly Security Monitoring:** Configure the client with devices:core:read and dns:read25. This allows the model to view topology without permitting configuration changes. +* **GitOps Validation Pipelines:** Configure the client with policy\_file:read25. This scope restricts the integration to parsing and validating ACL changes25. +* **Automated Device Provisioning:** Configure the client with the auth\_keys scope25. To enforce maximum isolation, administrators must associate specific security tags with the OAuth client47. The control plane then guarantees that any generated keys inherit those exact tags47. + +### **API Rate Limits** + +To protect system stability, the Admin API enforces strict rate limits on write operations49. +To maintain resilience during intense LLM interactions, servers must implement smart rate-limiting protection3. This is done by intercepting HTTP 429 Too Many Requests responses, parsing the Retry-After header (which can be formatted as an integer or HTTP date), and applying exponential backoff with jitter3. Highly concurrent tools should expose configuration settings like TAILSCALE\_MAX\_CONCURRENT to cap concurrent requests, alongside global query timeouts to handle heavy workflows smoothly3. + +### **2025–2026 Admin API Updates** + +* **Workload Identity Federation API:** Facilitates passwordless token exchanges, allowing workloads running in systems like GitHub Actions or GitLab CI to authenticate using native OIDC tokens without static credentials26. +* **Tailscale Services Management:** Introduces REST endpoints to configure and authorize virtual, node-agnostic tailnet destinations ("Services")26. +* **Declarative Daemon Config Files:** Transitioning away from legacy CLI flag bootstrap patterns, tailscaled now officially reads JSON configurations via /localapi/v0/reload-config33. + +## **4\. MCP Specification — Current State** + +The Model Context Protocol has matured into a standard for secure communication, defining structured guidelines for remote execution, authentication, and client control51. + +### **Streamable HTTP Transport** + +The Streamable HTTP transport defines the standard for connecting clients to remote MCP servers, replacing legacy stdio connections in distributed environments7: + +* **Message Processing:** The client issues JSON-RPC payloads (such as initialize or tools/call) to a POST route on the MCP server53. Real-time, server-to-client notifications are pushed over an active SSE (Server-Sent Events) GET stream53. +* **Session Tracking:** Connections are tracked and managed using the custom Mcp-Session-Id header53. +* **Origin Validation:** To prevent cross-site request forgery and DNS rebinding attacks, the server must validate the Origin header of incoming HTTP requests, returning a 403 Forbidden for unexpected domains54. +* **Header Mirroring:** Clients using the HTTP transport must mirror the JSON-RPC method and params.name properties into standard HTTP headers (e.g., Mcp-Method and Mcp-Name)54. This allows reverse proxies and firewalls to log and inspect requests without parsing the JSON body54. + +### **OAuth Flows and Specification Authorization** + +The MCP specification defines a structured authorization flow for remote servers51: + +┌────────────┐ ┌────────────┐ ┌─────────────┐ +│ MCP Client │ │ MCP Server │ │ Auth Server │ +└─────┬──────┘ └─────┬──────┘ └──────┬──────┘ + │ │ │ + │── 1\. Init Handshake (GET) ─\> │ + │\<─ 401 Unauthorized ────────│ │ + │ (WWW-Authenticate \+ PRM) │ │ + │ │ │ + │── 2\. Discover Metadata ─────────────────────────────────\>│ + │ (Get Endpoints/Scopes) │ + │ │ + │── 3\. Client Credentials Authorization Request ──────────\>│ + │\<─ Access Token (Bearer Token) ───────────────────────────│ + │ │ │ + │── 4\. Call Tool (POST) ────\>│ │ + │ (Authorization: Bearer) │ │ + v v v + +First-generation stdio integrations typically inherit the user's local operating system permissions51. Remote servers, however, must follow the Protected Resource Metadata (PRM) standard to declare required scopes51 and support the dynamic machine-to-machine client credentials flow using symmetric secrets or signed JWT assertions56. + +### **Tool Annotations** + +Tool annotations are static metadata tags included in a tool's schema definition, signaling the potential impact of an action to the client57: + +* readOnlyHint (boolean): Signals that the tool only retrieves information and does not alter the environment57. +* destructiveHint (boolean): Flags that the tool deletes or irreversibly modifies resources57. +* idempotentHint (boolean): Indicates that the tool can be safely run multiple times with the same arguments57. +* openWorldHint (boolean): Flags that the tool queries external third-party services or the open internet57. + +To maintain a secure baseline, the MCP specification defaults to a conservative approach: any tool with missing annotations is assumed to be non-read-only, destructive, non-idempotent, and open-world57. + +### **Client Support Matrix** + +| MCP Specification Component | Claude Desktop | Claude Code | Cursor / VS Code | OpenAI Clients | +| :---- | :---- | :---- | :---- | :---- | +| **Stdio Transport** | **Full** (Default)7 | **Full** (Primary bootstrap)61 | **Full** (Default engine) | **Partial** (Developer tools) | +| **Streamable HTTP** | **None** (Requires proxy bridge)7 | **Full** (Direct network) | **None** (Needs stdio fallback) | **Partial** (Custom routing) | +| **Tool Annotations** | **Partial** (Uses read/write split for confirmation UI)59 | **Full** (Uses readOnlyHint as concurrency flag)14 | **None** (Undeclared heuristic parsing) | **None** (Undeclared processing) | +| **Dynamic Resources** | **Full** (Renders files/docs in chat context)16 | **Full** (Used for workspace awareness) | **Partial** (Manual indexing) | **None** (Treats as flat tool context) | +| **Progress / Elicitation** | **None** (Ignores interactive context callbacks) | **Partial** (Supports text-based progress tickers) | **None** (Silent execution blocks) | **None** (Fails on out-of-order execution) | + +### **Specification Anti-Patterns: Features to Avoid** + +When building tool integrations, developers should avoid the following unimplemented or deprecated parts of the MCP specification: + +* **Dynamic Resource Subscriptions:** While supported by the specification, no major client implements resource change subscription events. +* **Step-Up Authorization Challenges:** Dynamic authentication elevation during a tool call is not supported by current client UI shells, resulting in unhandled execution errors. +* **Bidirectional Requests on Streamable HTTP SSE:** The updated specification restricts Streamable HTTP servers from initiating independent requests back to the client over an active SSE stream54. Any server-to-client operations (such as sampling or user elicitation) must be returned as inline inputs within an InputRequiredResult payload54. + +## **5\. Security Posture for Infrastructure MCP Servers** + +MCP servers that interface with network-controlling software like Tailscale introduce unique risk profiles3. If an agent is granted write access to a tailnet, it can become an appealing target for lateral movement and network-level attacks. + +### **Threat Vector Analysis** + +* **Prompt-Injection and Tool-Misuse Chains:** If an LLM processes untrusted input (such as a public web page or security log) that contains hidden instructions, it can be hijacked into running unexpected commands57. For example, a malicious log entry could trigger the agent to run deauthorize\_node or configure a public egress route, compromising network isolation6. +* **The Confused-Deputy Problem:** This occurs when an unprivileged user leverages a highly privileged agent to execute unauthorized changes63. If the MCP server connects to the Tailscale Admin API using a global tailnet administrator API key, it acts with full administrative privileges63. An unprivileged developer could then ask their local IDE agent to alter routing configurations or invite external users, bypassing standard security gates6. + +### **Tailscale-Specific Vulnerability History** + +* **CVE-2022-41924 & CVE-2022-41925 (Local/PeerAPI DNS Rebinding):** Vulnerabilities allowed remote websites to execute unauthorized DNS rebinding attacks against local loopback interfaces28. This could be used to retrieve tailnet status28 or send unauthorized files via Taildrop28. To address this, Tailscale implemented strict Host header validation allowlists on both the LocalAPI and PeerAPI28. +* **TS-2026-005 (Privileged Socket Proxying Bypass):** A vulnerability where unprivileged users configured as local Tailscale operators could instruct the root-owned Tailscale Serve process to target privileged system sockets (such as /var/run/docker.sock)41. This allowed users to bypass operating system file permission checks41. +* **TS-2026-009 (Tailscale SSH Leading-Dash Injection):** A command injection vulnerability in Tailscale SSH allowed users to connect using usernames with a leading dash (such as \-i)41. This bypassed standard OS verification checks and dropped the user directly into an interactive root session41. +* **TS-2026-001 (tssentinelId macOS Command Injection):** A command injection vulnerability on macOS allowed local processes to execute arbitrary commands by manipulating the tssentinelId identifier26. + +### **Recommended Security Architectures** + +┌────────────────────────────────────────────────────────┐ +│ Security Gate Architecture │ +├──────────────────────────┬─────────────────────────────┤ +│ Tool Execution Request │ Check Risk Level │ +│ │ (TAILSCALE\_ALLOWED\_RISK) │ +└───────────────┬──────────┴───────────┬─────────────────┘ + │ │ + v v +┌──────────────────────────┐ ┌──────────────────────────┐ +│ Risk Check Failed │ │ Risk Check Passed │ +│ (Deny and Return Error) │ │ (Validate against ACL) │ +└──────────────────────────┘ └──────────┬───────────────┘ + │ + v + ┌──────────────────────────┐ + │ Final Tool Execution │ + └──────────────────────────┘ + +#### **Multi-Tier Environment Restrictions** + +The server should categorize tools into distinct risk groups: read, write, and admin6. At startup, the server should evaluate the environment to restrict registration to authorized levels6: + +Bash +TAILSCALE\_ALLOWED\_TOOL\_RISK="read" + +If the environment limits the server to the read tier, any mutating tools should not be registered during the MCP initialization handshake6. + +#### **Strict Pre-Flight Confirmations** + +Any mutating tool must default to a dry-run mode2. The server should be designed to require a structured verification step, requiring the model to display the planned changes and receive explicit user confirmation before executing the action2. + +#### **Application Capability Grants** + +To resolve the confused-deputy problem, the server should not rely on a shared, global API key63. Instead, it should inspect the user's Tailscale identity (retrieved via /localapi/v0/whois) and validate their permissions against application capability grants configured in the central tailnet ACL policy file16. If the user lacks the required grant, the server must deny execution16. + +## **6\. Distribution Channels** + +The distribution landscape for Model Context Protocol servers has expanded beyond traditional package managers, adopting containerized runtimes and centralized integration directories6. + +### **Distribution Registries and Directories** + +* **Docker MCP Catalog:** A curated registry of verified MCP servers packaged as Docker containers and distributed through Docker Hub67. + * *Requirements:* Submissions must include full Software Bill of Materials (SBOM) metadata, OCI-compliant container files, and digital signatures for security67. +* **Smithery.ai:** An integration directory that indexes, hosts, and deploys MCP-compliant servers52. It offers cloud hosting, proxy gateways, and automated installers52. + * *Requirements:* Submissions must support the Streamable HTTP transport and include accurate schema declarations to support Smithery's automated scanning66. +* **mcp.so:** A community-driven MCP indexing directory52. It provides direct links to external source repositories and package listings, rather than hosting the servers directly52. +* **Claude Connectors Directory:** A highly curated marketplace integrated directly into Anthropic's chat platforms53. + * *Requirements:* Requires strict conformance testing, including comprehensive tool annotations, validated origin checks, and production-ready security compliance53. + +### **The Limits of NPM-Only Distribution** + +Relying exclusively on NPM package distribution introduces several challenges for enterprise users and system administrators4: + +1. **Platform Dependency Friction:** Forcing system administrators or developers working in Go, Python, or C\# environments to maintain a local Node.js runtime just to run a network management agent significantly increases setup friction4. +2. **Container Security Restraints:** Modern infrastructure teams often enforce strict read-only filesystems and minimal container footprints in production4. Delivering pre-compiled, static binaries or scratch-based Docker images (\<20MB) meets these compliance needs, whereas NPM installations require larger, high-privilege base images4. + +To maximize adoption, implementations should distribute pre-compiled standalone binaries for Windows, macOS, and Linux16, alongside official Docker images4 and npm wrappers. + +## **7\. Recommendations** + +This section provides a structured, actionable plan for the @tmhs/tailscale-mcp v0.2–1.0 roadmap, categorized by build, skip, or wait decisions. + +### **Roadmap Priorities** + +| Action | Technical Recommendation | Justification | +| :---- | :---- | :---- | +| **BUILD** | **Integrate LocalAPI /whois and Status Checks** \[cite: 10, 11, 17\] | Interfacing directly with the local Unix socket/Named pipe provides low-latency, real-time node state and cryptographic identity validation10. | +| **BUILD** | **Implement Granular Tool Annotations** \[cite: 57\] | Declarative annotations (specifically readOnlyHint) enable parallel tool execution in Claude Code14 and prevent unnecessary confirmation warnings in supportive clients57. | +| **BUILD** | **Transition to Go-Based Admin API Integration** \[cite: 4\] | Transitioning from parsing CLI strings to using official Go SDK clients provides structured, typed Zod schemas and comprehensive access to admin features3. | +| **BUILD** | **Deploy via OCI Containers and Smithery** \[cite: 66, 67\] | Providing signed Docker images and Smithery gateway links lowers adoption barriers for enterprise and non-Node.js users4. | +| **SKIP** | **Developing a Custom Stdio-to-HTTP Remote Proxy** | Developing custom network proxies is redundant, as robust options like jaxxstorm/tailscale-mcp-proxy are already available7. | +| **SKIP** | **Restricting Scope to Local CLI Commands** | Restricting the integration to CLI commands limits execution to local targets, missing the broader tailnet features exposed by the Admin API3. | +| **SKIP** | **Building Custom Webapp Dashboards** | Creating custom visualization dashboards redirects valuable development effort away from securing the core tool execution plane21. | +| **WAIT** | **Implementing Complex PRM and OAuth Metadata Discovery** \[cite: 51, 70\] | Most mainstream desktop clients do not currently render or support dynamic authorization flow handshakes8. | + +#### **Works cited** + +1. MCP server proxying · Tailscale Docs, [https://tailscale.com/docs/aperture/mcp-server](https://tailscale.com/docs/aperture/mcp-server) +2. A curated list of awesome MCP servers focused on DevOps tools and capabilities. \- GitHub, [https://github.com/rohitg00/awesome-devops-mcp-servers](https://github.com/rohitg00/awesome-devops-mcp-servers) +3. YawLabs/tailscale-mcp \- GitHub, [https://github.com/YawLabs/tailscale-mcp](https://github.com/YawLabs/tailscale-mcp) +4. pnocera/tailscale-mcp-server \- GitHub, [https://github.com/pnocera/tailscale-mcp-server](https://github.com/pnocera/tailscale-mcp-server) +5. MCP server for safe read-only operations on the Tailscale CLI \- GitHub, [https://github.com/paulsmith/tailscale-mcp-server](https://github.com/paulsmith/tailscale-mcp-server) +6. Tailscale MCP Server, [https://mcpservers.org/servers/HexSleeves/tailscale-mcp](https://mcpservers.org/servers/HexSleeves/tailscale-mcp) +7. jaxxstorm/tailscale-mcp-proxy \- GitHub, [https://github.com/jaxxstorm/tailscale-mcp-proxy](https://github.com/jaxxstorm/tailscale-mcp-proxy) +8. Identity aware MCP server example using Tailscale serve. \- GitHub, [https://github.com/remyguercio/tailscale-mcp-echo](https://github.com/remyguercio/tailscale-mcp-echo) +9. How Aperture works · Tailscale Docs, [https://tailscale.com/docs/aperture/how-aperture-works](https://tailscale.com/docs/aperture/how-aperture-works) +10. Tailscale – agentgateway | Agent Connectivity Solved, [https://agentgateway.dev/docs/standalone/latest/integrations/auth/tailscale/](https://agentgateway.dev/docs/standalone/latest/integrations/auth/tailscale/) +11. GitHub \- jtdowney/tailscale-localapi: Rust client for the Tailscale Local API, [https://github.com/jtdowney/tailscale-localapi](https://github.com/jtdowney/tailscale-localapi) +12. Windows tailscale client v1.52.0 will broken after connecting to other node. \#10025 \- GitHub, [https://github.com/tailscale/tailscale/issues/10025](https://github.com/tailscale/tailscale/issues/10025) +13. localapi.go \- tailscale \- GitHub, [https://github.com/tailscale/tailscale/blob/main/ipn/localapi/localapi.go](https://github.com/tailscale/tailscale/blob/main/ipn/localapi/localapi.go) +14. Expose MCP tool annotations (readOnlyHint, destructiveHint) in PreToolCallDecideHook \#62 \- GitHub, [https://github.com/google-antigravity/antigravity-sdk-python/issues/62](https://github.com/google-antigravity/antigravity-sdk-python/issues/62) +15. PSA: MCP tools aren't serialized in Claude Code if your server sets readOnlyHint correctly, [https://www.reddit.com/r/ClaudeAI/comments/1r344re/psa\_mcp\_tools\_arent\_serialized\_in\_claude\_code\_if/](https://www.reddit.com/r/ClaudeAI/comments/1r344re/psa_mcp_tools_arent_serialized_in_claude_code_if/) +16. jaxxstorm/tailscale-mcp \- GitHub, [https://github.com/jaxxstorm/tailscale-mcp](https://github.com/jaxxstorm/tailscale-mcp) +17. tsidp · Tailscale Docs, [https://tailscale.com/docs/features/tsidp](https://tailscale.com/docs/features/tsidp) +18. Yaw Labs \- GitHub, [https://github.com/YawLabs](https://github.com/YawLabs) +19. Brian Kalinowski briankski \- GitHub, [https://github.com/briankski](https://github.com/briankski) +20. MCP server for managing your Tailscale network (tailnet) through Claude Code and other MCP clients \- GitHub, [https://github.com/aplaceforallmystuff/mcp-tailscale](https://github.com/aplaceforallmystuff/mcp-tailscale) +21. tailscale-mcp/docs/PRD.md at master \- GitHub, [https://github.com/sandraschi/tailscale-mcp/blob/master/docs/PRD.md](https://github.com/sandraschi/tailscale-mcp/blob/master/docs/PRD.md) +22. ASSESSMENT.md \- sandraschi/tailscale-mcp \- GitHub, [https://github.com/sandraschi/tailscale-mcp/blob/master/ASSESSMENT.md](https://github.com/sandraschi/tailscale-mcp/blob/master/ASSESSMENT.md) +23. tailscale-mcp/docs/monitoring/README.md at master \- GitHub, [https://github.com/sandraschi/tailscale-mcp/blob/master/docs/monitoring/README.md](https://github.com/sandraschi/tailscale-mcp/blob/master/docs/monitoring/README.md) +24. Tailscale Model Context Protocol (MCP) Server, [https://mcp.so/server/tailscale-mcp-server/paulsmith](https://mcp.so/server/tailscale-mcp-server/paulsmith) +25. Trust credentials · Tailscale Docs, [https://tailscale.com/docs/reference/trust-credentials](https://tailscale.com/docs/reference/trust-credentials) +26. Changelog \- Tailscale, [https://tailscale.com/changelog](https://tailscale.com/changelog) +27. tailscaled daemon · Tailscale Docs, [https://tailscale.com/docs/reference/tailscaled](https://tailscale.com/docs/reference/tailscaled) +28. CVE-2022-41924 \- RCE in Tailscale, DNS Rebinding, and You \- Emily Trau, [https://emily.id.au/tailscale](https://emily.id.au/tailscale) +29. Failing to Connect to Local Tailscale · Issue \#18321 \- GitHub, [https://github.com/tailscale/tailscale/issues/18321](https://github.com/tailscale/tailscale/issues/18321) +30. Localapi no longer working on local port 41112 · Issue \#6777 · tailscale/tailscale \- GitHub, [https://github.com/tailscale/tailscale/issues/6777](https://github.com/tailscale/tailscale/issues/6777) +31. TailscaleKit: LocalAPI types not updated to new version · Issue \#18754 \- GitHub, [https://github.com/tailscale/tailscale/issues/18754](https://github.com/tailscale/tailscale/issues/18754) +32. How To Seamlessly Authenticate to Grafana using Tailscale | Guide, [https://tailscale.com/blog/grafana-auth](https://tailscale.com/blog/grafana-auth) +33. Tailscale daemon configuration file, [https://tailscale.com/docs/reference/tailscaled/tailescaled-config-file](https://tailscale.com/docs/reference/tailscaled/tailescaled-config-file) +34. ipn: persist per-service launch preferences for desktop clients · Issue \#20429 \- GitHub, [https://github.com/tailscale/tailscale/issues/20429](https://github.com/tailscale/tailscale/issues/20429) +35. Examining Tailscale Artifacts \- ogmini \- Exploration of DFIR, [https://ogmini.github.io/2026/04/21/Examining-Tailscale-Artifacts.html](https://ogmini.github.io/2026/04/21/Examining-Tailscale-Artifacts.html) +36. Taildrop was kind of easy, actually \- Tailscale, [https://tailscale.com/blog/2021-06-taildrop-was-easy](https://tailscale.com/blog/2021-06-taildrop-was-easy) +37. tailscale serve command, [https://tailscale.com/docs/reference/tailscale-cli/serve](https://tailscale.com/docs/reference/tailscale-cli/serve) +38. Tailscale Funnel, [https://tailscale.com/docs/features/tailscale-funnel](https://tailscale.com/docs/features/tailscale-funnel) +39. Containerboot polls /localapi/v0/debug?action=current-netmap every 15s causing localapi POST log spam · Issue \#19852 · tailscale/tailscale \- GitHub, [https://github.com/tailscale/tailscale/issues/19852](https://github.com/tailscale/tailscale/issues/19852) +40. cccc-pair \- PyPI, [https://pypi.org/project/cccc-pair/](https://pypi.org/project/cccc-pair/) +41. Security Bulletins \- Tailscale, [https://tailscale.com/security-bulletins](https://tailscale.com/security-bulletins) +42. Authorizing the Tailscale system extension on macOS, [https://tailscale.com/docs/concepts/macos-sysext](https://tailscale.com/docs/concepts/macos-sysext) +43. localapi package \- tailscale.com/ipn/localapi \- Go Packages, [https://pkg.go.dev/tailscale.com/ipn/localapi](https://pkg.go.dev/tailscale.com/ipn/localapi) +44. Tailscale API, [https://tailscale.com/docs/reference/tailscale-api](https://tailscale.com/docs/reference/tailscale-api) +45. Troubleshooting grants · Tailscale Docs, [https://tailscale.com/docs/reference/troubleshooting/grants](https://tailscale.com/docs/reference/troubleshooting/grants) +46. Auth keys · Tailscale Docs, [https://tailscale.com/docs/features/access-control/auth-keys](https://tailscale.com/docs/features/access-control/auth-keys) +47. OAuth clients · Tailscale Docs, [https://tailscale.com/docs/features/oauth-clients](https://tailscale.com/docs/features/oauth-clients) +48. Key and secret management · Tailscale Docs, [https://tailscale.com/docs/reference/key-secret-management](https://tailscale.com/docs/reference/key-secret-management) +49. Rate Limits | Getting Started \- SCAYLE Documentation, [https://scayle.dev/api-guides/admin-api/getting-started/rate-limits](https://scayle.dev/api-guides/admin-api/getting-started/rate-limits) +50. Set per-user spending limits · Tailscale Docs, [https://tailscale.com/docs/aperture/how-to/set-per-user-spending-limits](https://tailscale.com/docs/aperture/how-to/set-per-user-spending-limits) +51. Understanding Authorization in MCP \- Model Context Protocol, [https://modelcontextprotocol.io/docs/tutorials/security/authorization](https://modelcontextprotocol.io/docs/tutorials/security/authorization) +52. Unveiling Smithery: The Ultimate Platform for Agentic AI \- MCP.so, [https://mcp.so/smithery-ai](https://mcp.so/smithery-ai) +53. I Made My API Claude Compatible (the Hard Way) — The Full Guide. | by TheTechDude, [https://medium.com/@TheTechDude/i-made-my-api-claude-compatible-the-hard-way-the-full-guide-5c9c64cc2b49](https://medium.com/@TheTechDude/i-made-my-api-claude-compatible-the-hard-way-the-full-guide-5c9c64cc2b49) +54. Streamable HTTP \- Model Context Protocol, [https://modelcontextprotocol.io/specification/draft/basic/transports/streamable-http](https://modelcontextprotocol.io/specification/draft/basic/transports/streamable-http) +55. Authorization \- Model Context Protocol, [https://modelcontextprotocol.io/specification/draft/basic/authorization](https://modelcontextprotocol.io/specification/draft/basic/authorization) +56. OAuth Client Credentials \- Model Context Protocol, [https://modelcontextprotocol.io/extensions/auth/oauth-client-credentials](https://modelcontextprotocol.io/extensions/auth/oauth-client-credentials) +57. Tool Annotations as Risk Vocabulary: What Hints Can and Can't Do, [https://blog.modelcontextprotocol.io/posts/2026-03-16-tool-annotations/](https://blog.modelcontextprotocol.io/posts/2026-03-16-tool-annotations/) +58. MCP Tool Annotations: How to Control Claude's Permission UI from Your Server \- Medium, [https://parthdevai.medium.com/mcp-tool-annotations-how-to-control-claudes-permission-ui-from-your-server-024997defd16](https://parthdevai.medium.com/mcp-tool-annotations-how-to-control-claudes-permission-ui-from-your-server-024997defd16) +59. Testing MCP Tool Annotations: Validate readOnlyHint, destructiveHint, and openWorldHint for ChatGPT and Claude (May 2026\) \- Sunpeak.ai, [https://sunpeak.ai/blogs/testing-mcp-tool-annotations/](https://sunpeak.ai/blogs/testing-mcp-tool-annotations/) +60. Add tool annotation hint fields (readOnlyHint, destructiveHint, etc.) to Annotations · Issue \#259 · modelcontextprotocol/ruby-sdk \- GitHub, [https://github.com/modelcontextprotocol/ruby-sdk/issues/259](https://github.com/modelcontextprotocol/ruby-sdk/issues/259) +61. Securely troubleshoot Kubernetes clusters with Claude Code and MCP \- Tailscale, [https://tailscale.com/learn/kubernetes-mcp](https://tailscale.com/learn/kubernetes-mcp) +62. HexSleeves/tailscale-mcp: server that provides seamless integration with Tailscale's CLI commands and REST API, enabling automated network management and monitoring through a standardized interface \- GitHub, [https://github.com/HexSleeves/tailscale-mcp](https://github.com/HexSleeves/tailscale-mcp) +63. General Best Practices | Best Practices | Hosted MCP Servers \- Salesforce Developers, [https://developer.salesforce.com/docs/platform/hosted-mcp-servers/guide/general-best-practices.html](https://developer.salesforce.com/docs/platform/hosted-mcp-servers/guide/general-best-practices.html) +64. \[tl;dr sec\] \#278 \- North Korean IT Workers, How Sentinel One Defends Itself, How Threat Actors Use Claude, [https://tldrsec.com/p/tldr-sec-278](https://tldrsec.com/p/tldr-sec-278) +65. meshclaw \- PyPI, [https://pypi.org/project/meshclaw/](https://pypi.org/project/meshclaw/) +66. Publish \- Smithery Documentation, [https://smithery.ai/docs/build/publish](https://smithery.ai/docs/build/publish) +67. Docker MCP Catalog, [https://docs.docker.com/ai/mcp-catalog-and-toolkit/catalog/](https://docs.docker.com/ai/mcp-catalog-and-toolkit/catalog/) +68. mcp-server-logseq \- PyPI, [https://pypi.org/project/mcp-server-logseq/](https://pypi.org/project/mcp-server-logseq/) +69. Tailscale REST API documentation and Go client implementation is out of sync · Issue \#11122 \- GitHub, [https://github.com/tailscale/tailscale/issues/11122](https://github.com/tailscale/tailscale/issues/11122) +70. Authorization Server Discovery \- Model Context Protocol, [https://modelcontextprotocol.io/specification/draft/basic/authorization/authorization-server-discovery](https://modelcontextprotocol.io/specification/draft/basic/authorization/authorization-server-discovery) \ No newline at end of file diff --git a/docs/research/gemini-deep-research-prompt.md b/docs/research/gemini-deep-research-prompt.md new file mode 100644 index 0000000..3f02e19 --- /dev/null +++ b/docs/research/gemini-deep-research-prompt.md @@ -0,0 +1,38 @@ +# Deep-research prompt for Gemini + +Copy everything below the line into Gemini Deep Research. Save the resulting report as +`docs/research/tailscale-mcp-landscape-2026.md` in this repo. + +--- + +I maintain **@tmhs/tailscale-mcp**, an open-source MCP (Model Context Protocol) server that wraps the **local Tailscale daemon** — currently via the `tailscale` CLI over stdio. Shipped tools: tailnet status, SSH-config generation, port sharing via Serve/Funnel (tailnet-only by default, Funnel behind an explicit opt-in), and a concurrent latency/ping matrix. Design principles: dry-run defaults, structured errors with remedy commands, never touching auth keys or tailnet credentials. + +I'm planning versions 0.2–1.0 and need a rigorous landscape report. Research the following, with citations to primary sources (official docs, source code, changelogs) wherever possible, and clearly flag anything that is speculative or based on unofficial sources: + +## 1. Competitive landscape + +Find every actively maintained MCP server for Tailscale (GitHub, npm, PyPI, MCP registries). For each: tool surface, whether it uses the CLI, the LocalAPI, or the Admin API; auth model; download/star traction; last release; license. End with a gap table: capabilities nobody offers well, and capabilities that are commoditized. + +## 2. Tailscale LocalAPI + +Document the daemon's LocalAPI (HTTP over the Unix socket / Windows named pipe, as used by the CLI itself): endpoint inventory, how stable/documented it is, official stance on third-party use, authentication on each platform (peerapi vs localapi, Windows named-pipe ACLs, macOS sandboxed variants), and known breakage history across versions. Which endpoints are safe to build a provider on vs likely to churn? + +## 3. Tailscale Admin API (api.tailscale.com) + +Current capability inventory: device management, ACL read/validate, auth-key creation (scopes, ephemeral, tags), DNS, webhooks, device posture, logging APIs. OAuth-client scopes model and best practice for least-privilege credentials held by an automated agent. Rate limits. Anything announced/changed in 2025–2026. + +## 4. MCP specification — current state + +As of mid-2026: status of Streamable HTTP transport, authorization spec (OAuth flows for remote MCP servers), tool annotations (readOnlyHint/destructiveHint), resources and resource subscriptions, prompts, progress notifications, elicitation. Which of these do the major clients (Claude Desktop/Code, Cursor, VS Code, OpenAI clients) actually support today? A feature the spec has but no client renders is not worth building yet — call those out. + +## 5. Security posture for infrastructure MCP servers + +Published guidance and incident history for MCP servers that control network infrastructure: prompt-injection → tool-misuse chains, confused-deputy risks, recommended confirmation/permission patterns, sandboxing, and what "read-only mode" conventions have emerged. Any published security reviews of Tailscale-related agents/tools. + +## 6. Distribution channels + +Which MCP registries/catalogs actually drive installs in 2026 (official MCP registry, Docker MCP Catalog, Smithery, mcp.so, client-specific directories)? Listing requirements for each, and whether npm-only distribution is leaving adoption on the table. Any signing/attestation requirements emerging. + +## Output format + +Markdown report with: an executive summary of the 5 most consequential findings for my roadmap; one section per topic above; every factual claim cited with a link; a final "recommendations" section that maps findings to concrete roadmap moves (build / skip / wait), each with a one-line justification.