keycloak-model-context-protocol 0.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 (3) hide show
  1. package/README.md +104 -0
  2. package/dist/index.js +178 -0
  3. package/package.json +29 -0
package/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # Keycloak MCP Server
2
+
3
+ A Model Context Protocol server for Keycloak administration, providing tools to manage users and realms.
4
+
5
+ ## Features
6
+
7
+ - Create new users in specific realms
8
+ - Delete users from realms
9
+ - List available realms
10
+ - List users in specific realms
11
+
12
+ ## Installation
13
+
14
+ ### Prerequisites
15
+
16
+ - Node.js 18 or higher
17
+ - Running Keycloak instance
18
+
19
+ ### Setup
20
+
21
+ ```bash
22
+ npm install
23
+ npm run build
24
+ ```
25
+
26
+ ### Configuration
27
+
28
+ Configure the server in your Claude Desktop configuration file:
29
+
30
+ ```json
31
+ {
32
+ "mcpServers": {
33
+ "keycloak": {
34
+ "command": "node",
35
+ "args": ["path/to/dist/index.js"],
36
+ "env": {
37
+ "KEYCLOAK_URL": "http://localhost:8080",
38
+ "KEYCLOAK_ADMIN": "admin",
39
+ "KEYCLOAK_ADMIN_PASSWORD": "admin"
40
+ }
41
+ }
42
+ }
43
+ }
44
+ ```
45
+
46
+ ## Available Tools
47
+
48
+ ### create-user
49
+ Creates a new user in a specified realm.
50
+
51
+ **Inputs**:
52
+ - `realm`: The realm name
53
+ - `username`: Username for the new user
54
+ - `email`: Email address for the user
55
+ - `firstName`: User's first name
56
+ - `lastName`: User's last name
57
+
58
+ ### delete-user
59
+ Deletes a user from a specified realm.
60
+
61
+ **Inputs**:
62
+ - `realm`: The realm name
63
+ - `userId`: The ID of the user to delete
64
+
65
+ ### list-realms
66
+ Lists all available realms.
67
+
68
+ ### list-users
69
+ Lists all users in a specified realm.
70
+
71
+ **Inputs**:
72
+ - `realm`: The realm name
73
+
74
+ ## Development
75
+
76
+ ```bash
77
+ npm run watch
78
+ ```
79
+
80
+ ## Deployment
81
+
82
+ ### NPM Package
83
+
84
+ This project is set up for automated deployment to NPM via GitHub Actions. When a new release is published on GitHub:
85
+
86
+ 1. The workflow automatically builds the package
87
+ 2. Tests are run
88
+ 3. The package is published to NPM if all checks pass
89
+
90
+ #### Setup Requirements
91
+
92
+ 1. Create NPM account and get access token
93
+ 2. Add NPM_TOKEN secret to GitHub repository
94
+ - Go to repository Settings > Secrets
95
+ - Add new secret named `NPM_TOKEN`
96
+ - Paste your NPM access token as the value
97
+
98
+ ### Using the Package
99
+
100
+ After deployment, install globally:
101
+
102
+ ```bash
103
+ npm install -g keycloak-model-context-protocol
104
+ ```
package/dist/index.js ADDED
@@ -0,0 +1,178 @@
1
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
4
+ import KcAdminClient from '@keycloak/keycloak-admin-client';
5
+ import { z } from 'zod';
6
+ const server = new Server({
7
+ name: "keycloak-admin",
8
+ version: "0.0.1",
9
+ }, {
10
+ capabilities: {
11
+ tools: {},
12
+ },
13
+ });
14
+ // Initialize Keycloak client
15
+ const kcAdminClient = new KcAdminClient({
16
+ baseUrl: process.env.KEYCLOAK_URL || 'http://localhost:8080',
17
+ realmName: 'master'
18
+ });
19
+ // Tool schemas
20
+ const CreateUserSchema = z.object({
21
+ realm: z.string(),
22
+ username: z.string(),
23
+ email: z.string().email(),
24
+ firstName: z.string(),
25
+ lastName: z.string()
26
+ });
27
+ const DeleteUserSchema = z.object({
28
+ realm: z.string(),
29
+ userId: z.string()
30
+ });
31
+ const ListUsersSchema = z.object({
32
+ realm: z.string()
33
+ });
34
+ // List available tools
35
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
36
+ return {
37
+ tools: [
38
+ {
39
+ name: "create-user",
40
+ description: "Create a new user in a specific realm",
41
+ inputSchema: {
42
+ type: "object",
43
+ properties: {
44
+ realm: { type: "string" },
45
+ username: { type: "string" },
46
+ email: { type: "string", format: "email" },
47
+ firstName: { type: "string" },
48
+ lastName: { type: "string" }
49
+ },
50
+ required: ["realm", "username", "email", "firstName", "lastName"]
51
+ }
52
+ },
53
+ {
54
+ name: "delete-user",
55
+ description: "Delete a user from a specific realm",
56
+ inputSchema: {
57
+ type: "object",
58
+ properties: {
59
+ realm: { type: "string" },
60
+ userId: { type: "string" }
61
+ },
62
+ required: ["realm", "userId"]
63
+ }
64
+ },
65
+ {
66
+ name: "list-realms",
67
+ description: "List all available realms",
68
+ inputSchema: {
69
+ type: "object",
70
+ properties: {},
71
+ required: []
72
+ }
73
+ },
74
+ {
75
+ name: "list-users",
76
+ description: "List users in a specific realm",
77
+ inputSchema: {
78
+ type: "object",
79
+ properties: {
80
+ realm: { type: "string" }
81
+ },
82
+ required: ["realm"]
83
+ }
84
+ }
85
+ ]
86
+ };
87
+ });
88
+ // Handle tool calls
89
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
90
+ // Authenticate before each request
91
+ await kcAdminClient.auth({
92
+ username: process.env.KEYCLOAK_ADMIN || 'admin',
93
+ password: process.env.KEYCLOAK_ADMIN_PASSWORD || 'admin',
94
+ grantType: 'password',
95
+ clientId: 'admin-cli',
96
+ });
97
+ const { name, arguments: args } = request.params;
98
+ try {
99
+ switch (name) {
100
+ case "create-user": {
101
+ const { realm, username, email, firstName, lastName } = CreateUserSchema.parse(args);
102
+ kcAdminClient.setConfig({
103
+ realmName: realm
104
+ });
105
+ const user = await kcAdminClient.users.create({
106
+ realm,
107
+ username,
108
+ email,
109
+ firstName,
110
+ lastName,
111
+ enabled: true
112
+ });
113
+ return {
114
+ content: [{
115
+ type: "text",
116
+ text: `User created successfully. User ID: ${user.id}`
117
+ }]
118
+ };
119
+ }
120
+ case "delete-user": {
121
+ const { realm, userId } = DeleteUserSchema.parse(args);
122
+ kcAdminClient.setConfig({
123
+ realmName: realm
124
+ });
125
+ await kcAdminClient.users.del({
126
+ id: userId,
127
+ realm
128
+ });
129
+ return {
130
+ content: [{
131
+ type: "text",
132
+ text: `User ${userId} deleted successfully from realm ${realm}`
133
+ }]
134
+ };
135
+ }
136
+ case "list-realms": {
137
+ const realms = await kcAdminClient.realms.find();
138
+ return {
139
+ content: [{
140
+ type: "text",
141
+ text: `Available realms:\n${realms.map(r => `- ${r.realm}`).join('\n')}`
142
+ }]
143
+ };
144
+ }
145
+ case "list-users": {
146
+ const { realm } = ListUsersSchema.parse(args);
147
+ kcAdminClient.setConfig({
148
+ realmName: realm
149
+ });
150
+ const users = await kcAdminClient.users.find();
151
+ return {
152
+ content: [{
153
+ type: "text",
154
+ text: `Users in realm ${realm}:\n${users.map(u => `- ${u.username} (${u.id})`).join('\n')}`
155
+ }]
156
+ };
157
+ }
158
+ default:
159
+ throw new Error(`Unknown tool: ${name}`);
160
+ }
161
+ }
162
+ catch (error) {
163
+ if (error instanceof z.ZodError) {
164
+ return {
165
+ isError: true,
166
+ content: [{
167
+ type: "text",
168
+ text: `Invalid arguments: ${error.errors.map(e => `${e.path.join(".")}: ${e.message}`).join(", ")}`
169
+ }]
170
+ };
171
+ }
172
+ throw error;
173
+ }
174
+ });
175
+ // Start the server
176
+ const transport = new StdioServerTransport();
177
+ await server.connect(transport);
178
+ console.error("Keycloak MCP Server running on stdio");
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "keycloak-model-context-protocol",
3
+ "version": "0.0.1",
4
+ "description": "MCP server for Keycloak administration",
5
+ "license": "MIT",
6
+ "author": "Christoph Englisch",
7
+ "type": "module",
8
+ "bin": {
9
+ "mcp-server-keycloak": "./dist/index.js"
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc && shx chmod +x dist/*.js",
16
+ "prepare": "npm run build",
17
+ "watch": "tsc --watch"
18
+ },
19
+ "dependencies": {
20
+ "@modelcontextprotocol/sdk": "0.5.0",
21
+ "@keycloak/keycloak-admin-client": "^22.0.5",
22
+ "zod": "^3.22.4"
23
+ },
24
+ "devDependencies": {
25
+ "@types/node": "^22",
26
+ "shx": "^0.3.4",
27
+ "typescript": "^5.3.3"
28
+ }
29
+ }