@yawlabs/tailscale-mcp 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +3 -17
  2. package/dist/index.js +22922 -120
  3. package/package.json +10 -11
  4. package/dist/api.d.ts +0 -35
  5. package/dist/api.js +0 -134
  6. package/dist/api.js.map +0 -1
  7. package/dist/cli.d.ts +0 -5
  8. package/dist/cli.js +0 -43
  9. package/dist/cli.js.map +0 -1
  10. package/dist/index.d.ts +0 -2
  11. package/dist/index.js.map +0 -1
  12. package/dist/tools/acl.d.ts +0 -86
  13. package/dist/tools/acl.js +0 -105
  14. package/dist/tools/acl.js.map +0 -1
  15. package/dist/tools/audit.d.ts +0 -50
  16. package/dist/tools/audit.js +0 -60
  17. package/dist/tools/audit.js.map +0 -1
  18. package/dist/tools/devices.d.ts +0 -290
  19. package/dist/tools/devices.js +0 -254
  20. package/dist/tools/devices.js.map +0 -1
  21. package/dist/tools/dns.d.ts +0 -130
  22. package/dist/tools/dns.js +0 -139
  23. package/dist/tools/dns.js.map +0 -1
  24. package/dist/tools/invites.d.ts +0 -158
  25. package/dist/tools/invites.js +0 -160
  26. package/dist/tools/invites.js.map +0 -1
  27. package/dist/tools/keys.d.ts +0 -94
  28. package/dist/tools/keys.js +0 -92
  29. package/dist/tools/keys.js.map +0 -1
  30. package/dist/tools/log-streaming.d.ts +0 -90
  31. package/dist/tools/log-streaming.js +0 -89
  32. package/dist/tools/log-streaming.js.map +0 -1
  33. package/dist/tools/network-lock.d.ts +0 -14
  34. package/dist/tools/network-lock.js +0 -20
  35. package/dist/tools/network-lock.js.map +0 -1
  36. package/dist/tools/oauth-clients.d.ts +0 -118
  37. package/dist/tools/oauth-clients.js +0 -102
  38. package/dist/tools/oauth-clients.js.map +0 -1
  39. package/dist/tools/posture.d.ts +0 -126
  40. package/dist/tools/posture.js +0 -103
  41. package/dist/tools/posture.js.map +0 -1
  42. package/dist/tools/services.d.ts +0 -124
  43. package/dist/tools/services.js +0 -106
  44. package/dist/tools/services.js.map +0 -1
  45. package/dist/tools/status.d.ts +0 -26
  46. package/dist/tools/status.js +0 -38
  47. package/dist/tools/status.js.map +0 -1
  48. package/dist/tools/tailnet.d.ts +0 -142
  49. package/dist/tools/tailnet.js +0 -111
  50. package/dist/tools/tailnet.js.map +0 -1
  51. package/dist/tools/users.d.ts +0 -118
  52. package/dist/tools/users.js +0 -108
  53. package/dist/tools/users.js.map +0 -1
  54. package/dist/tools/webhooks.d.ts +0 -126
  55. package/dist/tools/webhooks.js +0 -121
  56. package/dist/tools/webhooks.js.map +0 -1
  57. package/dist/tools/workload-identity.d.ts +0 -118
  58. package/dist/tools/workload-identity.js +0 -105
  59. package/dist/tools/workload-identity.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yawlabs/tailscale-mcp",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Tailscale MCP server for managing your tailnet from AI assistants",
5
5
  "license": "MIT",
6
6
  "author": "YawLabs <contact@yaw.sh>",
@@ -22,27 +22,26 @@
22
22
  "tailscale-mcp": "dist/index.js"
23
23
  },
24
24
  "files": [
25
- "dist",
26
- "!dist/**/*.test.*"
25
+ "dist/index.js"
27
26
  ],
