tailscale-mcp 2026.3.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/.env.example +17 -0
  2. package/ARCHITECTURE.md +220 -0
  3. package/CHANGELOG.md +93 -0
  4. package/CLAUDE.md +180 -0
  5. package/COMMERCIAL_LICENSE.md +44 -0
  6. package/CONTRIBUTING.md +54 -0
  7. package/LICENSE +661 -0
  8. package/PRODUCT_PACKAGING.md +138 -0
  9. package/README.md +276 -0
  10. package/ROADMAP.md +67 -0
  11. package/SECURITY.md +24 -0
  12. package/dist/client/client-factory.d.ts +12 -0
  13. package/dist/client/client-factory.d.ts.map +1 -0
  14. package/dist/client/client-factory.js +31 -0
  15. package/dist/client/client-factory.js.map +1 -0
  16. package/dist/client/tailscale-client.d.ts +18 -0
  17. package/dist/client/tailscale-client.d.ts.map +1 -0
  18. package/dist/client/tailscale-client.js +101 -0
  19. package/dist/client/tailscale-client.js.map +1 -0
  20. package/dist/client/tailscale-oauth-client.d.ts +19 -0
  21. package/dist/client/tailscale-oauth-client.d.ts.map +1 -0
  22. package/dist/client/tailscale-oauth-client.js +119 -0
  23. package/dist/client/tailscale-oauth-client.js.map +1 -0
  24. package/dist/client/types.d.ts +281 -0
  25. package/dist/client/types.d.ts.map +1 -0
  26. package/dist/client/types.js +3 -0
  27. package/dist/client/types.js.map +1 -0
  28. package/dist/index.d.ts +2 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +100 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/tools/acl.d.ts +80 -0
  33. package/dist/tools/acl.d.ts.map +1 -0
  34. package/dist/tools/acl.js +180 -0
  35. package/dist/tools/acl.js.map +1 -0
  36. package/dist/tools/devices.d.ts +162 -0
  37. package/dist/tools/devices.d.ts.map +1 -0
  38. package/dist/tools/devices.js +347 -0
  39. package/dist/tools/devices.js.map +1 -0
  40. package/dist/tools/diagnostics.d.ts +65 -0
  41. package/dist/tools/diagnostics.d.ts.map +1 -0
  42. package/dist/tools/diagnostics.js +178 -0
  43. package/dist/tools/diagnostics.js.map +1 -0
  44. package/dist/tools/dns.d.ts +98 -0
  45. package/dist/tools/dns.d.ts.map +1 -0
  46. package/dist/tools/dns.js +179 -0
  47. package/dist/tools/dns.js.map +1 -0
  48. package/dist/tools/keys.d.ts +107 -0
  49. package/dist/tools/keys.d.ts.map +1 -0
  50. package/dist/tools/keys.js +167 -0
  51. package/dist/tools/keys.js.map +1 -0
  52. package/dist/tools/posture.d.ts +98 -0
  53. package/dist/tools/posture.d.ts.map +1 -0
  54. package/dist/tools/posture.js +155 -0
  55. package/dist/tools/posture.js.map +1 -0
  56. package/dist/tools/tailnet.d.ts +132 -0
  57. package/dist/tools/tailnet.d.ts.map +1 -0
  58. package/dist/tools/tailnet.js +222 -0
  59. package/dist/tools/tailnet.js.map +1 -0
  60. package/dist/tools/users.d.ts +44 -0
  61. package/dist/tools/users.d.ts.map +1 -0
  62. package/dist/tools/users.js +90 -0
  63. package/dist/tools/users.js.map +1 -0
  64. package/dist/tools/webhooks.d.ts +88 -0
  65. package/dist/tools/webhooks.d.ts.map +1 -0
  66. package/dist/tools/webhooks.js +168 -0
  67. package/dist/tools/webhooks.js.map +1 -0
  68. package/dist/transport.d.ts +13 -0
  69. package/dist/transport.d.ts.map +1 -0
  70. package/dist/transport.js +42 -0
  71. package/dist/transport.js.map +1 -0
  72. package/dist/utils/errors.d.ts +8 -0
  73. package/dist/utils/errors.d.ts.map +1 -0
  74. package/dist/utils/errors.js +42 -0
  75. package/dist/utils/errors.js.map +1 -0
  76. package/dist/utils/validation.d.ts +18 -0
  77. package/dist/utils/validation.d.ts.map +1 -0
  78. package/dist/utils/validation.js +35 -0
  79. package/dist/utils/validation.js.map +1 -0
  80. package/package.json +55 -0
  81. package/vitest.config.ts +8 -0
