zitadel-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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +127 -0
  3. package/build/auth/client.d.ts +28 -0
  4. package/build/auth/client.js +125 -0
  5. package/build/auth/client.js.map +1 -0
  6. package/build/index.d.ts +6 -0
  7. package/build/index.js +81 -0
  8. package/build/index.js.map +1 -0
  9. package/build/tools/applications.d.ts +7 -0
  10. package/build/tools/applications.js +189 -0
  11. package/build/tools/applications.js.map +1 -0
  12. package/build/tools/index.d.ts +8 -0
  13. package/build/tools/index.js +44 -0
  14. package/build/tools/index.js.map +1 -0
  15. package/build/tools/organizations.d.ts +7 -0
  16. package/build/tools/organizations.js +65 -0
  17. package/build/tools/organizations.js.map +1 -0
  18. package/build/tools/portal.d.ts +10 -0
  19. package/build/tools/portal.js +191 -0
  20. package/build/tools/portal.js.map +1 -0
  21. package/build/tools/projects.d.ts +7 -0
  22. package/build/tools/projects.js +109 -0
  23. package/build/tools/projects.js.map +1 -0
  24. package/build/tools/roles.d.ts +7 -0
  25. package/build/tools/roles.js +203 -0
  26. package/build/tools/roles.js.map +1 -0
  27. package/build/tools/service-accounts.d.ts +7 -0
  28. package/build/tools/service-accounts.js +122 -0
  29. package/build/tools/service-accounts.js.map +1 -0
  30. package/build/tools/users.d.ts +7 -0
  31. package/build/tools/users.js +183 -0
  32. package/build/tools/users.js.map +1 -0
  33. package/build/tools/utility.d.ts +7 -0
  34. package/build/tools/utility.js +51 -0
  35. package/build/tools/utility.js.map +1 -0
  36. package/build/types/tools.d.ts +43 -0
  37. package/build/types/tools.js +16 -0
  38. package/build/types/tools.js.map +1 -0
  39. package/build/types/zitadel.d.ts +232 -0
  40. package/build/types/zitadel.js +6 -0
  41. package/build/types/zitadel.js.map +1 -0
  42. package/build/utils/config.d.ts +36 -0
  43. package/build/utils/config.js +35 -0
  44. package/build/utils/config.js.map +1 -0
  45. package/build/utils/error-handler.d.ts +18 -0
  46. package/build/utils/error-handler.js +56 -0
  47. package/build/utils/error-handler.js.map +1 -0
  48. package/build/utils/logger.d.ts +20 -0
  49. package/build/utils/logger.js +46 -0
  50. package/build/utils/logger.js.map +1 -0
  51. package/package.json +54 -0
