keycloak-model-context-protocol 0.0.2 → 1.0.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 (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +188 -101
  3. package/dist/config.js +178 -0
  4. package/dist/config.js.map +1 -0
  5. package/dist/guards.js +47 -0
  6. package/dist/guards.js.map +1 -0
  7. package/dist/index.js +36 -174
  8. package/dist/index.js.map +1 -0
  9. package/dist/keycloak/errors.js +86 -0
  10. package/dist/keycloak/errors.js.map +1 -0
  11. package/dist/keycloak/gateway.js +131 -0
  12. package/dist/keycloak/gateway.js.map +1 -0
  13. package/dist/logging.js +49 -0
  14. package/dist/logging.js.map +1 -0
  15. package/dist/prompts/audit-realm-security.js +26 -0
  16. package/dist/prompts/audit-realm-security.js.map +1 -0
  17. package/dist/prompts/index.js +12 -0
  18. package/dist/prompts/index.js.map +1 -0
  19. package/dist/prompts/investigate-failed-logins.js +34 -0
  20. package/dist/prompts/investigate-failed-logins.js.map +1 -0
  21. package/dist/prompts/offboard-employee.js +31 -0
  22. package/dist/prompts/offboard-employee.js.map +1 -0
  23. package/dist/prompts/onboard-employee.js +50 -0
  24. package/dist/prompts/onboard-employee.js.map +1 -0
  25. package/dist/prompts/shared.js +46 -0
  26. package/dist/prompts/shared.js.map +1 -0
  27. package/dist/resources/index.js +8 -0
  28. package/dist/resources/index.js.map +1 -0
  29. package/dist/resources/realms.js +96 -0
  30. package/dist/resources/realms.js.map +1 -0
  31. package/dist/resources/shared.js +44 -0
  32. package/dist/resources/shared.js.map +1 -0
  33. package/dist/resources/users.js +26 -0
  34. package/dist/resources/users.js.map +1 -0
  35. package/dist/server.js +16 -0
  36. package/dist/server.js.map +1 -0
  37. package/dist/tools/clients.js +137 -0
  38. package/dist/tools/clients.js.map +1 -0
  39. package/dist/tools/events.js +161 -0
  40. package/dist/tools/events.js.map +1 -0
  41. package/dist/tools/groups.js +135 -0
  42. package/dist/tools/groups.js.map +1 -0
  43. package/dist/tools/index.js +31 -0
  44. package/dist/tools/index.js.map +1 -0
  45. package/dist/tools/realms.js +99 -0
  46. package/dist/tools/realms.js.map +1 -0
  47. package/dist/tools/roles.js +270 -0
  48. package/dist/tools/roles.js.map +1 -0
  49. package/dist/tools/security.js +58 -0
  50. package/dist/tools/security.js.map +1 -0
  51. package/dist/tools/sessions.js +68 -0
  52. package/dist/tools/sessions.js.map +1 -0
  53. package/dist/tools/shared.js +144 -0
  54. package/dist/tools/shared.js.map +1 -0
  55. package/dist/tools/users.js +272 -0
  56. package/dist/tools/users.js.map +1 -0
  57. package/dist/version.js +5 -0
  58. package/dist/version.js.map +1 -0
  59. package/package.json +47 -12
@@ -0,0 +1,272 @@
1
+ import { z } from "zod";
2
+ import { ToolError } from "../keycloak/errors.js";
3
+ import { defineTool, pageOf, paginationShape, realmField, toPage } from "./shared.js";
4
+ const userSummary = z.object({
5
+ id: z.string().describe("User ID (UUID); use it as `userId` in other tools."),
6
+ username: z.string().describe("Login name."),
7
+ email: z.string().optional().describe("E-mail address, if set."),
8
+ firstName: z.string().optional().describe("First name, if set."),
9
+ lastName: z.string().optional().describe("Last name, if set."),
10
+ enabled: z.boolean().optional().describe("Whether the user can log in."),
11
+ emailVerified: z.boolean().optional().describe("Whether the e-mail address is verified."),
12
+ });
13
+ /** Projects a Keycloak user onto the safe subset we expose (no attributes, no credentials). */
14
+ export function toUserSummary(user) {
15
+ return {
16
+ id: user.id ?? "",
17
+ username: user.username ?? "",
18
+ ...(user.email !== undefined && { email: user.email }),
19
+ ...(user.firstName !== undefined && { firstName: user.firstName }),
20
+ ...(user.lastName !== undefined && { lastName: user.lastName }),
21
+ ...(user.enabled !== undefined && { enabled: user.enabled }),
22
+ ...(user.emailVerified !== undefined && { emailVerified: user.emailVerified }),
23
+ };
24
+ }
25
+ // Pattern for list tools: paginationShape in, pageOf() out, query max + 1 and use toPage().
26
+ const userSearch = defineTool({
27
+ name: "user_search",
28
+ title: "Search users",
29
+ description: "Search users in a realm by free text and/or exact fields, with pagination. Without filters it lists all users. Use `search` for a general match on username, name and e-mail (prefix/infix); set `exact` to match username/email exactly.",
30
+ kind: "read",
31
+ input: z.object({
32
+ realm: realmField,
33
+ search: z.string().optional().describe("Free-text search across username, name and e-mail."),
34
+ username: z.string().optional().describe("Filter by username."),
35
+ email: z.string().optional().describe("Filter by e-mail address."),
36
+ exact: z
37
+ .boolean()
38
+ .optional()
39
+ .describe("If true, `username`/`email`/`search` must match exactly instead of by prefix."),
40
+ ...paginationShape,
41
+ }),
42
+ output: pageOf(userSummary).extend({ realm: z.string().describe("Realm that was searched.") }),
43
+ async handler({ realm, search, username, email, exact, first, max }, { gateway }) {
44
+ const rows = await gateway.run((kc) => kc.users.find({
45
+ realm,
46
+ first,
47
+ max: max + 1,
48
+ briefRepresentation: true,
49
+ ...(search !== undefined && { search }),
50
+ ...(username !== undefined && { username }),
51
+ ...(email !== undefined && { email }),
52
+ ...(exact !== undefined && { exact }),
53
+ }));
54
+ const page = toPage(rows.map(toUserSummary), first, max);
55
+ return {
56
+ data: { ...page, realm },
57
+ summary: `Found ${page.items.length} user(s) in realm '${realm}' (first=${first}, max=${max}${page.hasMore ? ", more available" : ""}).`,
58
+ };
59
+ },
60
+ });
61
+ const userCreate = defineTool({
62
+ name: "user_create",
63
+ title: "Create user",
64
+ description: "Create a new user in a realm. The user is enabled by default and has no credentials; use a separate flow to set a password or send required actions.",
65
+ kind: "write",
66
+ idempotent: false,
67
+ input: z.object({
68
+ realm: realmField,
69
+ username: z.string().min(1).describe("Unique login name."),
70
+ email: z.email().optional().describe("E-mail address."),
71
+ firstName: z.string().optional().describe("First name."),
72
+ lastName: z.string().optional().describe("Last name."),
73
+ enabled: z.boolean().default(true).describe("Whether the user can log in (default true)."),
74
+ emailVerified: z.boolean().optional().describe("Mark the e-mail address as verified."),
75
+ }),
76
+ output: z.object({
77
+ id: z.string().describe("ID of the created user."),
78
+ username: z.string().describe("Username of the created user."),
79
+ realm: z.string().describe("Realm the user was created in."),
80
+ }),
81
+ async handler({ realm, username, email, firstName, lastName, enabled, emailVerified }, { gateway }) {
82
+ const created = await gateway.run((kc) => kc.users.create({
83
+ realm,
84
+ username,
85
+ enabled,
86
+ ...(email !== undefined && { email }),
87
+ ...(firstName !== undefined && { firstName }),
88
+ ...(lastName !== undefined && { lastName }),
89
+ ...(emailVerified !== undefined && { emailVerified }),
90
+ }));
91
+ return {
92
+ data: { id: created.id, username, realm },
93
+ summary: `Created user '${username}' (id ${created.id}) in realm '${realm}'.`,
94
+ };
95
+ },
96
+ });
97
+ const userDelete = defineTool({
98
+ name: "user_delete",
99
+ title: "Delete user",
100
+ description: "Permanently delete a user from a realm. This cannot be undone. Requires confirm: true (ask the user first).",
101
+ kind: "destructive",
102
+ input: z.object({
103
+ realm: realmField,
104
+ userId: z.string().min(1).describe("ID (UUID) of the user to delete, e.g. from user_search."),
105
+ }),
106
+ output: z.object({
107
+ deleted: z.boolean().describe("True if the user was deleted."),
108
+ userId: z.string().describe("ID of the deleted user."),
109
+ realm: z.string().describe("Realm the user was deleted from."),
110
+ }),
111
+ async preview({ realm, userId }, { gateway }) {
112
+ const user = await gateway.run((kc) => kc.users.findOne({ realm, id: userId }));
113
+ if (!user)
114
+ throw new ToolError("not_found", `User ${userId} does not exist in realm '${realm}'.`);
115
+ return `permanently delete user '${user.username ?? userId}' (id ${userId}) from realm '${realm}'.`;
116
+ },
117
+ async handler({ realm, userId }, { gateway }) {
118
+ await gateway.run((kc) => kc.users.del({ realm, id: userId }));
119
+ return {
120
+ data: { deleted: true, userId, realm },
121
+ summary: `Deleted user ${userId} from realm '${realm}'.`,
122
+ };
123
+ },
124
+ });
125
+ export function toUserDetails(user) {
126
+ return {
127
+ ...toUserSummary(user),
128
+ ...(user.createdTimestamp !== undefined && { createdTimestamp: user.createdTimestamp }),
129
+ ...(user.requiredActions !== undefined && { requiredActions: user.requiredActions }),
130
+ ...(user.totp !== undefined && { totp: user.totp }),
131
+ ...(user.federationLink !== undefined && { federationLink: user.federationLink }),
132
+ };
133
+ }
134
+ const userGet = defineTool({
135
+ name: "user_get",
136
+ title: "Get user",
137
+ description: "Get one user by ID with a safe subset of fields (no attributes, no credentials). Use user_search to find the ID.",
138
+ kind: "read",
139
+ input: z.object({
140
+ realm: realmField,
141
+ userId: z.string().min(1).describe("ID (UUID) of the user, e.g. from user_search."),
142
+ }),
143
+ output: userSummary.extend({
144
+ createdTimestamp: z.number().optional().describe("Creation time in epoch milliseconds."),
145
+ requiredActions: z.array(z.string()).optional().describe("Pending required actions."),
146
+ totp: z.boolean().optional().describe("Whether the user has OTP configured."),
147
+ federationLink: z.string().optional().describe("ID of the federation provider, if any."),
148
+ }),
149
+ async handler({ realm, userId }, { gateway }) {
150
+ const user = await gateway.run((kc) => kc.users.findOne({ realm, id: userId }));
151
+ if (!user)
152
+ throw new ToolError("not_found", `User ${userId} does not exist in realm '${realm}'.`);
153
+ return {
154
+ data: toUserDetails(user),
155
+ summary: `Returned user ${userId} from realm '${realm}'.`,
156
+ };
157
+ },
158
+ });
159
+ const userUpdate = defineTool({
160
+ name: "user_update",
161
+ title: "Update user",
162
+ description: "Update selected fields of a user (partial update; omitted fields stay unchanged). At least one field besides realm and userId is required. Setting `requiredActions` replaces the existing list.",
163
+ kind: "write",
164
+ idempotent: true,
165
+ input: z
166
+ .object({
167
+ realm: realmField,
168
+ userId: z.string().min(1).describe("ID (UUID) of the user to update."),
169
+ email: z.email().optional().describe("New e-mail address."),
170
+ firstName: z.string().optional().describe("New first name."),
171
+ lastName: z.string().optional().describe("New last name."),
172
+ enabled: z.boolean().optional().describe("Enable or disable the user."),
173
+ emailVerified: z.boolean().optional().describe("Mark the e-mail as verified or not."),
174
+ requiredActions: z
175
+ .array(z.string().min(1))
176
+ .optional()
177
+ .describe("Required actions to set, e.g. UPDATE_PASSWORD (replaces the existing list)."),
178
+ })
179
+ .refine((v) => v.email !== undefined ||
180
+ v.firstName !== undefined ||
181
+ v.lastName !== undefined ||
182
+ v.enabled !== undefined ||
183
+ v.emailVerified !== undefined ||
184
+ v.requiredActions !== undefined, { message: "Provide at least one field to update." }),
185
+ output: z.object({
186
+ userId: z.string().describe("ID of the updated user."),
187
+ realm: z.string().describe("Realm of the user."),
188
+ updatedFields: z.array(z.string()).describe("Names of the fields that were set."),
189
+ }),
190
+ async handler({ realm, userId, ...changes }, { gateway }) {
191
+ const fields = Object.entries(changes).filter(([, v]) => v !== undefined);
192
+ if (fields.length === 0)
193
+ throw new ToolError("bad_request", "Provide at least one field to update.");
194
+ await gateway.run(async (kc) => {
195
+ // Keycloak's PUT replaces the representation, so merge into the current one.
196
+ const current = await kc.users.findOne({ realm, id: userId });
197
+ if (!current)
198
+ throw new ToolError("not_found", `User ${userId} does not exist in realm '${realm}'.`);
199
+ await kc.users.update({ realm, id: userId }, { ...current, ...Object.fromEntries(fields) });
200
+ });
201
+ return {
202
+ data: { userId, realm, updatedFields: fields.map(([k]) => k) },
203
+ summary: `Updated ${fields.length} field(s) of user ${userId} in realm '${realm}'.`,
204
+ };
205
+ },
206
+ });
207
+ const userSendActionsEmail = defineTool({
208
+ name: "user_send_actions_email",
209
+ title: "Send required-actions e-mail",
210
+ description: "Send the user an e-mail with a link to perform required actions (e.g. update password, verify e-mail). Each call sends another e-mail. Requires SMTP to be configured in the realm and the user to have an e-mail address.",
211
+ kind: "write",
212
+ idempotent: false,
213
+ input: z.object({
214
+ realm: realmField,
215
+ userId: z.string().min(1).describe("ID (UUID) of the user to e-mail."),
216
+ actions: z
217
+ .array(z.enum([
218
+ "UPDATE_PASSWORD",
219
+ "VERIFY_EMAIL",
220
+ "CONFIGURE_TOTP",
221
+ "UPDATE_PROFILE",
222
+ "TERMS_AND_CONDITIONS",
223
+ ]))
224
+ .min(1)
225
+ .describe("Actions the user must perform via the e-mailed link."),
226
+ lifespan: z
227
+ .number()
228
+ .int()
229
+ .min(1)
230
+ .optional()
231
+ .describe("Link validity in seconds (Keycloak default if omitted)."),
232
+ clientId: z
233
+ .string()
234
+ .min(1)
235
+ .optional()
236
+ .describe("Client ID used for the redirect after the actions."),
237
+ redirectUri: z
238
+ .string()
239
+ .min(1)
240
+ .optional()
241
+ .describe("Redirect URI after the actions; requires clientId."),
242
+ }),
243
+ output: z.object({
244
+ sent: z.boolean().describe("True if Keycloak accepted the e-mail request."),
245
+ userId: z.string().describe("ID of the user."),
246
+ realm: z.string().describe("Realm of the user."),
247
+ actions: z.array(z.string()).describe("Actions requested in the e-mail."),
248
+ }),
249
+ async handler({ realm, userId, actions, lifespan, clientId, redirectUri }, { gateway }) {
250
+ await gateway.run((kc) => kc.users.executeActionsEmail({
251
+ realm,
252
+ id: userId,
253
+ actions,
254
+ ...(lifespan !== undefined && { lifespan }),
255
+ ...(clientId !== undefined && { clientId }),
256
+ ...(redirectUri !== undefined && { redirectUri }),
257
+ }));
258
+ return {
259
+ data: { sent: true, userId, realm, actions },
260
+ summary: `Requested actions e-mail (${actions.join(", ")}) for user ${userId} in realm '${realm}'.`,
261
+ };
262
+ },
263
+ });
264
+ export const userTools = [
265
+ userSearch,
266
+ userGet,
267
+ userCreate,
268
+ userUpdate,
269
+ userDelete,
270
+ userSendActionsEmail,
271
+ ];
272
+ //# sourceMappingURL=users.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"users.js","sourceRoot":"","sources":["../../src/tools/users.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { readFileSync } from "node:fs";
2
+ // Resolves to the package root from both src/ (tests) and dist/ (published build).
3
+ const packageJsonUrl = new URL("../package.json", import.meta.url);
4
+ export const VERSION = JSON.parse(readFileSync(packageJsonUrl, "utf8")).version;
5
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,mFAAmF;AACnF,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,iBAAiB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAEnE,MAAM,CAAC,MAAM,OAAO,GAClB,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,MAAM,CAAC,CAChD,CAAC,OAAO,CAAC"}
package/package.json CHANGED
@@ -1,29 +1,64 @@
1
1
  {
2
2
  "name": "keycloak-model-context-protocol",
3
- "version": "0.0.2",
3
+ "version": "1.0.1",
4
4
  "description": "MCP server for Keycloak administration",
5
+ "mcpName": "io.github.ChristophEnglisch/keycloak-model-context-protocol",
5
6
  "license": "MIT",
6
7
  "author": "Christoph Englisch",
7
8
  "type": "module",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/ChristophEnglisch/keycloak-model-context-protocol.git"
12
+ },
13
+ "homepage": "https://github.com/ChristophEnglisch/keycloak-model-context-protocol#readme",
14
+ "bugs": {
15
+ "url": "https://github.com/ChristophEnglisch/keycloak-model-context-protocol/issues"
16
+ },
17
+ "keywords": [
18
+ "mcp",
19
+ "model-context-protocol",
20
+ "keycloak",
21
+ "iam",
22
+ "identity",
23
+ "admin",
24
+ "ai"
25
+ ],
26
+ "engines": {
27
+ "node": ">=22"
28
+ },
8
29
  "bin": {
9
- "keycloak-model-context-protocol": "./dist/index.js"
30
+ "keycloak-model-context-protocol": "dist/index.js"
10
31
  },
11
32
  "files": [
12
33
  "dist"
13
34
  ],
14
35
  "scripts": {
15
- "build": "tsc && shx chmod +x dist/*.js",
16
- "prepare": "npm run build",
17
- "watch": "tsc --watch"
36
+ "build": "tsc -p tsconfig.build.json && node -e \"require('node:fs').chmodSync('dist/index.js', 0o755)\"",
37
+ "clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
38
+ "typecheck": "tsc -p tsconfig.json --noEmit",
39
+ "lint": "biome check .",
40
+ "format": "biome check --write .",
41
+ "test": "vitest run tests/unit",
42
+ "test:watch": "vitest tests/unit",
43
+ "test:integration": "vitest run --config vitest.integration.config.ts",
44
+ "prepublishOnly": "npm run clean && npm run build && npm test",
45
+ "test:smoke": "npm run build && node tests/smoke/pack-smoke.mjs",
46
+ "test:all": "npm test && npm run test:integration && npm run test:smoke",
47
+ "docs:tools": "npm run build && node scripts/generate-tools-reference.mjs",
48
+ "docs:check": "npm run build && node scripts/generate-tools-reference.mjs --check"
18
49
  },
19
50
  "dependencies": {
20
- "@modelcontextprotocol/sdk": "0.5.0",
21
- "@keycloak/keycloak-admin-client": "^22.0.5",
22
- "zod": "^3.22.4"
51
+ "@keycloak/keycloak-admin-client": "^26.8.1",
52
+ "@modelcontextprotocol/server": "^2.4.0",
53
+ "zod": "^4.6.7"
23
54
  },
24
55
  "devDependencies": {
25
- "@types/node": "^22",
26
- "shx": "^0.3.4",
27
- "typescript": "^5.3.3"
56
+ "@biomejs/biome": "^2.6.2",
57
+ "@modelcontextprotocol/client": "^2.4.0",
58
+ "@types/node": "^22.20.5",
59
+ "@vitest/coverage-v8": "^5.0.5",
60
+ "testcontainers": "^12.2.1",
61
+ "typescript": "^7.0.2",
62
+ "vitest": "^5.0.5"
28
63
  }
29
- }
64
+ }