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.
- package/.env.example +17 -0
- package/ARCHITECTURE.md +220 -0
- package/CHANGELOG.md +93 -0
- package/CLAUDE.md +180 -0
- package/COMMERCIAL_LICENSE.md +44 -0
- package/CONTRIBUTING.md +54 -0
- package/LICENSE +661 -0
- package/PRODUCT_PACKAGING.md +138 -0
- package/README.md +276 -0
- package/ROADMAP.md +67 -0
- package/SECURITY.md +24 -0
- package/dist/client/client-factory.d.ts +12 -0
- package/dist/client/client-factory.d.ts.map +1 -0
- package/dist/client/client-factory.js +31 -0
- package/dist/client/client-factory.js.map +1 -0
- package/dist/client/tailscale-client.d.ts +18 -0
- package/dist/client/tailscale-client.d.ts.map +1 -0
- package/dist/client/tailscale-client.js +101 -0
- package/dist/client/tailscale-client.js.map +1 -0
- package/dist/client/tailscale-oauth-client.d.ts +19 -0
- package/dist/client/tailscale-oauth-client.d.ts.map +1 -0
- package/dist/client/tailscale-oauth-client.js +119 -0
- package/dist/client/tailscale-oauth-client.js.map +1 -0
- package/dist/client/types.d.ts +281 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +3 -0
- package/dist/client/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +100 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/acl.d.ts +80 -0
- package/dist/tools/acl.d.ts.map +1 -0
- package/dist/tools/acl.js +180 -0
- package/dist/tools/acl.js.map +1 -0
- package/dist/tools/devices.d.ts +162 -0
- package/dist/tools/devices.d.ts.map +1 -0
- package/dist/tools/devices.js +347 -0
- package/dist/tools/devices.js.map +1 -0
- package/dist/tools/diagnostics.d.ts +65 -0
- package/dist/tools/diagnostics.d.ts.map +1 -0
- package/dist/tools/diagnostics.js +178 -0
- package/dist/tools/diagnostics.js.map +1 -0
- package/dist/tools/dns.d.ts +98 -0
- package/dist/tools/dns.d.ts.map +1 -0
- package/dist/tools/dns.js +179 -0
- package/dist/tools/dns.js.map +1 -0
- package/dist/tools/keys.d.ts +107 -0
- package/dist/tools/keys.d.ts.map +1 -0
- package/dist/tools/keys.js +167 -0
- package/dist/tools/keys.js.map +1 -0
- package/dist/tools/posture.d.ts +98 -0
- package/dist/tools/posture.d.ts.map +1 -0
- package/dist/tools/posture.js +155 -0
- package/dist/tools/posture.js.map +1 -0
- package/dist/tools/tailnet.d.ts +132 -0
- package/dist/tools/tailnet.d.ts.map +1 -0
- package/dist/tools/tailnet.js +222 -0
- package/dist/tools/tailnet.js.map +1 -0
- package/dist/tools/users.d.ts +44 -0
- package/dist/tools/users.d.ts.map +1 -0
- package/dist/tools/users.js +90 -0
- package/dist/tools/users.js.map +1 -0
- package/dist/tools/webhooks.d.ts +88 -0
- package/dist/tools/webhooks.d.ts.map +1 -0
- package/dist/tools/webhooks.js +168 -0
- package/dist/tools/webhooks.js.map +1 -0
- package/dist/transport.d.ts +13 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +42 -0
- package/dist/transport.js.map +1 -0
- package/dist/utils/errors.d.ts +8 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +42 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/validation.d.ts +18 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +35 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +55 -0
- 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
|
package/ARCHITECTURE.md
ADDED
|
@@ -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.
|
package/CONTRIBUTING.md
ADDED
|
@@ -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.
|