@mtaap/mcp 0.2.13 → 0.4.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.
- package/README.md +1 -1
- package/dist/cli.js +469 -260
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +19 -4
- package/dist/index.js +467 -258
- package/dist/index.js.map +1 -1
- package/dist/server.js +597 -269
- package/dist/server.js.map +1 -1
- package/package.json +2 -1
package/dist/server.js
CHANGED
|
@@ -36,7 +36,7 @@ var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
|
36
36
|
// package.json
|
|
37
37
|
var package_default = {
|
|
38
38
|
name: "@mtaap/mcp",
|
|
39
|
-
version: "0.
|
|
39
|
+
version: "0.4.1",
|
|
40
40
|
description: "Model Context Protocol (MCP) server for AI agents to interact with Collab - the multi-tenant collaborative agent development platform",
|
|
41
41
|
mcpName: "collab",
|
|
42
42
|
scripts: {
|
|
@@ -45,6 +45,7 @@ var package_default = {
|
|
|
45
45
|
main: "./dist/index.js",
|
|
46
46
|
types: "./dist/index.d.ts",
|
|
47
47
|
bin: {
|
|
48
|
+
mcp: "./dist/cli.js",
|
|
48
49
|
"collab-mcp": "./dist/cli.js",
|
|
49
50
|
"collab-mcp-server": "./dist/server.js"
|
|
50
51
|
},
|
|
@@ -94,7 +95,7 @@ var package_default = {
|
|
|
94
95
|
var VERSION = package_default.version;
|
|
95
96
|
|
|
96
97
|
// src/index.ts
|
|
97
|
-
var
|
|
98
|
+
var import_zod4 = require("zod");
|
|
98
99
|
|
|
99
100
|
// ../../packages/core/dist/constants/enums.js
|
|
100
101
|
var TaskState;
|
|
@@ -181,12 +182,6 @@ var WebSocketEventType;
|
|
|
181
182
|
WebSocketEventType2["TASK_DELETED"] = "task.deleted";
|
|
182
183
|
WebSocketEventType2["MEMBER_JOINED"] = "member.joined";
|
|
183
184
|
})(WebSocketEventType || (WebSocketEventType = {}));
|
|
184
|
-
var AuthProvider;
|
|
185
|
-
(function(AuthProvider2) {
|
|
186
|
-
AuthProvider2["CREDENTIALS"] = "credentials";
|
|
187
|
-
AuthProvider2["LDAP"] = "ldap";
|
|
188
|
-
AuthProvider2["SSO"] = "sso";
|
|
189
|
-
})(AuthProvider || (AuthProvider = {}));
|
|
190
185
|
var SubscriptionStatus;
|
|
191
186
|
(function(SubscriptionStatus2) {
|
|
192
187
|
SubscriptionStatus2["ACTIVE"] = "ACTIVE";
|
|
@@ -202,6 +197,12 @@ var EventType;
|
|
|
202
197
|
EventType2["ACCESS"] = "ACCESS";
|
|
203
198
|
EventType2["MODIFICATION"] = "MODIFICATION";
|
|
204
199
|
})(EventType || (EventType = {}));
|
|
200
|
+
var CreatedVia;
|
|
201
|
+
(function(CreatedVia2) {
|
|
202
|
+
CreatedVia2["UI"] = "UI";
|
|
203
|
+
CreatedVia2["API_KEY"] = "API_KEY";
|
|
204
|
+
CreatedVia2["OAUTH"] = "OAUTH";
|
|
205
|
+
})(CreatedVia || (CreatedVia = {}));
|
|
205
206
|
|
|
206
207
|
// ../../packages/core/dist/constants/state-machine.js
|
|
207
208
|
var VALID_TRANSITIONS = {
|
|
@@ -225,6 +226,62 @@ var VALID_TRANSITIONS = {
|
|
|
225
226
|
[TaskState.DONE]: []
|
|
226
227
|
};
|
|
227
228
|
|
|
229
|
+
// ../../packages/core/dist/constants/oauth.js
|
|
230
|
+
var OAuthScopes = {
|
|
231
|
+
/** Read-only access to MCP resources */
|
|
232
|
+
READ: "mcp:read",
|
|
233
|
+
/** Read and write access to MCP resources */
|
|
234
|
+
WRITE: "mcp:write",
|
|
235
|
+
/** Full administrative access */
|
|
236
|
+
ADMIN: "mcp:admin"
|
|
237
|
+
};
|
|
238
|
+
var VALID_OAUTH_SCOPES = [
|
|
239
|
+
OAuthScopes.READ,
|
|
240
|
+
OAuthScopes.WRITE,
|
|
241
|
+
OAuthScopes.ADMIN
|
|
242
|
+
];
|
|
243
|
+
var DEFAULT_OAUTH_SCOPES = `${OAuthScopes.READ} ${OAuthScopes.WRITE}`;
|
|
244
|
+
var OAUTH_SCOPE_TO_PERMISSION = {
|
|
245
|
+
[OAuthScopes.READ]: ApiKeyPermission.READ,
|
|
246
|
+
[OAuthScopes.WRITE]: ApiKeyPermission.WRITE,
|
|
247
|
+
[OAuthScopes.ADMIN]: ApiKeyPermission.ADMIN
|
|
248
|
+
};
|
|
249
|
+
var PERMISSION_TO_OAUTH_SCOPE = {
|
|
250
|
+
[ApiKeyPermission.READ]: OAuthScopes.READ,
|
|
251
|
+
[ApiKeyPermission.WRITE]: OAuthScopes.WRITE,
|
|
252
|
+
[ApiKeyPermission.ADMIN]: OAuthScopes.ADMIN
|
|
253
|
+
};
|
|
254
|
+
var OAuthTokenLifetimes = {
|
|
255
|
+
/** Access token lifetime: 1 hour */
|
|
256
|
+
ACCESS_TOKEN_MS: 60 * 60 * 1e3,
|
|
257
|
+
/** Refresh token lifetime: 30 days */
|
|
258
|
+
REFRESH_TOKEN_MS: 30 * 24 * 60 * 60 * 1e3,
|
|
259
|
+
/** Authorization code lifetime: 10 minutes */
|
|
260
|
+
AUTHORIZATION_CODE_MS: 10 * 60 * 1e3
|
|
261
|
+
};
|
|
262
|
+
var OAuthGrantTypes = {
|
|
263
|
+
AUTHORIZATION_CODE: "authorization_code",
|
|
264
|
+
REFRESH_TOKEN: "refresh_token"
|
|
265
|
+
};
|
|
266
|
+
var SUPPORTED_GRANT_TYPES = [
|
|
267
|
+
OAuthGrantTypes.AUTHORIZATION_CODE,
|
|
268
|
+
OAuthGrantTypes.REFRESH_TOKEN
|
|
269
|
+
];
|
|
270
|
+
var OAuthResponseTypes = {
|
|
271
|
+
CODE: "code"
|
|
272
|
+
};
|
|
273
|
+
var OAuthCodeChallengeMethods = {
|
|
274
|
+
S256: "S256"
|
|
275
|
+
};
|
|
276
|
+
var OAuthRateLimits = {
|
|
277
|
+
/** /oauth/token: 30 requests per minute per client */
|
|
278
|
+
TOKEN_ENDPOINT: { limit: 30, windowMs: 60 * 1e3 },
|
|
279
|
+
/** /oauth/authorize: 10 requests per minute per user */
|
|
280
|
+
AUTHORIZE_ENDPOINT: { limit: 10, windowMs: 60 * 1e3 },
|
|
281
|
+
/** /oauth/register: 5 requests per minute per IP */
|
|
282
|
+
REGISTER_ENDPOINT: { limit: 5, windowMs: 60 * 1e3 }
|
|
283
|
+
};
|
|
284
|
+
|
|
228
285
|
// ../../packages/core/dist/config/deployment.js
|
|
229
286
|
var config = {
|
|
230
287
|
deploymentMode: process.env.DEPLOYMENT_MODE || "saas"
|
|
@@ -232,20 +289,24 @@ var config = {
|
|
|
232
289
|
var isSaas = config.deploymentMode === "saas";
|
|
233
290
|
var isOnPrem = config.deploymentMode === "onprem";
|
|
234
291
|
|
|
235
|
-
// ../../packages/core/dist/
|
|
236
|
-
var
|
|
292
|
+
// ../../packages/core/dist/versions.js
|
|
293
|
+
var VERSIONS = {
|
|
294
|
+
core: "0.3.0",
|
|
295
|
+
web: "0.3.0",
|
|
296
|
+
mcp: "0.4.1"
|
|
297
|
+
};
|
|
298
|
+
var VERSION2 = VERSIONS.core;
|
|
237
299
|
|
|
238
300
|
// ../../packages/core/dist/config/index.js
|
|
239
301
|
var DEPLOYMENT_MODE = process.env.DEPLOYMENT_MODE || "saas";
|
|
240
302
|
var config2 = {
|
|
241
303
|
version: VERSION2,
|
|
304
|
+
packages: VERSIONS,
|
|
242
305
|
deploymentMode: DEPLOYMENT_MODE,
|
|
243
306
|
billing: {
|
|
244
307
|
enabled: DEPLOYMENT_MODE === "saas",
|
|
245
308
|
revenuecat: {
|
|
246
|
-
publicKey: process.env.
|
|
247
|
-
stripeKey: process.env.STRIPE_SECRET_KEY
|
|
248
|
-
// Required by RevenueCat Web Billing
|
|
309
|
+
publicKey: process.env.NEXT_PUBLIC_REVENUECAT_PUBLIC_KEY
|
|
249
310
|
}
|
|
250
311
|
},
|
|
251
312
|
licensing: {
|
|
@@ -351,7 +412,6 @@ var OrganizationIdSchema = import_zod.z.string().regex(/^org_[a-zA-Z0-9]+$/);
|
|
|
351
412
|
var OrganizationSchema = import_zod.z.object({
|
|
352
413
|
id: OrganizationIdSchema,
|
|
353
414
|
name: import_zod.z.string().min(1).max(255),
|
|
354
|
-
slug: import_zod.z.string().min(1).max(100).regex(/^[a-z0-9-]+$/),
|
|
355
415
|
logoUrl: import_zod.z.string().url().nullable(),
|
|
356
416
|
accentColor: import_zod.z.string().regex(/^#[0-9A-Fa-f]{6}$/).nullable(),
|
|
357
417
|
tenantName: import_zod.z.string().nullable(),
|
|
@@ -479,239 +539,375 @@ var ProjectCollaboratorSchema = import_zod.z.object({
|
|
|
479
539
|
});
|
|
480
540
|
|
|
481
541
|
// ../../packages/core/dist/validation/index.js
|
|
542
|
+
var import_zod3 = require("zod");
|
|
543
|
+
|
|
544
|
+
// ../../packages/core/dist/validation/oauth.js
|
|
482
545
|
var import_zod2 = require("zod");
|
|
483
|
-
var
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
var
|
|
546
|
+
var scopeString = import_zod2.z.string().optional().transform((val) => {
|
|
547
|
+
if (!val)
|
|
548
|
+
return void 0;
|
|
549
|
+
const scopes = val.split(" ").filter(Boolean);
|
|
550
|
+
const validScopes = scopes.filter((s) => VALID_OAUTH_SCOPES.includes(s));
|
|
551
|
+
return validScopes.length > 0 ? validScopes.join(" ") : void 0;
|
|
552
|
+
});
|
|
553
|
+
var redirectUri = import_zod2.z.string().url().refine((uri) => {
|
|
554
|
+
const url = new URL(uri);
|
|
555
|
+
return url.protocol === "https:" || url.hostname === "localhost" || url.hostname === "127.0.0.1";
|
|
556
|
+
}, { message: "redirect_uri must use HTTPS or be localhost" });
|
|
557
|
+
var codeVerifier = import_zod2.z.string().min(43).max(128).regex(/^[A-Za-z0-9._~-]+$/, "code_verifier must only contain unreserved characters");
|
|
558
|
+
var codeChallenge = import_zod2.z.string().min(43).max(128).regex(/^[A-Za-z0-9_-]+$/, "code_challenge must be base64url encoded (no padding)");
|
|
559
|
+
var DynamicClientRegistrationSchema = import_zod2.z.object({
|
|
560
|
+
redirect_uris: import_zod2.z.array(redirectUri).min(1),
|
|
561
|
+
client_name: import_zod2.z.string().min(1).max(255),
|
|
562
|
+
client_uri: import_zod2.z.string().url().optional(),
|
|
563
|
+
logo_uri: import_zod2.z.string().url().optional(),
|
|
564
|
+
// Accept lowercase OAuth spec values
|
|
565
|
+
grant_types: import_zod2.z.array(import_zod2.z.enum(["authorization_code", "refresh_token"])).default(["authorization_code", "refresh_token"]),
|
|
566
|
+
response_types: import_zod2.z.array(import_zod2.z.enum([OAuthResponseTypes.CODE])).default([OAuthResponseTypes.CODE]),
|
|
567
|
+
scope: scopeString,
|
|
568
|
+
// Accept lowercase OAuth spec values
|
|
569
|
+
token_endpoint_auth_method: import_zod2.z.enum(["none", "client_secret_post", "client_secret_basic"]).default("none")
|
|
570
|
+
});
|
|
571
|
+
var DynamicClientRegistrationResponseSchema = import_zod2.z.object({
|
|
572
|
+
client_id: import_zod2.z.string(),
|
|
573
|
+
client_secret: import_zod2.z.string().optional(),
|
|
574
|
+
client_id_issued_at: import_zod2.z.number(),
|
|
575
|
+
client_secret_expires_at: import_zod2.z.number().optional(),
|
|
576
|
+
redirect_uris: import_zod2.z.array(import_zod2.z.string()),
|
|
577
|
+
client_name: import_zod2.z.string(),
|
|
578
|
+
client_uri: import_zod2.z.string().optional(),
|
|
579
|
+
logo_uri: import_zod2.z.string().optional(),
|
|
580
|
+
grant_types: import_zod2.z.array(import_zod2.z.string()),
|
|
581
|
+
response_types: import_zod2.z.array(import_zod2.z.string()),
|
|
582
|
+
scope: import_zod2.z.string(),
|
|
583
|
+
token_endpoint_auth_method: import_zod2.z.string(),
|
|
584
|
+
registration_access_token: import_zod2.z.string().optional(),
|
|
585
|
+
registration_client_uri: import_zod2.z.string().optional()
|
|
586
|
+
});
|
|
587
|
+
var AuthorizationRequestSchema = import_zod2.z.object({
|
|
588
|
+
response_type: import_zod2.z.literal(OAuthResponseTypes.CODE),
|
|
589
|
+
client_id: import_zod2.z.string().min(1),
|
|
590
|
+
redirect_uri: redirectUri,
|
|
591
|
+
scope: scopeString,
|
|
592
|
+
state: import_zod2.z.string().max(255).optional(),
|
|
593
|
+
// PKCE is mandatory in OAuth 2.1
|
|
594
|
+
code_challenge: codeChallenge,
|
|
595
|
+
code_challenge_method: import_zod2.z.literal(OAuthCodeChallengeMethods.S256)
|
|
596
|
+
});
|
|
597
|
+
var TokenRequestAuthorizationCodeSchema = import_zod2.z.object({
|
|
598
|
+
grant_type: import_zod2.z.literal(OAuthGrantTypes.AUTHORIZATION_CODE),
|
|
599
|
+
code: import_zod2.z.string().min(1),
|
|
600
|
+
redirect_uri: redirectUri,
|
|
601
|
+
client_id: import_zod2.z.string().min(1),
|
|
602
|
+
// PKCE code verifier is mandatory
|
|
603
|
+
code_verifier: codeVerifier,
|
|
604
|
+
// Client secret is optional (for confidential clients)
|
|
605
|
+
client_secret: import_zod2.z.string().optional()
|
|
606
|
+
});
|
|
607
|
+
var TokenRequestRefreshTokenSchema = import_zod2.z.object({
|
|
608
|
+
grant_type: import_zod2.z.literal(OAuthGrantTypes.REFRESH_TOKEN),
|
|
609
|
+
refresh_token: import_zod2.z.string().min(1),
|
|
610
|
+
client_id: import_zod2.z.string().min(1),
|
|
611
|
+
// Optional: request reduced scope
|
|
612
|
+
scope: scopeString,
|
|
613
|
+
// Client secret is optional (for confidential clients)
|
|
614
|
+
client_secret: import_zod2.z.string().optional()
|
|
615
|
+
});
|
|
616
|
+
var TokenRequestSchema = import_zod2.z.discriminatedUnion("grant_type", [
|
|
617
|
+
TokenRequestAuthorizationCodeSchema,
|
|
618
|
+
TokenRequestRefreshTokenSchema
|
|
619
|
+
]);
|
|
620
|
+
var TokenResponseSchema = import_zod2.z.object({
|
|
621
|
+
access_token: import_zod2.z.string(),
|
|
622
|
+
token_type: import_zod2.z.literal("Bearer"),
|
|
623
|
+
expires_in: import_zod2.z.number(),
|
|
624
|
+
refresh_token: import_zod2.z.string().optional(),
|
|
625
|
+
scope: import_zod2.z.string()
|
|
626
|
+
});
|
|
627
|
+
var TokenRevocationRequestSchema = import_zod2.z.object({
|
|
628
|
+
token: import_zod2.z.string().min(1),
|
|
629
|
+
token_type_hint: import_zod2.z.enum(["access_token", "refresh_token"]).optional(),
|
|
630
|
+
client_id: import_zod2.z.string().min(1),
|
|
631
|
+
client_secret: import_zod2.z.string().optional()
|
|
632
|
+
});
|
|
633
|
+
var OAuthErrorResponseSchema = import_zod2.z.object({
|
|
634
|
+
error: import_zod2.z.string(),
|
|
635
|
+
error_description: import_zod2.z.string().optional(),
|
|
636
|
+
error_uri: import_zod2.z.string().url().optional(),
|
|
637
|
+
state: import_zod2.z.string().optional()
|
|
638
|
+
});
|
|
639
|
+
var AuthorizationServerMetadataSchema = import_zod2.z.object({
|
|
640
|
+
issuer: import_zod2.z.string().url(),
|
|
641
|
+
authorization_endpoint: import_zod2.z.string().url(),
|
|
642
|
+
token_endpoint: import_zod2.z.string().url(),
|
|
643
|
+
registration_endpoint: import_zod2.z.string().url().optional(),
|
|
644
|
+
revocation_endpoint: import_zod2.z.string().url().optional(),
|
|
645
|
+
scopes_supported: import_zod2.z.array(import_zod2.z.string()),
|
|
646
|
+
response_types_supported: import_zod2.z.array(import_zod2.z.string()),
|
|
647
|
+
grant_types_supported: import_zod2.z.array(import_zod2.z.string()),
|
|
648
|
+
token_endpoint_auth_methods_supported: import_zod2.z.array(import_zod2.z.string()),
|
|
649
|
+
code_challenge_methods_supported: import_zod2.z.array(import_zod2.z.string()),
|
|
650
|
+
service_documentation: import_zod2.z.string().url().optional()
|
|
651
|
+
});
|
|
652
|
+
var ProtectedResourceMetadataSchema = import_zod2.z.object({
|
|
653
|
+
resource: import_zod2.z.string().url(),
|
|
654
|
+
authorization_servers: import_zod2.z.array(import_zod2.z.string().url()),
|
|
655
|
+
scopes_supported: import_zod2.z.array(import_zod2.z.string()).optional(),
|
|
656
|
+
bearer_methods_supported: import_zod2.z.array(import_zod2.z.string()).optional(),
|
|
657
|
+
resource_signing_alg_values_supported: import_zod2.z.array(import_zod2.z.string()).optional(),
|
|
658
|
+
resource_documentation: import_zod2.z.string().url().optional()
|
|
659
|
+
});
|
|
660
|
+
var InternalTokenValidationRequestSchema = import_zod2.z.object({
|
|
661
|
+
access_token: import_zod2.z.string().min(1)
|
|
662
|
+
});
|
|
663
|
+
var InternalTokenValidationResponseSchema = import_zod2.z.object({
|
|
664
|
+
valid: import_zod2.z.boolean(),
|
|
665
|
+
userId: import_zod2.z.string().optional(),
|
|
666
|
+
userEmail: import_zod2.z.string().optional(),
|
|
667
|
+
userName: import_zod2.z.string().optional(),
|
|
668
|
+
scope: import_zod2.z.string().optional(),
|
|
669
|
+
permissions: import_zod2.z.string().optional(),
|
|
670
|
+
clientId: import_zod2.z.string().optional(),
|
|
671
|
+
expiresAt: import_zod2.z.string().optional()
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
// ../../packages/core/dist/validation/index.js
|
|
675
|
+
var ListProjectsInputSchema = import_zod3.z.object({
|
|
676
|
+
workspaceType: import_zod3.z.preprocess((val) => typeof val === "string" ? val.toUpperCase() : val, import_zod3.z.enum(["TEAM", "PERSONAL", "ALL"]).optional())
|
|
677
|
+
});
|
|
678
|
+
var ListTasksInputSchema = import_zod3.z.object({
|
|
679
|
+
projectId: import_zod3.z.string().optional(),
|
|
680
|
+
state: import_zod3.z.nativeEnum(TaskState).optional(),
|
|
681
|
+
assigneeId: import_zod3.z.string().optional(),
|
|
682
|
+
includeArchived: import_zod3.z.boolean().optional()
|
|
683
|
+
});
|
|
684
|
+
var cuidOrPrefixedId = import_zod3.z.string().regex(/^([a-z0-9]+|[a-z]+_[a-zA-Z0-9]+)$/);
|
|
685
|
+
var gitBranchName = import_zod3.z.string().min(1).max(100).regex(/^[a-zA-Z0-9][-a-zA-Z0-9._/]*[a-zA-Z0-9]$|^[a-zA-Z0-9]$/, "Branch name must start and end with alphanumeric character").refine((val) => !val.includes("..") && !val.includes("@{") && !val.includes("//") && !val.endsWith(".lock") && !val.includes("~") && !val.includes("^") && !val.includes(":") && !val.includes("?") && !val.includes("*") && !val.includes("[") && !val.includes("\\") && !val.includes(" ") && !val.includes(";") && !val.includes("&") && !val.includes("|") && !val.includes("$") && !val.includes("`") && !val.includes("'") && !val.includes('"') && !val.includes("<") && !val.includes(">") && !val.includes("(") && !val.includes(")"), "Invalid branch name: contains forbidden characters or sequences");
|
|
686
|
+
var GetTaskInputSchema = import_zod3.z.object({
|
|
495
687
|
taskId: cuidOrPrefixedId
|
|
496
688
|
});
|
|
497
|
-
var AssignTaskInputSchema =
|
|
689
|
+
var AssignTaskInputSchema = import_zod3.z.object({
|
|
498
690
|
projectId: cuidOrPrefixedId,
|
|
499
691
|
taskId: cuidOrPrefixedId,
|
|
500
|
-
expectedState:
|
|
692
|
+
expectedState: import_zod3.z.nativeEnum(TaskState).default(TaskState.TODO)
|
|
501
693
|
});
|
|
502
|
-
var UpdateProgressInputSchema =
|
|
694
|
+
var UpdateProgressInputSchema = import_zod3.z.object({
|
|
503
695
|
taskId: cuidOrPrefixedId,
|
|
504
|
-
statusMessage:
|
|
505
|
-
completedCheckpointIds:
|
|
506
|
-
currentCheckpointIndex:
|
|
696
|
+
statusMessage: import_zod3.z.string().max(1e3).optional(),
|
|
697
|
+
completedCheckpointIds: import_zod3.z.array(import_zod3.z.string()).optional(),
|
|
698
|
+
currentCheckpointIndex: import_zod3.z.number().int().optional()
|
|
507
699
|
});
|
|
508
|
-
var CompleteTaskInputSchema =
|
|
700
|
+
var CompleteTaskInputSchema = import_zod3.z.object({
|
|
509
701
|
projectId: cuidOrPrefixedId,
|
|
510
702
|
taskId: cuidOrPrefixedId,
|
|
511
|
-
pullRequestTitle:
|
|
512
|
-
pullRequestBody:
|
|
703
|
+
pullRequestTitle: import_zod3.z.string().min(1).max(300).optional(),
|
|
704
|
+
pullRequestBody: import_zod3.z.string().max(1e4).optional()
|
|
513
705
|
});
|
|
514
|
-
var ReportErrorInputSchema =
|
|
706
|
+
var ReportErrorInputSchema = import_zod3.z.object({
|
|
515
707
|
taskId: cuidOrPrefixedId,
|
|
516
|
-
errorType:
|
|
517
|
-
errorMessage:
|
|
518
|
-
context:
|
|
708
|
+
errorType: import_zod3.z.nativeEnum(ErrorType),
|
|
709
|
+
errorMessage: import_zod3.z.string().min(1).max(1e3),
|
|
710
|
+
context: import_zod3.z.string().max(2e3).optional()
|
|
519
711
|
});
|
|
520
|
-
var GetProjectContextInputSchema =
|
|
712
|
+
var GetProjectContextInputSchema = import_zod3.z.object({
|
|
521
713
|
projectId: cuidOrPrefixedId
|
|
522
714
|
});
|
|
523
|
-
var AddNoteInputSchema =
|
|
715
|
+
var AddNoteInputSchema = import_zod3.z.object({
|
|
524
716
|
taskId: cuidOrPrefixedId,
|
|
525
|
-
content:
|
|
717
|
+
content: import_zod3.z.string().min(1).max(500)
|
|
526
718
|
});
|
|
527
|
-
var AbandonTaskInputSchema =
|
|
719
|
+
var AbandonTaskInputSchema = import_zod3.z.object({
|
|
528
720
|
projectId: cuidOrPrefixedId,
|
|
529
721
|
taskId: cuidOrPrefixedId,
|
|
530
|
-
deleteBranch:
|
|
722
|
+
deleteBranch: import_zod3.z.boolean().optional()
|
|
531
723
|
});
|
|
532
|
-
var RequestChangesInputSchema =
|
|
724
|
+
var RequestChangesInputSchema = import_zod3.z.object({
|
|
533
725
|
projectId: cuidOrPrefixedId,
|
|
534
726
|
taskId: cuidOrPrefixedId,
|
|
535
|
-
reviewComments:
|
|
536
|
-
requestedChanges:
|
|
727
|
+
reviewComments: import_zod3.z.string().min(1).max(5e3),
|
|
728
|
+
requestedChanges: import_zod3.z.array(import_zod3.z.string().min(1).max(500)).optional()
|
|
537
729
|
});
|
|
538
|
-
var ApproveTaskInputSchema =
|
|
730
|
+
var ApproveTaskInputSchema = import_zod3.z.object({
|
|
539
731
|
projectId: cuidOrPrefixedId,
|
|
540
732
|
taskId: cuidOrPrefixedId,
|
|
541
|
-
reviewComments:
|
|
733
|
+
reviewComments: import_zod3.z.string().max(2e3).optional()
|
|
542
734
|
});
|
|
543
|
-
var ArchiveTaskInputSchema =
|
|
735
|
+
var ArchiveTaskInputSchema = import_zod3.z.object({
|
|
544
736
|
projectId: cuidOrPrefixedId,
|
|
545
737
|
taskId: cuidOrPrefixedId
|
|
546
738
|
});
|
|
547
|
-
var UnarchiveTaskInputSchema =
|
|
739
|
+
var UnarchiveTaskInputSchema = import_zod3.z.object({
|
|
548
740
|
projectId: cuidOrPrefixedId,
|
|
549
741
|
taskId: cuidOrPrefixedId
|
|
550
742
|
});
|
|
551
|
-
var CreatePersonalProjectInputSchema =
|
|
552
|
-
name:
|
|
553
|
-
description:
|
|
554
|
-
repositoryUrl:
|
|
743
|
+
var CreatePersonalProjectInputSchema = import_zod3.z.object({
|
|
744
|
+
name: import_zod3.z.string().min(1).max(100),
|
|
745
|
+
description: import_zod3.z.string().max(500).optional(),
|
|
746
|
+
repositoryUrl: import_zod3.z.string().url()
|
|
555
747
|
});
|
|
556
|
-
var CheckActiveTaskInputSchema =
|
|
557
|
-
var CreateTaskMCPInputSchema =
|
|
748
|
+
var CheckActiveTaskInputSchema = import_zod3.z.object({});
|
|
749
|
+
var CreateTaskMCPInputSchema = import_zod3.z.object({
|
|
558
750
|
projectId: cuidOrPrefixedId,
|
|
559
751
|
epicId: cuidOrPrefixedId.nullable().optional(),
|
|
560
|
-
title:
|
|
561
|
-
description:
|
|
562
|
-
priority:
|
|
563
|
-
acceptanceCriteria:
|
|
564
|
-
description:
|
|
752
|
+
title: import_zod3.z.string().min(1).max(200),
|
|
753
|
+
description: import_zod3.z.string().max(5e3),
|
|
754
|
+
priority: import_zod3.z.nativeEnum(TaskPriority).default(TaskPriority.MEDIUM),
|
|
755
|
+
acceptanceCriteria: import_zod3.z.array(import_zod3.z.object({
|
|
756
|
+
description: import_zod3.z.string().min(1).max(500)
|
|
565
757
|
})).min(1)
|
|
566
758
|
});
|
|
567
|
-
var CreateOrganizationInputSchema =
|
|
568
|
-
name:
|
|
569
|
-
slug: import_zod2.z.string().min(1).max(100).regex(/^[a-z0-9-]+$/).optional()
|
|
759
|
+
var CreateOrganizationInputSchema = import_zod3.z.object({
|
|
760
|
+
name: import_zod3.z.string().min(1).max(255)
|
|
570
761
|
});
|
|
571
|
-
var UpdateOrganizationInputSchema =
|
|
762
|
+
var UpdateOrganizationInputSchema = import_zod3.z.object({
|
|
572
763
|
organizationId: cuidOrPrefixedId,
|
|
573
|
-
name:
|
|
574
|
-
logoUrl:
|
|
575
|
-
accentColor:
|
|
576
|
-
tenantName:
|
|
577
|
-
});
|
|
578
|
-
var CreateProjectInputSchema =
|
|
579
|
-
name:
|
|
580
|
-
description:
|
|
581
|
-
type:
|
|
582
|
-
repositoryUrl:
|
|
583
|
-
baseBranch:
|
|
584
|
-
tags:
|
|
585
|
-
});
|
|
586
|
-
var UpdateProjectInputSchema =
|
|
587
|
-
projectId:
|
|
588
|
-
name:
|
|
589
|
-
description:
|
|
590
|
-
repositoryUrl:
|
|
591
|
-
baseBranch:
|
|
592
|
-
tags:
|
|
593
|
-
allowMemberArchive:
|
|
594
|
-
});
|
|
595
|
-
var CreateEpicInputSchema =
|
|
764
|
+
name: import_zod3.z.string().min(1).max(255).optional(),
|
|
765
|
+
logoUrl: import_zod3.z.string().url().nullable().optional(),
|
|
766
|
+
accentColor: import_zod3.z.string().regex(/^#[0-9A-Fa-f]{6}$/, "Invalid hex color format. Expected #RRGGBB").nullable().optional(),
|
|
767
|
+
tenantName: import_zod3.z.string().max(255).nullable().optional()
|
|
768
|
+
});
|
|
769
|
+
var CreateProjectInputSchema = import_zod3.z.object({
|
|
770
|
+
name: import_zod3.z.string().min(1).max(100),
|
|
771
|
+
description: import_zod3.z.string().max(500).optional(),
|
|
772
|
+
type: import_zod3.z.nativeEnum(ProjectType),
|
|
773
|
+
repositoryUrl: import_zod3.z.string().url(),
|
|
774
|
+
baseBranch: import_zod3.z.string().default("develop").optional(),
|
|
775
|
+
tags: import_zod3.z.array(import_zod3.z.string()).default([])
|
|
776
|
+
});
|
|
777
|
+
var UpdateProjectInputSchema = import_zod3.z.object({
|
|
778
|
+
projectId: import_zod3.z.string().min(1).optional(),
|
|
779
|
+
name: import_zod3.z.string().min(1).max(100).optional(),
|
|
780
|
+
description: import_zod3.z.string().max(500).optional(),
|
|
781
|
+
repositoryUrl: import_zod3.z.string().url().optional(),
|
|
782
|
+
baseBranch: import_zod3.z.string().optional(),
|
|
783
|
+
tags: import_zod3.z.array(import_zod3.z.string()).optional(),
|
|
784
|
+
allowMemberArchive: import_zod3.z.boolean().optional()
|
|
785
|
+
});
|
|
786
|
+
var CreateEpicInputSchema = import_zod3.z.object({
|
|
596
787
|
projectId: cuidOrPrefixedId,
|
|
597
|
-
name:
|
|
598
|
-
description:
|
|
599
|
-
});
|
|
600
|
-
var CreateTaskInputSchema =
|
|
601
|
-
projectId:
|
|
602
|
-
epicId:
|
|
603
|
-
title:
|
|
604
|
-
description:
|
|
605
|
-
priority:
|
|
606
|
-
acceptanceCriteria:
|
|
607
|
-
description:
|
|
788
|
+
name: import_zod3.z.string().min(1).max(200),
|
|
789
|
+
description: import_zod3.z.string().max(2e3).optional()
|
|
790
|
+
});
|
|
791
|
+
var CreateTaskInputSchema = import_zod3.z.object({
|
|
792
|
+
projectId: import_zod3.z.string().min(1),
|
|
793
|
+
epicId: import_zod3.z.string().min(1).nullable().optional(),
|
|
794
|
+
title: import_zod3.z.string().min(1).max(200),
|
|
795
|
+
description: import_zod3.z.string().max(5e3),
|
|
796
|
+
priority: import_zod3.z.nativeEnum(TaskPriority).default(TaskPriority.MEDIUM),
|
|
797
|
+
acceptanceCriteria: import_zod3.z.array(import_zod3.z.object({
|
|
798
|
+
description: import_zod3.z.string().min(1).max(500)
|
|
608
799
|
})).min(1)
|
|
609
800
|
});
|
|
610
|
-
var UpdateTaskInputSchema =
|
|
611
|
-
taskId:
|
|
612
|
-
title:
|
|
613
|
-
description:
|
|
614
|
-
priority:
|
|
615
|
-
state:
|
|
616
|
-
assigneeId:
|
|
617
|
-
acceptanceCriteria:
|
|
618
|
-
id:
|
|
619
|
-
description:
|
|
620
|
-
completed:
|
|
801
|
+
var UpdateTaskInputSchema = import_zod3.z.object({
|
|
802
|
+
taskId: import_zod3.z.string().min(1),
|
|
803
|
+
title: import_zod3.z.string().min(1).max(200).optional(),
|
|
804
|
+
description: import_zod3.z.string().max(5e3).optional(),
|
|
805
|
+
priority: import_zod3.z.nativeEnum(TaskPriority).optional(),
|
|
806
|
+
state: import_zod3.z.nativeEnum(TaskState).optional(),
|
|
807
|
+
assigneeId: import_zod3.z.string().nullable().optional(),
|
|
808
|
+
acceptanceCriteria: import_zod3.z.array(import_zod3.z.object({
|
|
809
|
+
id: import_zod3.z.string().optional(),
|
|
810
|
+
description: import_zod3.z.string().min(1).max(500),
|
|
811
|
+
completed: import_zod3.z.boolean().optional()
|
|
621
812
|
})).optional()
|
|
622
813
|
});
|
|
623
|
-
var AssignTaskWebappInputSchema =
|
|
624
|
-
taskId:
|
|
625
|
-
userId:
|
|
814
|
+
var AssignTaskWebappInputSchema = import_zod3.z.object({
|
|
815
|
+
taskId: import_zod3.z.string().min(1),
|
|
816
|
+
userId: import_zod3.z.string().min(1)
|
|
626
817
|
});
|
|
627
|
-
var CreateTagInputSchema =
|
|
818
|
+
var CreateTagInputSchema = import_zod3.z.object({
|
|
628
819
|
organizationId: cuidOrPrefixedId,
|
|
629
|
-
name:
|
|
820
|
+
name: import_zod3.z.string().min(1).max(50).regex(/^[a-zA-Z0-9\s-]+$/)
|
|
630
821
|
});
|
|
631
|
-
var UpdateTagInputSchema =
|
|
632
|
-
name:
|
|
822
|
+
var UpdateTagInputSchema = import_zod3.z.object({
|
|
823
|
+
name: import_zod3.z.string().min(1).max(50).regex(/^[a-zA-Z0-9\s-]+$/)
|
|
633
824
|
});
|
|
634
|
-
var UpdateOrganizationSettingsInputSchema =
|
|
825
|
+
var UpdateOrganizationSettingsInputSchema = import_zod3.z.object({
|
|
635
826
|
organizationId: cuidOrPrefixedId,
|
|
636
|
-
ldapEnabled:
|
|
637
|
-
ldapUrl:
|
|
638
|
-
ldapBindDN:
|
|
639
|
-
ldapSearchBase:
|
|
640
|
-
deleteMergedBranches:
|
|
641
|
-
enforceConventionalCommits:
|
|
642
|
-
maxPersonalProjectsPerUser:
|
|
643
|
-
logoUrl:
|
|
644
|
-
accentColor:
|
|
645
|
-
tenantName:
|
|
646
|
-
});
|
|
647
|
-
var InviteUserInputSchema =
|
|
827
|
+
ldapEnabled: import_zod3.z.boolean().optional(),
|
|
828
|
+
ldapUrl: import_zod3.z.string().url().nullable().optional(),
|
|
829
|
+
ldapBindDN: import_zod3.z.string().nullable().optional(),
|
|
830
|
+
ldapSearchBase: import_zod3.z.string().nullable().optional(),
|
|
831
|
+
deleteMergedBranches: import_zod3.z.boolean().optional(),
|
|
832
|
+
enforceConventionalCommits: import_zod3.z.boolean().optional(),
|
|
833
|
+
maxPersonalProjectsPerUser: import_zod3.z.number().int().min(0).optional(),
|
|
834
|
+
logoUrl: import_zod3.z.string().url().nullable().optional(),
|
|
835
|
+
accentColor: import_zod3.z.string().regex(/^#[0-9A-Fa-f]{6}$/, "Invalid hex color format. Expected #RRGGBB").nullable().optional(),
|
|
836
|
+
tenantName: import_zod3.z.string().max(255).nullable().optional()
|
|
837
|
+
});
|
|
838
|
+
var InviteUserInputSchema = import_zod3.z.object({
|
|
648
839
|
organizationId: cuidOrPrefixedId,
|
|
649
|
-
email:
|
|
650
|
-
role:
|
|
651
|
-
tags:
|
|
840
|
+
email: import_zod3.z.string().email(),
|
|
841
|
+
role: import_zod3.z.nativeEnum(UserRole).default(UserRole.MEMBER),
|
|
842
|
+
tags: import_zod3.z.array(import_zod3.z.string()).default([])
|
|
652
843
|
});
|
|
653
|
-
var AssignUserTagsInputSchema =
|
|
844
|
+
var AssignUserTagsInputSchema = import_zod3.z.object({
|
|
654
845
|
userId: cuidOrPrefixedId,
|
|
655
|
-
tags:
|
|
846
|
+
tags: import_zod3.z.array(import_zod3.z.string()).min(0)
|
|
656
847
|
});
|
|
657
|
-
var InviteCollaboratorInputSchema =
|
|
848
|
+
var InviteCollaboratorInputSchema = import_zod3.z.object({
|
|
658
849
|
projectId: cuidOrPrefixedId,
|
|
659
|
-
email:
|
|
850
|
+
email: import_zod3.z.string().email()
|
|
660
851
|
});
|
|
661
|
-
var PublishProjectInputSchema =
|
|
852
|
+
var PublishProjectInputSchema = import_zod3.z.object({
|
|
662
853
|
projectId: cuidOrPrefixedId,
|
|
663
|
-
transferOwnership:
|
|
664
|
-
tags:
|
|
854
|
+
transferOwnership: import_zod3.z.boolean().default(false),
|
|
855
|
+
tags: import_zod3.z.array(import_zod3.z.string()).min(1)
|
|
856
|
+
});
|
|
857
|
+
var GenerateApiKeyInputSchema = import_zod3.z.object({
|
|
858
|
+
name: import_zod3.z.string().min(1).max(100),
|
|
859
|
+
publicNickname: import_zod3.z.string().max(50).optional(),
|
|
860
|
+
expiresInDays: import_zod3.z.number().int().min(1).max(365).default(90),
|
|
861
|
+
permissions: import_zod3.z.nativeEnum(ApiKeyPermission).default(ApiKeyPermission.WRITE)
|
|
665
862
|
});
|
|
666
|
-
var
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
863
|
+
var UpdateApiKeyInputSchema = import_zod3.z.object({
|
|
864
|
+
publicNickname: import_zod3.z.string().max(50).nullable().optional(),
|
|
865
|
+
scopedOrganizationId: import_zod3.z.string().optional().nullable(),
|
|
866
|
+
scopedProjectIds: import_zod3.z.array(import_zod3.z.string()).optional()
|
|
670
867
|
});
|
|
671
|
-
var RevokeApiKeyInputSchema =
|
|
868
|
+
var RevokeApiKeyInputSchema = import_zod3.z.object({
|
|
672
869
|
keyId: cuidOrPrefixedId
|
|
673
870
|
});
|
|
674
|
-
var LoginInputSchema =
|
|
675
|
-
email:
|
|
676
|
-
password:
|
|
871
|
+
var LoginInputSchema = import_zod3.z.object({
|
|
872
|
+
email: import_zod3.z.string().email(),
|
|
873
|
+
password: import_zod3.z.string().min(8).max(255)
|
|
677
874
|
});
|
|
678
|
-
var RegisterInputSchema =
|
|
679
|
-
email:
|
|
680
|
-
password:
|
|
681
|
-
name:
|
|
682
|
-
organizationSlug: import_zod2.z.string().min(1).max(100).regex(/^[a-z0-9-]+$/).optional()
|
|
875
|
+
var RegisterInputSchema = import_zod3.z.object({
|
|
876
|
+
email: import_zod3.z.string().email(),
|
|
877
|
+
password: import_zod3.z.string().min(8).max(255),
|
|
878
|
+
name: import_zod3.z.string().min(1).max(255)
|
|
683
879
|
});
|
|
684
|
-
var VerifyTaskInputSchema =
|
|
880
|
+
var VerifyTaskInputSchema = import_zod3.z.object({
|
|
685
881
|
projectId: cuidOrPrefixedId,
|
|
686
882
|
taskId: cuidOrPrefixedId,
|
|
687
|
-
approved:
|
|
688
|
-
feedback:
|
|
883
|
+
approved: import_zod3.z.boolean(),
|
|
884
|
+
feedback: import_zod3.z.string().max(5e3).optional()
|
|
689
885
|
});
|
|
690
|
-
var GetTaskPromptInputSchema =
|
|
886
|
+
var GetTaskPromptInputSchema = import_zod3.z.object({
|
|
691
887
|
projectId: cuidOrPrefixedId,
|
|
692
888
|
taskId: cuidOrPrefixedId
|
|
693
889
|
});
|
|
694
|
-
var UpdateTaskMCPInputSchema =
|
|
890
|
+
var UpdateTaskMCPInputSchema = import_zod3.z.object({
|
|
695
891
|
projectId: cuidOrPrefixedId,
|
|
696
892
|
taskId: cuidOrPrefixedId,
|
|
697
|
-
title:
|
|
698
|
-
description:
|
|
699
|
-
priority:
|
|
700
|
-
acceptanceCriteria:
|
|
701
|
-
id:
|
|
702
|
-
description:
|
|
893
|
+
title: import_zod3.z.string().min(1).max(200).optional(),
|
|
894
|
+
description: import_zod3.z.string().max(5e3).optional(),
|
|
895
|
+
priority: import_zod3.z.nativeEnum(TaskPriority).optional(),
|
|
896
|
+
acceptanceCriteria: import_zod3.z.array(import_zod3.z.object({
|
|
897
|
+
id: import_zod3.z.string().optional(),
|
|
898
|
+
description: import_zod3.z.string().min(1).max(500)
|
|
703
899
|
})).optional()
|
|
704
900
|
});
|
|
705
|
-
var ReportBranchInputSchema =
|
|
901
|
+
var ReportBranchInputSchema = import_zod3.z.object({
|
|
706
902
|
projectId: cuidOrPrefixedId,
|
|
707
903
|
taskId: cuidOrPrefixedId,
|
|
708
904
|
branchName: gitBranchName
|
|
709
905
|
});
|
|
710
|
-
var ReportPRInputSchema =
|
|
906
|
+
var ReportPRInputSchema = import_zod3.z.object({
|
|
711
907
|
projectId: cuidOrPrefixedId,
|
|
712
908
|
taskId: cuidOrPrefixedId,
|
|
713
|
-
pullRequestUrl:
|
|
714
|
-
pullRequestNumber:
|
|
909
|
+
pullRequestUrl: import_zod3.z.string().url(),
|
|
910
|
+
pullRequestNumber: import_zod3.z.number().int().positive()
|
|
715
911
|
});
|
|
716
912
|
|
|
717
913
|
// ../../packages/core/dist/logging/metrics.js
|
|
@@ -792,23 +988,16 @@ function createHistogram(name, help, buckets = [5e-3, 0.01, 0.025, 0.05, 0.1, 0.
|
|
|
792
988
|
var httpRequestsTotal = createCounter("mtaap_http_requests_total", "Total number of HTTP requests");
|
|
793
989
|
var httpRequestDuration = createHistogram("mtaap_http_request_duration_seconds", "HTTP request duration in seconds");
|
|
794
990
|
var activeUsers = createGauge("mtaap_active_users", "Number of active users");
|
|
795
|
-
var tasksTotal = createCounter("mtaap_tasks_total", "Total number of tasks by state");
|
|
796
|
-
var taskStateChanges = createCounter("mtaap_task_state_changes_total", "Total number of task state changes");
|
|
797
991
|
var httpErrorsTotal = createCounter("mtaap_http_errors_total", "Total number of HTTP errors");
|
|
798
992
|
var httpActiveConnections = createGauge("mtaap_http_active_connections", "Number of active HTTP connections");
|
|
799
993
|
var newSignupsTotal = createCounter("mtaap_new_signups_total", "Total number of new user signups");
|
|
800
994
|
var loginSuccessTotal = createCounter("mtaap_login_success_total", "Total number of successful logins");
|
|
801
995
|
var loginFailureTotal = createCounter("mtaap_login_failure_total", "Total number of failed logins");
|
|
802
|
-
var dbConnectionPoolActive = createGauge("mtaap_db_connection_pool_active", "Number of active database connections");
|
|
803
|
-
var dbConnectionPoolIdle = createGauge("mtaap_db_connection_pool_idle", "Number of idle database connections");
|
|
804
|
-
var dbConnectionPoolMax = createGauge("mtaap_db_connection_pool_max", "Maximum number of database connections");
|
|
805
996
|
var dbQueryDuration = createHistogram("mtaap_db_query_duration_seconds", "Database query duration in seconds");
|
|
806
997
|
var dbSlowQueriesTotal = createCounter("mtaap_db_slow_queries_total", "Total number of slow database queries (>1s)");
|
|
807
|
-
var dbErrorsTotal = createCounter("mtaap_db_errors_total", "Total number of database errors");
|
|
808
998
|
var tasksCreatedTotal = createCounter("mtaap_tasks_created_total", "Total number of tasks created");
|
|
809
999
|
var tasksAssignedTotal = createCounter("mtaap_tasks_assigned_total", "Total number of tasks assigned");
|
|
810
1000
|
var tasksCompletedTotal = createCounter("mtaap_tasks_completed_total", "Total number of tasks completed");
|
|
811
|
-
var tasksByState = createGauge("mtaap_tasks_by_state", "Number of tasks by state");
|
|
812
1001
|
|
|
813
1002
|
// ../../packages/core/dist/logging/performance-monitor.js
|
|
814
1003
|
var MAX_SAMPLES = 1e3;
|
|
@@ -1030,12 +1219,17 @@ var ApiError = class extends Error {
|
|
|
1030
1219
|
var MCPApiClient = class {
|
|
1031
1220
|
baseUrl;
|
|
1032
1221
|
apiKey;
|
|
1222
|
+
oauthToken;
|
|
1033
1223
|
timeout;
|
|
1034
1224
|
debug;
|
|
1035
1225
|
authContext = null;
|
|
1036
1226
|
constructor(config3) {
|
|
1227
|
+
if (!config3.apiKey && !config3.oauthToken) {
|
|
1228
|
+
throw new Error("Either apiKey or oauthToken must be provided");
|
|
1229
|
+
}
|
|
1037
1230
|
this.baseUrl = config3.baseUrl.replace(/\/$/, "");
|
|
1038
1231
|
this.apiKey = config3.apiKey;
|
|
1232
|
+
this.oauthToken = config3.oauthToken;
|
|
1039
1233
|
this.timeout = config3.timeout ?? DEFAULT_TIMEOUT;
|
|
1040
1234
|
this.debug = config3.debug ?? false;
|
|
1041
1235
|
}
|
|
@@ -1050,18 +1244,33 @@ var MCPApiClient = class {
|
|
|
1050
1244
|
console.error(`[mcp-api] ${method} ${sanitizeForLogging(path)}`);
|
|
1051
1245
|
}
|
|
1052
1246
|
try {
|
|
1247
|
+
const headers = {
|
|
1248
|
+
"Content-Type": "application/json"
|
|
1249
|
+
};
|
|
1250
|
+
if (this.oauthToken) {
|
|
1251
|
+
headers["Authorization"] = `Bearer ${this.oauthToken}`;
|
|
1252
|
+
} else if (this.apiKey) {
|
|
1253
|
+
headers["X-API-Key"] = this.apiKey;
|
|
1254
|
+
}
|
|
1053
1255
|
const response = await fetch(url, {
|
|
1054
1256
|
method,
|
|
1055
|
-
headers
|
|
1056
|
-
"Content-Type": "application/json",
|
|
1057
|
-
"X-API-Key": this.apiKey
|
|
1058
|
-
},
|
|
1257
|
+
headers,
|
|
1059
1258
|
body: body ? JSON.stringify(body) : void 0,
|
|
1060
1259
|
signal: controller.signal
|
|
1061
1260
|
});
|
|
1062
1261
|
clearTimeout(timeoutId);
|
|
1063
1262
|
const data = await response.json();
|
|
1064
1263
|
if (!response.ok) {
|
|
1264
|
+
if (response.status === 403 && data.code === "EMAIL_NOT_VERIFIED" && data.verificationUrl) {
|
|
1265
|
+
throw new ApiError(
|
|
1266
|
+
`${data.error}
|
|
1267
|
+
|
|
1268
|
+
To verify your email, visit: ${data.verificationUrl}
|
|
1269
|
+
${data.hint ? `Hint: ${data.hint}` : ""}`,
|
|
1270
|
+
"EMAIL_NOT_VERIFIED",
|
|
1271
|
+
403
|
|
1272
|
+
);
|
|
1273
|
+
}
|
|
1065
1274
|
throw new ApiError(
|
|
1066
1275
|
data.error || "API request failed",
|
|
1067
1276
|
data.code || "UNKNOWN_ERROR",
|
|
@@ -1309,7 +1518,7 @@ var PERMISSION_RANK = {
|
|
|
1309
1518
|
ADMIN: 3
|
|
1310
1519
|
};
|
|
1311
1520
|
function assertApiKeyPermission(apiKey, required, toolName) {
|
|
1312
|
-
const actualRank = PERMISSION_RANK[apiKey.permissions] ?? 0;
|
|
1521
|
+
const actualRank = apiKey.permissions ? PERMISSION_RANK[apiKey.permissions] ?? 0 : 0;
|
|
1313
1522
|
const requiredRank = PERMISSION_RANK[required] ?? 0;
|
|
1314
1523
|
if (actualRank >= requiredRank) {
|
|
1315
1524
|
return;
|
|
@@ -1430,7 +1639,7 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1430
1639
|
{
|
|
1431
1640
|
description: "Discover all accessible projects. Use first to find project IDs. Filter by TEAM, PERSONAL, or ALL workspaces.",
|
|
1432
1641
|
inputSchema: {
|
|
1433
|
-
workspaceType:
|
|
1642
|
+
workspaceType: import_zod4.z.enum(["TEAM", "PERSONAL", "ALL"]).optional().describe("Filter by workspace type")
|
|
1434
1643
|
}
|
|
1435
1644
|
},
|
|
1436
1645
|
async (args) => {
|
|
@@ -1460,10 +1669,10 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1460
1669
|
{
|
|
1461
1670
|
description: "Query tasks with filters. Use state=TODO for assignable tasks, state=REVIEW for pending reviews.",
|
|
1462
1671
|
inputSchema: {
|
|
1463
|
-
projectId:
|
|
1464
|
-
state:
|
|
1465
|
-
assigneeId:
|
|
1466
|
-
includeArchived:
|
|
1672
|
+
projectId: import_zod4.z.string().optional().describe("Filter by project ID"),
|
|
1673
|
+
state: import_zod4.z.nativeEnum(TaskState).optional().describe("Filter by task state"),
|
|
1674
|
+
assigneeId: import_zod4.z.string().optional().describe("Filter by assignee ID"),
|
|
1675
|
+
includeArchived: import_zod4.z.boolean().optional().describe("Include archived tasks (default: false)")
|
|
1467
1676
|
}
|
|
1468
1677
|
},
|
|
1469
1678
|
async (args) => {
|
|
@@ -1494,7 +1703,7 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1494
1703
|
{
|
|
1495
1704
|
description: "Get complete task details with acceptance criteria and notes. Call before assign_task to understand requirements.",
|
|
1496
1705
|
inputSchema: {
|
|
1497
|
-
taskId:
|
|
1706
|
+
taskId: import_zod4.z.string().describe("The task ID to retrieve")
|
|
1498
1707
|
}
|
|
1499
1708
|
},
|
|
1500
1709
|
async (args) => {
|
|
@@ -1520,9 +1729,9 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1520
1729
|
{
|
|
1521
1730
|
description: "Atomically claim a task. Race-safe - fails if already assigned. Task must be TODO. Returns suggested branch name and worktree path for isolated parallel development.",
|
|
1522
1731
|
inputSchema: {
|
|
1523
|
-
projectId:
|
|
1524
|
-
taskId:
|
|
1525
|
-
expectedState:
|
|
1732
|
+
projectId: import_zod4.z.string().describe("The project ID"),
|
|
1733
|
+
taskId: import_zod4.z.string().describe("The task ID to assign"),
|
|
1734
|
+
expectedState: import_zod4.z.nativeEnum(TaskState).optional().describe("Expected task state (default: TODO)")
|
|
1526
1735
|
}
|
|
1527
1736
|
},
|
|
1528
1737
|
async (args) => {
|
|
@@ -1556,10 +1765,10 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1556
1765
|
{
|
|
1557
1766
|
description: "Report progress and checkpoint work. Call frequently during execution. Marks acceptance criteria complete.",
|
|
1558
1767
|
inputSchema: {
|
|
1559
|
-
taskId:
|
|
1560
|
-
statusMessage:
|
|
1561
|
-
completedCheckpointIds:
|
|
1562
|
-
currentCheckpointIndex:
|
|
1768
|
+
taskId: import_zod4.z.string().describe("The task ID to update"),
|
|
1769
|
+
statusMessage: import_zod4.z.string().optional().describe("Status message (max 1000 chars)"),
|
|
1770
|
+
completedCheckpointIds: import_zod4.z.array(import_zod4.z.string()).optional().describe("Array of completed checkpoint IDs"),
|
|
1771
|
+
currentCheckpointIndex: import_zod4.z.number().optional().describe("Current checkpoint index")
|
|
1563
1772
|
}
|
|
1564
1773
|
},
|
|
1565
1774
|
async (args) => {
|
|
@@ -1593,10 +1802,10 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1593
1802
|
{
|
|
1594
1803
|
description: "Prepare task for PR creation. Returns PR suggestions. After creating PR locally, call report_pr to transition to REVIEW. Requires IN_PROGRESS state.",
|
|
1595
1804
|
inputSchema: {
|
|
1596
|
-
projectId:
|
|
1597
|
-
taskId:
|
|
1598
|
-
pullRequestTitle:
|
|
1599
|
-
pullRequestBody:
|
|
1805
|
+
projectId: import_zod4.z.string().describe("The project ID"),
|
|
1806
|
+
taskId: import_zod4.z.string().describe("The task ID to complete"),
|
|
1807
|
+
pullRequestTitle: import_zod4.z.string().optional().describe("PR title (max 300 chars)"),
|
|
1808
|
+
pullRequestBody: import_zod4.z.string().optional().describe("PR body/description (max 10000 chars)")
|
|
1600
1809
|
}
|
|
1601
1810
|
},
|
|
1602
1811
|
async (args) => {
|
|
@@ -1653,10 +1862,10 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1653
1862
|
{
|
|
1654
1863
|
description: "Report unrecoverable errors (BUILD_FAILURE, TEST_FAILURE, CONFLICT, AUTH_ERROR). Consider abandon_task after.",
|
|
1655
1864
|
inputSchema: {
|
|
1656
|
-
taskId:
|
|
1657
|
-
errorType:
|
|
1658
|
-
errorMessage:
|
|
1659
|
-
context:
|
|
1865
|
+
taskId: import_zod4.z.string().describe("The task ID"),
|
|
1866
|
+
errorType: import_zod4.z.nativeEnum(ErrorType).describe("Error type: BUILD_FAILURE, TEST_FAILURE, CONFLICT, AUTH_ERROR, OTHER"),
|
|
1867
|
+
errorMessage: import_zod4.z.string().describe("Error message (max 1000 chars)"),
|
|
1868
|
+
context: import_zod4.z.string().optional().describe("Additional context (max 2000 chars)")
|
|
1660
1869
|
}
|
|
1661
1870
|
},
|
|
1662
1871
|
async (args) => {
|
|
@@ -1691,7 +1900,7 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1691
1900
|
{
|
|
1692
1901
|
description: "Load project README, tech stack, and coding conventions. Call after selecting project.",
|
|
1693
1902
|
inputSchema: {
|
|
1694
|
-
projectId:
|
|
1903
|
+
projectId: import_zod4.z.string().describe("The project ID")
|
|
1695
1904
|
}
|
|
1696
1905
|
},
|
|
1697
1906
|
async (args) => {
|
|
@@ -1721,8 +1930,8 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1721
1930
|
{
|
|
1722
1931
|
description: "Document implementation decisions. Notes persist for future reference and handoff.",
|
|
1723
1932
|
inputSchema: {
|
|
1724
|
-
taskId:
|
|
1725
|
-
content:
|
|
1933
|
+
taskId: import_zod4.z.string().describe("The task ID"),
|
|
1934
|
+
content: import_zod4.z.string().describe("Note content (max 500 chars)")
|
|
1726
1935
|
}
|
|
1727
1936
|
},
|
|
1728
1937
|
async (args) => {
|
|
@@ -1751,9 +1960,9 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1751
1960
|
{
|
|
1752
1961
|
description: "Release task assignment and optionally clean up branch. Task returns to TODO. Use after errors.",
|
|
1753
1962
|
inputSchema: {
|
|
1754
|
-
projectId:
|
|
1755
|
-
taskId:
|
|
1756
|
-
deleteBranch:
|
|
1963
|
+
projectId: import_zod4.z.string().describe("The project ID"),
|
|
1964
|
+
taskId: import_zod4.z.string().describe("The task ID to abandon"),
|
|
1965
|
+
deleteBranch: import_zod4.z.boolean().optional().describe("Whether to delete the associated branch")
|
|
1757
1966
|
}
|
|
1758
1967
|
},
|
|
1759
1968
|
async (args) => {
|
|
@@ -1787,9 +1996,9 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1787
1996
|
{
|
|
1788
1997
|
description: "Report a branch created by the agent. Call after using git to create and push a branch. Task must be IN_PROGRESS.",
|
|
1789
1998
|
inputSchema: {
|
|
1790
|
-
projectId:
|
|
1791
|
-
taskId:
|
|
1792
|
-
branchName:
|
|
1999
|
+
projectId: import_zod4.z.string().describe("The project ID"),
|
|
2000
|
+
taskId: import_zod4.z.string().describe("The task ID"),
|
|
2001
|
+
branchName: import_zod4.z.string().describe("Name of the branch created (e.g., feature/TASK-123-fix-login)")
|
|
1793
2002
|
}
|
|
1794
2003
|
},
|
|
1795
2004
|
async (args) => {
|
|
@@ -1823,10 +2032,10 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1823
2032
|
{
|
|
1824
2033
|
description: "Report a PR created by the agent. Call after using gh pr create. Transitions task to REVIEW state.",
|
|
1825
2034
|
inputSchema: {
|
|
1826
|
-
projectId:
|
|
1827
|
-
taskId:
|
|
1828
|
-
pullRequestUrl:
|
|
1829
|
-
pullRequestNumber:
|
|
2035
|
+
projectId: import_zod4.z.string().describe("The project ID"),
|
|
2036
|
+
taskId: import_zod4.z.string().describe("The task ID"),
|
|
2037
|
+
pullRequestUrl: import_zod4.z.string().describe("Full URL of the created PR (e.g., https://github.com/owner/repo/pull/123)"),
|
|
2038
|
+
pullRequestNumber: import_zod4.z.number().describe("PR number (e.g., 123)")
|
|
1830
2039
|
}
|
|
1831
2040
|
},
|
|
1832
2041
|
async (args) => {
|
|
@@ -1861,8 +2070,8 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1861
2070
|
{
|
|
1862
2071
|
description: "Soft-delete a task. Hidden but restorable via unarchive_task.",
|
|
1863
2072
|
inputSchema: {
|
|
1864
|
-
projectId:
|
|
1865
|
-
taskId:
|
|
2073
|
+
projectId: import_zod4.z.string().describe("The project ID"),
|
|
2074
|
+
taskId: import_zod4.z.string().describe("The task ID to archive")
|
|
1866
2075
|
}
|
|
1867
2076
|
},
|
|
1868
2077
|
async (args) => {
|
|
@@ -1895,8 +2104,8 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1895
2104
|
{
|
|
1896
2105
|
description: "Restore previously archived task to original state.",
|
|
1897
2106
|
inputSchema: {
|
|
1898
|
-
projectId:
|
|
1899
|
-
taskId:
|
|
2107
|
+
projectId: import_zod4.z.string().describe("The project ID"),
|
|
2108
|
+
taskId: import_zod4.z.string().describe("The task ID to restore")
|
|
1900
2109
|
}
|
|
1901
2110
|
},
|
|
1902
2111
|
async (args) => {
|
|
@@ -1929,9 +2138,9 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1929
2138
|
{
|
|
1930
2139
|
description: "Create new project in personal workspace linked to GitHub repository.",
|
|
1931
2140
|
inputSchema: {
|
|
1932
|
-
name:
|
|
1933
|
-
description:
|
|
1934
|
-
repositoryUrl:
|
|
2141
|
+
name: import_zod4.z.string().describe("Project name (max 100 chars)"),
|
|
2142
|
+
description: import_zod4.z.string().optional().describe("Project description (max 500 chars)"),
|
|
2143
|
+
repositoryUrl: import_zod4.z.string().describe("GitHub repository URL")
|
|
1935
2144
|
}
|
|
1936
2145
|
},
|
|
1937
2146
|
async (args) => {
|
|
@@ -1965,14 +2174,14 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
1965
2174
|
{
|
|
1966
2175
|
description: "Create task with title, description, acceptance criteria. Starts in DRAFT. Priority: LOW/MEDIUM/HIGH/CRITICAL.",
|
|
1967
2176
|
inputSchema: {
|
|
1968
|
-
projectId:
|
|
1969
|
-
epicId:
|
|
1970
|
-
title:
|
|
1971
|
-
description:
|
|
1972
|
-
priority:
|
|
1973
|
-
acceptanceCriteria:
|
|
1974
|
-
|
|
1975
|
-
description:
|
|
2177
|
+
projectId: import_zod4.z.string().describe("The project ID to create the task in"),
|
|
2178
|
+
epicId: import_zod4.z.string().nullable().optional().describe("Optional epic ID to associate the task with"),
|
|
2179
|
+
title: import_zod4.z.string().describe("Task title (max 200 chars)"),
|
|
2180
|
+
description: import_zod4.z.string().describe("Task description (max 5000 chars)"),
|
|
2181
|
+
priority: import_zod4.z.nativeEnum(TaskPriority).optional().describe("Task priority: LOW, MEDIUM, HIGH, CRITICAL (default: MEDIUM)"),
|
|
2182
|
+
acceptanceCriteria: import_zod4.z.array(
|
|
2183
|
+
import_zod4.z.object({
|
|
2184
|
+
description: import_zod4.z.string().describe("Acceptance criterion description (max 500 chars)")
|
|
1976
2185
|
})
|
|
1977
2186
|
).describe("Array of acceptance criteria (at least 1 required)")
|
|
1978
2187
|
}
|
|
@@ -2011,10 +2220,10 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
2011
2220
|
{
|
|
2012
2221
|
description: "Return task from REVIEW to IN_PROGRESS with feedback. Original assignee addresses changes.",
|
|
2013
2222
|
inputSchema: {
|
|
2014
|
-
projectId:
|
|
2015
|
-
taskId:
|
|
2016
|
-
reviewComments:
|
|
2017
|
-
requestedChanges:
|
|
2223
|
+
projectId: import_zod4.z.string().describe("The project ID"),
|
|
2224
|
+
taskId: import_zod4.z.string().describe("The task ID to review"),
|
|
2225
|
+
reviewComments: import_zod4.z.string().describe("Review comments explaining requested changes (max 5000 chars)"),
|
|
2226
|
+
requestedChanges: import_zod4.z.array(import_zod4.z.string()).optional().describe("List of specific changes requested")
|
|
2018
2227
|
}
|
|
2019
2228
|
},
|
|
2020
2229
|
async (args) => {
|
|
@@ -2049,9 +2258,9 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
2049
2258
|
{
|
|
2050
2259
|
description: "Approve completed work and mark DONE. Only for REVIEW state tasks.",
|
|
2051
2260
|
inputSchema: {
|
|
2052
|
-
projectId:
|
|
2053
|
-
taskId:
|
|
2054
|
-
reviewComments:
|
|
2261
|
+
projectId: import_zod4.z.string().describe("The project ID"),
|
|
2262
|
+
taskId: import_zod4.z.string().describe("The task ID to approve"),
|
|
2263
|
+
reviewComments: import_zod4.z.string().optional().describe("Optional approval comments (max 2000 chars)")
|
|
2055
2264
|
}
|
|
2056
2265
|
},
|
|
2057
2266
|
async (args) => {
|
|
@@ -2085,10 +2294,10 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
2085
2294
|
{
|
|
2086
2295
|
description: "Verify a DRAFT task and move it to TODO state. Requires task to pass programmatic validation (title 10+ chars, description 50+ chars, each criterion 20+ chars). If approved=false, stores feedback with NEEDS_REVISION status.",
|
|
2087
2296
|
inputSchema: {
|
|
2088
|
-
projectId:
|
|
2089
|
-
taskId:
|
|
2090
|
-
approved:
|
|
2091
|
-
feedback:
|
|
2297
|
+
projectId: import_zod4.z.string().describe("The project ID"),
|
|
2298
|
+
taskId: import_zod4.z.string().describe("The task ID to verify"),
|
|
2299
|
+
approved: import_zod4.z.boolean().describe("Whether to approve the task"),
|
|
2300
|
+
feedback: import_zod4.z.string().optional().describe("Feedback for the task (required if not approved)")
|
|
2092
2301
|
}
|
|
2093
2302
|
},
|
|
2094
2303
|
async (args) => {
|
|
@@ -2119,8 +2328,8 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
2119
2328
|
{
|
|
2120
2329
|
description: "Get state-appropriate prompt for a task. Returns verify prompt for DRAFT, assignment prompt for TODO, or continue prompt for IN_PROGRESS tasks.",
|
|
2121
2330
|
inputSchema: {
|
|
2122
|
-
projectId:
|
|
2123
|
-
taskId:
|
|
2331
|
+
projectId: import_zod4.z.string().describe("The project ID"),
|
|
2332
|
+
taskId: import_zod4.z.string().describe("The task ID")
|
|
2124
2333
|
}
|
|
2125
2334
|
},
|
|
2126
2335
|
async (args) => {
|
|
@@ -2153,15 +2362,15 @@ function initializeMCPServer(apiClient, authContext) {
|
|
|
2153
2362
|
{
|
|
2154
2363
|
description: "Update task details (title, description, priority, acceptanceCriteria). Only works for DRAFT and TODO states. If task is in TODO state, it reverts to DRAFT and requires re-verification.",
|
|
2155
2364
|
inputSchema: {
|
|
2156
|
-
projectId:
|
|
2157
|
-
taskId:
|
|
2158
|
-
title:
|
|
2159
|
-
description:
|
|
2160
|
-
priority:
|
|
2161
|
-
acceptanceCriteria:
|
|
2162
|
-
|
|
2163
|
-
id:
|
|
2164
|
-
description:
|
|
2365
|
+
projectId: import_zod4.z.string().describe("The project ID"),
|
|
2366
|
+
taskId: import_zod4.z.string().describe("The task ID to update"),
|
|
2367
|
+
title: import_zod4.z.string().optional().describe("New task title"),
|
|
2368
|
+
description: import_zod4.z.string().optional().describe("New task description"),
|
|
2369
|
+
priority: import_zod4.z.nativeEnum(TaskPriority).optional().describe("New task priority"),
|
|
2370
|
+
acceptanceCriteria: import_zod4.z.array(
|
|
2371
|
+
import_zod4.z.object({
|
|
2372
|
+
id: import_zod4.z.string().optional().describe("Existing criterion ID (for updates)"),
|
|
2373
|
+
description: import_zod4.z.string().describe("Criterion description")
|
|
2165
2374
|
})
|
|
2166
2375
|
).optional().describe("New acceptance criteria (replaces existing)")
|
|
2167
2376
|
}
|
|
@@ -2251,12 +2460,12 @@ function handleApiError(error) {
|
|
|
2251
2460
|
isError: true
|
|
2252
2461
|
};
|
|
2253
2462
|
}
|
|
2254
|
-
var ActiveTaskSchema =
|
|
2255
|
-
taskId:
|
|
2256
|
-
projectId:
|
|
2257
|
-
branchName:
|
|
2258
|
-
worktreePath:
|
|
2259
|
-
startedAt:
|
|
2463
|
+
var ActiveTaskSchema = import_zod4.z.object({
|
|
2464
|
+
taskId: import_zod4.z.string().min(1),
|
|
2465
|
+
projectId: import_zod4.z.string().min(1),
|
|
2466
|
+
branchName: import_zod4.z.string().optional(),
|
|
2467
|
+
worktreePath: import_zod4.z.string().optional(),
|
|
2468
|
+
startedAt: import_zod4.z.string().optional()
|
|
2260
2469
|
});
|
|
2261
2470
|
async function checkActiveTask() {
|
|
2262
2471
|
const fs = await import("fs");
|
|
@@ -2327,15 +2536,91 @@ async function checkActiveTask() {
|
|
|
2327
2536
|
}
|
|
2328
2537
|
|
|
2329
2538
|
// src/auth.ts
|
|
2539
|
+
function extractBearerToken(authorizationHeader) {
|
|
2540
|
+
if (!authorizationHeader) return null;
|
|
2541
|
+
const parts = authorizationHeader.split(" ");
|
|
2542
|
+
if (parts.length !== 2 || parts[0].toLowerCase() !== "bearer") {
|
|
2543
|
+
return null;
|
|
2544
|
+
}
|
|
2545
|
+
return parts[1];
|
|
2546
|
+
}
|
|
2547
|
+
async function validateOAuthToken(baseUrl, accessToken) {
|
|
2548
|
+
const internalUrl = process.env.COLLAB_INTERNAL_URL || baseUrl;
|
|
2549
|
+
const response = await fetch(`${internalUrl}/api/oauth/validate`, {
|
|
2550
|
+
method: "POST",
|
|
2551
|
+
headers: {
|
|
2552
|
+
"Content-Type": "application/json"
|
|
2553
|
+
},
|
|
2554
|
+
body: JSON.stringify({ access_token: accessToken })
|
|
2555
|
+
});
|
|
2556
|
+
if (!response.ok) {
|
|
2557
|
+
throw new Error(`Token validation failed: ${response.status}`);
|
|
2558
|
+
}
|
|
2559
|
+
return response.json();
|
|
2560
|
+
}
|
|
2330
2561
|
function createAuthMiddleware(baseUrl) {
|
|
2331
2562
|
return async (req, res, next) => {
|
|
2563
|
+
const authHeader = req.headers.authorization;
|
|
2564
|
+
const bearerToken = extractBearerToken(authHeader);
|
|
2565
|
+
if (bearerToken) {
|
|
2566
|
+
try {
|
|
2567
|
+
const validation = await validateOAuthToken(baseUrl, bearerToken);
|
|
2568
|
+
if (!validation.valid) {
|
|
2569
|
+
res.status(401).json({
|
|
2570
|
+
jsonrpc: "2.0",
|
|
2571
|
+
error: {
|
|
2572
|
+
code: -32001,
|
|
2573
|
+
message: validation.userId ? "Token expired" : "Invalid access token"
|
|
2574
|
+
},
|
|
2575
|
+
id: null
|
|
2576
|
+
});
|
|
2577
|
+
return;
|
|
2578
|
+
}
|
|
2579
|
+
const rawPermissions = validation.permissions || "WRITE";
|
|
2580
|
+
const validPermissions = ["READ", "WRITE", "ADMIN"];
|
|
2581
|
+
let permissions;
|
|
2582
|
+
if (validPermissions.includes(rawPermissions)) {
|
|
2583
|
+
permissions = rawPermissions;
|
|
2584
|
+
} else {
|
|
2585
|
+
console.warn(`[collab-mcp-server] Unexpected permissions value "${rawPermissions}", defaulting to WRITE`);
|
|
2586
|
+
permissions = "WRITE";
|
|
2587
|
+
}
|
|
2588
|
+
const authContext = {
|
|
2589
|
+
userId: validation.userId,
|
|
2590
|
+
userEmail: validation.userEmail,
|
|
2591
|
+
userName: validation.userName || validation.userEmail,
|
|
2592
|
+
permissions
|
|
2593
|
+
};
|
|
2594
|
+
const apiClient = new MCPApiClient({
|
|
2595
|
+
baseUrl,
|
|
2596
|
+
oauthToken: bearerToken,
|
|
2597
|
+
timeout: 3e4
|
|
2598
|
+
});
|
|
2599
|
+
req.apiClient = apiClient;
|
|
2600
|
+
req.authContext = authContext;
|
|
2601
|
+
req.authMethod = "oauth";
|
|
2602
|
+
next();
|
|
2603
|
+
return;
|
|
2604
|
+
} catch (error) {
|
|
2605
|
+
console.error("[collab-mcp-server] OAuth validation error:", error);
|
|
2606
|
+
res.status(401).json({
|
|
2607
|
+
jsonrpc: "2.0",
|
|
2608
|
+
error: {
|
|
2609
|
+
code: -32001,
|
|
2610
|
+
message: "OAuth token validation failed"
|
|
2611
|
+
},
|
|
2612
|
+
id: null
|
|
2613
|
+
});
|
|
2614
|
+
return;
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2332
2617
|
const apiKey = req.headers["x-api-key"];
|
|
2333
2618
|
if (!apiKey || typeof apiKey !== "string") {
|
|
2334
2619
|
res.status(401).json({
|
|
2335
2620
|
jsonrpc: "2.0",
|
|
2336
2621
|
error: {
|
|
2337
2622
|
code: -32001,
|
|
2338
|
-
message: "Missing or
|
|
2623
|
+
message: "Missing authentication. Provide Authorization: Bearer <token> or X-API-Key header"
|
|
2339
2624
|
},
|
|
2340
2625
|
id: null
|
|
2341
2626
|
});
|
|
@@ -2361,6 +2646,7 @@ function createAuthMiddleware(baseUrl) {
|
|
|
2361
2646
|
const authContext = await apiClient.authenticate();
|
|
2362
2647
|
req.apiClient = apiClient;
|
|
2363
2648
|
req.authContext = authContext;
|
|
2649
|
+
req.authMethod = "api_key";
|
|
2364
2650
|
next();
|
|
2365
2651
|
} catch (error) {
|
|
2366
2652
|
if (error instanceof ApiError) {
|
|
@@ -2408,7 +2694,9 @@ function startSessionCleanup() {
|
|
|
2408
2694
|
}
|
|
2409
2695
|
}
|
|
2410
2696
|
if (cleanedCount > 0) {
|
|
2411
|
-
console.error(
|
|
2697
|
+
console.error(
|
|
2698
|
+
`[collab-mcp-server] Cleaned up ${cleanedCount} expired session(s)`
|
|
2699
|
+
);
|
|
2412
2700
|
}
|
|
2413
2701
|
}, SESSION_CLEANUP_INTERVAL_MS);
|
|
2414
2702
|
}
|
|
@@ -2423,17 +2711,27 @@ async function createHTTPServer() {
|
|
|
2423
2711
|
const port = parseInt(process.env.PORT || String(DEFAULT_PORT), 10);
|
|
2424
2712
|
const baseUrl = process.env.COLLAB_BASE_URL;
|
|
2425
2713
|
if (!baseUrl) {
|
|
2426
|
-
console.error(
|
|
2714
|
+
console.error(
|
|
2715
|
+
"[collab-mcp-server] Error: COLLAB_BASE_URL environment variable is required"
|
|
2716
|
+
);
|
|
2427
2717
|
console.error("\nRequired environment variables:");
|
|
2428
|
-
console.error(
|
|
2718
|
+
console.error(
|
|
2719
|
+
" COLLAB_BASE_URL Collab webapp URL (e.g., https://collab.mtaap.de)"
|
|
2720
|
+
);
|
|
2429
2721
|
console.error(" PORT Server port (default: 3001)");
|
|
2430
|
-
console.error("\nClients must
|
|
2722
|
+
console.error("\nClients must authenticate using one of:");
|
|
2723
|
+
console.error(
|
|
2724
|
+
" - Authorization: Bearer <token> header with OAuth access token"
|
|
2725
|
+
);
|
|
2726
|
+
console.error(" - X-API-Key header with their Collab API key");
|
|
2431
2727
|
process.exit(1);
|
|
2432
2728
|
}
|
|
2433
2729
|
try {
|
|
2434
2730
|
new URL(baseUrl);
|
|
2435
2731
|
} catch {
|
|
2436
|
-
console.error(
|
|
2732
|
+
console.error(
|
|
2733
|
+
`[collab-mcp-server] Error: COLLAB_BASE_URL is not a valid URL: ${baseUrl}`
|
|
2734
|
+
);
|
|
2437
2735
|
process.exit(1);
|
|
2438
2736
|
}
|
|
2439
2737
|
const app = (0, import_express.default)();
|
|
@@ -2446,6 +2744,22 @@ async function createHTTPServer() {
|
|
|
2446
2744
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2447
2745
|
});
|
|
2448
2746
|
});
|
|
2747
|
+
app.get("/mcp/.well-known/oauth-protected-resource", (_req, res) => {
|
|
2748
|
+
const protocol = _req.headers["x-forwarded-proto"] || _req.protocol || "https";
|
|
2749
|
+
const host = _req.headers["x-forwarded-host"] || _req.headers.host;
|
|
2750
|
+
const resourceUrl = `${protocol}://${host}/mcp`;
|
|
2751
|
+
res.json({
|
|
2752
|
+
resource: resourceUrl,
|
|
2753
|
+
authorization_servers: [baseUrl],
|
|
2754
|
+
scopes_supported: [
|
|
2755
|
+
OAuthScopes.READ,
|
|
2756
|
+
OAuthScopes.WRITE,
|
|
2757
|
+
OAuthScopes.ADMIN
|
|
2758
|
+
],
|
|
2759
|
+
bearer_methods_supported: ["header"],
|
|
2760
|
+
resource_documentation: `${baseUrl}/docs/mcp`
|
|
2761
|
+
});
|
|
2762
|
+
});
|
|
2449
2763
|
const authMiddleware = createAuthMiddleware(baseUrl);
|
|
2450
2764
|
app.post("/mcp", authMiddleware, async (req, res) => {
|
|
2451
2765
|
const authReq = req;
|
|
@@ -2477,7 +2791,9 @@ async function createHTTPServer() {
|
|
|
2477
2791
|
createdAt: now,
|
|
2478
2792
|
lastAccessedAt: now
|
|
2479
2793
|
});
|
|
2480
|
-
console.error(
|
|
2794
|
+
console.error(
|
|
2795
|
+
`[collab-mcp-server] Session initialized: ${id} (user: ${authReq.authContext.userEmail})`
|
|
2796
|
+
);
|
|
2481
2797
|
},
|
|
2482
2798
|
onsessionclosed: (id) => {
|
|
2483
2799
|
sessions.delete(id);
|
|
@@ -2487,10 +2803,15 @@ async function createHTTPServer() {
|
|
|
2487
2803
|
transport.onclose = () => {
|
|
2488
2804
|
if (transport.sessionId) {
|
|
2489
2805
|
sessions.delete(transport.sessionId);
|
|
2490
|
-
console.error(
|
|
2806
|
+
console.error(
|
|
2807
|
+
`[collab-mcp-server] Transport closed for session: ${transport.sessionId}`
|
|
2808
|
+
);
|
|
2491
2809
|
}
|
|
2492
2810
|
};
|
|
2493
|
-
const server = initializeMCPServer(
|
|
2811
|
+
const server = initializeMCPServer(
|
|
2812
|
+
authReq.apiClient,
|
|
2813
|
+
authReq.authContext
|
|
2814
|
+
);
|
|
2494
2815
|
await server.connect(transport);
|
|
2495
2816
|
sessionData = {
|
|
2496
2817
|
transport,
|
|
@@ -2573,8 +2894,13 @@ async function createHTTPServer() {
|
|
|
2573
2894
|
console.error(`[collab-mcp-server] Listening on http://0.0.0.0:${port}`);
|
|
2574
2895
|
console.error(`[collab-mcp-server] MCP endpoint: POST/GET/DELETE /mcp`);
|
|
2575
2896
|
console.error(`[collab-mcp-server] Health check: GET /mcp/health`);
|
|
2897
|
+
console.error(
|
|
2898
|
+
`[collab-mcp-server] OAuth metadata: GET /mcp/.well-known/oauth-protected-resource`
|
|
2899
|
+
);
|
|
2576
2900
|
console.error(`[collab-mcp-server] API URL: ${baseUrl}`);
|
|
2577
|
-
console.error(
|
|
2901
|
+
console.error(
|
|
2902
|
+
`[collab-mcp-server] Session timeout: ${SESSION_TIMEOUT_MS / 1e3 / 60} minutes`
|
|
2903
|
+
);
|
|
2578
2904
|
});
|
|
2579
2905
|
}
|
|
2580
2906
|
function handleCliFlags() {
|
|
@@ -2600,7 +2926,9 @@ Environment Variables:
|
|
|
2600
2926
|
PORT Server port (default: 3001)
|
|
2601
2927
|
|
|
2602
2928
|
Client Authentication:
|
|
2603
|
-
Clients must
|
|
2929
|
+
Clients must authenticate using one of these methods:
|
|
2930
|
+
- X-API-Key header with their Collab API key
|
|
2931
|
+
- Authorization: Bearer <token> header with OAuth access token
|
|
2604
2932
|
Each session is authenticated independently.
|
|
2605
2933
|
|
|
2606
2934
|
Example deployment with Docker:
|