@samik081/mcp-authentik 0.1.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 (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +581 -0
  3. package/dist/core/client.d.ts +48 -0
  4. package/dist/core/client.js +99 -0
  5. package/dist/core/config.d.ts +2 -0
  6. package/dist/core/config.js +47 -0
  7. package/dist/core/errors.d.ts +2 -0
  8. package/dist/core/errors.js +50 -0
  9. package/dist/core/logger.d.ts +6 -0
  10. package/dist/core/logger.js +17 -0
  11. package/dist/core/server.d.ts +3 -0
  12. package/dist/core/server.js +18 -0
  13. package/dist/core/tools.d.ts +15 -0
  14. package/dist/core/tools.js +41 -0
  15. package/dist/index.d.ts +6 -0
  16. package/dist/index.js +47 -0
  17. package/dist/tools/admin.d.ts +4 -0
  18. package/dist/tools/admin.js +128 -0
  19. package/dist/tools/applications.d.ts +4 -0
  20. package/dist/tools/applications.js +324 -0
  21. package/dist/tools/authenticators.d.ts +4 -0
  22. package/dist/tools/authenticators.js +136 -0
  23. package/dist/tools/brands.d.ts +4 -0
  24. package/dist/tools/brands.js +164 -0
  25. package/dist/tools/crypto.d.ts +4 -0
  26. package/dist/tools/crypto.js +163 -0
  27. package/dist/tools/enterprise.d.ts +4 -0
  28. package/dist/tools/enterprise.js +132 -0
  29. package/dist/tools/events.d.ts +4 -0
  30. package/dist/tools/events.js +451 -0
  31. package/dist/tools/flows.d.ts +4 -0
  32. package/dist/tools/flows.js +335 -0
  33. package/dist/tools/groups.d.ts +4 -0
  34. package/dist/tools/groups.js +161 -0
  35. package/dist/tools/index.d.ts +4 -0
  36. package/dist/tools/index.js +59 -0
  37. package/dist/tools/managed.d.ts +4 -0
  38. package/dist/tools/managed.js +145 -0
  39. package/dist/tools/oauth2.d.ts +4 -0
  40. package/dist/tools/oauth2.js +184 -0
  41. package/dist/tools/outposts.d.ts +4 -0
  42. package/dist/tools/outposts.js +320 -0
  43. package/dist/tools/policies.d.ts +4 -0
  44. package/dist/tools/policies.js +447 -0
  45. package/dist/tools/property-mappings.d.ts +4 -0
  46. package/dist/tools/property-mappings.js +287 -0
  47. package/dist/tools/providers.d.ts +4 -0
  48. package/dist/tools/providers.js +275 -0
  49. package/dist/tools/rac.d.ts +4 -0
  50. package/dist/tools/rac.js +190 -0
  51. package/dist/tools/rbac.d.ts +4 -0
  52. package/dist/tools/rbac.js +283 -0
  53. package/dist/tools/root.d.ts +4 -0
  54. package/dist/tools/root.js +14 -0
  55. package/dist/tools/sources.d.ts +4 -0
  56. package/dist/tools/sources.js +268 -0
  57. package/dist/tools/ssf.d.ts +4 -0
  58. package/dist/tools/ssf.js +47 -0
  59. package/dist/tools/stages.d.ts +4 -0
  60. package/dist/tools/stages.js +533 -0
  61. package/dist/tools/tasks.d.ts +4 -0
  62. package/dist/tools/tasks.js +67 -0
  63. package/dist/tools/tenants.d.ts +4 -0
  64. package/dist/tools/tenants.js +208 -0
  65. package/dist/tools/tokens.d.ts +4 -0
  66. package/dist/tools/tokens.js +159 -0
  67. package/dist/tools/users.d.ts +4 -0
  68. package/dist/tools/users.js +236 -0
  69. package/dist/types/index.d.ts +7 -0
  70. package/dist/types/index.js +1 -0
  71. package/package.json +55 -0
@@ -0,0 +1,324 @@
1
+ import { z } from 'zod';
2
+ import { registerTool } from '../core/tools.js';
3
+ export function registerApplicationTools(server, client, config) {
4
+ // 1. List applications
5
+ registerTool(server, config, {
6
+ name: 'authentik_apps_list',
7
+ description: 'List applications with optional filters for name, slug, group, search, and more.',
8
+ accessTier: 'read-only',
9
+ category: 'core',
10
+ inputSchema: {
11
+ name: z.string().optional().describe('Filter by exact application name'),
12
+ slug: z.string().optional().describe('Filter by exact slug'),
13
+ group: z.string().optional().describe('Filter by application group'),
14
+ search: z.string().optional().describe('Search across application fields'),
15
+ superuser_full_list: z.boolean().optional().describe('When true, return all apps regardless of policy'),
16
+ for_user: z.number().optional().describe('Filter applications accessible by this user ID'),
17
+ ordering: z.string().optional().describe('Field to order by (prefix with - for descending)'),
18
+ page: z.number().optional().describe('Page number'),
19
+ page_size: z.number().optional().describe('Number of results per page'),
20
+ },
21
+ handler: async (args) => {
22
+ const result = await client.coreApi.coreApplicationsList({
23
+ name: args.name,
24
+ slug: args.slug,
25
+ group: args.group,
26
+ search: args.search,
27
+ superuserFullList: args.superuser_full_list,
28
+ forUser: args.for_user,
29
+ ordering: args.ordering,
30
+ page: args.page,
31
+ pageSize: args.page_size,
32
+ });
33
+ return JSON.stringify(result, null, 2);
34
+ },
35
+ });
36
+ // 2. Get application
37
+ registerTool(server, config, {
38
+ name: 'authentik_apps_get',
39
+ description: 'Get a single application by its slug.',
40
+ accessTier: 'read-only',
41
+ category: 'core',
42
+ inputSchema: {
43
+ slug: z.string().describe('Application slug'),
44
+ },
45
+ handler: async (args) => {
46
+ const result = await client.coreApi.coreApplicationsRetrieve({
47
+ slug: args.slug,
48
+ });
49
+ return JSON.stringify(result, null, 2);
50
+ },
51
+ });
52
+ // 3. Create application
53
+ registerTool(server, config, {
54
+ name: 'authentik_apps_create',
55
+ description: 'Create a new application with name, slug, and optional provider, group, and metadata.',
56
+ accessTier: 'full',
57
+ category: 'core',
58
+ inputSchema: {
59
+ name: z.string().describe('Application display name (required)'),
60
+ slug: z.string().describe('Internal application slug for URLs (required)'),
61
+ provider: z.number().optional().describe('Provider ID to associate'),
62
+ group: z.string().optional().describe('Application group name'),
63
+ meta_launch_url: z.string().optional().describe('Launch URL for the application'),
64
+ meta_description: z.string().optional().describe('Application description'),
65
+ meta_publisher: z.string().optional().describe('Application publisher'),
66
+ policy_engine_mode: z.enum(['all', 'any']).optional().describe('Policy engine mode: "all" (all policies must pass) or "any" (any policy must pass)'),
67
+ open_in_new_tab: z.boolean().optional().describe('Open launch URL in a new browser tab'),
68
+ },
69
+ handler: async (args) => {
70
+ const result = await client.coreApi.coreApplicationsCreate({
71
+ applicationRequest: {
72
+ name: args.name,
73
+ slug: args.slug,
74
+ provider: args.provider,
75
+ group: args.group,
76
+ metaLaunchUrl: args.meta_launch_url,
77
+ metaDescription: args.meta_description,
78
+ metaPublisher: args.meta_publisher,
79
+ policyEngineMode: args.policy_engine_mode,
80
+ openInNewTab: args.open_in_new_tab,
81
+ },
82
+ });
83
+ return JSON.stringify(result, null, 2);
84
+ },
85
+ });
86
+ // 4. Update application
87
+ registerTool(server, config, {
88
+ name: 'authentik_apps_update',
89
+ description: 'Update an existing application. Only provided fields are modified (partial update).',
90
+ accessTier: 'full',
91
+ category: 'core',
92
+ inputSchema: {
93
+ slug: z.string().describe('Application slug (required, used as identifier)'),
94
+ name: z.string().optional().describe('New display name'),
95
+ provider: z.number().optional().describe('New provider ID'),
96
+ group: z.string().optional().describe('New application group name'),
97
+ meta_launch_url: z.string().optional().describe('New launch URL'),
98
+ meta_description: z.string().optional().describe('New description'),
99
+ meta_publisher: z.string().optional().describe('New publisher'),
100
+ policy_engine_mode: z.enum(['all', 'any']).optional().describe('Policy engine mode'),
101
+ open_in_new_tab: z.boolean().optional().describe('Open launch URL in a new browser tab'),
102
+ },
103
+ handler: async (args) => {
104
+ const result = await client.coreApi.coreApplicationsPartialUpdate({
105
+ slug: args.slug,
106
+ patchedApplicationRequest: {
107
+ name: args.name,
108
+ provider: args.provider,
109
+ group: args.group,
110
+ metaLaunchUrl: args.meta_launch_url,
111
+ metaDescription: args.meta_description,
112
+ metaPublisher: args.meta_publisher,
113
+ policyEngineMode: args.policy_engine_mode,
114
+ openInNewTab: args.open_in_new_tab,
115
+ },
116
+ });
117
+ return JSON.stringify(result, null, 2);
118
+ },
119
+ });
120
+ // 4b. Set application icon via URL
121
+ registerTool(server, config, {
122
+ name: 'authentik_apps_set_icon_url',
123
+ description: 'Set an application icon from a URL. Provide a URL pointing to an image to use as the application icon, or set clear to true to remove the current icon.',
124
+ accessTier: 'full',
125
+ category: 'core',
126
+ inputSchema: {
127
+ slug: z.string().describe('Application slug (required)'),
128
+ url: z.string().optional().describe('URL pointing to the icon image'),
129
+ clear: z.boolean().optional().describe('Set to true to clear/remove the current icon'),
130
+ },
131
+ handler: async (args) => {
132
+ const slug = args.slug;
133
+ if (args.clear) {
134
+ await client.coreApi.coreApplicationsSetIconCreate({ slug, clear: true });
135
+ return `Icon cleared for application "${slug}".`;
136
+ }
137
+ if (!args.url) {
138
+ throw new Error('Either "url" or "clear: true" must be provided.');
139
+ }
140
+ await client.coreApi.coreApplicationsSetIconUrlCreate({
141
+ slug,
142
+ filePathRequest: { url: args.url },
143
+ });
144
+ return `Icon set for application "${slug}" from URL: ${args.url}`;
145
+ },
146
+ });
147
+ // 5. Delete application
148
+ registerTool(server, config, {
149
+ name: 'authentik_apps_delete',
150
+ description: 'Delete an application by its slug. This action is irreversible.',
151
+ accessTier: 'full',
152
+ category: 'core',
153
+ tags: ['destructive'],
154
+ inputSchema: {
155
+ slug: z.string().describe('Application slug to delete'),
156
+ },
157
+ handler: async (args) => {
158
+ await client.coreApi.coreApplicationsDestroy({ slug: args.slug });
159
+ return `Application "${args.slug}" deleted successfully.`;
160
+ },
161
+ });
162
+ // 6. Check access
163
+ registerTool(server, config, {
164
+ name: 'authentik_apps_check_access',
165
+ description: 'Check whether a specific user has access to an application.',
166
+ accessTier: 'read-only',
167
+ category: 'core',
168
+ inputSchema: {
169
+ slug: z.string().describe('Application slug'),
170
+ for_user: z.number().optional().describe('User ID to check access for'),
171
+ },
172
+ handler: async (args) => {
173
+ const result = await client.coreApi.coreApplicationsCheckAccessRetrieve({
174
+ slug: args.slug,
175
+ forUser: args.for_user,
176
+ });
177
+ return JSON.stringify(result, null, 2);
178
+ },
179
+ });
180
+ // 7. Transactional application update (create app + provider atomically)
181
+ registerTool(server, config, {
182
+ name: 'authentik_apps_update_transactional',
183
+ description: 'Create or update an application and its provider in a single atomic transaction. Useful for setting up an application with a new provider.',
184
+ accessTier: 'full',
185
+ category: 'core',
186
+ inputSchema: {
187
+ app: z.object({
188
+ name: z.string().describe('Application display name'),
189
+ slug: z.string().describe('Application slug'),
190
+ provider: z.number().optional().describe('Existing provider ID'),
191
+ group: z.string().optional().describe('Application group'),
192
+ meta_launch_url: z.string().optional().describe('Launch URL'),
193
+ meta_description: z.string().optional().describe('Description'),
194
+ meta_publisher: z.string().optional().describe('Publisher'),
195
+ }).describe('Application configuration'),
196
+ provider_model: z.string().describe('Provider model identifier (e.g. "authentik_providers_oauth2.oauth2provider")'),
197
+ provider: z.record(z.unknown()).describe('Provider configuration object. IMPORTANT: Use camelCase field names (e.g. authorizationFlow, invalidationFlow, propertyMappings, clientType). Must include a providerModel discriminator field matching provider_model value. For OAuth2, redirectUris must be an array of {matchingMode: "strict", url: "..."} objects.'),
198
+ },
199
+ handler: async (args) => {
200
+ const app = args.app;
201
+ const result = await client.coreApi.coreTransactionalApplicationsUpdate({
202
+ transactionApplicationRequest: {
203
+ app: {
204
+ name: app.name,
205
+ slug: app.slug,
206
+ provider: app.provider,
207
+ group: app.group,
208
+ metaLaunchUrl: app.meta_launch_url,
209
+ metaDescription: app.meta_description,
210
+ metaPublisher: app.meta_publisher,
211
+ },
212
+ providerModel: args.provider_model,
213
+ provider: args.provider,
214
+ },
215
+ });
216
+ return JSON.stringify(result, null, 2);
217
+ },
218
+ });
219
+ // 8. List application entitlements
220
+ registerTool(server, config, {
221
+ name: 'authentik_app_entitlements_list',
222
+ description: 'List application entitlements with optional filters.',
223
+ accessTier: 'read-only',
224
+ category: 'core',
225
+ inputSchema: {
226
+ app: z.string().optional().describe('Filter by application slug'),
227
+ name: z.string().optional().describe('Filter by entitlement name'),
228
+ ordering: z.string().optional().describe('Field to order by'),
229
+ page: z.number().optional().describe('Page number'),
230
+ page_size: z.number().optional().describe('Number of results per page'),
231
+ search: z.string().optional().describe('Search across entitlement fields'),
232
+ },
233
+ handler: async (args) => {
234
+ const result = await client.coreApi.coreApplicationEntitlementsList({
235
+ app: args.app,
236
+ name: args.name,
237
+ ordering: args.ordering,
238
+ page: args.page,
239
+ pageSize: args.page_size,
240
+ search: args.search,
241
+ });
242
+ return JSON.stringify(result, null, 2);
243
+ },
244
+ });
245
+ // 9. Get application entitlement
246
+ registerTool(server, config, {
247
+ name: 'authentik_app_entitlements_get',
248
+ description: 'Get a single application entitlement by its UUID.',
249
+ accessTier: 'read-only',
250
+ category: 'core',
251
+ inputSchema: {
252
+ pbm_uuid: z.string().describe('Entitlement UUID'),
253
+ },
254
+ handler: async (args) => {
255
+ const result = await client.coreApi.coreApplicationEntitlementsRetrieve({
256
+ pbmUuid: args.pbm_uuid,
257
+ });
258
+ return JSON.stringify(result, null, 2);
259
+ },
260
+ });
261
+ // 10. Create application entitlement
262
+ registerTool(server, config, {
263
+ name: 'authentik_app_entitlements_create',
264
+ description: 'Create a new application entitlement.',
265
+ accessTier: 'full',
266
+ category: 'core',
267
+ inputSchema: {
268
+ name: z.string().describe('Entitlement name (required)'),
269
+ app: z.string().describe('Application slug or UUID (required)'),
270
+ attributes: z.record(z.unknown()).optional().describe('Custom attributes'),
271
+ },
272
+ handler: async (args) => {
273
+ const result = await client.coreApi.coreApplicationEntitlementsCreate({
274
+ applicationEntitlementRequest: {
275
+ name: args.name,
276
+ app: args.app,
277
+ attributes: args.attributes,
278
+ },
279
+ });
280
+ return JSON.stringify(result, null, 2);
281
+ },
282
+ });
283
+ // 11. Update application entitlement
284
+ registerTool(server, config, {
285
+ name: 'authentik_app_entitlements_update',
286
+ description: 'Update an existing application entitlement. Only provided fields are modified (partial update).',
287
+ accessTier: 'full',
288
+ category: 'core',
289
+ inputSchema: {
290
+ pbm_uuid: z.string().describe('Entitlement UUID (required)'),
291
+ name: z.string().optional().describe('New entitlement name'),
292
+ app: z.string().optional().describe('New application slug or UUID'),
293
+ attributes: z.record(z.unknown()).optional().describe('New custom attributes'),
294
+ },
295
+ handler: async (args) => {
296
+ const result = await client.coreApi.coreApplicationEntitlementsPartialUpdate({
297
+ pbmUuid: args.pbm_uuid,
298
+ patchedApplicationEntitlementRequest: {
299
+ name: args.name,
300
+ app: args.app,
301
+ attributes: args.attributes,
302
+ },
303
+ });
304
+ return JSON.stringify(result, null, 2);
305
+ },
306
+ });
307
+ // 12. Delete application entitlement
308
+ registerTool(server, config, {
309
+ name: 'authentik_app_entitlements_delete',
310
+ description: 'Delete an application entitlement by its UUID. This action is irreversible.',
311
+ accessTier: 'full',
312
+ category: 'core',
313
+ tags: ['destructive'],
314
+ inputSchema: {
315
+ pbm_uuid: z.string().describe('Entitlement UUID to delete'),
316
+ },
317
+ handler: async (args) => {
318
+ await client.coreApi.coreApplicationEntitlementsDestroy({
319
+ pbmUuid: args.pbm_uuid,
320
+ });
321
+ return `Application entitlement ${args.pbm_uuid} deleted successfully.`;
322
+ },
323
+ });
324
+ }
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { AuthentikClient } from '../core/client.js';
3
+ import type { AppConfig } from '../types/index.js';
4
+ export declare function registerAuthenticatorTools(server: McpServer, client: AuthentikClient, config: AppConfig): void;
@@ -0,0 +1,136 @@
1
+ import { z } from 'zod';
2
+ import { registerTool } from '../core/tools.js';
3
+ // SDK method name prefixes for each authenticator device type
4
+ const DEVICE_TYPES = ['duo', 'email', 'endpoint', 'sms', 'static', 'totp', 'webauthn'];
5
+ // SDK method name prefixes: authenticatorsAdmin{Prefix}List, etc.
6
+ const ADMIN_PREFIX = {
7
+ duo: 'AdminDuo',
8
+ email: 'AdminEmail',
9
+ endpoint: 'AdminEndpoint',
10
+ sms: 'AdminSms',
11
+ static: 'AdminStatic',
12
+ totp: 'AdminTotp',
13
+ webauthn: 'AdminWebauthn',
14
+ };
15
+ // User-facing method prefixes: authenticators{Prefix}List
16
+ const USER_PREFIX = {
17
+ duo: 'Duo',
18
+ email: 'Email',
19
+ endpoint: 'Endpoint',
20
+ sms: 'Sms',
21
+ static: 'Static',
22
+ totp: 'Totp',
23
+ webauthn: 'Webauthn',
24
+ };
25
+ // Endpoint uses uuid (string), all others use id (number)
26
+ function isEndpointType(deviceType) {
27
+ return deviceType === 'endpoint';
28
+ }
29
+ export function registerAuthenticatorTools(server, client, config) {
30
+ // 1. List all authenticator devices (cross-type)
31
+ registerTool(server, config, {
32
+ name: 'authentik_authenticators_list',
33
+ description: 'List all authenticator devices across all types for the current user.',
34
+ accessTier: 'read-only',
35
+ category: 'authenticators',
36
+ handler: async () => {
37
+ const result = await client.authenticatorsApi.authenticatorsAllList();
38
+ return JSON.stringify(result, null, 2);
39
+ },
40
+ });
41
+ // 2. Admin list devices by type
42
+ registerTool(server, config, {
43
+ name: 'authentik_authenticators_admin_by_type_list',
44
+ description: 'List authenticator devices of a specific type (admin view). Supports: duo, email, endpoint, sms, static, totp, webauthn.',
45
+ accessTier: 'read-only',
46
+ category: 'authenticators',
47
+ inputSchema: {
48
+ device_type: z.enum(DEVICE_TYPES).describe('Authenticator device type'),
49
+ name: z.string().optional().describe('Filter by device name'),
50
+ ordering: z.string().optional().describe('Field to order by'),
51
+ page: z.number().optional().describe('Page number'),
52
+ page_size: z.number().optional().describe('Number of results per page'),
53
+ },
54
+ handler: async (args) => {
55
+ const prefix = ADMIN_PREFIX[args.device_type];
56
+ const method = `authenticators${prefix}List`;
57
+ const fn = client.authenticatorsApi[method];
58
+ const result = await fn.call(client.authenticatorsApi, {
59
+ name: args.name,
60
+ ordering: args.ordering,
61
+ page: args.page,
62
+ pageSize: args.page_size,
63
+ });
64
+ return JSON.stringify(result, null, 2);
65
+ },
66
+ });
67
+ // 3. Admin get device by type
68
+ registerTool(server, config, {
69
+ name: 'authentik_authenticators_admin_by_type_get',
70
+ description: 'Get a single authenticator device by type and ID (admin view). Use numeric id for most types, uuid string for endpoint type.',
71
+ accessTier: 'read-only',
72
+ category: 'authenticators',
73
+ inputSchema: {
74
+ device_type: z.enum(DEVICE_TYPES).describe('Authenticator device type'),
75
+ id: z.union([z.number(), z.string()]).describe('Device ID (number for most types, UUID string for endpoint)'),
76
+ },
77
+ handler: async (args) => {
78
+ const prefix = ADMIN_PREFIX[args.device_type];
79
+ const method = `authenticators${prefix}Retrieve`;
80
+ const fn = client.authenticatorsApi[method];
81
+ const idParam = isEndpointType(args.device_type)
82
+ ? { uuid: args.id }
83
+ : { id: args.id };
84
+ const result = await fn.call(client.authenticatorsApi, idParam);
85
+ return JSON.stringify(result, null, 2);
86
+ },
87
+ });
88
+ // 4. Admin delete device by type
89
+ registerTool(server, config, {
90
+ name: 'authentik_authenticators_admin_by_type_delete',
91
+ description: 'Delete an authenticator device by type and ID (admin view). This action is irreversible.',
92
+ accessTier: 'full',
93
+ category: 'authenticators',
94
+ tags: ['destructive'],
95
+ inputSchema: {
96
+ device_type: z.enum(DEVICE_TYPES).describe('Authenticator device type'),
97
+ id: z.union([z.number(), z.string()]).describe('Device ID (number for most types, UUID string for endpoint)'),
98
+ },
99
+ handler: async (args) => {
100
+ const prefix = ADMIN_PREFIX[args.device_type];
101
+ const method = `authenticators${prefix}Destroy`;
102
+ const fn = client.authenticatorsApi[method];
103
+ const idParam = isEndpointType(args.device_type)
104
+ ? { uuid: args.id }
105
+ : { id: args.id };
106
+ await fn.call(client.authenticatorsApi, idParam);
107
+ return `Authenticator device (${args.device_type}) ${args.id} deleted successfully.`;
108
+ },
109
+ });
110
+ // 5. User list devices by type
111
+ registerTool(server, config, {
112
+ name: 'authentik_authenticators_user_by_type_list',
113
+ description: 'List authenticator devices of a specific type for the current user. Supports: duo, email, endpoint, sms, static, totp, webauthn.',
114
+ accessTier: 'read-only',
115
+ category: 'authenticators',
116
+ inputSchema: {
117
+ device_type: z.enum(DEVICE_TYPES).describe('Authenticator device type'),
118
+ name: z.string().optional().describe('Filter by device name'),
119
+ ordering: z.string().optional().describe('Field to order by'),
120
+ page: z.number().optional().describe('Page number'),
121
+ page_size: z.number().optional().describe('Number of results per page'),
122
+ },
123
+ handler: async (args) => {
124
+ const prefix = USER_PREFIX[args.device_type];
125
+ const method = `authenticators${prefix}List`;
126
+ const fn = client.authenticatorsApi[method];
127
+ const result = await fn.call(client.authenticatorsApi, {
128
+ name: args.name,
129
+ ordering: args.ordering,
130
+ page: args.page,
131
+ pageSize: args.page_size,
132
+ });
133
+ return JSON.stringify(result, null, 2);
134
+ },
135
+ });
136
+ }
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { AuthentikClient } from '../core/client.js';
3
+ import type { AppConfig } from '../types/index.js';
4
+ export declare function registerBrandTools(server: McpServer, client: AuthentikClient, config: AppConfig): void;
@@ -0,0 +1,164 @@
1
+ import { z } from 'zod';
2
+ import { registerTool } from '../core/tools.js';
3
+ export function registerBrandTools(server, client, config) {
4
+ // 1. List brands
5
+ registerTool(server, config, {
6
+ name: 'authentik_brands_list',
7
+ description: 'List brands with optional filters for UUID, domain, and search.',
8
+ accessTier: 'read-only',
9
+ category: 'core',
10
+ inputSchema: {
11
+ brand_uuid: z.string().optional().describe('Filter by brand UUID'),
12
+ domain: z.string().optional().describe('Filter by domain'),
13
+ search: z.string().optional().describe('Search across brand fields'),
14
+ ordering: z.string().optional().describe('Field to order by (prefix with - for descending)'),
15
+ page: z.number().optional().describe('Page number'),
16
+ page_size: z.number().optional().describe('Number of results per page'),
17
+ },
18
+ handler: async (args) => {
19
+ const result = await client.coreApi.coreBrandsList({
20
+ brandUuid: args.brand_uuid,
21
+ domain: args.domain,
22
+ search: args.search,
23
+ ordering: args.ordering,
24
+ page: args.page,
25
+ pageSize: args.page_size,
26
+ });
27
+ return JSON.stringify(result, null, 2);
28
+ },
29
+ });
30
+ // 2. Get brand
31
+ registerTool(server, config, {
32
+ name: 'authentik_brands_get',
33
+ description: 'Get a single brand by its UUID.',
34
+ accessTier: 'read-only',
35
+ category: 'core',
36
+ inputSchema: {
37
+ brand_uuid: z.string().describe('Brand UUID'),
38
+ },
39
+ handler: async (args) => {
40
+ const result = await client.coreApi.coreBrandsRetrieve({
41
+ brandUuid: args.brand_uuid,
42
+ });
43
+ return JSON.stringify(result, null, 2);
44
+ },
45
+ });
46
+ // 3. Create brand
47
+ registerTool(server, config, {
48
+ name: 'authentik_brands_create',
49
+ description: 'Create a new brand with domain, branding settings, flow assignments, and optional attributes.',
50
+ accessTier: 'full',
51
+ category: 'core',
52
+ inputSchema: {
53
+ domain: z.string().describe('Domain that activates this brand (required). Can be a superset, e.g. "a.b" matches "aa.b" and "ba.b".'),
54
+ is_default: z.boolean().optional().describe('Whether this is the default brand'),
55
+ branding_title: z.string().optional().describe('Branding title displayed in the UI'),
56
+ branding_logo: z.string().optional().describe('URL or path to the branding logo'),
57
+ branding_favicon: z.string().optional().describe('URL or path to the favicon'),
58
+ flow_authentication: z.string().optional().describe('Flow UUID for authentication'),
59
+ flow_invalidation: z.string().optional().describe('Flow UUID for session invalidation'),
60
+ flow_recovery: z.string().optional().describe('Flow UUID for account recovery'),
61
+ flow_unenrollment: z.string().optional().describe('Flow UUID for unenrollment'),
62
+ flow_user_settings: z.string().optional().describe('Flow UUID for user settings'),
63
+ flow_device_code: z.string().optional().describe('Flow UUID for device code authentication'),
64
+ default_application: z.string().optional().describe('Application slug to redirect external users to after authentication'),
65
+ web_certificate: z.string().optional().describe('Web certificate UUID for the authentik core webserver'),
66
+ attributes: z.record(z.unknown()).optional().describe('Custom attributes key-value pairs'),
67
+ },
68
+ handler: async (args) => {
69
+ const result = await client.coreApi.coreBrandsCreate({
70
+ brandRequest: {
71
+ domain: args.domain,
72
+ _default: args.is_default,
73
+ brandingTitle: args.branding_title,
74
+ brandingLogo: args.branding_logo,
75
+ brandingFavicon: args.branding_favicon,
76
+ flowAuthentication: args.flow_authentication,
77
+ flowInvalidation: args.flow_invalidation,
78
+ flowRecovery: args.flow_recovery,
79
+ flowUnenrollment: args.flow_unenrollment,
80
+ flowUserSettings: args.flow_user_settings,
81
+ flowDeviceCode: args.flow_device_code,
82
+ defaultApplication: args.default_application,
83
+ webCertificate: args.web_certificate,
84
+ attributes: args.attributes,
85
+ },
86
+ });
87
+ return JSON.stringify(result, null, 2);
88
+ },
89
+ });
90
+ // 4. Update brand
91
+ registerTool(server, config, {
92
+ name: 'authentik_brands_update',
93
+ description: 'Update an existing brand. Only provided fields are modified (partial update).',
94
+ accessTier: 'full',
95
+ category: 'core',
96
+ inputSchema: {
97
+ brand_uuid: z.string().describe('Brand UUID (required)'),
98
+ domain: z.string().optional().describe('New domain'),
99
+ is_default: z.boolean().optional().describe('Whether this is the default brand'),
100
+ branding_title: z.string().optional().describe('New branding title'),
101
+ branding_logo: z.string().optional().describe('New logo URL or path'),
102
+ branding_favicon: z.string().optional().describe('New favicon URL or path'),
103
+ flow_authentication: z.string().optional().describe('Flow UUID for authentication'),
104
+ flow_invalidation: z.string().optional().describe('Flow UUID for session invalidation'),
105
+ flow_recovery: z.string().optional().describe('Flow UUID for account recovery'),
106
+ flow_unenrollment: z.string().optional().describe('Flow UUID for unenrollment'),
107
+ flow_user_settings: z.string().optional().describe('Flow UUID for user settings'),
108
+ flow_device_code: z.string().optional().describe('Flow UUID for device code authentication'),
109
+ default_application: z.string().optional().describe('Application slug'),
110
+ web_certificate: z.string().optional().describe('Web certificate UUID'),
111
+ attributes: z.record(z.unknown()).optional().describe('Custom attributes key-value pairs'),
112
+ },
113
+ handler: async (args) => {
114
+ const result = await client.coreApi.coreBrandsPartialUpdate({
115
+ brandUuid: args.brand_uuid,
116
+ patchedBrandRequest: {
117
+ domain: args.domain,
118
+ _default: args.is_default,
119
+ brandingTitle: args.branding_title,
120
+ brandingLogo: args.branding_logo,
121
+ brandingFavicon: args.branding_favicon,
122
+ flowAuthentication: args.flow_authentication,
123
+ flowInvalidation: args.flow_invalidation,
124
+ flowRecovery: args.flow_recovery,
125
+ flowUnenrollment: args.flow_unenrollment,
126
+ flowUserSettings: args.flow_user_settings,
127
+ flowDeviceCode: args.flow_device_code,
128
+ defaultApplication: args.default_application,
129
+ webCertificate: args.web_certificate,
130
+ attributes: args.attributes,
131
+ },
132
+ });
133
+ return JSON.stringify(result, null, 2);
134
+ },
135
+ });
136
+ // 5. Delete brand
137
+ registerTool(server, config, {
138
+ name: 'authentik_brands_delete',
139
+ description: 'Delete a brand by its UUID. This action is irreversible.',
140
+ accessTier: 'full',
141
+ category: 'core',
142
+ tags: ['destructive'],
143
+ inputSchema: {
144
+ brand_uuid: z.string().describe('Brand UUID to delete'),
145
+ },
146
+ handler: async (args) => {
147
+ await client.coreApi.coreBrandsDestroy({
148
+ brandUuid: args.brand_uuid,
149
+ });
150
+ return `Brand ${args.brand_uuid} deleted successfully.`;
151
+ },
152
+ });
153
+ // 6. Get current brand
154
+ registerTool(server, config, {
155
+ name: 'authentik_brands_current',
156
+ description: 'Get the brand configuration for the current domain.',
157
+ accessTier: 'read-only',
158
+ category: 'core',
159
+ handler: async () => {
160
+ const result = await client.coreApi.coreBrandsCurrentRetrieve();
161
+ return JSON.stringify(result, null, 2);
162
+ },
163
+ });
164
+ }
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { AuthentikClient } from '../core/client.js';
3
+ import type { AppConfig } from '../types/index.js';
4
+ export declare function registerCryptoTools(server: McpServer, client: AuthentikClient, config: AppConfig): void;