28
27
  "scripts": {
29
- "build": "tsc",
28
+ "build": "tsc && node build.mjs",
30
29
  "dev": "tsc --watch",
31
30
  "start": "node dist/index.js",
32
- "test": "node --test dist/**/*.test.js",
33
- "test:ci": "npm run build && npm test",
31
+ "test": "npm run build && node --test dist/**/*.test.js",
32
+ "test:ci": "npm run test",
34
33
  "lint": "biome check src/",
35
34
  "lint:fix": "biome check --write src/",
36
35
  "prepublishOnly": "npm run build"
37
36
  },
38
- "dependencies": {
39
- "@modelcontextprotocol/sdk": "^1.29.0",
40
- "zod": "^3.24.4"
41
- },
37
+ "dependencies": {},
42
38
  "devDependencies": {
43
39
  "@biomejs/biome": "^1.9.4",
40
+ "@modelcontextprotocol/sdk": "^1.29.0",
44
41
  "@types/node": "^22.15.2",
45
- "typescript": "^5.8.3"
42
+ "esbuild": "^0.28.0",
43
+ "typescript": "^5.8.3",
44
+ "zod": "^3.24.4"
46
45
  },
47
46
  "engines": {
48
47
  "node": ">=18"
package/dist/api.d.ts DELETED
@@ -1,35 +0,0 @@
1
- /**
2
- * Tailscale API client with API key and OAuth authentication.
3
- */
4
- export declare function getTailnet(): string;
5
- /** URL-encode a path segment to prevent path traversal. */
6
- export declare function encPath(segment: string): string;
7
- export interface ApiResponse<T = unknown> {
8
- ok: boolean;
9
- status: number;
10
- data?: T;
11
- error?: string;
12
- rawBody?: string;
13
- etag?: string;
14
- }
15
- export declare function apiRequest<T = unknown>(method: string, path: string, body?: unknown, options?: {
16
- rawBody?: string;
17
- acceptRaw?: boolean;
18
- accept?: string;
19
- contentType?: string;
20
- ifMatch?: string;
21
- }): Promise<ApiResponse<T>>;
22
- export declare function apiGet<T = unknown>(path: string, options?: {
23
- acceptRaw?: boolean;
24
- accept?: string;
25
- }): Promise<ApiResponse<T>>;
26
- export declare function apiPost<T = unknown>(path: string, body?: unknown, options?: {
27
- rawBody?: string;
28
- acceptRaw?: boolean;
29
- accept?: string;
30
- contentType?: string;
31
- ifMatch?: string;
32
- }): Promise<ApiResponse<T>>;
33
- export declare function apiPut<T = unknown>(path: string, body?: unknown): Promise<ApiResponse<T>>;
34
- export declare function apiPatch<T = unknown>(path: string, body?: unknown): Promise<ApiResponse<T>>;
35
- export declare function apiDelete<T = unknown>(path: string): Promise<ApiResponse<T>>;
package/dist/api.js DELETED
@@ -1,134 +0,0 @@
1
- /**
2
- * Tailscale API client with API key and OAuth authentication.
3
- */
4
- const BASE_URL = "https://api.tailscale.com/api/v2";
5
- const REQUEST_TIMEOUT_MS = 30_000;
6
- let oauthToken = null;
7
- let oauthRefreshPromise = null;
8
- function getConfig() {
9
- const apiKey = process.env.TAILSCALE_API_KEY;
10
- const oauthClientId = process.env.TAILSCALE_OAUTH_CLIENT_ID;
11
- const oauthClientSecret = process.env.TAILSCALE_OAUTH_CLIENT_SECRET;
12
- const tailnet = process.env.TAILSCALE_TAILNET || "-";
13
- if (!apiKey && !(oauthClientId && oauthClientSecret)) {
14
- throw new Error("No Tailscale credentials configured. " +
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.");
19
- }
20
- return { apiKey, oauthClientId, oauthClientSecret, tailnet };
21
- }
22
- async function getOAuthAccessToken(clientId, clientSecret) {
23
- if (oauthToken && Date.now() < oauthToken.expires_at - 60_000) {
24
- return oauthToken.access_token;
25
- }
26
- // Deduplicate concurrent refresh requests
27
- if (oauthRefreshPromise) {
28
- return oauthRefreshPromise;
29
- }
30
- oauthRefreshPromise = (async () => {
31
- try {
32
- const res = await fetch("https://api.tailscale.com/api/v2/oauth/token", {
33
- method: "POST",
34
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
35
- body: new URLSearchParams({
36
- client_id: clientId,
37
- client_secret: clientSecret,
38
- grant_type: "client_credentials",
39
- }),
40
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
41
- });
42
- if (!res.ok) {
43
- const body = await res.text();
44
- throw new Error(`OAuth token exchange failed (${res.status}): ${body}`);
45
- }
46
- const data = (await res.json());
47
- oauthToken = {
48
- access_token: data.access_token,
49
- expires_at: Date.now() + data.expires_in * 1000,
50
- };
51
- return oauthToken.access_token;
52
- }
53
- finally {
54
- oauthRefreshPromise = null;
55
- }
56
- })();
57
- return oauthRefreshPromise;
58
- }
59
- async function getAuthHeader() {
60
- const config = getConfig();
61
- if (config.apiKey) {
62
- return `Basic ${Buffer.from(`${config.apiKey}:`).toString("base64")}`;
63
- }
64
- const token = await getOAuthAccessToken(config.oauthClientId, config.oauthClientSecret);
65
- return `Bearer ${token}`;
66
- }
67
- export function getTailnet() {
68
- return process.env.TAILSCALE_TAILNET || "-";
69
- }
70
- /** URL-encode a path segment to prevent path traversal. */
71
- export function encPath(segment) {
72
- return encodeURIComponent(segment);
73
- }
74
- export async function apiRequest(method, path, body, options) {
75
- const auth = await getAuthHeader();
76
- const headers = {
77
- Authorization: auth,
78
- };
79
- if (options?.accept) {
80
- headers.Accept = options.accept;
81
- }
82
- if (options?.ifMatch) {
83
- headers["If-Match"] = options.ifMatch;
84
- }
85
- let fetchBody;
86
- if (options?.rawBody !== undefined) {
87
- headers["Content-Type"] = options.contentType || "application/json";
88
- fetchBody = options.rawBody;
89
- }
90
- else if (body !== undefined) {
91
- headers["Content-Type"] = "application/json";
92
- fetchBody = JSON.stringify(body);
93
- }
94
- const url = path.startsWith("http") ? path : `${BASE_URL}${path}`;
95
- const res = await fetch(url, {
96
- method,
97
- headers,
98
- body: fetchBody,
99
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
100
- });
101
- const etag = res.headers.get("etag") || undefined;
102
- if (options?.acceptRaw) {
103
- const rawBody = await res.text();
104
- if (!res.ok) {
105
- return { ok: false, status: res.status, error: rawBody, rawBody, etag };
106
- }
107
- return { ok: true, status: res.status, rawBody, etag };
108
- }
109
- if (!res.ok) {
110
- const errorBody = await res.text();
111
- return { ok: false, status: res.status, error: errorBody, etag };
112
- }
113
- if (res.status === 204 || res.headers.get("content-length") === "0") {
114
- return { ok: true, status: res.status, etag };
115
- }
116
- const data = (await res.json());
117
- return { ok: true, status: res.status, data, etag };
118
- }
119
- export async function apiGet(path, options) {
120
- return apiRequest("GET", path, undefined, options);
121
- }
122
- export async function apiPost(path, body, options) {
123
- return apiRequest("POST", path, body, options);
124
- }
125
- export async function apiPut(path, body) {
126
- return apiRequest("PUT", path, body);
127
- }
128
- export async function apiPatch(path, body) {
129
- return apiRequest("PATCH", path, body);
130
- }
131
- export async function apiDelete(path) {
132
- return apiRequest("DELETE", path);
133
- }
134
- //# sourceMappingURL=api.js.map
package/dist/api.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts DELETED
@@ -1,5 +0,0 @@
1
- /**
2
- * CLI subcommands for tailscale-mcp.
3
- * These run instead of the MCP server when a subcommand is passed.
4
- */
5
- export declare function deployAcl(filePath: string): Promise<void>;
package/dist/cli.js DELETED
@@ -1,43 +0,0 @@
1
- /**
2
- * CLI subcommands for tailscale-mcp.
3
- * These run instead of the MCP server when a subcommand is passed.
4
- */
5
- import { readFileSync } from "node:fs";
6
- import { apiGet, apiPost, getTailnet } from "./api.js";
7
- export async function deployAcl(filePath) {
8
- let policy;
9
- try {
10
- policy = readFileSync(filePath, "utf-8");
11
- }
12
- catch (err) {
13
- console.error(`Failed to read ${filePath}: ${err instanceof Error ? err.message : err}`);
14
- process.exit(1);
15
- }
16
- // Fetch current ETag
17
- const getRes = await apiGet(`/tailnet/${getTailnet()}/acl`, { acceptRaw: true, accept: "application/hujson" });
18
- if (!getRes.ok || !getRes.etag) {
19
- console.error(`Failed to get current ACL: ${getRes.error || "no ETag returned"}`);
20
- process.exit(1);
21
- }
22
- // Validate before deploying
23
- const validateRes = await apiPost(`/tailnet/${getTailnet()}/acl/validate`, undefined, {
24
- rawBody: policy,
25
- contentType: "application/hujson",
26
- });
27
- if (!validateRes.ok) {
28
- console.error(`ACL validation failed: ${validateRes.error}`);
29
- process.exit(1);
30
- }
31
- // Deploy with ETag
32
- const deployRes = await apiPost(`/tailnet/${getTailnet()}/acl`, undefined, {
33
- rawBody: policy,
34
- contentType: "application/hujson",
35
- ifMatch: getRes.etag,
36
- });
37
- if (!deployRes.ok) {
38
- console.error(`ACL deploy failed: ${deployRes.error}`);
39
- process.exit(1);
40
- }
41
- console.log("ACL deployed successfully");
42
- }
43
- //# sourceMappingURL=cli.js.map
package/dist/cli.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEvD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAgB;IAC9C,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,kBAAkB,QAAQ,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QACzF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,qBAAqB;IACrB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,UAAU,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC,CAAC;IAC/G,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,8BAA8B,MAAM,CAAC,KAAK,IAAI,kBAAkB,EAAE,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,4BAA4B;IAC5B,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,YAAY,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE;QACpF,OAAO,EAAE,MAAM;QACf,WAAW,EAAE,oBAAoB;KAClC,CAAC,CAAC;IACH,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,0BAA0B,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,mBAAmB;IACnB,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,YAAY,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE;QACzE,OAAO,EAAE,MAAM;QACf,WAAW,EAAE,oBAAoB;QACjC,OAAO,EAAE,MAAM,CAAC,IAAI;KACrB,CAAC,CAAC;IACH,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,sBAAsB,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;QACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;AAC3C,CAAC"}
package/dist/index.d.ts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,86 +0,0 @@
1
- import { z } from "zod";
2
- export declare const aclTools: readonly [{
3
- readonly name: "tailscale_get_acl";
4
- readonly description: "Get the current ACL policy for your tailnet. Returns the raw policy text with original formatting preserved, including comments and trailing commas (HuJSON). Also returns an ETag — you must pass it to tailscale_update_acl to safely update the policy.";
5
- readonly annotations: {
6
- readonly title: "Get ACL policy";
7
- readonly readOnlyHint: true;
8
- readonly destructiveHint: false;
9
- readonly idempotentHint: true;
10
- readonly openWorldHint: true;
11
- };
12
- readonly inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
13
- readonly handler: () => Promise<import("../api.js").ApiResponse<unknown>>;
14
- }, {
15
- readonly name: "tailscale_update_acl";
16
- readonly description: "Update the ACL policy for your tailnet. Accepts the full policy as a string to preserve formatting, comments, and trailing commas (HuJSON). You MUST pass the ETag from tailscale_get_acl to prevent overwriting concurrent changes. Always get the current ACL first, make targeted edits to the text, and pass the full modified text back.";
17
- readonly annotations: {
18
- readonly title: "Update ACL policy";
19
- readonly readOnlyHint: false;
20
- readonly destructiveHint: false;
21
- readonly idempotentHint: true;
22
- readonly openWorldHint: true;
23
- };
24
- readonly inputSchema: z.ZodObject<{
25
- policy: z.ZodString;
26
- etag: z.ZodString;
27
- }, "strip", z.ZodTypeAny, {
28
- etag: string;
29
- policy: string;
30
- }, {
31
- etag: string;
32
- policy: string;
33
- }>;
34
- readonly handler: (input: {
35
- policy: string;
36
- etag: string;
37
- }) => Promise<import("../api.js").ApiResponse<unknown>>;
38
- }, {
39
- readonly name: "tailscale_validate_acl";
40
- readonly description: "Validate an ACL policy without applying it. Returns any errors found, or confirms the policy is valid.";
41
- readonly annotations: {
42
- readonly title: "Validate ACL policy";
43
- readonly readOnlyHint: true;
44
- readonly destructiveHint: false;
45
- readonly idempotentHint: true;
46
- readonly openWorldHint: true;
47
- };
48
- readonly inputSchema: z.ZodObject<{
49
- policy: z.ZodString;
50
- }, "strip", z.ZodTypeAny, {
51
- policy: string;
52
- }, {
53
- policy: string;
54
- }>;
55
- readonly handler: (input: {
56
- policy: string;
57
- }) => Promise<import("../api.js").ApiResponse<unknown>>;
58
- }, {
59
- readonly name: "tailscale_preview_acl";
60
- readonly description: "Preview the ACL rules that would apply to a specific user or IP address if a proposed policy were applied.";
61
- readonly annotations: {
62
- readonly title: "Preview ACL rules";
63
- readonly readOnlyHint: true;
64
- readonly destructiveHint: false;
65
- readonly idempotentHint: true;
66
- readonly openWorldHint: true;
67
- };
68
- readonly inputSchema: z.ZodObject<{
69
- policy: z.ZodString;
70
- type: z.ZodEnum<["user", "ipport"]>;
71
- previewFor: z.ZodString;
72
- }, "strip", z.ZodTypeAny, {
73
- type: "user" | "ipport";
74
- policy: string;
75
- previewFor: string;
76
- }, {
77
- type: "user" | "ipport";
78
- policy: string;
79
- previewFor: string;
80
- }>;
81
- readonly handler: (input: {
82
- policy: string;
83
- type: string;
84
- previewFor: string;
85
- }) => Promise<import("../api.js").ApiResponse<unknown>>;
86
- }];
package/dist/tools/acl.js DELETED
@@ -1,105 +0,0 @@
1
- import { z } from "zod";
2
- import { apiGet, apiPost, getTailnet } from "../api.js";
3
- export const aclTools = [
4
- {
5
- name: "tailscale_get_acl",
6
- description: "Get the current ACL policy for your tailnet. Returns the raw policy text with original formatting preserved, including comments and trailing commas (HuJSON). Also returns an ETag — you must pass it to tailscale_update_acl to safely update the policy.",
7
- annotations: {
8
- title: "Get ACL policy",
9
- readOnlyHint: true,
10
- destructiveHint: false,
11
- idempotentHint: true,
12
- openWorldHint: true,
13
- },
14
- inputSchema: z.object({}),
15
- handler: async () => {
16
- const res = await apiGet(`/tailnet/${getTailnet()}/acl`, {
17
- acceptRaw: true,
18
- accept: "application/hujson",
19
- });
20
- if (res.ok && res.etag) {
21
- return {
22
- ...res,
23
- rawBody: `${res.rawBody}\n\n---\nETag: ${res.etag}\nPass this ETag to tailscale_update_acl when updating the policy.`,
24
- };
25
- }
26
- return res;
27
- },
28
- },
29
- {
30
- name: "tailscale_update_acl",
31
- description: "Update the ACL policy for your tailnet. Accepts the full policy as a string to preserve formatting, comments, and trailing commas (HuJSON). You MUST pass the ETag from tailscale_get_acl to prevent overwriting concurrent changes. Always get the current ACL first, make targeted edits to the text, and pass the full modified text back.",
32
- annotations: {
33
- title: "Update ACL policy",
34
- readOnlyHint: false,
35
- destructiveHint: false,
36
- idempotentHint: true,
37
- openWorldHint: true,
38
- },
39
- inputSchema: z.object({
40
- policy: z
41
- .string()
42
- .describe("The full ACL policy text. Preserve existing formatting, comments, and structure. Only modify the specific parts that need to change."),
43
- etag: z.string().describe("The ETag from tailscale_get_acl. Required to prevent concurrent edit conflicts."),
44
- }),
45
- handler: async (input) => {
46
- return apiPost(`/tailnet/${getTailnet()}/acl`, undefined, {
47
- rawBody: input.policy,
48
- contentType: "application/hujson",
49
- ifMatch: input.etag,
50
- });
51
- },
52
- },
53
- {
54
- name: "tailscale_validate_acl",
55
- description: "Validate an ACL policy without applying it. Returns any errors found, or confirms the policy is valid.",
56
- annotations: {
57
- title: "Validate ACL policy",
58
- readOnlyHint: true,
59
- destructiveHint: false,
60
- idempotentHint: true,
61
- openWorldHint: true,
62
- },
63
- inputSchema: z.object({
64
- policy: z.string().describe("The full ACL policy text to validate"),
65
- }),
66
- handler: async (input) => {
67
- const res = await apiPost(`/tailnet/${getTailnet()}/acl/validate`, undefined, {
68
- rawBody: input.policy,
69
- contentType: "application/hujson",
70
- });
71
- if (res.ok && !res.data) {
72
- return { ...res, data: { message: "ACL policy is valid." } };
73
- }
74
- return res;
75
- },
76
- },
77
- {
78
- name: "tailscale_preview_acl",
79
- description: "Preview the ACL rules that would apply to a specific user or IP address if a proposed policy were applied.",
80
- annotations: {
81
- title: "Preview ACL rules",
82
- readOnlyHint: true,
83
- destructiveHint: false,
84
- idempotentHint: true,
85
- openWorldHint: true,
86
- },
87
- inputSchema: z.object({
88
- policy: z.string().describe("The proposed ACL policy text to preview"),
89
- type: z
90
- .enum(["user", "ipport"])
91
- .describe("Preview type: 'user' to see rules for a user, 'ipport' to see rules for an IP"),
92
- previewFor: z
93
- .string()
94
- .describe("The user email (for type 'user') or IP:port (for type 'ipport') to preview rules for"),
95
- }),
96
- handler: async (input) => {
97
- const params = new URLSearchParams({ type: input.type, previewFor: input.previewFor });
98
- return apiPost(`/tailnet/${getTailnet()}/acl/preview?${params}`, undefined, {
99
- rawBody: input.policy,
100
- contentType: "application/hujson",
101
- });
102
- },
103
- },
104
- ];
105
- //# sourceMappingURL=acl.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"acl.js","sourceRoot":"","sources":["../../src/tools/acl.ts"],"names":[],"mappings":"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"}
@@ -1,50 +0,0 @@
1
- import { z } from "zod";
2
- export declare const auditTools: readonly [{
3
- readonly name: "tailscale_get_audit_log";
4
- readonly description: "Get the tailnet audit/configuration log. Shows who changed what and when — useful for troubleshooting and compliance.";
5
- readonly annotations: {
6
- readonly title: "Get audit log";
7
- readonly readOnlyHint: true;
8
- readonly destructiveHint: false;
9
- readonly idempotentHint: true;
10
- readonly openWorldHint: true;
11
- };
12
- readonly inputSchema: z.ZodObject<{
13
- start: z.ZodString;
14
- end: z.ZodOptional<z.ZodString>;
15
- }, "strip", z.ZodTypeAny, {
16
- start: string;
17
- end?: string | undefined;
18
- }, {
19
- start: string;
20
- end?: string | undefined;
21
- }>;
22
- readonly handler: (input: {
23
- start: string;
24
- end?: string;
25
- }) => Promise<import("../api.js").ApiResponse<unknown>>;
26
- }, {
27
- readonly name: "tailscale_get_network_flow_logs";
28
- readonly description: "Get network traffic flow logs showing connections between devices. Shows source/destination nodes, timestamps, and traffic metadata — useful for security monitoring and debugging connectivity.";
29
- readonly annotations: {
30
- readonly title: "Get network flow logs";
31
- readonly readOnlyHint: true;
32
- readonly destructiveHint: false;
33
- readonly idempotentHint: true;
34
- readonly openWorldHint: true;
35
- };
36
- readonly inputSchema: z.ZodObject<{
37
- start: z.ZodString;
38
- end: z.ZodOptional<z.ZodString>;
39
- }, "strip", z.ZodTypeAny, {
40
- start: string;
41
- end?: string | undefined;
42
- }, {
43
- start: string;
44
- end?: string | undefined;
45
- }>;
46
- readonly handler: (input: {
47
- start: string;
48
- end?: string;
49
- }) => Promise<import("../api.js").ApiResponse<unknown>>;
50
- }];
@@ -1,60 +0,0 @@
1
- import { z } from "zod";
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 (Number.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
- }
10
- export const auditTools = [
11
- {
12
- name: "tailscale_get_audit_log",
13
- description: "Get the tailnet audit/configuration log. Shows who changed what and when — useful for troubleshooting and compliance.",
14
- annotations: {
15
- title: "Get audit log",
16
- readOnlyHint: true,
17
- destructiveHint: false,
18
- idempotentHint: true,
19
- openWorldHint: true,
20
- },
21
- inputSchema: z.object({
22
- start: z.string().describe("Start time in RFC3339 format (e.g. '2026-04-01T00:00:00Z'). Required."),
23
- end: z.string().optional().describe("End time in RFC3339 format. Defaults to now."),
24
- }),
25
- handler: async (input) => {
26
- assertRFC3339(input.start, "start");
27
- if (input.end)
28
- assertRFC3339(input.end, "end");
29
- const params = new URLSearchParams({ start: input.start });
30
- if (input.end)
31
- params.set("end", input.end);
32
- return apiGet(`/tailnet/${getTailnet()}/logging/configuration?${params}`);
33
- },
34
- },
35
- {
36
- name: "tailscale_get_network_flow_logs",
37
- description: "Get network traffic flow logs showing connections between devices. Shows source/destination nodes, timestamps, and traffic metadata — useful for security monitoring and debugging connectivity.",
38
- annotations: {
39
- title: "Get network flow logs",
40
- readOnlyHint: true,
41
- destructiveHint: false,
42
- idempotentHint: true,
43
- openWorldHint: true,
44
- },
45
- inputSchema: z.object({
46
- start: z.string().describe("Start time in RFC3339 format (e.g. '2026-04-01T00:00:00Z'). Required."),
47
- end: z.string().optional().describe("End time in RFC3339 format. Defaults to now."),
48
- }),
49
- handler: async (input) => {
50
- assertRFC3339(input.start, "start");
51
- if (input.end)
52
- assertRFC3339(input.end, "end");
53
- const params = new URLSearchParams({ start: input.start });
54
- if (input.end)
55
- params.set("end", input.end);
56
- return apiGet(`/tailnet/${getTailnet()}/logging/network?${params}`);
57
- },
58
- },
59
- ];
60
- //# sourceMappingURL=audit.js.map
@@ -1 +0,0 @@
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,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QAC9B,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;YACX,KAAK,EAAE,eAAe;YACtB,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;QACD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uEAAuE,CAAC;YACnG,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;SACpF,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,CAAC,YAAY,UAAU,EAAE,0BAA0B,MAAM,EAAE,CAAC,CAAC;QAC5E,CAAC;KACF;IACD;QACE,IAAI,EAAE,iCAAiC;QACvC,WAAW,EACT,kMAAkM;QACpM,WAAW,EAAE;YACX,KAAK,EAAE,uBAAuB;YAC9B,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;QACD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uEAAuE,CAAC;YACnG,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;SACpF,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,CAAC,YAAY,UAAU,EAAE,oBAAoB,MAAM,EAAE,CAAC,CAAC;QACtE,CAAC;KACF;CACO,CAAC"}