@@ -0,0 +1,43 @@
1
+ /**
2
+ * MCP Tool types — handler signatures, context, response format
3
+ * Annotation pattern from Auth0 MCP server
4
+ */
5
+ import { z } from 'zod';
6
+ import type { ZitadelClient } from '../auth/client.js';
7
+ import type { ZitadelConfig } from '../utils/config.js';
8
+ export interface ToolAnnotations {
9
+ title?: string;
10
+ readOnlyHint?: boolean;
11
+ destructiveHint?: boolean;
12
+ idempotentHint?: boolean;
13
+ openWorldHint?: boolean;
14
+ }
15
+ export interface ToolMeta {
16
+ readOnly?: boolean;
17
+ domain: 'users' | 'projects' | 'applications' | 'roles' | 'service-accounts' | 'organizations' | 'utility' | 'portal';
18
+ }
19
+ export interface ToolDefinition {
20
+ name: string;
21
+ description: string;
22
+ inputSchema: Record<string, unknown>;
23
+ _meta?: ToolMeta;
24
+ annotations?: ToolAnnotations;
25
+ }
26
+ export interface HandlerContext {
27
+ client: ZitadelClient;
28
+ config: ZitadelConfig;
29
+ }
30
+ export interface ToolResponse {
31
+ content: Array<{
32
+ type: 'text';
33
+ text: string;
34
+ }>;
35
+ isError?: boolean;
36
+ }
37
+ export type ToolHandler = (params: Record<string, unknown>, ctx: HandlerContext) => Promise<ToolResponse>;
38
+ /** Zitadel IDs are numeric strings — reject anything that could alter URL paths */
39
+ export declare const zitadelId: (label?: string) => z.ZodString;
40
+ /** Helper to create a successful text response */
41
+ export declare function textResponse(text: string): ToolResponse;
42
+ /** Helper to create an error text response */
43
+ export declare function errorResponse(text: string): ToolResponse;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * MCP Tool types — handler signatures, context, response format
3
+ * Annotation pattern from Auth0 MCP server
4
+ */
5
+ import { z } from 'zod';
6
+ /** Zitadel IDs are numeric strings — reject anything that could alter URL paths */
7
+ export const zitadelId = (label = 'ID') => z.string().min(1, `${label} is required`).regex(/^[a-zA-Z0-9_-]+$/, `${label} must be alphanumeric`);
8
+ /** Helper to create a successful text response */
9
+ export function textResponse(text) {
10
+ return { content: [{ type: 'text', text }] };
11
+ }
12
+ /** Helper to create an error text response */
13
+ export function errorResponse(text) {
14
+ return { content: [{ type: 'text', text }], isError: true };
15
+ }
16
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/types/tools.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAwCxB,mFAAmF;AACnF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE,EAAE,CACxC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,KAAK,cAAc,CAAC,CAAC,KAAK,CAAC,kBAAkB,EAAE,GAAG,KAAK,uBAAuB,CAAC,CAAC;AAEvG,kDAAkD;AAClD,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Zitadel Management API TypeScript Types
3
+ * Covers users, projects, apps, roles, grants, service accounts
4
+ */
5
+ export interface ResourceDetails {
6
+ sequence: string;
7
+ creationDate: string;
8
+ changeDate: string;
9
+ resourceOwner: string;
10
+ }
11
+ export interface ListDetails {
12
+ totalResult: string;
13
+ processedSequence: string;
14
+ timestamp: string;
15
+ }
16
+ export interface ZitadelError {
17
+ code: number;
18
+ message: string;
19
+ details?: Array<{
20
+ '@type': string;
21
+ id?: string;
22
+ message?: string;
23
+ }>;
24
+ }
25
+ export type UserState = 'USER_STATE_UNSPECIFIED' | 'USER_STATE_ACTIVE' | 'USER_STATE_INACTIVE' | 'USER_STATE_DELETED' | 'USER_STATE_LOCKED' | 'USER_STATE_INITIAL';
26
+ export interface HumanProfile {
27
+ givenName: string;
28
+ familyName: string;
29
+ nickName?: string;
30
+ displayName?: string;
31
+ preferredLanguage?: string;
32
+ gender?: 'GENDER_UNSPECIFIED' | 'GENDER_FEMALE' | 'GENDER_MALE' | 'GENDER_DIVERSE';
33
+ avatarUrl?: string;
34
+ }
35
+ export interface HumanEmail {
36
+ email: string;
37
+ isEmailVerified: boolean;
38
+ }
39
+ export interface HumanPhone {
40
+ phone?: string;
41
+ isPhoneVerified?: boolean;
42
+ }
43
+ export interface ZitadelUserDetails {
44
+ userId: string;
45
+ state: UserState;
46
+ username: string;
47
+ loginNames: string[];
48
+ preferredLoginName: string;
49
+ human?: {
50
+ profile: HumanProfile;
51
+ email: HumanEmail;
52
+ phone?: HumanPhone;
53
+ passwordChanged?: string;
54
+ };
55
+ details: ResourceDetails;
56
+ }
57
+ export interface ListUsersResponse {
58
+ details: ListDetails;
59
+ sortingColumn?: number;
60
+ result: ZitadelUserDetails[];
61
+ }
62
+ export interface GetUserResponse {
63
+ user: ZitadelUserDetails;
64
+ }
65
+ export interface CreateHumanUserRequest {
66
+ profile: {
67
+ givenName: string;
68
+ familyName: string;
69
+ nickName?: string;
70
+ displayName?: string;
71
+ preferredLanguage?: string;
72
+ };
73
+ email: {
74
+ email: string;
75
+ isVerified?: boolean;
76
+ };
77
+ phone?: {
78
+ phone: string;
79
+ isVerified?: boolean;
80
+ };
81
+ password?: {
82
+ password: string;
83
+ changeRequired?: boolean;
84
+ };
85
+ }
86
+ export interface CreateUserResponse {
87
+ userId: string;
88
+ details: ResourceDetails;
89
+ }
90
+ export interface ZitadelProject {
91
+ id: string;
92
+ name: string;
93
+ state: 'PROJECT_STATE_ACTIVE' | 'PROJECT_STATE_INACTIVE';
94
+ details: ResourceDetails;
95
+ projectRoleAssertion?: boolean;
96
+ projectRoleCheck?: boolean;
97
+ hasProjectCheck?: boolean;
98
+ }
99
+ export interface ListProjectsResponse {
100
+ details: ListDetails;
101
+ result: ZitadelProject[];
102
+ }
103
+ export interface CreateProjectRequest {
104
+ name: string;
105
+ projectRoleAssertion?: boolean;
106
+ projectRoleCheck?: boolean;
107
+ hasProjectCheck?: boolean;
108
+ }
109
+ export interface CreateProjectResponse {
110
+ id: string;
111
+ details: ResourceDetails;
112
+ }
113
+ export interface OIDCConfig {
114
+ clientId: string;
115
+ clientSecret?: string;
116
+ redirectUris: string[];
117
+ responseTypes: string[];
118
+ grantTypes: string[];
119
+ appType: string;
120
+ authMethodType: string;
121
+ postLogoutRedirectUris?: string[];
122
+ devMode?: boolean;
123
+ }
124
+ export interface ZitadelApp {
125
+ id: string;
126
+ name: string;
127
+ state: 'APP_STATE_ACTIVE' | 'APP_STATE_INACTIVE';
128
+ details: ResourceDetails;
129
+ oidcConfig?: OIDCConfig;
130
+ }
131
+ export interface ListAppsResponse {
132
+ details: ListDetails;
133
+ result: ZitadelApp[];
134
+ }
135
+ export interface GetAppResponse {
136
+ app: ZitadelApp;
137
+ }
138
+ export interface CreateOIDCAppRequest {
139
+ name: string;
140
+ redirectUris: string[];
141
+ responseTypes: string[];
142
+ grantTypes: string[];
143
+ appType: string;
144
+ authMethodType: string;
145
+ postLogoutRedirectUris?: string[];
146
+ devMode?: boolean;
147
+ }
148
+ export interface CreateOIDCAppResponse {
149
+ appId: string;
150
+ details: ResourceDetails;
151
+ clientId: string;
152
+ clientSecret?: string;
153
+ }
154
+ export interface UpdateOIDCAppRequest {
155
+ redirectUris?: string[];
156
+ responseTypes?: string[];
157
+ grantTypes?: string[];
158
+ appType?: string;
159
+ authMethodType?: string;
160
+ postLogoutRedirectUris?: string[];
161
+ devMode?: boolean;
162
+ }
163
+ export interface ProjectRole {
164
+ key: string;
165
+ displayName: string;
166
+ group?: string;
167
+ }
168
+ export interface ListProjectRolesResponse {
169
+ details: ListDetails;
170
+ result: ProjectRole[];
171
+ }
172
+ export interface CreateProjectRoleRequest {
173
+ roleKey: string;
174
+ displayName: string;
175
+ group?: string;
176
+ }
177
+ export interface UserGrant {
178
+ id: string;
179
+ details: ResourceDetails;
180
+ userId: string;
181
+ projectId: string;
182
+ projectGrantId?: string;
183
+ roleKeys: string[];
184
+ state: 'USER_GRANT_STATE_ACTIVE' | 'USER_GRANT_STATE_INACTIVE';
185
+ }
186
+ export interface ListUserGrantsResponse {
187
+ details: ListDetails;
188
+ result: UserGrant[];
189
+ }
190
+ export interface CreateUserGrantResponse {
191
+ userGrantId: string;
192
+ details: ResourceDetails;
193
+ }
194
+ export interface CreateMachineUserRequest {
195
+ userName: string;
196
+ name: string;
197
+ description?: string;
198
+ accessTokenType?: 'ACCESS_TOKEN_TYPE_BEARER' | 'ACCESS_TOKEN_TYPE_JWT';
199
+ }
200
+ export interface CreateMachineUserResponse {
201
+ userId: string;
202
+ details: ResourceDetails;
203
+ }
204
+ export interface MachineKeyDetails {
205
+ id: string;
206
+ details: ResourceDetails;
207
+ type: string;
208
+ expirationDate?: string;
209
+ }
210
+ export interface ListMachineKeysResponse {
211
+ details: ListDetails;
212
+ result: MachineKeyDetails[];
213
+ }
214
+ export interface CreateMachineKeyResponse {
215
+ keyId: string;
216
+ keyDetails: string;
217
+ details: ResourceDetails;
218
+ }
219
+ export interface ZitadelOrg {
220
+ id: string;
221
+ name: string;
222
+ state: 'ORG_STATE_ACTIVE' | 'ORG_STATE_INACTIVE';
223
+ details: ResourceDetails;
224
+ primaryDomain?: string;
225
+ }
226
+ export interface GetOrgResponse {
227
+ org: ZitadelOrg;
228
+ }
229
+ export interface ListOrgsResponse {
230
+ details: ListDetails;
231
+ result: ZitadelOrg[];
232
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Zitadel Management API TypeScript Types
3
+ * Covers users, projects, apps, roles, grants, service accounts
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=zitadel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zitadel.js","sourceRoot":"","sources":["../../src/types/zitadel.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Configuration loader with Zod validation
3
+ */
4
+ import { z } from 'zod';
5
+ declare const configSchema: z.ZodObject<{
6
+ issuer: z.ZodString;
7
+ serviceAccountUserId: z.ZodString;
8
+ serviceAccountKeyId: z.ZodString;
9
+ serviceAccountPrivateKey: z.ZodString;
10
+ orgId: z.ZodString;
11
+ projectId: z.ZodOptional<z.ZodString>;
12
+ portalDatabaseUrl: z.ZodOptional<z.ZodString>;
13
+ logLevel: z.ZodDefault<z.ZodEnum<["DEBUG", "INFO", "WARN", "ERROR"]>>;
14
+ }, "strip", z.ZodTypeAny, {
15
+ issuer: string;
16
+ serviceAccountUserId: string;
17
+ serviceAccountKeyId: string;
18
+ serviceAccountPrivateKey: string;
19
+ orgId: string;
20
+ logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR";
21
+ projectId?: string | undefined;
22
+ portalDatabaseUrl?: string | undefined;
23
+ }, {
24
+ issuer: string;
25
+ serviceAccountUserId: string;
26
+ serviceAccountKeyId: string;
27
+ serviceAccountPrivateKey: string;
28
+ orgId: string;
29
+ projectId?: string | undefined;
30
+ portalDatabaseUrl?: string | undefined;
31
+ logLevel?: "DEBUG" | "INFO" | "WARN" | "ERROR" | undefined;
32
+ }>;
33
+ export type ZitadelConfig = z.infer<typeof configSchema>;
34
+ export declare function loadConfig(): ZitadelConfig;
35
+ export declare function isPortalEnabled(config: ZitadelConfig): boolean;
36
+ export {};
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Configuration loader with Zod validation
3
+ */
4
+ import { z } from 'zod';
5
+ const configSchema = z.object({
6
+ issuer: z.string().url('ZITADEL_ISSUER must be a valid URL'),
7
+ serviceAccountUserId: z.string().min(1, 'ZITADEL_SERVICE_ACCOUNT_USER_ID is required'),
8
+ serviceAccountKeyId: z.string().min(1, 'ZITADEL_SERVICE_ACCOUNT_KEY_ID is required'),
9
+ serviceAccountPrivateKey: z.string().min(1, 'ZITADEL_SERVICE_ACCOUNT_PRIVATE_KEY is required'),
10
+ orgId: z.string().min(1, 'ZITADEL_ORG_ID is required'),
11
+ projectId: z.string().optional(),
12
+ portalDatabaseUrl: z.string().optional(),
13
+ logLevel: z.enum(['DEBUG', 'INFO', 'WARN', 'ERROR']).default('INFO'),
14
+ });
15
+ export function loadConfig() {
16
+ const result = configSchema.safeParse({
17
+ issuer: process.env['ZITADEL_ISSUER'],
18
+ serviceAccountUserId: process.env['ZITADEL_SERVICE_ACCOUNT_USER_ID'],
19
+ serviceAccountKeyId: process.env['ZITADEL_SERVICE_ACCOUNT_KEY_ID'],
20
+ serviceAccountPrivateKey: process.env['ZITADEL_SERVICE_ACCOUNT_PRIVATE_KEY'],
21
+ orgId: process.env['ZITADEL_ORG_ID'],
22
+ projectId: process.env['ZITADEL_PROJECT_ID'] || undefined,
23
+ portalDatabaseUrl: process.env['PORTAL_DATABASE_URL'] || undefined,
24
+ logLevel: process.env['LOG_LEVEL'] || 'INFO',
25
+ });
26
+ if (!result.success) {
27
+ const errors = result.error.issues.map(i => ` - ${i.path.join('.')}: ${i.message}`).join('\n');
28
+ throw new Error(`Configuration error:\n${errors}`);
29
+ }
30
+ return result.data;
31
+ }
32
+ export function isPortalEnabled(config) {
33
+ return !!config.portalDatabaseUrl;
34
+ }
35
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,oCAAoC,CAAC;IAC5D,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,6CAA6C,CAAC;IACtF,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,4CAA4C,CAAC;IACpF,wBAAwB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,iDAAiD,CAAC;IAC9F,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,4BAA4B,CAAC;IACtD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACxC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;CACrE,CAAC,CAAC;AAIH,MAAM,UAAU,UAAU;IACxB,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC;QACpC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACrC,oBAAoB,EAAE,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC;QACpE,mBAAmB,EAAE,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC;QAClE,wBAAwB,EAAE,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC;QAC5E,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACpC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,SAAS;QACzD,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,IAAI,SAAS;QAClE,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,MAAM;KAC7C,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChG,MAAM,IAAI,KAAK,CAAC,yBAAyB,MAAM,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAqB;IACnD,OAAO,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;AACpC,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Error classes and MCP error handling
3
+ */
4
+ import { McpError } from '@modelcontextprotocol/sdk/types.js';
5
+ export declare class ZitadelAPIError extends Error {
6
+ statusCode?: number | undefined;
7
+ originalError?: Error | undefined;
8
+ constructor(message: string, statusCode?: number | undefined, originalError?: Error | undefined);
9
+ }
10
+ export declare class ValidationError extends Error {
11
+ field?: string | undefined;
12
+ constructor(message: string, field?: string | undefined);
13
+ }
14
+ export declare class ConfigurationError extends Error {
15
+ constructor(message: string);
16
+ }
17
+ export declare function handleMCPError(error: unknown): McpError;
18
+ export declare function setupErrorHandlers(): void;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Error classes and MCP error handling
3
+ */
4
+ import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
5
+ export class ZitadelAPIError extends Error {
6
+ statusCode;
7
+ originalError;
8
+ constructor(message, statusCode, originalError) {
9
+ super(message);
10
+ this.statusCode = statusCode;
11
+ this.originalError = originalError;
12
+ this.name = 'ZitadelAPIError';
13
+ }
14
+ }
15
+ export class ValidationError extends Error {
16
+ field;
17
+ constructor(message, field) {
18
+ super(message);
19
+ this.field = field;
20
+ this.name = 'ValidationError';
21
+ }
22
+ }
23
+ export class ConfigurationError extends Error {
24
+ constructor(message) {
25
+ super(message);
26
+ this.name = 'ConfigurationError';
27
+ }
28
+ }
29
+ export function handleMCPError(error) {
30
+ if (error instanceof ValidationError) {
31
+ return new McpError(ErrorCode.InvalidParams, `Invalid parameter${error.field ? ` '${error.field}'` : ''}: ${error.message}`);
32
+ }
33
+ if (error instanceof ZitadelAPIError) {
34
+ if (error.statusCode === 404) {
35
+ return new McpError(ErrorCode.InvalidParams, 'Resource not found in Zitadel');
36
+ }
37
+ if (error.statusCode === 409) {
38
+ return new McpError(ErrorCode.InvalidParams, `Conflict: ${error.message}`);
39
+ }
40
+ if (error.statusCode === 429) {
41
+ return new McpError(ErrorCode.InternalError, 'Rate limit exceeded. Please try again later.');
42
+ }
43
+ return new McpError(ErrorCode.InternalError, `Zitadel API error: ${error.message}`);
44
+ }
45
+ return new McpError(ErrorCode.InternalError, error instanceof Error ? error.message : 'Unknown error occurred');
46
+ }
47
+ export function setupErrorHandlers() {
48
+ process.on('uncaughtException', (error) => {
49
+ console.error('Uncaught Exception:', error);
50
+ process.exit(1);
51
+ });
52
+ process.on('unhandledRejection', (reason, promise) => {
53
+ console.error('Unhandled Rejection at:', promise, 'reason:', reason);
54
+ });
55
+ }
56
+ //# sourceMappingURL=error-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/utils/error-handler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AAEzE,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAG/B;IACA;IAHT,YACE,OAAe,EACR,UAAmB,EACnB,aAAqB;QAE5B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,eAAU,GAAV,UAAU,CAAS;QACnB,kBAAa,GAAb,aAAa,CAAQ;QAG5B,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACJ;IAApC,YAAY,OAAe,EAAS,KAAc;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QADmB,UAAK,GAAL,KAAK,CAAS;QAEhD,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,KAAK,YAAY,eAAe,EAAE,CAAC;QACrC,OAAO,IAAI,QAAQ,CACjB,SAAS,CAAC,aAAa,EACvB,oBAAoB,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,OAAO,EAAE,CAC/E,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,YAAY,eAAe,EAAE,CAAC;QACrC,IAAI,KAAK,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;YAC7B,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,+BAA+B,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,KAAK,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;YAC7B,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,aAAa,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7E,CAAC;QACD,IAAI,KAAK,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;YAC7B,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,8CAA8C,CAAC,CAAC;QAC/F,CAAC;QACD,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,sBAAsB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,OAAO,IAAI,QAAQ,CACjB,SAAS,CAAC,aAAa,EACvB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAClE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,KAAK,EAAE,EAAE;QACxC,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QACnD,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Logger — all output to stderr (stdout reserved for MCP protocol)
3
+ */
4
+ export declare enum LogLevel {
5
+ DEBUG = 0,
6
+ INFO = 1,
7
+ WARN = 2,
8
+ ERROR = 3
9
+ }
10
+ export declare class Logger {
11
+ private logLevel;
12
+ constructor(level?: keyof typeof LogLevel);
13
+ private shouldLog;
14
+ private formatMessage;
15
+ debug(message: string, meta?: unknown): void;
16
+ info(message: string, meta?: unknown): void;
17
+ warn(message: string, meta?: unknown): void;
18
+ error(message: string, meta?: unknown): void;
19
+ }
20
+ export declare const logger: Logger;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Logger — all output to stderr (stdout reserved for MCP protocol)
3
+ */
4
+ export var LogLevel;
5
+ (function (LogLevel) {
6
+ LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
7
+ LogLevel[LogLevel["INFO"] = 1] = "INFO";
8
+ LogLevel[LogLevel["WARN"] = 2] = "WARN";
9
+ LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
10
+ })(LogLevel || (LogLevel = {}));
11
+ export class Logger {
12
+ logLevel;
13
+ constructor(level = 'INFO') {
14
+ this.logLevel = LogLevel[level];
15
+ }
16
+ shouldLog(level) {
17
+ return level >= this.logLevel;
18
+ }
19
+ formatMessage(level, message, meta) {
20
+ const timestamp = new Date().toISOString();
21
+ const metaStr = meta ? ` ${JSON.stringify(meta)}` : '';
22
+ return `[${timestamp}] ${level}: ${message}${metaStr}`;
23
+ }
24
+ debug(message, meta) {
25
+ if (this.shouldLog(LogLevel.DEBUG)) {
26
+ console.error(this.formatMessage('DEBUG', message, meta));
27
+ }
28
+ }
29
+ info(message, meta) {
30
+ if (this.shouldLog(LogLevel.INFO)) {
31
+ console.error(this.formatMessage('INFO', message, meta));
32
+ }
33
+ }
34
+ warn(message, meta) {
35
+ if (this.shouldLog(LogLevel.WARN)) {
36
+ console.error(this.formatMessage('WARN', message, meta));
37
+ }
38
+ }
39
+ error(message, meta) {
40
+ if (this.shouldLog(LogLevel.ERROR)) {
41
+ console.error(this.formatMessage('ERROR', message, meta));
42
+ }
43
+ }
44
+ }
45
+ export const logger = new Logger(process.env['LOG_LEVEL'] || 'INFO');
46
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAN,IAAY,QAKX;AALD,WAAY,QAAQ;IAClB,yCAAS,CAAA;IACT,uCAAQ,CAAA;IACR,uCAAQ,CAAA;IACR,yCAAS,CAAA;AACX,CAAC,EALW,QAAQ,KAAR,QAAQ,QAKnB;AAED,MAAM,OAAO,MAAM;IACT,QAAQ,CAAW;IAE3B,YAAY,QAA+B,MAAM;QAC/C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAEO,SAAS,CAAC,KAAe;QAC/B,OAAO,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC;IAChC,CAAC;IAEO,aAAa,CAAC,KAAa,EAAE,OAAe,EAAE,IAAc;QAClE,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,OAAO,IAAI,SAAS,KAAK,KAAK,KAAK,OAAO,GAAG,OAAO,EAAE,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAAc;QACnC,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAc;QAClC,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAc;QAClC,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAAc;QACnC,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;CACF;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,MAAM,CAC7B,OAAO,CAAC,GAAG,CAAC,WAAW,CAA2B,IAAI,MAAM,CAC9D,CAAC"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "zitadel-mcp-server",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for Zitadel identity management — manage users, projects, apps, roles, and service accounts",
5
+ "type": "module",
6
+ "main": "build/index.js",
7
+ "bin": {
8
+ "zitadel-mcp": "build/index.js"
9
+ },
10
+ "files": [
11
+ "build",
12
+ "LICENSE",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "start": "node build/index.js",
18
+ "dev": "tsx src/index.ts",
19
+ "clean": "rm -rf build",
20
+ "test": "vitest run",
21
+ "test:watch": "vitest",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "dependencies": {
25
+ "@modelcontextprotocol/sdk": "^1.26.0",
26
+ "dotenv": "^16.5.0",
27
+ "jose": "^5.0.0",
28
+ "postgres": "^3.4.0",
29
+ "zod": "^3.22.0"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^20.0.0",
33
+ "tsx": "^4.21.0",
34
+ "typescript": "^5.9.0",
35
+ "vitest": "^4.0.18"
36
+ },
37
+ "engines": {
38
+ "node": ">=18.0.0"
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/takleb3rry/zitadel-mcp.git"
43
+ },
44
+ "license": "MIT",
45
+ "keywords": [
46
+ "zitadel",
47
+ "mcp",
48
+ "model-context-protocol",
49
+ "identity",
50
+ "iam",
51
+ "authentication",
52
+ "authorization"
53
+ ]
54
+ }