@yawlabs/tailscale-mcp 0.1.4 → 0.1.6
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/README.md +40 -6
- package/dist/api.d.ts +3 -0
- package/dist/api.js +11 -1
- package/dist/api.js.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/tools/audit.js +13 -0
- package/dist/tools/audit.js.map +1 -1
- package/dist/tools/devices.d.ts +4 -4
- package/dist/tools/devices.js +26 -19
- package/dist/tools/devices.js.map +1 -1
- package/dist/tools/dns.d.ts +3 -3
- package/dist/tools/dns.js +5 -5
- package/dist/tools/dns.js.map +1 -1
- package/dist/tools/invites.d.ts +102 -0
- package/dist/tools/invites.js +110 -0
- package/dist/tools/invites.js.map +1 -0
- package/dist/tools/keys.d.ts +2 -2
- package/dist/tools/keys.js +5 -5
- package/dist/tools/keys.js.map +1 -1
- package/dist/tools/posture.d.ts +31 -2
- package/dist/tools/posture.js +26 -5
- package/dist/tools/posture.js.map +1 -1
- package/dist/tools/users.d.ts +1 -1
- package/dist/tools/users.js +7 -7
- package/dist/tools/users.js.map +1 -1
- package/dist/tools/webhooks.d.ts +13 -0
- package/dist/tools/webhooks.js +14 -4
- package/dist/tools/webhooks.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://github.com/YawLabs/tailscale-mcp/stargazers)
|
|
6
6
|
|
|
7
|
-
**Manage your Tailscale tailnet from Claude Code, Cursor, and any MCP client.**
|
|
7
|
+
**Manage your Tailscale tailnet from Claude Code, Cursor, and any MCP client.** 62 tools. One env var. Works on first try.
|
|
8
8
|
|
|
9
9
|
Built and maintained by [YawLabs](https://yaw.sh).
|
|
10
10
|
|
|
11
11
|
## Why this one?
|
|
12
12
|
|
|
13
|
-
Other Tailscale MCP servers were vibe-coded in a weekend and abandoned. This one was built for production use and tested against the real Tailscale API
|
|
13
|
+
Other Tailscale MCP servers were vibe-coded in a weekend and abandoned. This one was built for production use and tested against the real Tailscale API.
|
|
14
14
|
|
|
15
15
|
- **Preserves ACL formatting** — reads and writes HuJSON (comments, trailing commas, indentation). Others compact your carefully formatted policy into a single line.
|
|
16
16
|
- **Safe ACL updates** — uses ETags to prevent overwriting concurrent changes. No silent data loss.
|
|
@@ -72,14 +72,17 @@ The server checks for an API key first, then falls back to OAuth. If neither is
|
|
|
72
72
|
|
|
73
73
|
**Tailnet:** Uses your default tailnet automatically. Set `TAILSCALE_TAILNET` to specify one explicitly.
|
|
74
74
|
|
|
75
|
-
## Tools (
|
|
75
|
+
## Tools (62)
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
<details>
|
|
78
|
+
<summary><strong>Status</strong> (1 tool)</summary>
|
|
78
79
|
|
|
79
80
|
| Tool | Description |
|
|
80
81
|
|------|-------------|
|
|
81
82
|
| `tailscale_status` | Verify API connection, see tailnet info and device count |
|
|
82
83
|
|
|
84
|
+
</details>
|
|
85
|
+
|
|
83
86
|
<details>
|
|
84
87
|
<summary><strong>Devices</strong> (13 tools)</summary>
|
|
85
88
|
|
|
@@ -177,7 +180,7 @@ The server checks for an API key first, then falls back to OAuth. If neither is
|
|
|
177
180
|
</details>
|
|
178
181
|
|
|
179
182
|
<details>
|
|
180
|
-
<summary><strong>Webhooks</strong> (
|
|
183
|
+
<summary><strong>Webhooks</strong> (6 tools)</summary>
|
|
181
184
|
|
|
182
185
|
| Tool | Description |
|
|
183
186
|
|------|-------------|
|
|
@@ -186,21 +189,47 @@ The server checks for an API key first, then falls back to OAuth. If neither is
|
|
|
186
189
|
| `tailscale_create_webhook` | Create a webhook |
|
|
187
190
|
| `tailscale_update_webhook` | Update a webhook's endpoint URL and/or subscriptions |
|
|
188
191
|
| `tailscale_delete_webhook` | Delete a webhook |
|
|
192
|
+
| `tailscale_rotate_webhook_secret` | Rotate a webhook's secret |
|
|
189
193
|
|
|
190
194
|
</details>
|
|
191
195
|
|
|
192
196
|
<details>
|
|
193
|
-
<summary><strong>Posture Integrations</strong> (
|
|
197
|
+
<summary><strong>Posture Integrations</strong> (5 tools)</summary>
|
|
194
198
|
|
|
195
199
|
| Tool | Description |
|
|
196
200
|
|------|-------------|
|
|
197
201
|
| `tailscale_list_posture_integrations` | List posture integrations |
|
|
198
202
|
| `tailscale_get_posture_integration` | Get a posture integration |
|
|
199
203
|
| `tailscale_create_posture_integration` | Create a posture integration |
|
|
204
|
+
| `tailscale_update_posture_integration` | Update a posture integration |
|
|
200
205
|
| `tailscale_delete_posture_integration` | Delete a posture integration |
|
|
201
206
|
|
|
202
207
|
</details>
|
|
203
208
|
|
|
209
|
+
<details>
|
|
210
|
+
<summary><strong>Device Invites</strong> (4 tools)</summary>
|
|
211
|
+
|
|
212
|
+
| Tool | Description |
|
|
213
|
+
|------|-------------|
|
|
214
|
+
| `tailscale_list_device_invites` | List device invites |
|
|
215
|
+
| `tailscale_create_device_invite` | Create a device invite |
|
|
216
|
+
| `tailscale_get_device_invite` | Get a device invite |
|
|
217
|
+
| `tailscale_delete_device_invite` | Delete a device invite |
|
|
218
|
+
|
|
219
|
+
</details>
|
|
220
|
+
|
|
221
|
+
<details>
|
|
222
|
+
<summary><strong>User Invites</strong> (4 tools)</summary>
|
|
223
|
+
|
|
224
|
+
| Tool | Description |
|
|
225
|
+
|------|-------------|
|
|
226
|
+
| `tailscale_list_user_invites` | List user invites |
|
|
227
|
+
| `tailscale_create_user_invite` | Create a user invite |
|
|
228
|
+
| `tailscale_get_user_invite` | Get a user invite |
|
|
229
|
+
| `tailscale_delete_user_invite` | Delete a user invite |
|
|
230
|
+
|
|
231
|
+
</details>
|
|
232
|
+
|
|
204
233
|
<details>
|
|
205
234
|
<summary><strong>Logging</strong> (2 tools)</summary>
|
|
206
235
|
|
|
@@ -211,6 +240,10 @@ The server checks for an API key first, then falls back to OAuth. If neither is
|
|
|
211
240
|
|
|
212
241
|
</details>
|
|
213
242
|
|
|
243
|
+
## Requirements
|
|
244
|
+
|
|
245
|
+
- Node.js 18 or higher
|
|
246
|
+
|
|
214
247
|
## Contributing
|
|
215
248
|
|
|
216
249
|
Contributions are welcome. Please [open an issue](https://github.com/YawLabs/tailscale-mcp/issues) to discuss what you'd like to change before submitting a PR.
|
|
@@ -222,6 +255,7 @@ git clone https://github.com/YawLabs/tailscale-mcp.git
|
|
|
222
255
|
cd tailscale-mcp
|
|
223
256
|
npm install
|
|
224
257
|
npm run build
|
|
258
|
+
npm test
|
|
225
259
|
```
|
|
226
260
|
|
|
227
261
|
Test against your own tailnet by setting `TAILSCALE_API_KEY` and running:
|
package/dist/api.d.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Tailscale API client with API key and OAuth authentication.
|
|
3
3
|
*/
|
|
4
4
|
export declare function getTailnet(): string;
|
|
5
|
+
/** URL-encode a path segment to prevent path traversal. */
|
|
6
|
+
export declare function encPath(segment: string): string;
|
|
5
7
|
export interface ApiResponse<T = unknown> {
|
|
6
8
|
ok: boolean;
|
|
7
9
|
status: number;
|
|
@@ -28,5 +30,6 @@ export declare function apiPost<T = unknown>(path: string, body?: unknown, optio
|
|
|
28
30
|
contentType?: string;
|
|
29
31
|
ifMatch?: string;
|
|
30
32
|
}): Promise<ApiResponse<T>>;
|
|
33
|
+
export declare function apiPut<T = unknown>(path: string, body?: unknown): Promise<ApiResponse<T>>;
|
|
31
34
|
export declare function apiPatch<T = unknown>(path: string, body?: unknown): Promise<ApiResponse<T>>;
|
|
32
35
|
export declare function apiDelete<T = unknown>(path: string): Promise<ApiResponse<T>>;
|
package/dist/api.js
CHANGED
|
@@ -12,7 +12,10 @@ function getConfig() {
|
|
|
12
12
|
const tailnet = process.env.TAILSCALE_TAILNET || "-";
|
|
13
13
|
if (!apiKey && !(oauthClientId && oauthClientSecret)) {
|
|
14
14
|
throw new Error("No Tailscale credentials configured. " +
|
|
15
|
-
"Set TAILSCALE_API_KEY, or set TAILSCALE_OAUTH_CLIENT_ID and TAILSCALE_OAUTH_CLIENT_SECRET.");
|
|
15
|
+
"Set TAILSCALE_API_KEY, or set both TAILSCALE_OAUTH_CLIENT_ID and TAILSCALE_OAUTH_CLIENT_SECRET.");
|
|
16
|
+
}
|
|
17
|
+
if (apiKey && apiKey.trim() === "") {
|
|
18
|
+
throw new Error("TAILSCALE_API_KEY is set but empty. Provide a valid API key.");
|
|
16
19
|
}
|
|
17
20
|
return { apiKey, oauthClientId, oauthClientSecret, tailnet };
|
|
18
21
|
}
|
|
@@ -64,6 +67,10 @@ async function getAuthHeader() {
|
|
|
64
67
|
export function getTailnet() {
|
|
65
68
|
return process.env.TAILSCALE_TAILNET || "-";
|
|
66
69
|
}
|
|
70
|
+
/** URL-encode a path segment to prevent path traversal. */
|
|
71
|
+
export function encPath(segment) {
|
|
72
|
+
return encodeURIComponent(segment);
|
|
73
|
+
}
|
|
67
74
|
export async function apiRequest(method, path, body, options) {
|
|
68
75
|
const auth = await getAuthHeader();
|
|
69
76
|
const headers = {
|
|
@@ -115,6 +122,9 @@ export async function apiGet(path, options) {
|
|
|
115
122
|
export async function apiPost(path, body, options) {
|
|
116
123
|
return apiRequest("POST", path, body, options);
|
|
117
124
|
}
|
|
125
|
+
export async function apiPut(path, body) {
|
|
126
|
+
return apiRequest("PUT", path, body);
|
|
127
|
+
}
|
|
118
128
|
export async function apiPatch(path, body) {
|
|
119
129
|
return apiRequest("PATCH", path, body);
|
|
120
130
|
}
|
package/dist/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,QAAQ,GAAG,kCAAkC,CAAC;AACpD,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAOlC,IAAI,UAAU,GAAsB,IAAI,CAAC;AACzC,IAAI,mBAAmB,GAA2B,IAAI,CAAC;AAEvD,SAAS,SAAS;IAChB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC7C,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;IAC5D,MAAM,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC;IACpE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,GAAG,CAAC;IAErD,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,aAAa,IAAI,iBAAiB,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CACb,uCAAuC;YACrC,
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
4
5
|
import { deviceTools } from "./tools/devices.js";
|
|
5
6
|
import { aclTools } from "./tools/acl.js";
|
|
6
7
|
import { dnsTools } from "./tools/dns.js";
|
|
@@ -12,6 +13,9 @@ import { networkLockTools } from "./tools/network-lock.js";
|
|
|
12
13
|
import { postureTools } from "./tools/posture.js";
|
|
13
14
|
import { auditTools } from "./tools/audit.js";
|
|
14
15
|
import { statusTools } from "./tools/status.js";
|
|
16
|
+
import { inviteTools } from "./tools/invites.js";
|
|
17
|
+
const require = createRequire(import.meta.url);
|
|
18
|
+
const { version } = require("../package.json");
|
|
15
19
|
const allTools = [
|
|
16
20
|
...statusTools,
|
|
17
21
|
...deviceTools,
|
|
@@ -24,10 +28,11 @@ const allTools = [
|
|
|
24
28
|
...networkLockTools,
|
|
25
29
|
...postureTools,
|
|
26
30
|
...auditTools,
|
|
31
|
+
...inviteTools,
|
|
27
32
|
];
|
|
28
33
|
const server = new McpServer({
|
|
29
34
|
name: "@yawlabs/tailscale-mcp",
|
|
30
|
-
version
|
|
35
|
+
version,
|
|
31
36
|
});
|
|
32
37
|
for (const tool of allTools) {
|
|
33
38
|
server.tool(tool.name, tool.description, tool.inputSchema.shape, async (input) => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/audit.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { apiGet, getTailnet } from "../api.js";
|
|
3
|
+
/** Validate that a string is a valid RFC3339 date-time. */
|
|
4
|
+
function assertRFC3339(value, label) {
|
|
5
|
+
const d = new Date(value);
|
|
6
|
+
if (isNaN(d.getTime())) {
|
|
7
|
+
throw new Error(`${label} must be a valid RFC3339 date-time (e.g. '2026-04-01T00:00:00Z'), got: '${value}'`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
3
10
|
export const auditTools = [
|
|
4
11
|
{
|
|
5
12
|
name: "tailscale_get_audit_log",
|
|
@@ -14,6 +21,9 @@ export const auditTools = [
|
|
|
14
21
|
.describe("End time in RFC3339 format. Defaults to now."),
|
|
15
22
|
}),
|
|
16
23
|
handler: async (input) => {
|
|
24
|
+
assertRFC3339(input.start, "start");
|
|
25
|
+
if (input.end)
|
|
26
|
+
assertRFC3339(input.end, "end");
|
|
17
27
|
const params = new URLSearchParams({ start: input.start });
|
|
18
28
|
if (input.end)
|
|
19
29
|
params.set("end", input.end);
|
|
@@ -33,6 +43,9 @@ export const auditTools = [
|
|
|
33
43
|
.describe("End time in RFC3339 format. Defaults to now."),
|
|
34
44
|
}),
|
|
35
45
|
handler: async (input) => {
|
|
46
|
+
assertRFC3339(input.start, "start");
|
|
47
|
+
if (input.end)
|
|
48
|
+
assertRFC3339(input.end, "end");
|
|
36
49
|
const params = new URLSearchParams({ start: input.start });
|
|
37
50
|
if (input.end)
|
|
38
51
|
params.set("end", input.end);
|
package/dist/tools/audit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/tools/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE/C,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB;QACE,IAAI,EAAE,yBAAyB;QAC/B,WAAW,EACT,uHAAuH;QACzH,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,CAAC,uEAAuE,CAAC;YACpF,GAAG,EAAE,CAAC;iBACH,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,8CAA8C,CAAC;SAC5D,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAAsC,EAAE,EAAE;YACxD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;YAC3D,IAAI,KAAK,CAAC,GAAG;gBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;YAC5C,OAAO,MAAM,CACX,YAAY,UAAU,EAAE,0BAA0B,MAAM,EAAE,CAC3D,CAAC;QACJ,CAAC;KACF;IACD;QACE,IAAI,EAAE,iCAAiC;QACvC,WAAW,EACT,kMAAkM;QACpM,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,CAAC,uEAAuE,CAAC;YACpF,GAAG,EAAE,CAAC;iBACH,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,8CAA8C,CAAC;SAC5D,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAAsC,EAAE,EAAE;YACxD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;YAC3D,IAAI,KAAK,CAAC,GAAG;gBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;YAC5C,OAAO,MAAM,CACX,YAAY,UAAU,EAAE,oBAAoB,MAAM,EAAE,CACrD,CAAC;QACJ,CAAC;KACF;CACO,CAAC"}
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/tools/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE/C,2DAA2D;AAC3D,SAAS,aAAa,CAAC,KAAa,EAAE,KAAa;IACjD,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1B,IAAI,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,2EAA2E,KAAK,GAAG,CAAC,CAAC;IAC/G,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB;QACE,IAAI,EAAE,yBAAyB;QAC/B,WAAW,EACT,uHAAuH;QACzH,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,CAAC,uEAAuE,CAAC;YACpF,GAAG,EAAE,CAAC;iBACH,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,8CAA8C,CAAC;SAC5D,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAAsC,EAAE,EAAE;YACxD,aAAa,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YACpC,IAAI,KAAK,CAAC,GAAG;gBAAE,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;YAC3D,IAAI,KAAK,CAAC,GAAG;gBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;YAC5C,OAAO,MAAM,CACX,YAAY,UAAU,EAAE,0BAA0B,MAAM,EAAE,CAC3D,CAAC;QACJ,CAAC;KACF;IACD;QACE,IAAI,EAAE,iCAAiC;QACvC,WAAW,EACT,kMAAkM;QACpM,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,CAAC,uEAAuE,CAAC;YACpF,GAAG,EAAE,CAAC;iBACH,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,8CAA8C,CAAC;SAC5D,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAAsC,EAAE,EAAE;YACxD,aAAa,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YACpC,IAAI,KAAK,CAAC,GAAG;gBAAE,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;YAC3D,IAAI,KAAK,CAAC,GAAG;gBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;YAC5C,OAAO,MAAM,CACX,YAAY,UAAU,EAAE,oBAAoB,MAAM,EAAE,CACrD,CAAC;QACJ,CAAC;KACF;CACO,CAAC"}
|
package/dist/tools/devices.d.ts
CHANGED
|
@@ -109,7 +109,7 @@ export declare const deviceTools: readonly [{
|
|
|
109
109
|
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
110
110
|
}, {
|
|
111
111
|
readonly name: "tailscale_set_device_routes";
|
|
112
|
-
readonly description: "
|
|
112
|
+
readonly description: "Set the enabled subnet routes for a device. Replaces all currently enabled routes — pass the full list of routes you want enabled.";
|
|
113
113
|
readonly inputSchema: z.ZodObject<{
|
|
114
114
|
deviceId: z.ZodString;
|
|
115
115
|
routes: z.ZodArray<z.ZodString, "many">;
|
|
@@ -139,7 +139,7 @@ export declare const deviceTools: readonly [{
|
|
|
139
139
|
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
140
140
|
}, {
|
|
141
141
|
readonly name: "tailscale_set_device_posture_attribute";
|
|
142
|
-
readonly description: "Set a custom posture attribute on a device. Attribute keys must start with 'custom:'. Useful for compliance tracking, JIT access, and custom security policies.";
|
|
142
|
+
readonly description: "Set a custom posture attribute on a device. Creates or updates the attribute. Attribute keys must start with 'custom:'. Useful for compliance tracking, JIT access, and custom security policies.";
|
|
143
143
|
readonly inputSchema: z.ZodObject<{
|
|
144
144
|
deviceId: z.ZodString;
|
|
145
145
|
attributeKey: z.ZodString;
|
|
@@ -164,7 +164,7 @@ export declare const deviceTools: readonly [{
|
|
|
164
164
|
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
165
165
|
}, {
|
|
166
166
|
readonly name: "tailscale_delete_device_posture_attribute";
|
|
167
|
-
readonly description: "Delete a custom posture attribute from a device.";
|
|
167
|
+
readonly description: "Delete a custom posture attribute from a device. This is irreversible.";
|
|
168
168
|
readonly inputSchema: z.ZodObject<{
|
|
169
169
|
deviceId: z.ZodString;
|
|
170
170
|
attributeKey: z.ZodString;
|
|
@@ -181,7 +181,7 @@ export declare const deviceTools: readonly [{
|
|
|
181
181
|
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
182
182
|
}, {
|
|
183
183
|
readonly name: "tailscale_set_device_tags";
|
|
184
|
-
readonly description: "Set ACL tags on a device. Replaces all existing tags.";
|
|
184
|
+
readonly description: "Set ACL tags on a device. Replaces all existing tags — pass the full list of tags you want applied.";
|
|
185
185
|
readonly inputSchema: z.ZodObject<{
|
|
186
186
|
deviceId: z.ZodString;
|
|
187
187
|
tags: z.ZodArray<z.ZodString, "many">;
|
package/dist/tools/devices.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { apiGet, apiPost, apiDelete, getTailnet } from "../api.js";
|
|
2
|
+
import { apiGet, apiPost, apiDelete, getTailnet, encPath } from "../api.js";
|
|
3
3
|
export const deviceTools = [
|
|
4
4
|
{
|
|
5
5
|
name: "tailscale_list_devices",
|
|
@@ -22,7 +22,7 @@ export const deviceTools = [
|
|
|
22
22
|
deviceId: z.string().describe("The device ID (numeric or nodekey format)"),
|
|
23
23
|
}),
|
|
24
24
|
handler: async (input) => {
|
|
25
|
-
return apiGet(`/device/${input.deviceId}`);
|
|
25
|
+
return apiGet(`/device/${encPath(input.deviceId)}`);
|
|
26
26
|
},
|
|
27
27
|
},
|
|
28
28
|
{
|
|
@@ -32,7 +32,7 @@ export const deviceTools = [
|
|
|
32
32
|
deviceId: z.string().describe("The device ID to authorize"),
|
|
33
33
|
}),
|
|
34
34
|
handler: async (input) => {
|
|
35
|
-
return apiPost(`/device/${input.deviceId}/authorized`, { authorized: true });
|
|
35
|
+
return apiPost(`/device/${encPath(input.deviceId)}/authorized`, { authorized: true });
|
|
36
36
|
},
|
|
37
37
|
},
|
|
38
38
|
{
|
|
@@ -42,7 +42,7 @@ export const deviceTools = [
|
|
|
42
42
|
deviceId: z.string().describe("The device ID to deauthorize"),
|
|
43
43
|
}),
|
|
44
44
|
handler: async (input) => {
|
|
45
|
-
return apiPost(`/device/${input.deviceId}/authorized`, { authorized: false });
|
|
45
|
+
return apiPost(`/device/${encPath(input.deviceId)}/authorized`, { authorized: false });
|
|
46
46
|
},
|
|
47
47
|
},
|
|
48
48
|
{
|
|
@@ -52,7 +52,7 @@ export const deviceTools = [
|
|
|
52
52
|
deviceId: z.string().describe("The device ID to delete"),
|
|
53
53
|
}),
|
|
54
54
|
handler: async (input) => {
|
|
55
|
-
return apiDelete(`/device/${input.deviceId}`);
|
|
55
|
+
return apiDelete(`/device/${encPath(input.deviceId)}`);
|
|
56
56
|
},
|
|
57
57
|
},
|
|
58
58
|
{
|
|
@@ -63,7 +63,7 @@ export const deviceTools = [
|
|
|
63
63
|
name: z.string().describe("The new name for the device (FQDN within your tailnet)"),
|
|
64
64
|
}),
|
|
65
65
|
handler: async (input) => {
|
|
66
|
-
return apiPost(`/device/${input.deviceId}/name`, { name: input.name });
|
|
66
|
+
return apiPost(`/device/${encPath(input.deviceId)}/name`, { name: input.name });
|
|
67
67
|
},
|
|
68
68
|
},
|
|
69
69
|
{
|
|
@@ -73,7 +73,7 @@ export const deviceTools = [
|
|
|
73
73
|
deviceId: z.string().describe("The device ID to expire"),
|
|
74
74
|
}),
|
|
75
75
|
handler: async (input) => {
|
|
76
|
-
return apiPost(`/device/${input.deviceId}/expire`);
|
|
76
|
+
return apiPost(`/device/${encPath(input.deviceId)}/expire`);
|
|
77
77
|
},
|
|
78
78
|
},
|
|
79
79
|
{
|
|
@@ -83,18 +83,18 @@ export const deviceTools = [
|
|
|
83
83
|
deviceId: z.string().describe("The device ID"),
|
|
84
84
|
}),
|
|
85
85
|
handler: async (input) => {
|
|
86
|
-
return apiGet(`/device/${input.deviceId}/routes`);
|
|
86
|
+
return apiGet(`/device/${encPath(input.deviceId)}/routes`);
|
|
87
87
|
},
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
90
|
name: "tailscale_set_device_routes",
|
|
91
|
-
description: "
|
|
91
|
+
description: "Set the enabled subnet routes for a device. Replaces all currently enabled routes — pass the full list of routes you want enabled.",
|
|
92
92
|
inputSchema: z.object({
|
|
93
93
|
deviceId: z.string().describe("The device ID"),
|
|
94
|
-
routes: z.array(z.string()).describe("
|
|
94
|
+
routes: z.array(z.string()).describe("Full list of CIDR routes to enable (e.g. ['10.0.0.0/24', '192.168.1.0/24']). Replaces existing enabled routes."),
|
|
95
95
|
}),
|
|
96
96
|
handler: async (input) => {
|
|
97
|
-
return apiPost(`/device/${input.deviceId}/routes`, { routes: input.routes });
|
|
97
|
+
return apiPost(`/device/${encPath(input.deviceId)}/routes`, { routes: input.routes });
|
|
98
98
|
},
|
|
99
99
|
},
|
|
100
100
|
{
|
|
@@ -104,12 +104,12 @@ export const deviceTools = [
|
|
|
104
104
|
deviceId: z.string().describe("The device ID"),
|
|
105
105
|
}),
|
|
106
106
|
handler: async (input) => {
|
|
107
|
-
return apiGet(`/device/${input.deviceId}/attributes`);
|
|
107
|
+
return apiGet(`/device/${encPath(input.deviceId)}/attributes`);
|
|
108
108
|
},
|
|
109
109
|
},
|
|
110
110
|
{
|
|
111
111
|
name: "tailscale_set_device_posture_attribute",
|
|
112
|
-
description: "Set a custom posture attribute on a device. Attribute keys must start with 'custom:'. Useful for compliance tracking, JIT access, and custom security policies.",
|
|
112
|
+
description: "Set a custom posture attribute on a device. Creates or updates the attribute. Attribute keys must start with 'custom:'. Useful for compliance tracking, JIT access, and custom security policies.",
|
|
113
113
|
inputSchema: z.object({
|
|
114
114
|
deviceId: z.string().describe("The device ID"),
|
|
115
115
|
attributeKey: z.string().describe("The attribute key (must start with 'custom:', e.g. 'custom:lastAuditDate')"),
|
|
@@ -117,32 +117,39 @@ export const deviceTools = [
|
|
|
117
117
|
expiry: z.string().optional().describe("Optional expiry time in RFC3339 format (e.g. '2026-12-01T00:00:00Z'). Attribute is automatically removed after expiry."),
|
|
118
118
|
}),
|
|
119
119
|
handler: async (input) => {
|
|
120
|
+
if (!input.attributeKey.startsWith("custom:")) {
|
|
121
|
+
throw new Error(`attributeKey must start with 'custom:' prefix, got: '${input.attributeKey}'`);
|
|
122
|
+
}
|
|
120
123
|
const body = { value: input.value };
|
|
121
124
|
if (input.expiry !== undefined)
|
|
122
125
|
body.expiry = input.expiry;
|
|
123
|
-
return apiPost(`/device/${input.deviceId}/attributes/${input.attributeKey}`, body);
|
|
126
|
+
return apiPost(`/device/${encPath(input.deviceId)}/attributes/${encPath(input.attributeKey)}`, body);
|
|
124
127
|
},
|
|
125
128
|
},
|
|
126
129
|
{
|
|
127
130
|
name: "tailscale_delete_device_posture_attribute",
|
|
128
|
-
description: "Delete a custom posture attribute from a device.",
|
|
131
|
+
description: "Delete a custom posture attribute from a device. This is irreversible.",
|
|
129
132
|
inputSchema: z.object({
|
|
130
133
|
deviceId: z.string().describe("The device ID"),
|
|
131
134
|
attributeKey: z.string().describe("The attribute key to delete (e.g. 'custom:lastAuditDate')"),
|
|
132
135
|
}),
|
|
133
136
|
handler: async (input) => {
|
|
134
|
-
return apiDelete(`/device/${input.deviceId}/attributes/${input.attributeKey}`);
|
|
137
|
+
return apiDelete(`/device/${encPath(input.deviceId)}/attributes/${encPath(input.attributeKey)}`);
|
|
135
138
|
},
|
|
136
139
|
},
|
|
137
140
|
{
|
|
138
141
|
name: "tailscale_set_device_tags",
|
|
139
|
-
description: "Set ACL tags on a device. Replaces all existing tags.",
|
|
142
|
+
description: "Set ACL tags on a device. Replaces all existing tags — pass the full list of tags you want applied.",
|
|
140
143
|
inputSchema: z.object({
|
|
141
144
|
deviceId: z.string().describe("The device ID"),
|
|
142
|
-
tags: z.array(z.string()).describe("
|
|
145
|
+
tags: z.array(z.string()).describe("Full list of ACL tags (e.g. ['tag:server', 'tag:production']). Replaces all existing tags."),
|
|
143
146
|
}),
|
|
144
147
|
handler: async (input) => {
|
|
145
|
-
|
|
148
|
+
const invalid = input.tags.filter((t) => !t.startsWith("tag:"));
|
|
149
|
+
if (invalid.length > 0) {
|
|
150
|
+
throw new Error(`All tags must start with 'tag:' prefix. Invalid tags: ${invalid.join(", ")}`);
|
|
151
|
+
}
|
|
152
|
+
return apiPost(`/device/${encPath(input.deviceId)}/tags`, { tags: input.tags });
|
|
146
153
|
},
|
|
147
154
|
},
|
|
148
155
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devices.js","sourceRoot":"","sources":["../../src/tools/devices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"devices.js","sourceRoot":"","sources":["../../src/tools/devices.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/dns.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export declare const dnsTools: readonly [{
|
|
|
6
6
|
readonly handler: () => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
7
7
|
}, {
|
|
8
8
|
readonly name: "tailscale_set_nameservers";
|
|
9
|
-
readonly description: "Set the DNS nameservers for your tailnet.";
|
|
9
|
+
readonly description: "Set the DNS nameservers for your tailnet. Replaces all existing nameservers.";
|
|
10
10
|
readonly inputSchema: z.ZodObject<{
|
|
11
11
|
dns: z.ZodArray<z.ZodString, "many">;
|
|
12
12
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -24,7 +24,7 @@ export declare const dnsTools: readonly [{
|
|
|
24
24
|
readonly handler: () => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
25
25
|
}, {
|
|
26
26
|
readonly name: "tailscale_set_search_paths";
|
|
27
|
-
readonly description: "Set the DNS search paths for your tailnet.";
|
|
27
|
+
readonly description: "Set the DNS search paths for your tailnet. Replaces all existing search paths.";
|
|
28
28
|
readonly inputSchema: z.ZodObject<{
|
|
29
29
|
searchPaths: z.ZodArray<z.ZodString, "many">;
|
|
30
30
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -42,7 +42,7 @@ export declare const dnsTools: readonly [{
|
|
|
42
42
|
readonly handler: () => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
43
43
|
}, {
|
|
44
44
|
readonly name: "tailscale_set_split_dns";
|
|
45
|
-
readonly description: "Set split DNS configuration. Maps domains to specific nameservers.";
|
|
45
|
+
readonly description: "Set split DNS configuration. Maps domains to specific nameservers. Replaces the entire split DNS configuration.";
|
|
46
46
|
readonly inputSchema: z.ZodObject<{
|
|
47
47
|
splitDns: z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>;
|
|
48
48
|
}, "strip", z.ZodTypeAny, {
|
package/dist/tools/dns.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { apiGet, apiPost, getTailnet } from "../api.js";
|
|
2
|
+
import { apiGet, apiPost, apiPut, getTailnet } from "../api.js";
|
|
3
3
|
export const dnsTools = [
|
|
4
4
|
{
|
|
5
5
|
name: "tailscale_get_nameservers",
|
|
@@ -11,7 +11,7 @@ export const dnsTools = [
|
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
name: "tailscale_set_nameservers",
|
|
14
|
-
description: "Set the DNS nameservers for your tailnet.",
|
|
14
|
+
description: "Set the DNS nameservers for your tailnet. Replaces all existing nameservers.",
|
|
15
15
|
inputSchema: z.object({
|
|
16
16
|
dns: z.array(z.string()).describe("List of DNS server IP addresses (e.g. ['8.8.8.8', '1.1.1.1'])"),
|
|
17
17
|
}),
|
|
@@ -29,7 +29,7 @@ export const dnsTools = [
|
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
name: "tailscale_set_search_paths",
|
|
32
|
-
description: "Set the DNS search paths for your tailnet.",
|
|
32
|
+
description: "Set the DNS search paths for your tailnet. Replaces all existing search paths.",
|
|
33
33
|
inputSchema: z.object({
|
|
34
34
|
searchPaths: z.array(z.string()).describe("List of DNS search domains (e.g. ['example.com', 'internal.corp'])"),
|
|
35
35
|
}),
|
|
@@ -49,14 +49,14 @@ export const dnsTools = [
|
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
name: "tailscale_set_split_dns",
|
|
52
|
-
description: "Set split DNS configuration. Maps domains to specific nameservers.",
|
|
52
|
+
description: "Set split DNS configuration. Maps domains to specific nameservers. Replaces the entire split DNS configuration.",
|
|
53
53
|
inputSchema: z.object({
|
|
54
54
|
splitDns: z
|
|
55
55
|
.record(z.string(), z.array(z.string()))
|
|
56
56
|
.describe("Map of domain to nameserver list (e.g. { \"corp.example.com\": [\"10.0.0.1\"], \"internal.dev\": [\"10.0.0.2\"] })"),
|
|
57
57
|
}),
|
|
58
58
|
handler: async (input) => {
|
|
59
|
-
return
|
|
59
|
+
return apiPut(`/tailnet/${getTailnet()}/dns/split-dns`, input.splitDns);
|
|
60
60
|
},
|
|
61
61
|
},
|
|
62
62
|
{
|
package/dist/tools/dns.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dns.js","sourceRoot":"","sources":["../../src/tools/dns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"dns.js","sourceRoot":"","sources":["../../src/tools/dns.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const inviteTools: readonly [{
|
|
3
|
+
readonly name: "tailscale_list_device_invites";
|
|
4
|
+
readonly description: "List all device invites for your tailnet.";
|
|
5
|
+
readonly inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
|
|
6
|
+
readonly handler: () => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
7
|
+
}, {
|
|
8
|
+
readonly name: "tailscale_create_device_invite";
|
|
9
|
+
readonly description: "Create a new device invite that allows someone to add a device to your tailnet.";
|
|
10
|
+
readonly inputSchema: z.ZodObject<{
|
|
11
|
+
multiUse: z.ZodOptional<z.ZodBoolean>;
|
|
12
|
+
allowExitNode: z.ZodOptional<z.ZodBoolean>;
|
|
13
|
+
email: z.ZodOptional<z.ZodString>;
|
|
14
|
+
}, "strip", z.ZodTypeAny, {
|
|
15
|
+
email?: string | undefined;
|
|
16
|
+
multiUse?: boolean | undefined;
|
|
17
|
+
allowExitNode?: boolean | undefined;
|
|
18
|
+
}, {
|
|
19
|
+
email?: string | undefined;
|
|
20
|
+
multiUse?: boolean | undefined;
|
|
21
|
+
allowExitNode?: boolean | undefined;
|
|
22
|
+
}>;
|
|
23
|
+
readonly handler: (input: {
|
|
24
|
+
multiUse?: boolean;
|
|
25
|
+
allowExitNode?: boolean;
|
|
26
|
+
email?: string;
|
|
27
|
+
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
28
|
+
}, {
|
|
29
|
+
readonly name: "tailscale_get_device_invite";
|
|
30
|
+
readonly description: "Get details for a specific device invite.";
|
|
31
|
+
readonly inputSchema: z.ZodObject<{
|
|
32
|
+
inviteId: z.ZodString;
|
|
33
|
+
}, "strip", z.ZodTypeAny, {
|
|
34
|
+
inviteId: string;
|
|
35
|
+
}, {
|
|
36
|
+
inviteId: string;
|
|
37
|
+
}>;
|
|
38
|
+
readonly handler: (input: {
|
|
39
|
+
inviteId: string;
|
|
40
|
+
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
41
|
+
}, {
|
|
42
|
+
readonly name: "tailscale_delete_device_invite";
|
|
43
|
+
readonly description: "Delete a device invite. This is irreversible — the invite link will stop working.";
|
|
44
|
+
readonly inputSchema: z.ZodObject<{
|
|
45
|
+
inviteId: z.ZodString;
|
|
46
|
+
}, "strip", z.ZodTypeAny, {
|
|
47
|
+
inviteId: string;
|
|
48
|
+
}, {
|
|
49
|
+
inviteId: string;
|
|
50
|
+
}>;
|
|
51
|
+
readonly handler: (input: {
|
|
52
|
+
inviteId: string;
|
|
53
|
+
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
54
|
+
}, {
|
|
55
|
+
readonly name: "tailscale_list_user_invites";
|
|
56
|
+
readonly description: "List all user invites for your tailnet.";
|
|
57
|
+
readonly inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
|
|
58
|
+
readonly handler: () => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
59
|
+
}, {
|
|
60
|
+
readonly name: "tailscale_create_user_invite";
|
|
61
|
+
readonly description: "Create a new user invite that allows someone to join your tailnet.";
|
|
62
|
+
readonly inputSchema: z.ZodObject<{
|
|
63
|
+
email: z.ZodOptional<z.ZodString>;
|
|
64
|
+
role: z.ZodOptional<z.ZodEnum<["member", "admin", "it-admin", "network-admin", "billing-admin", "auditor"]>>;
|
|
65
|
+
}, "strip", z.ZodTypeAny, {
|
|
66
|
+
email?: string | undefined;
|
|
67
|
+
role?: "admin" | "it-admin" | "network-admin" | "billing-admin" | "auditor" | "member" | undefined;
|
|
68
|
+
}, {
|
|
69
|
+
email?: string | undefined;
|
|
70
|
+
role?: "admin" | "it-admin" | "network-admin" | "billing-admin" | "auditor" | "member" | undefined;
|
|
71
|
+
}>;
|
|
72
|
+
readonly handler: (input: {
|
|
73
|
+
email?: string;
|
|
74
|
+
role?: string;
|
|
75
|
+
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
76
|
+
}, {
|
|
77
|
+
readonly name: "tailscale_get_user_invite";
|
|
78
|
+
readonly description: "Get details for a specific user invite.";
|
|
79
|
+
readonly inputSchema: z.ZodObject<{
|
|
80
|
+
inviteId: z.ZodString;
|
|
81
|
+
}, "strip", z.ZodTypeAny, {
|
|
82
|
+
inviteId: string;
|
|
83
|
+
}, {
|
|
84
|
+
inviteId: string;
|
|
85
|
+
}>;
|
|
86
|
+
readonly handler: (input: {
|
|
87
|
+
inviteId: string;
|
|
88
|
+
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
89
|
+
}, {
|
|
90
|
+
readonly name: "tailscale_delete_user_invite";
|
|
91
|
+
readonly description: "Delete a user invite. This is irreversible — the invite link will stop working.";
|
|
92
|
+
readonly inputSchema: z.ZodObject<{
|
|
93
|
+
inviteId: z.ZodString;
|
|
94
|
+
}, "strip", z.ZodTypeAny, {
|
|
95
|
+
inviteId: string;
|
|
96
|
+
}, {
|
|
97
|
+
inviteId: string;
|
|
98
|
+
}>;
|
|
99
|
+
readonly handler: (input: {
|
|
100
|
+
inviteId: string;
|
|
101
|
+
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
102
|
+
}];
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiGet, apiPost, apiDelete, getTailnet, encPath } from "../api.js";
|
|
3
|
+
export const inviteTools = [
|
|
4
|
+
// --- Device Invites ---
|
|
5
|
+
{
|
|
6
|
+
name: "tailscale_list_device_invites",
|
|
7
|
+
description: "List all device invites for your tailnet.",
|
|
8
|
+
inputSchema: z.object({}),
|
|
9
|
+
handler: async () => {
|
|
10
|
+
return apiGet(`/tailnet/${getTailnet()}/device-invites`);
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: "tailscale_create_device_invite",
|
|
15
|
+
description: "Create a new device invite that allows someone to add a device to your tailnet.",
|
|
16
|
+
inputSchema: z.object({
|
|
17
|
+
multiUse: z.boolean().optional().describe("Whether the invite can be used more than once (default: false)"),
|
|
18
|
+
allowExitNode: z
|
|
19
|
+
.boolean()
|
|
20
|
+
.optional()
|
|
21
|
+
.describe("Whether the invited device can be used as an exit node (default: false)"),
|
|
22
|
+
email: z
|
|
23
|
+
.string()
|
|
24
|
+
.optional()
|
|
25
|
+
.describe("Email address to send the invite to"),
|
|
26
|
+
}),
|
|
27
|
+
handler: async (input) => {
|
|
28
|
+
const body = {};
|
|
29
|
+
if (input.multiUse !== undefined)
|
|
30
|
+
body.multiUse = input.multiUse;
|
|
31
|
+
if (input.allowExitNode !== undefined)
|
|
32
|
+
body.allowExitNode = input.allowExitNode;
|
|
33
|
+
if (input.email !== undefined)
|
|
34
|
+
body.email = input.email;
|
|
35
|
+
return apiPost(`/tailnet/${getTailnet()}/device-invites`, body);
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: "tailscale_get_device_invite",
|
|
40
|
+
description: "Get details for a specific device invite.",
|
|
41
|
+
inputSchema: z.object({
|
|
42
|
+
inviteId: z.string().describe("The device invite ID"),
|
|
43
|
+
}),
|
|
44
|
+
handler: async (input) => {
|
|
45
|
+
return apiGet(`/device-invites/${encPath(input.inviteId)}`);
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: "tailscale_delete_device_invite",
|
|
50
|
+
description: "Delete a device invite. This is irreversible — the invite link will stop working.",
|
|
51
|
+
inputSchema: z.object({
|
|
52
|
+
inviteId: z.string().describe("The device invite ID to delete"),
|
|
53
|
+
}),
|
|
54
|
+
handler: async (input) => {
|
|
55
|
+
return apiDelete(`/device-invites/${encPath(input.inviteId)}`);
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
// --- User Invites ---
|
|
59
|
+
{
|
|
60
|
+
name: "tailscale_list_user_invites",
|
|
61
|
+
description: "List all user invites for your tailnet.",
|
|
62
|
+
inputSchema: z.object({}),
|
|
63
|
+
handler: async () => {
|
|
64
|
+
return apiGet(`/tailnet/${getTailnet()}/user-invites`);
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: "tailscale_create_user_invite",
|
|
69
|
+
description: "Create a new user invite that allows someone to join your tailnet.",
|
|
70
|
+
inputSchema: z.object({
|
|
71
|
+
email: z
|
|
72
|
+
.string()
|
|
73
|
+
.optional()
|
|
74
|
+
.describe("Email address to send the invite to"),
|
|
75
|
+
role: z
|
|
76
|
+
.enum(["member", "admin", "it-admin", "network-admin", "billing-admin", "auditor"])
|
|
77
|
+
.optional()
|
|
78
|
+
.describe("Role to assign to the invited user (default: member)"),
|
|
79
|
+
}),
|
|
80
|
+
handler: async (input) => {
|
|
81
|
+
const body = {};
|
|
82
|
+
if (input.email !== undefined)
|
|
83
|
+
body.email = input.email;
|
|
84
|
+
if (input.role !== undefined)
|
|
85
|
+
body.role = input.role;
|
|
86
|
+
return apiPost(`/tailnet/${getTailnet()}/user-invites`, body);
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: "tailscale_get_user_invite",
|
|
91
|
+
description: "Get details for a specific user invite.",
|
|
92
|
+
inputSchema: z.object({
|
|
93
|
+
inviteId: z.string().describe("The user invite ID"),
|
|
94
|
+
}),
|
|
95
|
+
handler: async (input) => {
|
|
96
|
+
return apiGet(`/user-invites/${encPath(input.inviteId)}`);
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: "tailscale_delete_user_invite",
|
|
101
|
+
description: "Delete a user invite. This is irreversible — the invite link will stop working.",
|
|
102
|
+
inputSchema: z.object({
|
|
103
|
+
inviteId: z.string().describe("The user invite ID to delete"),
|
|
104
|
+
}),
|
|
105
|
+
handler: async (input) => {
|
|
106
|
+
return apiDelete(`/user-invites/${encPath(input.inviteId)}`);
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
//# sourceMappingURL=invites.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invites.js","sourceRoot":"","sources":["../../src/tools/invites.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/keys.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export declare const keyTools: readonly [{
|
|
|
19
19
|
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
20
20
|
}, {
|
|
21
21
|
readonly name: "tailscale_create_key";
|
|
22
|
-
readonly description: "Create a new auth key for adding devices to your tailnet.";
|
|
22
|
+
readonly description: "Create a new auth key for adding devices to your tailnet. Returns the key value — save it immediately, as it cannot be retrieved again.";
|
|
23
23
|
readonly inputSchema: z.ZodObject<{
|
|
24
24
|
reusable: z.ZodOptional<z.ZodBoolean>;
|
|
25
25
|
ephemeral: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -52,7 +52,7 @@ export declare const keyTools: readonly [{
|
|
|
52
52
|
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
53
53
|
}, {
|
|
54
54
|
readonly name: "tailscale_delete_key";
|
|
55
|
-
readonly description: "Delete an auth key.";
|
|
55
|
+
readonly description: "Delete an auth key. This is irreversible — devices already authenticated with this key are unaffected, but no new devices can use it.";
|
|
56
56
|
readonly inputSchema: z.ZodObject<{
|
|
57
57
|
keyId: z.ZodString;
|
|
58
58
|
}, "strip", z.ZodTypeAny, {
|
package/dist/tools/keys.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { apiGet, apiPost, apiDelete, getTailnet } from "../api.js";
|
|
2
|
+
import { apiGet, apiPost, apiDelete, getTailnet, encPath } from "../api.js";
|
|
3
3
|
export const keyTools = [
|
|
4
4
|
{
|
|
5
5
|
name: "tailscale_list_keys",
|
|
@@ -16,12 +16,12 @@ export const keyTools = [
|
|
|
16
16
|
keyId: z.string().describe("The auth key ID"),
|
|
17
17
|
}),
|
|
18
18
|
handler: async (input) => {
|
|
19
|
-
return apiGet(`/tailnet/${getTailnet()}/keys/${input.keyId}`);
|
|
19
|
+
return apiGet(`/tailnet/${getTailnet()}/keys/${encPath(input.keyId)}`);
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
name: "tailscale_create_key",
|
|
24
|
-
description: "Create a new auth key for adding devices to your tailnet.",
|
|
24
|
+
description: "Create a new auth key for adding devices to your tailnet. Returns the key value — save it immediately, as it cannot be retrieved again.",
|
|
25
25
|
inputSchema: z.object({
|
|
26
26
|
reusable: z.boolean().optional().describe("Whether the key can be used more than once (default: false)"),
|
|
27
27
|
ephemeral: z.boolean().optional().describe("Whether devices using this key are ephemeral (default: false)"),
|
|
@@ -52,12 +52,12 @@ export const keyTools = [
|
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
name: "tailscale_delete_key",
|
|
55
|
-
description: "Delete an auth key.",
|
|
55
|
+
description: "Delete an auth key. This is irreversible — devices already authenticated with this key are unaffected, but no new devices can use it.",
|
|
56
56
|
inputSchema: z.object({
|
|
57
57
|
keyId: z.string().describe("The auth key ID to delete"),
|
|
58
58
|
}),
|
|
59
59
|
handler: async (input) => {
|
|
60
|
-
return apiDelete(`/tailnet/${getTailnet()}/keys/${input.keyId}`);
|
|
60
|
+
return apiDelete(`/tailnet/${getTailnet()}/keys/${encPath(input.keyId)}`);
|
|
61
61
|
},
|
|
62
62
|
},
|
|
63
63
|
];
|
package/dist/tools/keys.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/tools/keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/tools/keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE5E,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB;QACE,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EAAE,qCAAqC;QAClD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,OAAO,MAAM,CAAC,YAAY,UAAU,EAAE,OAAO,CAAC,CAAC;QACjD,CAAC;KACF;IACD;QACE,IAAI,EAAE,mBAAmB;QACzB,WAAW,EAAE,sCAAsC;QACnD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;SAC9C,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAAwB,EAAE,EAAE;YAC1C,OAAO,MAAM,CAAC,YAAY,UAAU,EAAE,SAAS,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACzE,CAAC;KACF;IACD;QACE,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EAAE,yIAAyI;QACtJ,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6DAA6D,CAAC;YACxG,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+DAA+D,CAAC;YAC3G,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;YACrG,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;YAC5F,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;YACzF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;SACxE,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAOf,EAAE,EAAE;YACH,MAAM,IAAI,GAA4B;gBACpC,YAAY,EAAE;oBACZ,OAAO,EAAE;wBACP,MAAM,EAAE;4BACN,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK;4BACjC,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,KAAK;4BACnC,aAAa,EAAE,KAAK,CAAC,aAAa,IAAI,KAAK;4BAC3C,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE;yBACvB;qBACF;iBACF;aACF,CAAC;YACF,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS;gBAAE,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;YAChF,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;gBAAE,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;YAC1E,OAAO,OAAO,CAAC,YAAY,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QACxD,CAAC;KACF;IACD;QACE,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EAAE,uIAAuI;QACpJ,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;SACxD,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAAwB,EAAE,EAAE;YAC1C,OAAO,SAAS,CAAC,YAAY,UAAU,EAAE,SAAS,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5E,CAAC;KACF;CACO,CAAC"}
|
package/dist/tools/posture.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export declare const postureTools: readonly [{
|
|
|
6
6
|
readonly handler: () => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
7
7
|
}, {
|
|
8
8
|
readonly name: "tailscale_get_posture_integration";
|
|
9
|
-
readonly description: "Get details for a specific posture integration.";
|
|
9
|
+
readonly description: "Get details for a specific device posture integration.";
|
|
10
10
|
readonly inputSchema: z.ZodObject<{
|
|
11
11
|
integrationId: z.ZodString;
|
|
12
12
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -46,9 +46,38 @@ export declare const postureTools: readonly [{
|
|
|
46
46
|
tenantId?: string;
|
|
47
47
|
cloudEnvironment?: string;
|
|
48
48
|
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
49
|
+
}, {
|
|
50
|
+
readonly name: "tailscale_update_posture_integration";
|
|
51
|
+
readonly description: "Update an existing posture integration's credentials or configuration.";
|
|
52
|
+
readonly inputSchema: z.ZodObject<{
|
|
53
|
+
integrationId: z.ZodString;
|
|
54
|
+
clientId: z.ZodOptional<z.ZodString>;
|
|
55
|
+
clientSecret: z.ZodOptional<z.ZodString>;
|
|
56
|
+
tenantId: z.ZodOptional<z.ZodString>;
|
|
57
|
+
cloudEnvironment: z.ZodOptional<z.ZodString>;
|
|
58
|
+
}, "strip", z.ZodTypeAny, {
|
|
59
|
+
integrationId: string;
|
|
60
|
+
clientId?: string | undefined;
|
|
61
|
+
clientSecret?: string | undefined;
|
|
62
|
+
tenantId?: string | undefined;
|
|
63
|
+
cloudEnvironment?: string | undefined;
|
|
64
|
+
}, {
|
|
65
|
+
integrationId: string;
|
|
66
|
+
clientId?: string | undefined;
|
|
67
|
+
clientSecret?: string | undefined;
|
|
68
|
+
tenantId?: string | undefined;
|
|
69
|
+
cloudEnvironment?: string | undefined;
|
|
70
|
+
}>;
|
|
71
|
+
readonly handler: (input: {
|
|
72
|
+
integrationId: string;
|
|
73
|
+
clientId?: string;
|
|
74
|
+
clientSecret?: string;
|
|
75
|
+
tenantId?: string;
|
|
76
|
+
cloudEnvironment?: string;
|
|
77
|
+
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
49
78
|
}, {
|
|
50
79
|
readonly name: "tailscale_delete_posture_integration";
|
|
51
|
-
readonly description: "Delete a posture integration.";
|
|
80
|
+
readonly description: "Delete a posture integration. This is irreversible.";
|
|
52
81
|
readonly inputSchema: z.ZodObject<{
|
|
53
82
|
integrationId: z.ZodString;
|
|
54
83
|
}, "strip", z.ZodTypeAny, {
|
package/dist/tools/posture.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { apiGet, apiPost, apiDelete, getTailnet } from "../api.js";
|
|
2
|
+
import { apiGet, apiPost, apiPatch, apiDelete, getTailnet, encPath } from "../api.js";
|
|
3
3
|
export const postureTools = [
|
|
4
4
|
{
|
|
5
5
|
name: "tailscale_list_posture_integrations",
|
|
@@ -11,12 +11,12 @@ export const postureTools = [
|
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
name: "tailscale_get_posture_integration",
|
|
14
|
-
description: "Get details for a specific posture integration.",
|
|
14
|
+
description: "Get details for a specific device posture integration.",
|
|
15
15
|
inputSchema: z.object({
|
|
16
16
|
integrationId: z.string().describe("The posture integration ID"),
|
|
17
17
|
}),
|
|
18
18
|
handler: async (input) => {
|
|
19
|
-
return apiGet(`/tailnet/${getTailnet()}/posture/integrations/${input.integrationId}`);
|
|
19
|
+
return apiGet(`/tailnet/${getTailnet()}/posture/integrations/${encPath(input.integrationId)}`);
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
22
|
{
|
|
@@ -33,14 +33,35 @@ export const postureTools = [
|
|
|
33
33
|
return apiPost(`/tailnet/${getTailnet()}/posture/integrations`, input);
|
|
34
34
|
},
|
|
35
35
|
},
|
|
36
|
+
{
|
|
37
|
+
name: "tailscale_update_posture_integration",
|
|
38
|
+
description: "Update an existing posture integration's credentials or configuration.",
|
|
39
|
+
inputSchema: z.object({
|
|
40
|
+
integrationId: z.string().describe("The posture integration ID to update"),
|
|
41
|
+
clientId: z.string().optional().describe("Updated OAuth client ID for the provider"),
|
|
42
|
+
clientSecret: z.string().optional().describe("Updated OAuth client secret for the provider"),
|
|
43
|
+
tenantId: z.string().optional().describe("Updated tenant ID"),
|
|
44
|
+
cloudEnvironment: z.string().optional().describe("Updated cloud environment (e.g. 'us-1', 'eu-1')"),
|
|
45
|
+
}),
|
|
46
|
+
handler: async (input) => {
|
|
47
|
+
const { integrationId, ...body } = input;
|
|
48
|
+
// Remove undefined values so we only send fields the user wants to update
|
|
49
|
+
const cleanBody = {};
|
|
50
|
+
for (const [key, value] of Object.entries(body)) {
|
|
51
|
+
if (value !== undefined)
|
|
52
|
+
cleanBody[key] = value;
|
|
53
|
+
}
|
|
54
|
+
return apiPatch(`/tailnet/${getTailnet()}/posture/integrations/${encPath(integrationId)}`, cleanBody);
|
|
55
|
+
},
|
|
56
|
+
},
|
|
36
57
|
{
|
|
37
58
|
name: "tailscale_delete_posture_integration",
|
|
38
|
-
description: "Delete a posture integration.",
|
|
59
|
+
description: "Delete a posture integration. This is irreversible.",
|
|
39
60
|
inputSchema: z.object({
|
|
40
61
|
integrationId: z.string().describe("The posture integration ID to delete"),
|
|
41
62
|
}),
|
|
42
63
|
handler: async (input) => {
|
|
43
|
-
return apiDelete(`/tailnet/${getTailnet()}/posture/integrations/${input.integrationId}`);
|
|
64
|
+
return apiDelete(`/tailnet/${getTailnet()}/posture/integrations/${encPath(input.integrationId)}`);
|
|
44
65
|
},
|
|
45
66
|
},
|
|
46
67
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"posture.js","sourceRoot":"","sources":["../../src/tools/posture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"posture.js","sourceRoot":"","sources":["../../src/tools/posture.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/users.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export declare const userTools: readonly [{
|
|
|
32
32
|
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
33
33
|
}, {
|
|
34
34
|
readonly name: "tailscale_suspend_user";
|
|
35
|
-
readonly description: "Suspend a user, immediately revoking their access to the tailnet. Their devices will be disconnected.";
|
|
35
|
+
readonly description: "Suspend a user, immediately revoking their access to the tailnet. Their devices will be disconnected. Can be reversed with tailscale_restore_user.";
|
|
36
36
|
readonly inputSchema: z.ZodObject<{
|
|
37
37
|
userId: z.ZodString;
|
|
38
38
|
}, "strip", z.ZodTypeAny, {
|
package/dist/tools/users.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { apiGet, apiPost, apiPatch, getTailnet } from "../api.js";
|
|
2
|
+
import { apiGet, apiPost, apiPatch, getTailnet, encPath } from "../api.js";
|
|
3
3
|
export const userTools = [
|
|
4
4
|
{
|
|
5
5
|
name: "tailscale_list_users",
|
|
@@ -16,7 +16,7 @@ export const userTools = [
|
|
|
16
16
|
userId: z.string().describe("The user ID"),
|
|
17
17
|
}),
|
|
18
18
|
handler: async (input) => {
|
|
19
|
-
return apiGet(`/users/${input.userId}`);
|
|
19
|
+
return apiGet(`/users/${encPath(input.userId)}`);
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
22
|
{
|
|
@@ -26,17 +26,17 @@ export const userTools = [
|
|
|
26
26
|
userId: z.string().describe("The user ID to approve"),
|
|
27
27
|
}),
|
|
28
28
|
handler: async (input) => {
|
|
29
|
-
return apiPost(`/users/${input.userId}/approve`);
|
|
29
|
+
return apiPost(`/users/${encPath(input.userId)}/approve`);
|
|
30
30
|
},
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
name: "tailscale_suspend_user",
|
|
34
|
-
description: "Suspend a user, immediately revoking their access to the tailnet. Their devices will be disconnected.",
|
|
34
|
+
description: "Suspend a user, immediately revoking their access to the tailnet. Their devices will be disconnected. Can be reversed with tailscale_restore_user.",
|
|
35
35
|
inputSchema: z.object({
|
|
36
36
|
userId: z.string().describe("The user ID to suspend"),
|
|
37
37
|
}),
|
|
38
38
|
handler: async (input) => {
|
|
39
|
-
return apiPost(`/users/${input.userId}/suspend`);
|
|
39
|
+
return apiPost(`/users/${encPath(input.userId)}/suspend`);
|
|
40
40
|
},
|
|
41
41
|
},
|
|
42
42
|
{
|
|
@@ -46,7 +46,7 @@ export const userTools = [
|
|
|
46
46
|
userId: z.string().describe("The user ID to restore"),
|
|
47
47
|
}),
|
|
48
48
|
handler: async (input) => {
|
|
49
|
-
return apiPost(`/users/${input.userId}/restore`);
|
|
49
|
+
return apiPost(`/users/${encPath(input.userId)}/restore`);
|
|
50
50
|
},
|
|
51
51
|
},
|
|
52
52
|
{
|
|
@@ -58,7 +58,7 @@ export const userTools = [
|
|
|
58
58
|
.describe("The new role to assign"),
|
|
59
59
|
}),
|
|
60
60
|
handler: async (input) => {
|
|
61
|
-
return apiPatch(`/users/${input.userId}/role`, { role: input.role });
|
|
61
|
+
return apiPatch(`/users/${encPath(input.userId)}/role`, { role: input.role });
|
|
62
62
|
},
|
|
63
63
|
},
|
|
64
64
|
];
|
package/dist/tools/users.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"users.js","sourceRoot":"","sources":["../../src/tools/users.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"users.js","sourceRoot":"","sources":["../../src/tools/users.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE3E,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB;QACE,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EAAE,iCAAiC;QAC9C,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,OAAO,MAAM,CAAC,YAAY,UAAU,EAAE,QAAQ,CAAC,CAAC;QAClD,CAAC;KACF;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EAAE,kCAAkC;QAC/C,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC;SAC3C,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAAyB,EAAE,EAAE;YAC3C,OAAO,MAAM,CAAC,UAAU,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACnD,CAAC;KACF;IACD;QACE,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EAAE,8DAA8D;QAC3E,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;SACtD,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAAyB,EAAE,EAAE;YAC3C,OAAO,OAAO,CAAC,UAAU,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC5D,CAAC;KACF;IACD;QACE,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EAAE,oJAAoJ;QACjK,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;SACtD,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAAyB,EAAE,EAAE;YAC3C,OAAO,OAAO,CAAC,UAAU,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC5D,CAAC;KACF;IACD;QACE,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EAAE,8EAA8E;QAC3F,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;SACtD,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAAyB,EAAE,EAAE;YAC3C,OAAO,OAAO,CAAC,UAAU,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC5D,CAAC;KACF;IACD;QACE,IAAI,EAAE,4BAA4B;QAClC,WAAW,EAAE,sCAAsC;QACnD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC;YAC1C,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;iBAChG,QAAQ,CAAC,wBAAwB,CAAC;SACtC,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAAuC,EAAE,EAAE;YACzD,OAAO,QAAQ,CAAC,UAAU,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAChF,CAAC;KACF;CACO,CAAC"}
|
package/dist/tools/webhooks.d.ts
CHANGED
|
@@ -68,4 +68,17 @@ export declare const webhookTools: readonly [{
|
|
|
68
68
|
readonly handler: (input: {
|
|
69
69
|
webhookId: string;
|
|
70
70
|
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
71
|
+
}, {
|
|
72
|
+
readonly name: "tailscale_rotate_webhook_secret";
|
|
73
|
+
readonly description: "Rotate a webhook's secret. Returns the new secret — save it immediately, as it cannot be retrieved again. The old secret is immediately invalidated.";
|
|
74
|
+
readonly inputSchema: z.ZodObject<{
|
|
75
|
+
webhookId: z.ZodString;
|
|
76
|
+
}, "strip", z.ZodTypeAny, {
|
|
77
|
+
webhookId: string;
|
|
78
|
+
}, {
|
|
79
|
+
webhookId: string;
|
|
80
|
+
}>;
|
|
81
|
+
readonly handler: (input: {
|
|
82
|
+
webhookId: string;
|
|
83
|
+
}) => Promise<import("../api.js").ApiResponse<unknown>>;
|
|
71
84
|
}];
|
package/dist/tools/webhooks.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { apiGet, apiPost, apiPatch, apiDelete, getTailnet } from "../api.js";
|
|
2
|
+
import { apiGet, apiPost, apiPatch, apiDelete, getTailnet, encPath } from "../api.js";
|
|
3
3
|
export const webhookTools = [
|
|
4
4
|
{
|
|
5
5
|
name: "tailscale_list_webhooks",
|
|
@@ -16,7 +16,7 @@ export const webhookTools = [
|
|
|
16
16
|
webhookId: z.string().describe("The webhook ID"),
|
|
17
17
|
}),
|
|
18
18
|
handler: async (input) => {
|
|
19
|
-
return apiGet(`/webhooks/${input.webhookId}`);
|
|
19
|
+
return apiGet(`/webhooks/${encPath(input.webhookId)}`);
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
22
|
{
|
|
@@ -52,7 +52,7 @@ export const webhookTools = [
|
|
|
52
52
|
body.endpointUrl = input.endpointUrl;
|
|
53
53
|
if (input.subscriptions !== undefined)
|
|
54
54
|
body.subscriptions = input.subscriptions;
|
|
55
|
-
return apiPatch(`/webhooks/${input.webhookId}`, body);
|
|
55
|
+
return apiPatch(`/webhooks/${encPath(input.webhookId)}`, body);
|
|
56
56
|
},
|
|
57
57
|
},
|
|
58
58
|
{
|
|
@@ -62,7 +62,17 @@ export const webhookTools = [
|
|
|
62
62
|
webhookId: z.string().describe("The webhook ID to delete"),
|
|
63
63
|
}),
|
|
64
64
|
handler: async (input) => {
|
|
65
|
-
return apiDelete(`/webhooks/${input.webhookId}`);
|
|
65
|
+
return apiDelete(`/webhooks/${encPath(input.webhookId)}`);
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: "tailscale_rotate_webhook_secret",
|
|
70
|
+
description: "Rotate a webhook's secret. Returns the new secret — save it immediately, as it cannot be retrieved again. The old secret is immediately invalidated.",
|
|
71
|
+
inputSchema: z.object({
|
|
72
|
+
webhookId: z.string().describe("The webhook ID whose secret to rotate"),
|
|
73
|
+
}),
|
|
74
|
+
handler: async (input) => {
|
|
75
|
+
return apiPost(`/webhooks/${encPath(input.webhookId)}/rotate`);
|
|
66
76
|
},
|
|
67
77
|
},
|
|
68
78
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../src/tools/webhooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../src/tools/webhooks.ts"],"names":[],"mappings":"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"}
|