@yawlabs/tailscale-mcp 0.1.1

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 (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +218 -0
  3. package/dist/api.d.ts +30 -0
  4. package/dist/api.js +108 -0
  5. package/dist/api.js.map +1 -0
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.js +70 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/tools/acl.d.ts +58 -0
  10. package/dist/tools/acl.js +72 -0
  11. package/dist/tools/acl.js.map +1 -0
  12. package/dist/tools/audit.d.ts +19 -0
  13. package/dist/tools/audit.js +24 -0
  14. package/dist/tools/audit.js.map +1 -0
  15. package/dist/tools/devices.d.ts +144 -0
  16. package/dist/tools/devices.js +112 -0
  17. package/dist/tools/devices.js.map +1 -0
  18. package/dist/tools/dns.d.ts +74 -0
  19. package/dist/tools/dns.js +83 -0
  20. package/dist/tools/dns.js.map +1 -0
  21. package/dist/tools/keys.d.ts +66 -0
  22. package/dist/tools/keys.js +64 -0
  23. package/dist/tools/keys.js.map +1 -0
  24. package/dist/tools/network-lock.d.ts +7 -0
  25. package/dist/tools/network-lock.js +13 -0
  26. package/dist/tools/network-lock.js.map +1 -0
  27. package/dist/tools/posture.d.ts +62 -0
  28. package/dist/tools/posture.js +47 -0
  29. package/dist/tools/posture.js.map +1 -0
  30. package/dist/tools/status.d.ts +18 -0
  31. package/dist/tools/status.js +28 -0
  32. package/dist/tools/status.js.map +1 -0
  33. package/dist/tools/tailnet.d.ts +85 -0
  34. package/dist/tools/tailnet.js +48 -0
  35. package/dist/tools/tailnet.js.map +1 -0
  36. package/dist/tools/users.d.ts +20 -0
  37. package/dist/tools/users.js +23 -0
  38. package/dist/tools/users.js.map +1 -0
  39. package/dist/tools/webhooks.d.ts +50 -0
  40. package/dist/tools/webhooks.js +49 -0
  41. package/dist/tools/webhooks.js.map +1 -0
  42. package/package.json +45 -0
@@ -0,0 +1,47 @@
1
+ import { z } from "zod";
2
+ import { apiGet, apiPost, apiDelete, getTailnet } from "../api.js";
3
+ export const postureTools = [
4
+ {
5
+ name: "tailscale_list_posture_integrations",
6
+ description: "List all device posture integrations configured for your tailnet.",
7
+ inputSchema: z.object({}),
8
+ handler: async () => {
9
+ return apiGet(`/tailnet/${getTailnet()}/posture/integrations`);
10
+ },
11
+ },
12
+ {
13
+ name: "tailscale_get_posture_integration",
14
+ description: "Get details for a specific posture integration.",
15
+ inputSchema: z.object({
16
+ integrationId: z.string().describe("The posture integration ID"),
17
+ }),
18
+ handler: async (input) => {
19
+ return apiGet(`/tailnet/${getTailnet()}/posture/integrations/${input.integrationId}`);
20
+ },
21
+ },
22
+ {
23
+ name: "tailscale_create_posture_integration",
24
+ description: "Create a new device posture integration.",
25
+ inputSchema: z.object({
26
+ provider: z.string().describe("The posture provider (e.g. 'crowdstrike', 'sentinelone', 'intune')"),
27
+ clientId: z.string().describe("The OAuth client ID for the provider"),
28
+ clientSecret: z.string().describe("The OAuth client secret for the provider"),
29
+ tenantId: z.string().optional().describe("The tenant ID (required for some providers)"),
30
+ cloudEnvironment: z.string().optional().describe("Cloud environment (e.g. 'us-1', 'eu-1')"),
31
+ }),
32
+ handler: async (input) => {
33
+ return apiPost(`/tailnet/${getTailnet()}/posture/integrations`, input);
34
+ },
35
+ },
36
+ {
37
+ name: "tailscale_delete_posture_integration",
38
+ description: "Delete a posture integration.",
39
+ inputSchema: z.object({
40
+ integrationId: z.string().describe("The posture integration ID to delete"),
41
+ }),
42
+ handler: async (input) => {
43
+ return apiDelete(`/tailnet/${getTailnet()}/posture/integrations/${input.integrationId}`);
44
+ },
45
+ },
46
+ ];
47
+ //# sourceMappingURL=posture.js.map
@@ -0,0 +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;AAEnE,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B;QACE,IAAI,EAAE,qCAAqC;QAC3C,WAAW,EAAE,mEAAmE;QAChF,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,OAAO,MAAM,CAAC,YAAY,UAAU,EAAE,uBAAuB,CAAC,CAAC;QACjE,CAAC;KACF;IACD;QACE,IAAI,EAAE,mCAAmC;QACzC,WAAW,EAAE,iDAAiD;QAC9D,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;SACjE,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAAgC,EAAE,EAAE;YAClD,OAAO,MAAM,CACX,YAAY,UAAU,EAAE,yBAAyB,KAAK,CAAC,aAAa,EAAE,CACvE,CAAC;QACJ,CAAC;KACF;IACD;QACE,IAAI,EAAE,sCAAsC;QAC5C,WAAW,EAAE,0CAA0C;QACvD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oEAAoE,CAAC;YACnG,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;YACrE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;YAC7E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;YACvF,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;SAC5F,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAMf,EAAE,EAAE;YACH,OAAO,OAAO,CACZ,YAAY,UAAU,EAAE,uBAAuB,EAC/C,KAAK,CACN,CAAC;QACJ,CAAC;KACF;IACD;QACE,IAAI,EAAE,sCAAsC;QAC5C,WAAW,EAAE,+BAA+B;QAC5C,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;SAC3E,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAAgC,EAAE,EAAE;YAClD,OAAO,SAAS,CACd,YAAY,UAAU,EAAE,yBAAyB,KAAK,CAAC,aAAa,EAAE,CACvE,CAAC;QACJ,CAAC;KACF;CACO,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+ export declare const statusTools: readonly [{
3
+ readonly name: "tailscale_status";
4
+ readonly description: "Check that the Tailscale API connection is working. Returns your tailnet name, device count, and confirms authentication is valid. Use this to verify setup.";
5
+ readonly inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
6
+ readonly handler: () => Promise<import("../api.js").ApiResponse<{
7
+ devices: unknown[];
8
+ }> | {
9
+ ok: boolean;
10
+ status: number;
11
+ data: {
12
+ connected: boolean;
13
+ tailnet: string;
14
+ deviceCount: number;
15
+ settings: Record<string, unknown> | undefined;
16
+ };
17
+ }>;
18
+ }];
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ import { apiGet, getTailnet } from "../api.js";
3
+ export const statusTools = [
4
+ {
5
+ name: "tailscale_status",
6
+ description: "Check that the Tailscale API connection is working. Returns your tailnet name, device count, and confirms authentication is valid. Use this to verify setup.",
7
+ inputSchema: z.object({}),
8
+ handler: async () => {
9
+ const devicesRes = await apiGet(`/tailnet/${getTailnet()}/devices?fields=id`);
10
+ if (!devicesRes.ok) {
11
+ return devicesRes;
12
+ }
13
+ const deviceCount = devicesRes.data?.devices?.length ?? 0;
14
+ const settingsRes = await apiGet(`/tailnet/${getTailnet()}/settings`);
15
+ return {
16
+ ok: true,
17
+ status: 200,
18
+ data: {
19
+ connected: true,
20
+ tailnet: getTailnet(),
21
+ deviceCount,
22
+ settings: settingsRes.ok ? settingsRes.data : undefined,
23
+ },
24
+ };
25
+ },
26
+ },
27
+ ];
28
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/tools/status.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,WAAW,GAAG;IACzB;QACE,IAAI,EAAE,kBAAkB;QACxB,WAAW,EACT,8JAA8J;QAChK,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,UAAU,GAAG,MAAM,MAAM,CAC7B,YAAY,UAAU,EAAE,oBAAoB,CAC7C,CAAC;YACF,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC;gBACnB,OAAO,UAAU,CAAC;YACpB,CAAC;YACD,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC;YAE1D,MAAM,WAAW,GAAG,MAAM,MAAM,CAC9B,YAAY,UAAU,EAAE,WAAW,CACpC,CAAC;YAEF,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,MAAM,EAAE,GAAG;gBACX,IAAI,EAAE;oBACJ,SAAS,EAAE,IAAI;oBACf,OAAO,EAAE,UAAU,EAAE;oBACrB,WAAW;oBACX,QAAQ,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;iBACxD;aACF,CAAC;QACJ,CAAC;KACF;CACO,CAAC"}
@@ -0,0 +1,85 @@
1
+ import { z } from "zod";
2
+ export declare const tailnetTools: readonly [{
3
+ readonly name: "tailscale_get_tailnet_settings";
4
+ readonly description: "Get your tailnet settings (device approval, key expiry, etc.).";
5
+ readonly inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
6
+ readonly handler: () => Promise<import("../api.js").ApiResponse<unknown>>;
7
+ }, {
8
+ readonly name: "tailscale_update_tailnet_settings";
9
+ readonly description: "Update tailnet settings.";
10
+ readonly inputSchema: z.ZodObject<{
11
+ devicesApprovalOn: z.ZodOptional<z.ZodBoolean>;
12
+ devicesAutoUpdatesOn: z.ZodOptional<z.ZodBoolean>;
13
+ devicesKeyDurationDays: z.ZodOptional<z.ZodNumber>;
14
+ usersApprovalOn: z.ZodOptional<z.ZodBoolean>;
15
+ networkFlowLoggingOn: z.ZodOptional<z.ZodBoolean>;
16
+ regionalRoutingOn: z.ZodOptional<z.ZodBoolean>;
17
+ }, "strip", z.ZodTypeAny, {
18
+ devicesApprovalOn?: boolean | undefined;
19
+ devicesAutoUpdatesOn?: boolean | undefined;
20
+ devicesKeyDurationDays?: number | undefined;
21
+ usersApprovalOn?: boolean | undefined;
22
+ networkFlowLoggingOn?: boolean | undefined;
23
+ regionalRoutingOn?: boolean | undefined;
24
+ }, {
25
+ devicesApprovalOn?: boolean | undefined;
26
+ devicesAutoUpdatesOn?: boolean | undefined;
27
+ devicesKeyDurationDays?: number | undefined;
28
+ usersApprovalOn?: boolean | undefined;
29
+ networkFlowLoggingOn?: boolean | undefined;
30
+ regionalRoutingOn?: boolean | undefined;
31
+ }>;
32
+ readonly handler: (input: Record<string, unknown>) => Promise<import("../api.js").ApiResponse<unknown>>;
33
+ }, {
34
+ readonly name: "tailscale_get_contacts";
35
+ readonly description: "Get the tailnet contact information (security, support, admin emails).";
36
+ readonly inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
37
+ readonly handler: () => Promise<import("../api.js").ApiResponse<unknown>>;
38
+ }, {
39
+ readonly name: "tailscale_set_contacts";
40
+ readonly description: "Update tailnet contact information.";
41
+ readonly inputSchema: z.ZodObject<{
42
+ account: z.ZodOptional<z.ZodObject<{
43
+ email: z.ZodString;
44
+ }, "strip", z.ZodTypeAny, {
45
+ email: string;
46
+ }, {
47
+ email: string;
48
+ }>>;
49
+ support: z.ZodOptional<z.ZodObject<{
50
+ email: z.ZodString;
51
+ }, "strip", z.ZodTypeAny, {
52
+ email: string;
53
+ }, {
54
+ email: string;
55
+ }>>;
56
+ security: z.ZodOptional<z.ZodObject<{
57
+ email: z.ZodString;
58
+ }, "strip", z.ZodTypeAny, {
59
+ email: string;
60
+ }, {
61
+ email: string;
62
+ }>>;
63
+ }, "strip", z.ZodTypeAny, {
64
+ account?: {
65
+ email: string;
66
+ } | undefined;
67
+ support?: {
68
+ email: string;
69
+ } | undefined;
70
+ security?: {
71
+ email: string;
72
+ } | undefined;
73
+ }, {
74
+ account?: {
75
+ email: string;
76
+ } | undefined;
77
+ support?: {
78
+ email: string;
79
+ } | undefined;
80
+ security?: {
81
+ email: string;
82
+ } | undefined;
83
+ }>;
84
+ readonly handler: (input: Record<string, unknown>) => Promise<import("../api.js").ApiResponse<unknown>>;
85
+ }];
@@ -0,0 +1,48 @@
1
+ import { z } from "zod";
2
+ import { apiGet, apiPatch, getTailnet } from "../api.js";
3
+ export const tailnetTools = [
4
+ {
5
+ name: "tailscale_get_tailnet_settings",
6
+ description: "Get your tailnet settings (device approval, key expiry, etc.).",
7
+ inputSchema: z.object({}),
8
+ handler: async () => {
9
+ return apiGet(`/tailnet/${getTailnet()}/settings`);
10
+ },
11
+ },
12
+ {
13
+ name: "tailscale_update_tailnet_settings",
14
+ description: "Update tailnet settings.",
15
+ inputSchema: z.object({
16
+ devicesApprovalOn: z.boolean().optional().describe("Whether device approval is required"),
17
+ devicesAutoUpdatesOn: z.boolean().optional().describe("Whether auto-updates are enabled"),
18
+ devicesKeyDurationDays: z.number().optional().describe("Key expiry duration in days"),
19
+ usersApprovalOn: z.boolean().optional().describe("Whether user approval is required"),
20
+ networkFlowLoggingOn: z.boolean().optional().describe("Whether network flow logging is enabled"),
21
+ regionalRoutingOn: z.boolean().optional().describe("Whether regional routing is enabled"),
22
+ }),
23
+ handler: async (input) => {
24
+ return apiPatch(`/tailnet/${getTailnet()}/settings`, input);
25
+ },
26
+ },
27
+ {
28
+ name: "tailscale_get_contacts",
29
+ description: "Get the tailnet contact information (security, support, admin emails).",
30
+ inputSchema: z.object({}),
31
+ handler: async () => {
32
+ return apiGet(`/tailnet/${getTailnet()}/contacts`);
33
+ },
34
+ },
35
+ {
36
+ name: "tailscale_set_contacts",
37
+ description: "Update tailnet contact information.",
38
+ inputSchema: z.object({
39
+ account: z.object({ email: z.string() }).optional().describe("Account contact email"),
40
+ support: z.object({ email: z.string() }).optional().describe("Support contact email"),
41
+ security: z.object({ email: z.string() }).optional().describe("Security contact email"),
42
+ }),
43
+ handler: async (input) => {
44
+ return apiPatch(`/tailnet/${getTailnet()}/contacts`, input);
45
+ },
46
+ },
47
+ ];
48
+ //# sourceMappingURL=tailnet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tailnet.js","sourceRoot":"","sources":["../../src/tools/tailnet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEzD,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B;QACE,IAAI,EAAE,gCAAgC;QACtC,WAAW,EAAE,gEAAgE;QAC7E,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,OAAO,MAAM,CAAC,YAAY,UAAU,EAAE,WAAW,CAAC,CAAC;QACrD,CAAC;KACF;IACD;QACE,IAAI,EAAE,mCAAmC;QACzC,WAAW,EAAE,0BAA0B;QACvC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;YACzF,oBAAoB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;YACzF,sBAAsB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;YACrF,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;YACrF,oBAAoB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;YAChG,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;SAC1F,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAA8B,EAAE,EAAE;YAChD,OAAO,QAAQ,CAAC,YAAY,UAAU,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;QAC9D,CAAC;KACF;IACD;QACE,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EAAE,wEAAwE;QACrF,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,OAAO,MAAM,CAAC,YAAY,UAAU,EAAE,WAAW,CAAC,CAAC;QACrD,CAAC;KACF;IACD;QACE,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EAAE,qCAAqC;QAClD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;YACrF,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;YACrF,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;SACxF,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAA8B,EAAE,EAAE;YAChD,OAAO,QAAQ,CAAC,YAAY,UAAU,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;QAC9D,CAAC;KACF;CACO,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ export declare const userTools: readonly [{
3
+ readonly name: "tailscale_list_users";
4
+ readonly description: "List all users in your tailnet.";
5
+ readonly inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
6
+ readonly handler: () => Promise<import("../api.js").ApiResponse<unknown>>;
7
+ }, {
8
+ readonly name: "tailscale_get_user";
9
+ readonly description: "Get details for a specific user.";
10
+ readonly inputSchema: z.ZodObject<{
11
+ userId: z.ZodString;
12
+ }, "strip", z.ZodTypeAny, {
13
+ userId: string;
14
+ }, {
15
+ userId: string;
16
+ }>;
17
+ readonly handler: (input: {
18
+ userId: string;
19
+ }) => Promise<import("../api.js").ApiResponse<unknown>>;
20
+ }];
@@ -0,0 +1,23 @@
1
+ import { z } from "zod";
2
+ import { apiGet, getTailnet } from "../api.js";
3
+ export const userTools = [
4
+ {
5
+ name: "tailscale_list_users",
6
+ description: "List all users in your tailnet.",
7
+ inputSchema: z.object({}),
8
+ handler: async () => {
9
+ return apiGet(`/tailnet/${getTailnet()}/users`);
10
+ },
11
+ },
12
+ {
13
+ name: "tailscale_get_user",
14
+ description: "Get details for a specific user.",
15
+ inputSchema: z.object({
16
+ userId: z.string().describe("The user ID"),
17
+ }),
18
+ handler: async (input) => {
19
+ return apiGet(`/users/${input.userId}`);
20
+ },
21
+ },
22
+ ];
23
+ //# sourceMappingURL=users.js.map
@@ -0,0 +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,UAAU,EAAE,MAAM,WAAW,CAAC;AAE/C,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,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1C,CAAC;KACF;CACO,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { z } from "zod";
2
+ export declare const webhookTools: readonly [{
3
+ readonly name: "tailscale_list_webhooks";
4
+ readonly description: "List all webhooks configured 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_get_webhook";
9
+ readonly description: "Get details for a specific webhook.";
10
+ readonly inputSchema: z.ZodObject<{
11
+ webhookId: z.ZodString;
12
+ }, "strip", z.ZodTypeAny, {
13
+ webhookId: string;
14
+ }, {
15
+ webhookId: string;
16
+ }>;
17
+ readonly handler: (input: {
18
+ webhookId: string;
19
+ }) => Promise<import("../api.js").ApiResponse<unknown>>;
20
+ }, {
21
+ readonly name: "tailscale_create_webhook";
22
+ readonly description: "Create a new webhook.";
23
+ readonly inputSchema: z.ZodObject<{
24
+ endpointUrl: z.ZodString;
25
+ subscriptions: z.ZodArray<z.ZodString, "many">;
26
+ }, "strip", z.ZodTypeAny, {
27
+ endpointUrl: string;
28
+ subscriptions: string[];
29
+ }, {
30
+ endpointUrl: string;
31
+ subscriptions: string[];
32
+ }>;
33
+ readonly handler: (input: {
34
+ endpointUrl: string;
35
+ subscriptions: string[];
36
+ }) => Promise<import("../api.js").ApiResponse<unknown>>;
37
+ }, {
38
+ readonly name: "tailscale_delete_webhook";
39
+ readonly description: "Delete a webhook.";
40
+ readonly inputSchema: z.ZodObject<{
41
+ webhookId: z.ZodString;
42
+ }, "strip", z.ZodTypeAny, {
43
+ webhookId: string;
44
+ }, {
45
+ webhookId: string;
46
+ }>;
47
+ readonly handler: (input: {
48
+ webhookId: string;
49
+ }) => Promise<import("../api.js").ApiResponse<unknown>>;
50
+ }];
@@ -0,0 +1,49 @@
1
+ import { z } from "zod";
2
+ import { apiGet, apiPost, apiDelete, getTailnet } from "../api.js";
3
+ export const webhookTools = [
4
+ {
5
+ name: "tailscale_list_webhooks",
6
+ description: "List all webhooks configured for your tailnet.",
7
+ inputSchema: z.object({}),
8
+ handler: async () => {
9
+ return apiGet(`/tailnet/${getTailnet()}/webhooks`);
10
+ },
11
+ },
12
+ {
13
+ name: "tailscale_get_webhook",
14
+ description: "Get details for a specific webhook.",
15
+ inputSchema: z.object({
16
+ webhookId: z.string().describe("The webhook ID"),
17
+ }),
18
+ handler: async (input) => {
19
+ return apiGet(`/webhooks/${input.webhookId}`);
20
+ },
21
+ },
22
+ {
23
+ name: "tailscale_create_webhook",
24
+ description: "Create a new webhook.",
25
+ inputSchema: z.object({
26
+ endpointUrl: z.string().describe("The URL to send webhook events to"),
27
+ subscriptions: z
28
+ .array(z.string())
29
+ .describe("Event types to subscribe to (e.g. ['nodeCreated', 'nodeDeleted', 'nodeApproved', 'policyUpdate', 'userCreated', 'userDeleted'])"),
30
+ }),
31
+ handler: async (input) => {
32
+ return apiPost(`/tailnet/${getTailnet()}/webhooks`, {
33
+ endpointUrl: input.endpointUrl,
34
+ subscriptions: input.subscriptions,
35
+ });
36
+ },
37
+ },
38
+ {
39
+ name: "tailscale_delete_webhook",
40
+ description: "Delete a webhook.",
41
+ inputSchema: z.object({
42
+ webhookId: z.string().describe("The webhook ID to delete"),
43
+ }),
44
+ handler: async (input) => {
45
+ return apiDelete(`/webhooks/${input.webhookId}`);
46
+ },
47
+ },
48
+ ];
49
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +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,EAAY,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE7E,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B;QACE,IAAI,EAAE,yBAAyB;QAC/B,WAAW,EAAE,gDAAgD;QAC7D,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,OAAO,MAAM,CAAC,YAAY,UAAU,EAAE,WAAW,CAAC,CAAC;QACrD,CAAC;KACF;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EAAE,qCAAqC;QAClD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC;SACjD,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAA4B,EAAE,EAAE;YAC9C,OAAO,MAAM,CAAC,aAAa,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;QAChD,CAAC;KACF;IACD;QACE,IAAI,EAAE,0BAA0B;QAChC,WAAW,EAAE,uBAAuB;QACpC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;YACrE,aAAa,EAAE,CAAC;iBACb,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;iBACjB,QAAQ,CACP,iIAAiI,CAClI;SACJ,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAAuD,EAAE,EAAE;YACzE,OAAO,OAAO,CAAC,YAAY,UAAU,EAAE,WAAW,EAAE;gBAClD,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,aAAa,EAAE,KAAK,CAAC,aAAa;aACnC,CAAC,CAAC;QACL,CAAC;KACF;IACD;QACE,IAAI,EAAE,0BAA0B;QAChC,WAAW,EAAE,mBAAmB;QAChC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;SAC3D,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,KAA4B,EAAE,EAAE;YAC9C,OAAO,SAAS,CAAC,aAAa,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;QACnD,CAAC;KACF;CACO,CAAC"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@yawlabs/tailscale-mcp",
3
+ "version": "0.1.1",
4
+ "description": "Tailscale MCP server for managing your tailnet from AI assistants",
5
+ "license": "MIT",
6
+ "author": "YawLabs <hello@yaw.sh>",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/YawLabs/tailscale-mcp"
10
+ },
11
+ "keywords": [
12
+ "tailscale",
13
+ "mcp",
14
+ "model-context-protocol",
15
+ "ai",
16
+ "networking",
17
+ "vpn"
18
+ ],
19
+ "type": "module",
20
+ "main": "dist/index.js",
21
+ "bin": {
22
+ "tailscale-mcp": "dist/index.js"
23
+ },
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "scripts": {
28
+ "build": "tsc",
29
+ "dev": "tsc --watch",
30
+ "start": "node dist/index.js",
31
+ "test": "node --test dist/**/*.test.js",
32
+ "prepublishOnly": "npm run build"
33
+ },
34
+ "dependencies": {
35
+ "@modelcontextprotocol/sdk": "^1.12.1",
36
+ "zod": "^3.24.4"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^22.15.2",
40
+ "typescript": "^5.8.3"
41
+ },
42
+ "engines": {
43
+ "node": ">=18"
44
+ }
45
+ }