@clavex/mcp-server 1.0.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 (83) hide show
  1. package/README.md +107 -0
  2. package/dist/client.d.ts +38 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +121 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/helpers.d.ts +14 -0
  7. package/dist/helpers.d.ts.map +1 -0
  8. package/dist/helpers.js +44 -0
  9. package/dist/helpers.js.map +1 -0
  10. package/dist/index.d.ts +24 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +59 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/tools/access_reviews.d.ts +3 -0
  15. package/dist/tools/access_reviews.d.ts.map +1 -0
  16. package/dist/tools/access_reviews.js +131 -0
  17. package/dist/tools/access_reviews.js.map +1 -0
  18. package/dist/tools/ai.d.ts +3 -0
  19. package/dist/tools/ai.d.ts.map +1 -0
  20. package/dist/tools/ai.js +443 -0
  21. package/dist/tools/ai.js.map +1 -0
  22. package/dist/tools/ciba.d.ts +3 -0
  23. package/dist/tools/ciba.d.ts.map +1 -0
  24. package/dist/tools/ciba.js +85 -0
  25. package/dist/tools/ciba.js.map +1 -0
  26. package/dist/tools/clients.d.ts +3 -0
  27. package/dist/tools/clients.d.ts.map +1 -0
  28. package/dist/tools/clients.js +124 -0
  29. package/dist/tools/clients.js.map +1 -0
  30. package/dist/tools/developer.d.ts +3 -0
  31. package/dist/tools/developer.d.ts.map +1 -0
  32. package/dist/tools/developer.js +580 -0
  33. package/dist/tools/developer.js.map +1 -0
  34. package/dist/tools/fga.d.ts +3 -0
  35. package/dist/tools/fga.d.ts.map +1 -0
  36. package/dist/tools/fga.js +126 -0
  37. package/dist/tools/fga.js.map +1 -0
  38. package/dist/tools/groups.d.ts +3 -0
  39. package/dist/tools/groups.d.ts.map +1 -0
  40. package/dist/tools/groups.js +135 -0
  41. package/dist/tools/groups.js.map +1 -0
  42. package/dist/tools/idps.d.ts +3 -0
  43. package/dist/tools/idps.d.ts.map +1 -0
  44. package/dist/tools/idps.js +98 -0
  45. package/dist/tools/idps.js.map +1 -0
  46. package/dist/tools/orgs.d.ts +3 -0
  47. package/dist/tools/orgs.d.ts.map +1 -0
  48. package/dist/tools/orgs.js +90 -0
  49. package/dist/tools/orgs.js.map +1 -0
  50. package/dist/tools/pam.d.ts +3 -0
  51. package/dist/tools/pam.d.ts.map +1 -0
  52. package/dist/tools/pam.js +238 -0
  53. package/dist/tools/pam.js.map +1 -0
  54. package/dist/tools/policies.d.ts +3 -0
  55. package/dist/tools/policies.d.ts.map +1 -0
  56. package/dist/tools/policies.js +173 -0
  57. package/dist/tools/policies.js.map +1 -0
  58. package/dist/tools/ssf.d.ts +3 -0
  59. package/dist/tools/ssf.d.ts.map +1 -0
  60. package/dist/tools/ssf.js +65 -0
  61. package/dist/tools/ssf.js.map +1 -0
  62. package/dist/tools/users.d.ts +3 -0
  63. package/dist/tools/users.d.ts.map +1 -0
  64. package/dist/tools/users.js +144 -0
  65. package/dist/tools/users.js.map +1 -0
  66. package/package.json +48 -0
  67. package/src/client.ts +148 -0
  68. package/src/helpers.ts +45 -0
  69. package/src/index.ts +63 -0
  70. package/src/tools/access_reviews.ts +163 -0
  71. package/src/tools/ai.ts +581 -0
  72. package/src/tools/ciba.ts +109 -0
  73. package/src/tools/clients.ts +168 -0
  74. package/src/tools/developer.ts +661 -0
  75. package/src/tools/fga.ts +148 -0
  76. package/src/tools/groups.ts +200 -0
  77. package/src/tools/idps.ts +137 -0
  78. package/src/tools/orgs.ts +119 -0
  79. package/src/tools/pam.ts +285 -0
  80. package/src/tools/policies.ts +233 -0
  81. package/src/tools/ssf.ts +82 -0
  82. package/src/tools/users.ts +202 -0
  83. package/tsconfig.json +18 -0