package/.env.example ADDED
@@ -0,0 +1,17 @@
1
+ # Authentication — use API key OR OAuth (not both)
2
+ # Option 1: API key
3
+ TAILSCALE_API_KEY=your-api-key-here
4
+
5
+ # Option 2: OAuth client credentials (takes priority over API key)
6
+ # TAILSCALE_OAUTH_CLIENT_ID=your-oauth-client-id
7
+ # TAILSCALE_OAUTH_CLIENT_SECRET=your-oauth-client-secret
8
+
9
+ TAILSCALE_TAILNET=your-tailnet-name
10
+ TAILSCALE_API_URL=https://api.tailscale.com
11
+ TAILSCALE_TIMEOUT=30000
12
+
13
+ # Transport — stdio (default) or sse
14
+ # TAILSCALE_MCP_TRANSPORT=sse
15
+ # TAILSCALE_MCP_AUTH_TOKEN=your-mcp-auth-token
16
+ # TAILSCALE_MCP_PORT=3000
17
+ # TAILSCALE_MCP_HOST=localhost
@@ -0,0 +1,220 @@
1
+ # Architecture
2
+
3
+ This document describes the architecture of mcp-tailscale — from the current single-runtime design to the target multi-component architecture.
4
+
5
+ ## Current Architecture
6
+
7
+ mcp-tailscale is a single-process MCP server that translates MCP tool calls into Tailscale API v2 requests.
8
+
9
+ ```
10
+ ┌─────────────────────────────────────────────────────────────────┐
11
+ │ MCP Client │
12
+ │ (Claude Code, AI Agent, Custom) │
13
+ └──────────────────────────┬──────────────────────────────────────┘
14
+ │ MCP Protocol (stdio or SSE)
15
+
16
+ ┌─────────────────────────────────────────────────────────────────┐
17
+ │ mcp-tailscale Runtime │
18
+ │ │
19
+ │ ┌──────────┐ ┌──────────┐ ┌──────────────────────────────┐ │
20
+ │ │Transport │ │ Tool │ │ Tailscale Client │ │
21
+ │ │ stdio/SSE│──│ Registry │──│ (API Key or OAuth) │ │
22
+ │ │ + Auth │ │ 48 tools │ │ Bearer token, auto-refresh │ │
23
+ │ └──────────┘ └──────────┘ └──────────────┬───────────────┘ │
24
+ │ │ │
25
+ │ ┌──────────┐ ┌──────────┐ │ │
26
+ │ │Validation│ │ Error │ │ │
27
+ │ │ (Zod) │ │ Handling │ │ │
28
+ │ └──────────┘ └──────────┘ │ │
29
+ └──────────────────────────────────────────────┼──────────────────┘
30
+ │ HTTPS
31
+
32
+ ┌──────────────────────────┐
33
+ │ Tailscale API v2 │
34
+ │ api.tailscale.com │
35
+ └──────────────┬───────────┘
36
+
37
+
38
+ ┌──────────────────────────┐
39
+ │ Your Tailnet │
40
+ │ Devices, DNS, ACL, ... │
41
+ └──────────────────────────┘
42
+ ```
43
+
44
+ ### Components
45
+
46
+ | Component | File | Responsibility |
47
+ |-----------|------|----------------|
48
+ | Transport | `src/index.ts`, `src/transport.ts` | stdio/SSE transport, Bearer auth middleware |
49
+ | Tool Registry | `src/tools/*.ts` | 48 tools across 9 domains, Zod input schemas |
50
+ | Tailscale Client | `src/client/tailscale-client.ts` | HTTP client, API key Bearer auth |
51
+ | OAuth Client | `src/client/tailscale-oauth-client.ts` | OAuth credentials, token auto-refresh |
52
+ | Client Factory | `src/client/client-factory.ts` | Selects auth method (OAuth > API key) |
53
+ | Validation | `src/utils/validation.ts` | Shared Zod schemas (device IDs, CIDR, domains) |
54
+ | Error Handling | `src/utils/errors.ts` | TailscaleApiError, credential-safe messages |
55
+ | Types | `src/client/types.ts` | API response types, ITailscaleClient interface |
56
+
57
+ ### Data Flow
58
+
59
+ ```
60
+ 1. MCP Client sends tool call (e.g., tailscale_device_list)
61
+ 2. Transport layer receives and routes to tool handler
62
+ 3. Zod schema validates input parameters
63
+ 4. Tool handler calls TailscaleClient method
64
+ 5. Client adds Bearer token, sends HTTPS request to api.tailscale.com
65
+ 6. API response is typed and returned as JSON text content
66
+ 7. On error: TailscaleApiError extracts message without leaking credentials
67
+ ```
68
+
69
+ ## Target Architecture
70
+
71
+ As mcp-tailscale evolves from a single runtime into a product platform, the architecture separates into three distinct layers:
72
+
73
+ ```
74
+ ┌─────────────────────────────────────────────────────────────────┐
75
+ │ MCP Clients │
76
+ │ Claude Code · AI Agents · Custom Apps │
77
+ └──────────────────────────┬──────────────────────────────────────┘
78
+ │ MCP Protocol
79
+
80
+ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┐
81
+ │ Cloud Layer (Future) │
82
+ │ │
83
+ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
84
+ │ │ Admin │ │ Fleet │ │ Observability │ │
85
+ │ │ Console │ │ Manager │ │ (Logs, Metrics) │ │
86
+ │ └──────────────┘ └──────────────┘ └──────────────────────┘ │
87
+ │ │
88
+ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
89
+
90
+ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┐
91
+ │ Enterprise Layer │
92
+ │ │
93
+ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
94
+ │ │ RBAC │ │ SSO │ │ Audit │ │ Policy │ │
95
+ │ │ │ │OIDC/SAML │ │ Events │ │ Engine │ │
96
+ │ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │
97
+ │ │
98
+ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
99
+
100
+ ┌──────────────────────────┼──────────────────────────────────────┐
101
+ │ Core Runtime (OSS) │
102
+ │ │
103
+ │ ┌──────────┐ ┌──────────┐ ┌──────────────────────────────┐ │
104
+ │ │Transport │ │ Tool │ │ API Clients │ │
105
+ │ │ stdio/SSE│ │ Registry │ │ Tailscale · (Extensible) │ │
106
+ │ └──────────┘ └──────────┘ └──────────────────────────────┘ │
107
+ │ │
108
+ │ ┌──────────┐ ┌──────────┐ ┌──────────────────────────────┐ │
109
+ │ │Validation│ │ Error │ │ Plugin / Connector SDK │ │
110
+ │ │ (Zod) │ │ Handling │ │ (Future) │ │
111
+ │ └──────────┘ └──────────┘ └──────────────────────────────┘ │
112
+ └──────────────────────────┬──────────────────────────────────────┘
113
+ │ HTTPS
114
+
115
+ ┌──────────────────────────┐
116
+ │ Infrastructure APIs │
117
+ │ Tailscale · (Others) │
118
+ └──────────────────────────┘
119
+ ```
120
+
121
+ ### Layer Responsibilities
122
+
123
+ | Layer | Scope | Repository | License |
124
+ |-------|-------|------------|---------|
125
+ | **Core Runtime** | Execution — MCP protocol, tool registry, API clients, validation | `mcp-tailscale` (public) | AGPL-3.0 |
126
+ | **Enterprise** | Governance — RBAC, SSO, audit, policy engine, multi-tenancy | Private (future) | Commercial |
127
+ | **Cloud** | Operations — Hosted control plane, fleet management, observability | Private (future) | Commercial SaaS |
128
+
129
+ ### Boundary Definitions
130
+
131
+ **Core Runtime** is the execution engine. It handles:
132
+ - MCP protocol negotiation (stdio/SSE)
133
+ - Tool discovery and invocation
134
+ - Input validation and error handling
135
+ - API client authentication and requests
136
+ - Plugin/connector lifecycle (future)
137
+
138
+ **Enterprise Layer** wraps the Core Runtime with governance:
139
+ - Who can use which tools (RBAC)
140
+ - How users authenticate (SSO)
141
+ - What happened and when (Audit)
142
+ - What is allowed and what is not (Policy)
143
+ - Isolation between teams (Multi-tenancy)
144
+
145
+ **Cloud Layer** manages fleets of Enterprise instances:
146
+ - Deployment and scaling of gateway instances
147
+ - Centralized monitoring and alerting
148
+ - Configuration management across instances
149
+ - Usage tracking and billing
150
+
151
+ ### Security Model
152
+
153
+ ```
154
+ MCP Client
155
+
156
+
157
+ Transport Auth ──── Bearer token (SSE) or process isolation (stdio)
158
+
159
+
160
+ [Enterprise: RBAC] ── Role check: does this identity have access to this tool?
161
+
162
+
163
+ [Enterprise: Policy] ── Policy check: is this operation allowed right now?
164
+
165
+
166
+ Tool Execution ──── Zod validates input, tool handler runs
167
+
168
+
169
+ [Enterprise: Audit] ── Log: who, what, when, result
170
+
171
+
172
+ API Client Auth ──── Bearer token (API key) or OAuth (auto-refresh)
173
+
174
+
175
+ Tailscale API ──── HTTPS to api.tailscale.com
176
+ ```
177
+
178
+ Items in `[brackets]` are enterprise layer additions — the Core Runtime operates without them.
179
+
180
+ ## Technology Decisions
181
+
182
+ | Decision | Choice | Rationale |
183
+ |----------|--------|-----------|
184
+ | Runtime | Node.js ≥ 20 | Native ES modules, broad MCP SDK support |
185
+ | Language | TypeScript (strict) | Type safety, IDE support, refactoring confidence |
186
+ | Validation | Zod | Runtime + compile-time validation, composable schemas |
187
+ | HTTP Client | Axios | Interceptors for auth, timeout, error handling |
188
+ | Transport | stdio + SSE (Express) | stdio for local, SSE for remote/multi-client |
189
+ | Testing | Vitest | Fast, TypeScript-native, ESM support |
190
+ | Auth | API key + OAuth | API key for humans, OAuth for services |
191
+
192
+ ## File Structure
193
+
194
+ ```
195
+ src/
196
+ index.ts # Entry point — server setup, tool registration
197
+ transport.ts # Transport config + SSE auth middleware
198
+ client/
199
+ tailscale-client.ts # API key HTTP client
200
+ tailscale-oauth-client.ts # OAuth client (auto-refresh)
201
+ client-factory.ts # Auth method selection
202
+ types.ts # API types + ITailscaleClient interface
203
+ tools/
204
+ devices.ts # 11 device management tools
205
+ dns.ts # 8 DNS tools
206
+ acl.ts # 5 ACL tools
207
+ keys.ts # 4 auth key tools
208
+ tailnet.ts # 5 tailnet tools
209
+ users.ts # 2 user tools
210
+ webhooks.ts # 4 webhook tools
211
+ posture.ts # 4 posture integration tools
212
+ diagnostics.ts # 5 diagnostics tools
213
+ utils/
214
+ validation.ts # Shared Zod schemas
215
+ errors.ts # Error extraction, TailscaleApiError
216
+ tests/ # Vitest unit tests (mocked API)
217
+ docs/
218
+ plans/ # Design documents
219
+ api-reference.md # Tailscale API v2 endpoint mapping
220
+ ```
package/CHANGELOG.md ADDED
@@ -0,0 +1,93 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ This project uses [Calendar Versioning](https://calver.org/) (`YYYY.MM.DD.TS`).
5
+
6
+
7
+ ## v2026.03.15.5
8
+
9
+ - Publish to npm as `@itunified/mcp-tailscale`, add `.npmignore`, `bin` entry, expanded keywords (#12)
10
+ - Update package.json version to `2026.3.15`, description aligned with product positioning
11
+
12
+ ## v2026.03.15.4
13
+
14
+ - Add product positioning docs: restructured README, ROADMAP.md, ARCHITECTURE.md, PRODUCT_PACKAGING.md (#29)
15
+
16
+ ## v2026.03.15.3
17
+
18
+ - Switch Glama badge from score to card format (#11)
19
+
20
+ ## v2026.03.15.2
21
+
22
+ - Add Glama registry badge to README (#11)
23
+
24
+ ## v2026.03.15.1
25
+
26
+ - fix: use `/acl/validate` endpoint for `acl_test` tool — nonexistent `/acl/test` returned 404 (#17)
27
+ - fix: remove unsupported `"generic"` webhook provider type, make `providerType` optional (#18)
28
+
29
+ ## v2026.03.14.9
30
+
31
+ - Add skill documentation to README and `.claude/skills/README.md` per ADR-0022 (#23)
32
+
33
+ ## v2026.03.14.8
34
+
35
+ - Add `docs/superpowers/` to `.gitignore` per ADR-0021 (#21)
36
+
37
+ ## v2026.03.14.7
38
+
39
+ - Update design doc 001 status from Draft to Accepted (#19)
40
+
41
+ ## v2026.03.14.6
42
+
43
+ - **Tier 2 Enhancement: HTTP/SSE transport with Bearer token auth** (#14)
44
+ - Add SSE transport as opt-in alternative to stdio (`TAILSCALE_MCP_TRANSPORT=sse`)
45
+ - Mandatory `TAILSCALE_MCP_AUTH_TOKEN` for SSE — server refuses to start without it
46
+ - Timing-safe token comparison via `crypto.timingSafeEqual()`
47
+ - Add `express` dependency (runtime deps: 3 → 4)
48
+ - 188 unit tests (was 178)
49
+ - Design doc: `docs/plans/002-tier2-enhancement.md`
50
+
51
+ ## v2026.03.14.5
52
+
53
+ - **Tier 2 Enhancement: Device expire/rename + posture integration tools** (#13)
54
+ - Add `tailscale_device_expire` — force device key expiry (+1 tool)
55
+ - Add `tailscale_device_rename` — set device display name (+1 tool)
56
+ - Add posture integration tools: `tailscale_posture_integration_list`, `tailscale_posture_integration_get`, `tailscale_posture_integration_create`, `tailscale_posture_integration_delete` (+4 tools)
57
+ - Total: 42 → 48 tools across 9 domains
58
+ - 178 unit tests (was 158)
59
+ - Design doc: `docs/plans/002-tier2-enhancement.md`
60
+
61
+ ## v2026.03.14.4
62
+
63
+ - **Tier 1 Enhancement: OAuth, Users, Webhooks, Tailnet Settings Write** (#7)
64
+ - Add OAuth client credentials auth support (`TAILSCALE_OAUTH_CLIENT_ID` + `TAILSCALE_OAUTH_CLIENT_SECRET`)
65
+ - Add `ITailscaleClient` interface and `client-factory.ts` for dual auth (OAuth > API key)
66
+ - Add user management tools: `tailscale_user_list`, `tailscale_user_get` (+2 tools)
67
+ - Add webhook management tools: `tailscale_webhook_list`, `tailscale_webhook_create`, `tailscale_webhook_get`, `tailscale_webhook_delete` (+4 tools)
68
+ - Add `tailscale_tailnet_settings_update` tool (+1 tool)
69
+ - Total: 35 → 42 tools across 8 domains
70
+ - 149 unit tests (was 110)
71
+ - Update README, CLAUDE.md, api-reference.md, .env.example
72
+ - Add design doc `docs/plans/001-tier1-enhancement.md`
73
+
74
+ ## v2026.03.14.3
75
+
76
+ - Add acceptance criteria gate to CLAUDE.md PR Workflow (ADR-0017) (#8)
77
+
78
+ ## v2026.03.14.2
79
+
80
+ - Clarify license: internal/commercial use requires commercial license (#5)
81
+
82
+ ## v2026.03.14.1
83
+
84
+ - 35 tools across 6 domains: Devices (9), DNS (8), ACL (5), Keys (4), Tailnet (4), Diagnostics (5) (#1)
85
+ - TailscaleClient with Bearer token auth, tailnet-scoped API paths, direct JSON responses (#1)
86
+ - 6 skills: dns-management, health (/ts-health), device-management, acl-management, key-management, onboarding (#1)
87
+ - 110 unit tests with vitest, all passing (#1)
88
+ - Zod input validation on all tools, structured error handling with TailscaleApiError (#1)
89
+
90
+ ## v2026.03.13.1
91
+
92
+ - Initial project scaffold: TailscaleClient, validation schemas, error handling
93
+ - Repository setup: package.json, tsconfig, CLAUDE.md, README, SECURITY.md (#1)
package/CLAUDE.md ADDED
@@ -0,0 +1,180 @@
1
+ # mcp-tailscale — CLAUDE.md
2
+
3
+ ## Table of Contents
4
+
5
+ - [Project Overview](#project-overview)
6
+ - [Architecture](#architecture)
7
+ - [Code Conventions](#code-conventions)
8
+ - [Security](#security)
9
+ - [Design/Plan Documents — MANDATORY](#designplan-documents--mandatory)
10
+ - [CHANGELOG.md — MANDATORY](#changelogmd--mandatory)
11
+ - [Versioning & Releases (CalVer)](#versioning--releases-calver)
12
+ - [Git Workflow](#git-workflow)
13
+ - [Language](#language)
14
+ - [Development Setup](#development-setup)
15
+ - [Testing](#testing)
16
+
17
+ ## Project Overview
18
+
19
+ Slim Tailscale MCP Server for managing devices, DNS/Split DNS, ACL policies, auth keys, users, webhooks, and tailnet settings via Tailscale API v2.
20
+
21
+ **No SSH. No shell execution. API-only. 4 runtime dependencies.**
22
+
23
+ ## Architecture
24
+
25
+ ```
26
+ src/
27
+ index.ts # MCP Server entry point (stdio + SSE transport)
28
+ transport.ts # Transport config validation + auth middleware
29
+ client/
30
+ tailscale-client.ts # Axios HTTP client (API key Bearer token auth)
31
+ tailscale-oauth-client.ts # OAuth client credentials auth (auto-refresh)
32
+ client-factory.ts # Client selection (OAuth > API key) from env vars
33
+ types.ts # Tailscale API v2 response types + ITailscaleClient interface
34
+ tools/
35
+ devices.ts # Device management tools (11 tools)
36
+ dns.ts # DNS nameservers, search paths, split DNS, preferences (8 tools)
37
+ acl.ts # ACL policy management (5 tools)
38
+ keys.ts # Auth key management (4 tools)
39
+ tailnet.ts # Tailnet settings (read/write), contacts, lock status (5 tools)
40
+ users.ts # User management tools (2 tools)
41
+ webhooks.ts # Webhook management tools (4 tools)
42
+ posture.ts # Posture integration tools (4 tools)
43
+ diagnostics.ts # Status, API verify, log streaming, DERP map (5 tools)
44
+ utils/
45
+ validation.ts # Shared Zod schemas (device IDs, CIDR, domains, etc.)
46
+ errors.ts # Tailscale error extraction and TailscaleApiError
47
+ tests/ # Vitest unit tests
48
+ docs/
49
+ plans/ # Design/plan documents
50
+ api-reference.md # Tailscale API v2 endpoint mapping
51
+ ```
52
+
53
+ ## Code Conventions
54
+
55
+ ### TypeScript
56
+ - Strict mode enabled (`"strict": true` in tsconfig.json)
57
+ - All tool parameters validated with Zod schemas
58
+ - Generically typed API client (`get<T>()`, `post<T>()`, `put<T>()`, `patch<T>()`, `delete<T>()`, `deleteVoid()`, `postVoid()`)
59
+ - No `any` types — use `unknown` and narrow
60
+
61
+ ### Tool Design
62
+ - **Granular tools**: one MCP tool per operation (e.g., `tailscale_device_routes_set`)
63
+ - Tool naming: `tailscale_<domain>_<action>`
64
+ - Each tool has its own Zod input schema and clear description
65
+ - Destructive operations require `confirm: true` parameter
66
+ - Response format: always `{ content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }`
67
+
68
+ ### Tailscale API Specifics
69
+ - Auth: Bearer token (API key), not Global API Key
70
+ - Base URL: `https://api.tailscale.com/api/v2`
71
+ - Response format: Direct JSON — no `{ success, errors, result }` wrapper
72
+ - Tailnet required: Most endpoints use `/tailnet/{tailnet}/` prefix
73
+ - Device endpoints: `/device/{deviceId}/` (not tailnet-scoped)
74
+
75
+ ### Dependencies
76
+ - **4 runtime dependencies**: `@modelcontextprotocol/sdk`, `axios`, `express`, `zod`
77
+ - No SSH libraries, no Redis, no PostgreSQL
78
+ - Dev: `typescript`, `vitest`, `@types/node`
79
+
80
+ ## Security
81
+
82
+ - **Transport**: stdio (default) or SSE with mandatory Bearer token auth (`crypto.timingSafeEqual`)
83
+ - **Authentication**: API Key exclusively via environment variables. Never hardcoded, logged, or committed.
84
+ - **No SSH**: Exclusively Tailscale REST API v2
85
+ - **Input validation**: Zod schemas for all tool parameters
86
+ - **Error handling**: No credential leaks in error messages (Bearer token never appears in logs or errors)
87
+ - **Credentials**: Never hardcoded, never logged, never in git
88
+ - **Secret Redaction — MANDATORY**: When using `grep`, `cat`, `sed`, `awk`, shell scripts, or any tool that reads/displays file contents containing secrets (`.env`, credentials, API keys, tokens, passwords), **ALWAYS redact the secret values** in output. Never display raw secret values in terminal output, logs, conversation context, or commit messages.
89
+ - **Public Repo Documentation Policy — MANDATORY**: This is a **public repository**. All documentation, code examples, test data, and commit messages MUST use only generic placeholders:
90
+ - Tailnet names: `your-tailnet-name`, `example.com`
91
+ - Device IDs: `123456789`
92
+ - API keys: `your-api-key-here`, `tskey-api-test`
93
+ - Emails: `admin@example.com`, `user@example.com`
94
+ - IPs: `100.64.0.1`, `10.0.0.0/8` (Tailscale CGNAT range is acceptable as generic example)
95
+ - **NEVER** include real tailnet names, device IDs, API keys, or internal topology
96
+ - Infrastructure-specific documentation belongs in the private `itunified-io/infrastructure` repo
97
+
98
+ ## Design/Plan Documents — MANDATORY
99
+
100
+ - **Every significant change MUST have a design/plan document** in `docs/plans/`
101
+ - Naming: `docs/plans/<NNN>-<short-description>.md`
102
+ - The design doc MUST be referenced in the corresponding GitHub issue (bidirectional link)
103
+ - Design docs contain: problem, solution, prerequisites, execution steps, rollback, verification
104
+ - Trivial changes (typos, minor doc updates) are exempt
105
+
106
+ ## CHANGELOG.md — MANDATORY
107
+
108
+ - **`CHANGELOG.md` MUST exist and MUST be kept up to date**
109
+ - **Every PR merge MUST add a new entry** before tagging/releasing
110
+ - Format: CalVer date header (`## v2026.03.13.1`) followed by a list of changes with issue references
111
+ - Never skip CHANGELOG updates — they are the source of truth for what changed and when
112
+
113
+ ## Versioning & Releases (CalVer)
114
+
115
+ - Schema: `YYYY.MM.DD.TS` (e.g., `2026.03.13.1`)
116
+ - `package.json`: npm-compatible without leading zeros (`2026.3.13`)
117
+ - Git tags: `v2026.03.13.1` (leading zeros for sorting)
118
+
119
+ ### Release Workflow — MANDATORY after every PR merge
120
+ 1. **Update CHANGELOG.md** with new version entry
121
+ 2. Update `package.json` version if date changed
122
+ 3. Create annotated git tag: `git tag -a v2026.03.13.1 -m "v2026.03.13.1: <summary>"`
123
+ 4. Push tag: `git push origin --tags`
124
+ 5. Create GitHub release: `gh release create v2026.03.13.1 --title "v2026.03.13.1 — <title>" --notes "<release notes>"`
125
+ 6. Release notes must list what changed and reference closed issues
126
+
127
+ ## Git Workflow
128
+
129
+ - **NEVER work on main** — all changes via feature branches + PR
130
+ - **Branching**: `feature/<issue-nr>-<description>`, `fix/<issue-nr>-<description>`, `chore/<description>`
131
+ - **Worktree naming**: `.claude/worktrees/<branch-name>`
132
+ - **GitHub Issues mandatory**: every change must have an associated GH issue
133
+ - **Commit messages**: must reference GH issue — `feat: add device posture tools (#3)` or `fix: handle 404 on device delete (#5)`
134
+ - **No commit without issue reference** (exceptions: initial setup, typo fixes)
135
+ - **PR workflow**: feature branch -> `gh pr create` -> review -> merge into main
136
+ - **Acceptance Criteria Gate — MANDATORY** (see [ADR-0017](https://github.com/itunified-io/infrastructure/blob/main/docs/adr/0017-acceptance-criteria-before-merge.md)):
137
+ - All acceptance criteria in the associated GH issue MUST be checked and verified as successful before merge to `main`
138
+ - Verification is active: criteria must be actually tested, not assumed to pass
139
+ - Includes: tests pass (`npm test`), build succeeds (`npm run build`), live tests pass (`/ts-test`), CHANGELOG updated, docs updated
140
+ - If any criterion cannot be satisfied, the PR must NOT be merged
141
+ - **After PR merge: branch/worktree cleanup is mandatory** — `git branch -d <branch>`, `git remote prune origin`, remove worktree
142
+
143
+ ### Bug Fixes — MANDATORY Workflow
144
+ - **Every bug fix MUST have a GitHub issue** with appropriate labels (`bug`, scope labels)
145
+ - Issue-first: create issue → branch (`fix/<issue-nr>-<description>`) → fix → PR → merge
146
+ - Bug fix commits must reference the issue: `fix: <description> (#<nr>)`
147
+ - CHANGELOG entry required for every bug fix
148
+
149
+ ## Language
150
+
151
+ - All documentation, code comments, commit messages: **English only**
152
+
153
+ ## Development Setup
154
+
155
+ ```bash
156
+ # Prerequisites: Node.js >= 20, npm
157
+
158
+ # Install dependencies
159
+ npm install
160
+
161
+ # Copy and configure environment
162
+ cp .env.example .env
163
+ # Edit .env with your Tailscale API key and tailnet name
164
+
165
+ # Build
166
+ npm run build
167
+
168
+ # Test
169
+ npm test
170
+
171
+ # Run (stdio transport)
172
+ node dist/index.js
173
+ ```
174
+
175
+ ## Testing
176
+
177
+ - Unit tests with vitest (mocked API responses)
178
+ - Zod schema validation for invalid inputs
179
+ - Error handling for API errors (401, 403, 404, 500)
180
+ - Run: `npm test`
@@ -0,0 +1,44 @@
1
+ # Commercial License
2
+
3
+ ## mcp-tailscale — Commercial Licensing
4
+
5
+ This project is dual-licensed:
6
+
7
+ 1. **Open Source** — [GNU Affero General Public License v3.0 (AGPL-3.0)](LICENSE)
8
+ 2. **Commercial** — Available for organizations that cannot or prefer not to comply with AGPL-3.0 terms
9
+
10
+ ## When You Need a Commercial License
11
+
12
+ The AGPL-3.0 requires that if you modify this software or use it as part of a network service, you must make the complete source code of your application available under the AGPL-3.0. A commercial license removes this requirement.
13
+
14
+ You likely need a commercial license if:
15
+
16
+ - You integrate mcp-tailscale into a **proprietary product or service**
17
+ - You offer mcp-tailscale as part of a **managed or SaaS platform** without releasing your source code
18
+ - You **modify** the software and do not want to release your modifications under AGPL-3.0
19
+ - Your organization's **legal or compliance policies** prohibit use of AGPL-licensed software
20
+
21
+ ## When You Do NOT Need a Commercial License
22
+
23
+ - **Personal or non-commercial use** — using the software for personal projects or non-commercial purposes
24
+ - **Open-source projects** — integrating with other AGPL-3.0 or compatible open-source projects
25
+ - **Unmodified use** — running the unmodified MCP server to manage your own Tailscale tailnet
26
+
27
+ ## Obtaining a Commercial License
28
+
29
+ Contact us to discuss commercial licensing options:
30
+
31
+ - **GitHub Sponsors**: <https://github.com/sponsors/itunified-io>
32
+
33
+ Commercial licenses are priced based on scope and usage. Sponsoring the project through GitHub Sponsors is the primary way to support development and obtain commercial terms.
34
+
35
+ ## FAQ
36
+
37
+ **Q: Can I use mcp-tailscale for free in my company?**
38
+ A: Only if you fully comply with the AGPL-3.0 license terms, which requires making your complete source code available under AGPL-3.0. If your company uses mcp-tailscale internally for commercial operations and does not want to release its source code, a commercial license is required.
39
+
40
+ **Q: Does the AGPL apply if I just run the MCP server internally?**
41
+ A: Running the server internally within a commercial organization requires either full AGPL-3.0 compliance (including releasing your source code) or a commercial license. The AGPL-3.0 free use is intended for personal and non-commercial purposes only.
42
+
43
+ **Q: What if I build a product that includes mcp-tailscale?**
44
+ A: If your product is proprietary (closed-source), you need a commercial license. If your product is also AGPL-3.0 licensed, you can use it under the open-source license.
@@ -0,0 +1,54 @@
1
+ # Contributing to mcp-tailscale
2
+
3
+ Thank you for your interest in contributing!
4
+
5
+ ## Workflow
6
+
7
+ 1. **Issue first** — Create a GitHub issue describing the change before starting work
8
+ 2. **Fork & branch** — Fork the repo, create a feature branch: `feature/<issue-nr>-<description>`
9
+ 3. **Develop** — Write code, add tests, update documentation
10
+ 4. **Test** — Ensure all tests pass: `npm test`
11
+ 5. **PR** — Create a pull request referencing the issue
12
+
13
+ ## Branch Naming
14
+
15
+ - `feature/<issue-nr>-<description>` — New features
16
+ - `fix/<issue-nr>-<description>` — Bug fixes
17
+ - `chore/<description>` — Maintenance tasks
18
+
19
+ ## Commit Messages
20
+
21
+ Use conventional commits with issue references:
22
+
23
+ ```
24
+ feat: add device posture tools (#12)
25
+ fix: handle 404 on device delete gracefully (#5)
26
+ chore: update dependencies
27
+ ```
28
+
29
+ ## Code Standards
30
+
31
+ - TypeScript strict mode
32
+ - All tool parameters validated with Zod schemas
33
+ - No `any` types
34
+ - No SSH or shell execution
35
+ - Credentials only via environment variables
36
+ - Tests for all new tools
37
+ - Tool naming: `tailscale_<domain>_<action>`
38
+
39
+ ## Documentation
40
+
41
+ - All documentation MUST use generic placeholders only (see CLAUDE.md Security section)
42
+ - No real tailnet names, device IDs, API keys, or internal topology in any file
43
+ - Use `your-tailnet-name`, `your-api-key-here`, `example.com`
44
+
45
+ ## Review
46
+
47
+ - All PRs require code review before merging
48
+ - Tests must pass
49
+ - Documentation must be updated (especially README.md)
50
+ - CHANGELOG.md must be updated before tagging/releasing
51
+
52
+ ## After Merge
53
+
54
+ Branch and worktree cleanup is mandatory after PR merge to prevent drift.