@mtaap/mcp 0.2.7 → 0.2.10

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 CHANGED
@@ -518,19 +518,6 @@ report_error -> abandon_task -> list_tasks -> assign_task (retry or pick differe
518
518
 
519
519
  3. Use the tools from your AI agent
520
520
 
521
- ## Development
522
-
523
- ```bash
524
- # Build
525
- pnpm build
526
-
527
- # Watch mode
528
- pnpm dev
529
-
530
- # Run locally
531
- COLLAB_API_KEY=your-key COLLAB_BASE_URL=https://collab.mtaap.de pnpm start
532
- ```
533
-
534
521
  ## Troubleshooting
535
522
 
536
523
  ### "COLLAB_API_KEY is required"
@@ -553,16 +540,6 @@ Ensure your firewall allows outbound connections to your Collab instance. The se
553
540
 
554
541
  The MCP API is rate limited to 100 requests per minute. If you exceed this limit, you'll receive a 429 error with a `Retry-After` header indicating when you can retry.
555
542
 
556
- ## Publishing
557
-
558
- This package is published as `@mtaap/mcp` to npm.
559
-
560
- ```bash
561
- # Build and publish
562
- pnpm build
563
- npm publish
564
- ```
565
-
566
543
  ## License
567
544
 
568
545
  Proprietary - See LICENSE file for details.
package/dist/cli.js CHANGED
@@ -162,12 +162,19 @@ var VALID_TRANSITIONS = {
162
162
  [TaskState.DONE]: []
163
163
  };
164
164
 
165
+ // ../../packages/core/dist/config/deployment.js
166
+ var config = {
167
+ deploymentMode: process.env.DEPLOYMENT_MODE || "saas"
168
+ };
169
+ var isSaas = config.deploymentMode === "saas";
170
+ var isOnPrem = config.deploymentMode === "onprem";
171
+
165
172
  // ../../packages/core/dist/version.js
166
173
  var VERSION2 = "0.1.0";
167
174
 
168
175
  // ../../packages/core/dist/config/index.js
169
176
  var DEPLOYMENT_MODE = process.env.DEPLOYMENT_MODE || "saas";
170
- var config = {
177
+ var config2 = {
171
178
  version: VERSION2,
172
179
  deploymentMode: DEPLOYMENT_MODE,
173
180
  billing: {
@@ -252,9 +259,9 @@ var config = {
252
259
  }
253
260
  };
254
261
  var DEFAULT_SEAT_LIMITS = {
255
- [PricingTier.FREE]: config.pricing.defaultSeats.FREE,
256
- [PricingTier.PRO]: config.pricing.defaultSeats.PRO,
257
- [PricingTier.ENTERPRISE]: config.pricing.defaultSeats.ENTERPRISE
262
+ [PricingTier.FREE]: config2.pricing.defaultSeats.FREE,
263
+ [PricingTier.PRO]: config2.pricing.defaultSeats.PRO,
264
+ [PricingTier.ENTERPRISE]: config2.pricing.defaultSeats.ENTERPRISE
258
265
  };
259
266
 
260
267
  // ../../packages/core/dist/types/index.js
@@ -420,6 +427,7 @@ var ListTasksInputSchema = import_zod2.z.object({
420
427
  includeArchived: import_zod2.z.boolean().optional()
421
428
  });
422
429
  var cuidOrPrefixedId = import_zod2.z.string().regex(/^([a-z0-9]+|[a-z]+_[a-zA-Z0-9]+)$/);
430
+ var gitBranchName = import_zod2.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");
423
431
  var GetTaskInputSchema = import_zod2.z.object({
424
432
  taskId: cuidOrPrefixedId
425
433
  });
@@ -634,7 +642,7 @@ var UpdateTaskMCPInputSchema = import_zod2.z.object({
634
642
  var ReportBranchInputSchema = import_zod2.z.object({
635
643
  projectId: cuidOrPrefixedId,
636
644
  taskId: cuidOrPrefixedId,
637
- branchName: import_zod2.z.string().min(1).max(100)
645
+ branchName: gitBranchName
638
646
  });
639
647
  var ReportPRInputSchema = import_zod2.z.object({
640
648
  projectId: cuidOrPrefixedId,
@@ -941,6 +949,12 @@ var errorTrackerInstance = new NoOpErrorTracker();
941
949
 
942
950
  // src/api-client.ts
943
951
  var DEFAULT_TIMEOUT = 3e4;
952
+ function sanitizeForLogging(str) {
953
+ let sanitized = str.replace(/\bcollab_[a-zA-Z0-9_-]+\b/gi, "[REDACTED_API_KEY]");
954
+ sanitized = sanitized.replace(/\bBearer\s+[a-zA-Z0-9._-]+\b/gi, "Bearer [REDACTED]");
955
+ sanitized = sanitized.replace(/([?&](api_?key|token|auth|key|secret)=)[^&\s]+/gi, "$1[REDACTED]");
956
+ return sanitized;
957
+ }
944
958
  var ApiError = class extends Error {
945
959
  constructor(message, code, status, details) {
946
960
  super(message);
@@ -956,11 +970,11 @@ var MCPApiClient = class {
956
970
  timeout;
957
971
  debug;
958
972
  authContext = null;
959
- constructor(config2) {
960
- this.baseUrl = config2.baseUrl.replace(/\/$/, "");
961
- this.apiKey = config2.apiKey;
962
- this.timeout = config2.timeout ?? DEFAULT_TIMEOUT;
963
- this.debug = config2.debug ?? false;
973
+ constructor(config3) {
974
+ this.baseUrl = config3.baseUrl.replace(/\/$/, "");
975
+ this.apiKey = config3.apiKey;
976
+ this.timeout = config3.timeout ?? DEFAULT_TIMEOUT;
977
+ this.debug = config3.debug ?? false;
964
978
  }
965
979
  /**
966
980
  * Make an HTTP request to the API
@@ -970,7 +984,7 @@ var MCPApiClient = class {
970
984
  const controller = new AbortController();
971
985
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
972
986
  if (this.debug) {
973
- console.error(`[mcp-api] ${method} ${url}`);
987
+ console.error(`[mcp-api] ${method} ${sanitizeForLogging(path)}`);
974
988
  }
975
989
  try {
976
990
  const response = await fetch(url, {
@@ -1005,8 +1019,9 @@ var MCPApiClient = class {
1005
1019
  408
1006
1020
  );
1007
1021
  }
1022
+ const rawMessage = error instanceof Error ? error.message : "Unknown error";
1008
1023
  throw new ApiError(
1009
- error instanceof Error ? error.message : "Unknown error",
1024
+ sanitizeForLogging(rawMessage),
1010
1025
  "NETWORK_ERROR",
1011
1026
  0
1012
1027
  );
@@ -2192,22 +2207,76 @@ function handleApiError(error) {
2192
2207
  isError: true
2193
2208
  };
2194
2209
  }
2210
+ var ActiveTaskSchema = import_zod3.z.object({
2211
+ taskId: import_zod3.z.string().min(1),
2212
+ projectId: import_zod3.z.string().min(1),
2213
+ branchName: import_zod3.z.string().optional(),
2214
+ startedAt: import_zod3.z.string().optional()
2215
+ });
2195
2216
  async function checkActiveTask() {
2196
2217
  const fs = await import("fs");
2197
2218
  const path = await import("path");
2198
- const activeTaskPath = path.join(process.cwd(), ".collab", "active-task.json");
2219
+ const cwd = process.cwd();
2220
+ const collabDir = path.join(cwd, ".collab");
2221
+ const activeTaskPath = path.join(collabDir, "active-task.json");
2199
2222
  try {
2200
- await fs.promises.access(activeTaskPath);
2223
+ const resolvedPath = path.resolve(activeTaskPath);
2224
+ const resolvedCollabDir = path.resolve(collabDir);
2225
+ if (!resolvedPath.startsWith(resolvedCollabDir + path.sep) && resolvedPath !== resolvedCollabDir) {
2226
+ return {
2227
+ hasActiveTask: false,
2228
+ task: null,
2229
+ error: "Invalid active task path"
2230
+ };
2231
+ }
2232
+ const stats = await fs.promises.lstat(activeTaskPath);
2233
+ if (stats.isSymbolicLink()) {
2234
+ return {
2235
+ hasActiveTask: false,
2236
+ task: null,
2237
+ error: "Symlinks not allowed for active task file"
2238
+ };
2239
+ }
2240
+ if (!stats.isFile()) {
2241
+ return {
2242
+ hasActiveTask: false,
2243
+ task: null
2244
+ };
2245
+ }
2201
2246
  const content = await fs.promises.readFile(activeTaskPath, "utf-8");
2202
- const activeTask = JSON.parse(content);
2247
+ let parsed;
2248
+ try {
2249
+ parsed = JSON.parse(content);
2250
+ } catch {
2251
+ return {
2252
+ hasActiveTask: false,
2253
+ task: null,
2254
+ error: "Invalid JSON in active task file"
2255
+ };
2256
+ }
2257
+ const validationResult = ActiveTaskSchema.safeParse(parsed);
2258
+ if (!validationResult.success) {
2259
+ return {
2260
+ hasActiveTask: false,
2261
+ task: null,
2262
+ error: "Active task file has invalid structure"
2263
+ };
2264
+ }
2203
2265
  return {
2204
2266
  hasActiveTask: true,
2205
- task: activeTask
2267
+ task: validationResult.data
2206
2268
  };
2207
- } catch {
2269
+ } catch (err) {
2270
+ if (err instanceof Error && "code" in err && err.code === "ENOENT") {
2271
+ return {
2272
+ hasActiveTask: false,
2273
+ task: null
2274
+ };
2275
+ }
2208
2276
  return {
2209
2277
  hasActiveTask: false,
2210
- task: null
2278
+ task: null,
2279
+ error: "Failed to read active task file"
2211
2280
  };
2212
2281
  }
2213
2282
  }