@@ -0,0 +1,202 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { z } from "zod";
3
+ import { getClient } from "../client.js";
4
+ import { handleError, mdTable } from "../helpers.js";
5
+
6
+ export function registerUserTools(server: McpServer): void {
7
+ // ── List users ─────────────────────────────────────────────────────────────
8
+ server.registerTool(
9
+ "clavex_list_users",
10
+ {
11
+ title: "List Users",
12
+ description: `List all users in an organization.
13
+
14
+ Returns a table with: id, email, first_name, last_name, is_active, created_at.
15
+
16
+ Use when: "show users in org <id>", "list all accounts for acme", "who are the members?".`,
17
+ inputSchema: {
18
+ org_id: z.string().uuid().describe("Organization UUID"),
19
+ },
20
+ annotations: { readOnlyHint: true, destructiveHint: false },
21
+ },
22
+ async ({ org_id }) =>
23
+ handleError(async () => {
24
+ const users = await getClient().get<Array<Record<string, unknown>>>(
25
+ getClient().orgPath(org_id, "/users"),
26
+ );
27
+ return mdTable(users, ["id", "email", "first_name", "last_name", "is_active", "created_at"]);
28
+ }),
29
+ );
30
+
31
+ // ── Get user ───────────────────────────────────────────────────────────────
32
+ server.registerTool(
33
+ "clavex_get_user",
34
+ {
35
+ title: "Get User",
36
+ description: `Get detailed information about a specific user.
37
+
38
+ Returns full user JSON including roles, groups, and metadata.
39
+
40
+ Use when: "get user <id>", "show me alice's account details".`,
41
+ inputSchema: {
42
+ org_id: z.string().uuid().describe("Organization UUID"),
43
+ user_id: z.string().uuid().describe("User UUID"),
44
+ },
45
+ annotations: { readOnlyHint: true, destructiveHint: false },
46
+ },
47
+ async ({ org_id, user_id }) =>
48
+ handleError(async () => {
49
+ const user = await getClient().get<Record<string, unknown>>(
50
+ getClient().orgPath(org_id, `/users/${user_id}`),
51
+ );
52
+ return JSON.stringify(user, null, 2);
53
+ }),
54
+ );
55
+
56
+ // ── Create user ────────────────────────────────────────────────────────────
57
+ server.registerTool(
58
+ "clavex_create_user",
59
+ {
60
+ title: "Create User",
61
+ description: `Create a new user in an organization.
62
+
63
+ Args:
64
+ - org_id: Organization UUID
65
+ - email: User's email address (must be unique within the org)
66
+ - first_name: Given name
67
+ - last_name: Family name
68
+ - password (optional): Initial password. If omitted, a welcome/reset email is sent.
69
+ - send_welcome_email (optional): Send a welcome email (default true)
70
+
71
+ Returns: Created user JSON with the new user_id.
72
+
73
+ Use when: "add user alice@example.com to org <id>", "create account for John Doe".`,
74
+ inputSchema: {
75
+ org_id: z.string().uuid().describe("Organization UUID"),
76
+ email: z.string().email().describe("User email address"),
77
+ first_name: z.string().describe("Given name"),
78
+ last_name: z.string().describe("Family name"),
79
+ password: z.string().optional().describe("Initial password (omit to trigger welcome email)"),
80
+ send_welcome_email: z.boolean().default(true).describe("Send welcome/activation email"),
81
+ },
82
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
83
+ },
84
+ async ({ org_id, email, first_name, last_name, password, send_welcome_email }) =>
85
+ handleError(async () => {
86
+ const user = await getClient().post<Record<string, unknown>>(
87
+ getClient().orgPath(org_id, "/users"),
88
+ { email, first_name, last_name, password, send_welcome_email },
89
+ );
90
+ return `User created:\n\n${JSON.stringify(user, null, 2)}`;
91
+ }),
92
+ );
93
+
94
+ // ── Update user ────────────────────────────────────────────────────────────
95
+ server.registerTool(
96
+ "clavex_update_user",
97
+ {
98
+ title: "Update User",
99
+ description: `Update a user's profile or status (PATCH semantics — only provided fields change).
100
+
101
+ Args:
102
+ - org_id, user_id: identifiers
103
+ - first_name, last_name, email (optional): new values
104
+ - is_active (optional): set to false to suspend the account
105
+ - password (optional): force-set a new password
106
+
107
+ Returns: Updated user JSON.
108
+
109
+ Use when: "disable Alice's account", "change Bob's email", "rename user".`,
110
+ inputSchema: {
111
+ org_id: z.string().uuid().describe("Organization UUID"),
112
+ user_id: z.string().uuid().describe("User UUID"),
113
+ email: z.string().email().optional().describe("New email address"),
114
+ first_name: z.string().optional().describe("New given name"),
115
+ last_name: z.string().optional().describe("New family name"),
116
+ is_active: z.boolean().optional().describe("Set to false to suspend the account"),
117
+ password: z.string().optional().describe("Force-set a new password"),
118
+ },
119
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
120
+ },
121
+ async ({ org_id, user_id, ...updates }) =>
122
+ handleError(async () => {
123
+ const body = Object.fromEntries(
124
+ Object.entries(updates).filter(([, v]) => v !== undefined),
125
+ );
126
+ const user = await getClient().patch<Record<string, unknown>>(
127
+ getClient().orgPath(org_id, `/users/${user_id}`),
128
+ body,
129
+ );
130
+ return `User updated:\n\n${JSON.stringify(user, null, 2)}`;
131
+ }),
132
+ );
133
+
134
+ // ── Delete user ────────────────────────────────────────────────────────────
135
+ server.registerTool(
136
+ "clavex_delete_user",
137
+ {
138
+ title: "Delete User",
139
+ description: `Permanently delete a user from an organization. This action is irreversible.
140
+
141
+ Consider using clavex_update_user with is_active=false to suspend without deleting.
142
+
143
+ Use when: "delete user <id>", "remove Alice's account permanently".`,
144
+ inputSchema: {
145
+ org_id: z.string().uuid().describe("Organization UUID"),
146
+ user_id: z.string().uuid().describe("User UUID to delete"),
147
+ },
148
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true },
149
+ },
150
+ async ({ org_id, user_id }) =>
151
+ handleError(async () => {
152
+ await getClient().del(getClient().orgPath(org_id, `/users/${user_id}`));
153
+ return `User ${user_id} deleted from org ${org_id}.`;
154
+ }),
155
+ );
156
+
157
+ // ── Password reset ─────────────────────────────────────────────────────────
158
+ server.registerTool(
159
+ "clavex_send_password_reset",
160
+ {
161
+ title: "Send Password Reset Email",
162
+ description: `Send a password reset email to a user.
163
+
164
+ Use when: "send password reset to alice", "user locked out — send reset email".`,
165
+ inputSchema: {
166
+ org_id: z.string().uuid().describe("Organization UUID"),
167
+ user_id: z.string().uuid().describe("User UUID"),
168
+ },
169
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
170
+ },
171
+ async ({ org_id, user_id }) =>
172
+ handleError(async () => {
173
+ await getClient().post(
174
+ getClient().orgPath(org_id, `/users/${user_id}/send-password-reset`),
175
+ );
176
+ return `Password reset email sent to user ${user_id}.`;
177
+ }),
178
+ );
179
+
180
+ // ── List user roles ────────────────────────────────────────────────────────
181
+ server.registerTool(
182
+ "clavex_list_user_roles",
183
+ {
184
+ title: "List User Roles",
185
+ description: `List all roles assigned to a specific user.
186
+
187
+ Use when: "what roles does Alice have?", "list permissions for user <id>".`,
188
+ inputSchema: {
189
+ org_id: z.string().uuid().describe("Organization UUID"),
190
+ user_id: z.string().uuid().describe("User UUID"),
191
+ },
192
+ annotations: { readOnlyHint: true, destructiveHint: false },
193
+ },
194
+ async ({ org_id, user_id }) =>
195
+ handleError(async () => {
196
+ const roles = await getClient().get<Array<Record<string, unknown>>>(
197
+ getClient().orgPath(org_id, `/users/${user_id}/roles`),
198
+ );
199
+ return mdTable(roles, ["id", "name", "description"]);
200
+ }),
201
+ );
202
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "declaration": true,
13
+ "declarationMap": true,
14
+ "sourceMap": true
15
+ },
16
+ "include": ["src/**/*"],
17
+ "exclude": ["node_modules", "dist"]
18
+ }