@topolo/mcp 0.14.4 → 0.14.5

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 (2) hide show
  1. package/dist/index.js +175 -39
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // src/index.ts
4
4
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
5
 
6
- // node_modules/.pnpm/@topolo+sdk@0.21.4/node_modules/@topolo/sdk/dist/index.js
6
+ // node_modules/.pnpm/@topolo+sdk@0.22.0/node_modules/@topolo/sdk/dist/index.js
7
7
  function applyAuthHeaders(headers, credential) {
8
8
  if (credential.kind === "api_key") {
9
9
  headers.set("X-Api-Key", credential.apiKey);
@@ -77,6 +77,9 @@ var PUBLIC_ERROR_CODES = /* @__PURE__ */ new Set([
77
77
  "unknown_service"
78
78
  ]);
79
79
  var ERROR_CODE_PATTERN = /^[a-z][a-z0-9_]{0,63}$/;
80
+ var SERVICE_ERROR_CODE_PATTERN = /^[a-z][a-z0-9]*(?:_[a-z][a-z0-9]*){1,9}$/;
81
+ var SERVICE_MESSAGE_MAX_LENGTH = 300;
82
+ var SERVICE_ISSUE_LIMIT = 32;
80
83
  var TOPOLO_REQUEST_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
81
84
  var CLOUDFLARE_RAY_ID_PATTERN = /^[0-9a-f]{16}-[A-Z]{3}$/;
82
85
  var PERMISSION_PATTERN = /^[a-z][a-z0-9_-]{0,63}(?:\.[a-z][a-z0-9_-]{0,63})*:(?:[a-z][a-z0-9_-]{0,63}|\*)$/;
@@ -101,6 +104,24 @@ function canonicalTopoloErrorCode(value) {
101
104
  if (!ERROR_CODE_PATTERN.test(candidate) || !PUBLIC_ERROR_CODES.has(candidate)) return null;
102
105
  return candidate;
103
106
  }
107
+ function canonicalTopoloServiceErrorCode(value) {
108
+ const platform2 = canonicalTopoloErrorCode(value);
109
+ if (platform2) return platform2;
110
+ if (typeof value !== "string") return null;
111
+ const candidate = value.trim();
112
+ if (candidate.length > 64 || !SERVICE_ERROR_CODE_PATTERN.test(candidate)) return null;
113
+ const wordLike = candidate.split("_").every((segment) => {
114
+ const digits = segment.replace(/[a-z]/g, "").length;
115
+ return digits === 0 || digits < segment.length - digits && segment.length <= 8;
116
+ });
117
+ return wordLike ? candidate : null;
118
+ }
119
+ function sanitizeTopoloServiceMessage(value) {
120
+ if (typeof value !== "string") return void 0;
121
+ const text2 = value.replace(/[\u0000-\u001f\u007f-\u009f\u200b-\u200f\u2028-\u202e\u2066-\u2069\ufeff]/g, " ").replace(/\b[a-z][a-z0-9+.-]*:\/\/\S+/gi, "[url]").replace(/[^\s@<>()[\],;:"']+@[^\s@<>()[\],;:"']+\.[a-z]{2,}/gi, "[email]").replace(/[A-Za-z0-9_\-+/=.]{20,}/g, (run) => /[0-9]/.test(run) && /[A-Za-z]/.test(run) ? "[redacted]" : run).replace(/\s+/g, " ").trim();
122
+ if (!text2) return void 0;
123
+ return text2.length > SERVICE_MESSAGE_MAX_LENGTH ? `${text2.slice(0, SERVICE_MESSAGE_MAX_LENGTH - 1).trimEnd()}\u2026` : text2;
124
+ }
104
125
  function canonicalTopoloRequestId(value) {
105
126
  if (typeof value !== "string") return void 0;
106
127
  const candidate = value.trim();
@@ -125,7 +146,7 @@ var TopoloAuthError = class extends TopoloSdkError {
125
146
  retryAfter;
126
147
  details;
127
148
  constructor(message, code = "auth_error", options = {}) {
128
- super(canonicalTopoloErrorCode(code) ?? "auth_error", message);
149
+ super(canonicalTopoloServiceErrorCode(code) ?? "auth_error", message);
129
150
  this.name = "TopoloAuthError";
130
151
  this.status = options.status ?? 401;
131
152
  this.body = options.body;
@@ -149,7 +170,7 @@ var TopoloPermissionError = class extends TopoloSdkError {
149
170
  details;
150
171
  constructor(message, required, options = {}) {
151
172
  super(
152
- canonicalTopoloErrorCode(options.code) ?? serviceErrorCode(options.body, "permission_denied"),
173
+ canonicalTopoloServiceErrorCode(options.code) ?? serviceErrorCode(options.body, "permission_denied"),
153
174
  message
154
175
  );
155
176
  this.name = "TopoloPermissionError";
@@ -168,18 +189,34 @@ var TopoloPermissionError = class extends TopoloSdkError {
168
189
  function extractTopoloServiceErrorCode(body) {
169
190
  if (!body || typeof body !== "object" || Array.isArray(body)) return null;
170
191
  const record2 = body;
171
- const topLevel = canonicalTopoloErrorCode(record2.code);
192
+ const topLevel = canonicalTopoloServiceErrorCode(record2.code);
172
193
  if (topLevel) return topLevel;
173
194
  const nested = record2.error;
174
- const nestedString = canonicalTopoloErrorCode(nested);
195
+ const nestedString = canonicalTopoloServiceErrorCode(nested);
175
196
  if (nestedString) return nestedString;
176
197
  if (nested && typeof nested === "object" && !Array.isArray(nested)) {
177
198
  const code = nested.code;
178
- const nestedCode = canonicalTopoloErrorCode(code);
199
+ const nestedCode = canonicalTopoloServiceErrorCode(code);
179
200
  if (nestedCode) return nestedCode;
180
201
  }
181
202
  return null;
182
203
  }
204
+ function extractTopoloServiceErrorMessage(body) {
205
+ if (!body || typeof body !== "object" || Array.isArray(body)) return void 0;
206
+ const record2 = body;
207
+ const nested = record2.error;
208
+ const candidates = [];
209
+ if (nested && typeof nested === "object" && !Array.isArray(nested)) {
210
+ candidates.push(nested.message);
211
+ }
212
+ candidates.push(record2.message, record2.error_description);
213
+ if (typeof nested === "string" && !canonicalTopoloServiceErrorCode(nested)) candidates.push(nested);
214
+ for (const candidate of candidates) {
215
+ const message = sanitizeTopoloServiceMessage(candidate);
216
+ if (message) return message;
217
+ }
218
+ return void 0;
219
+ }
183
220
  function serviceErrorCode(body, fallback) {
184
221
  return extractTopoloServiceErrorCode(body) ?? fallback;
185
222
  }
@@ -193,10 +230,7 @@ function extractTopoloServiceErrorDetails(body) {
193
230
  if (candidate === void 0) candidate = nestedRecord.details ?? nestedRecord;
194
231
  }
195
232
  if (candidate === void 0) candidate = record2;
196
- if (Array.isArray(candidate)) {
197
- const paths = canonicalTopoloValidationPaths(candidate);
198
- return paths.length ? { paths } : void 0;
199
- }
233
+ if (Array.isArray(candidate)) return validationIssueDetails(canonicalTopoloValidationIssues(candidate)) ?? void 0;
200
234
  if (!candidate || typeof candidate !== "object") return void 0;
201
235
  const source = candidate;
202
236
  const safe = {};
@@ -238,18 +272,59 @@ function extractTopoloServiceErrorDetails(body) {
238
272
  if (paths.length) safe[key] = paths;
239
273
  }
240
274
  }
275
+ const issues = [
276
+ ...Array.isArray(source.issues) ? canonicalTopoloValidationIssues(source.issues) : [],
277
+ ...flattenedValidationIssues(source.formErrors, source.fieldErrors)
278
+ ].slice(0, SERVICE_ISSUE_LIMIT);
279
+ Object.assign(safe, validationIssueDetails(issues));
241
280
  return Object.keys(safe).length ? safe : void 0;
242
281
  }
243
- function canonicalTopoloValidationPaths(issues) {
282
+ function validationIssueDetails(issues) {
283
+ if (!issues.length) return null;
244
284
  const paths = [];
245
- for (const issue of issues) {
246
- if (!issue || typeof issue !== "object" || Array.isArray(issue)) continue;
247
- const record2 = issue;
285
+ for (const issue22 of issues) {
286
+ if (issue22.path && !paths.includes(issue22.path)) paths.push(issue22.path);
287
+ }
288
+ return paths.length ? { paths, issues } : { issues };
289
+ }
290
+ function issue(path, message) {
291
+ const text2 = sanitizeTopoloServiceMessage(message);
292
+ if (!path && !text2) return null;
293
+ return { ...path ? { path } : {}, ...text2 ? { message: text2 } : {} };
294
+ }
295
+ function canonicalTopoloValidationIssues(values) {
296
+ const issues = [];
297
+ for (const value of values) {
298
+ if (!value || typeof value !== "object" || Array.isArray(value)) continue;
299
+ const record2 = value;
248
300
  const path = canonicalTopoloValidationPath(record2.field) ?? canonicalTopoloValidationPath(record2.path);
249
- if (path && !paths.includes(path)) paths.push(path);
250
- if (paths.length === 32) break;
301
+ if (!path) continue;
302
+ const projected = issue(path, record2.message);
303
+ if (projected) issues.push(projected);
304
+ if (issues.length === SERVICE_ISSUE_LIMIT) break;
305
+ }
306
+ return issues;
307
+ }
308
+ function flattenedValidationIssues(formErrors, fieldErrors) {
309
+ const issues = [];
310
+ if (Array.isArray(formErrors)) {
311
+ for (const message of formErrors) {
312
+ const projected = issue(void 0, message);
313
+ if (projected) issues.push(projected);
314
+ }
315
+ }
316
+ if (fieldErrors && typeof fieldErrors === "object" && !Array.isArray(fieldErrors)) {
317
+ for (const [key, messages] of Object.entries(fieldErrors)) {
318
+ const path = canonicalTopoloValidationPath(key);
319
+ if (!path) continue;
320
+ const list = Array.isArray(messages) && messages.length ? messages : [void 0];
321
+ for (const message of list) {
322
+ const projected = issue(path, message);
323
+ if (projected) issues.push(projected);
324
+ }
325
+ }
251
326
  }
252
- return paths;
327
+ return issues;
253
328
  }
254
329
  function canonicalTopoloValidationPath(value) {
255
330
  if (typeof value === "string") {
@@ -271,7 +346,9 @@ function canonicalTopoloValidationPath(value) {
271
346
  return PUBLIC_FIELD_PATH_PATTERN.test(path) ? path : void 0;
272
347
  }
273
348
  function publicTopoloErrorMessage(error) {
274
- const code = canonicalTopoloErrorCode(
349
+ const serviceMessage = typeof error === "string" ? void 0 : extractTopoloServiceErrorMessage(error.body);
350
+ if (serviceMessage) return serviceMessage;
351
+ const code = canonicalTopoloServiceErrorCode(
275
352
  typeof error === "string" ? error : error.code ?? extractTopoloServiceErrorCode(error.body)
276
353
  ) ?? "request_failed";
277
354
  if (/(?:organization|org).*(?:enroll|membership|member|admission)/.test(code)) {
@@ -288,7 +365,7 @@ function publicTopoloErrorMessage(error) {
288
365
  return `Topolo request failed (${code}).`;
289
366
  }
290
367
  function topoloErrorHint(error) {
291
- const code = canonicalTopoloErrorCode(
368
+ const code = canonicalTopoloServiceErrorCode(
292
369
  typeof error === "string" ? error : error.code ?? extractTopoloServiceErrorCode(error.body)
293
370
  );
294
371
  if (!code) return void 0;
@@ -655,8 +732,8 @@ function inspectSchema(schema, path, root, depth) {
655
732
  );
656
733
  for (const [key, child] of children) {
657
734
  if (!isRecord2(child)) continue;
658
- const issue = inspectSchema(child, `${path}.${key}`, root, depth + 1);
659
- if (issue) return issue;
735
+ const issue22 = inspectSchema(child, `${path}.${key}`, root, depth + 1);
736
+ if (issue22) return issue22;
660
737
  }
661
738
  return null;
662
739
  }
@@ -1972,7 +2049,7 @@ var TopoloClient = class _TopoloClient {
1972
2049
  input: selectedInput,
1973
2050
  inputSource: input ? "provided" : example ? "example" : "empty",
1974
2051
  missingFields: [...new Set(
1975
- plan.validation.errors.filter((issue) => issue.code === "required").map((issue) => issue.path)
2052
+ plan.validation.errors.filter((issue22) => issue22.code === "required").map((issue22) => issue22.path)
1976
2053
  )],
1977
2054
  plan
1978
2055
  };
@@ -2037,7 +2114,7 @@ var TopoloClient = class _TopoloClient {
2037
2114
  if (!validation.valid) {
2038
2115
  throw new TopoloSdkError(
2039
2116
  "invalid_action_input",
2040
- `Topolo action "${entry.actionId}" input is invalid: ${validation.errors.map((issue) => `${issue.path} ${issue.message}`).join("; ")}`
2117
+ `Topolo action "${entry.actionId}" input is invalid: ${validation.errors.map((issue22) => `${issue22.path} ${issue22.message}`).join("; ")}`
2041
2118
  );
2042
2119
  }
2043
2120
  const resourceIssue = validateActionResource(entry, options.resource);
@@ -3328,7 +3405,7 @@ function createTopolo(options) {
3328
3405
  };
3329
3406
  }
3330
3407
 
3331
- // node_modules/.pnpm/@topolo+sdk@0.21.4/node_modules/@topolo/sdk/dist/node/credential-store.js
3408
+ // node_modules/.pnpm/@topolo+sdk@0.22.0/node_modules/@topolo/sdk/dist/node/credential-store.js
3332
3409
  import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2, chmod as chmod2, rm as rm2, stat } from "fs/promises";
3333
3410
  import { existsSync as existsSync2 } from "fs";
3334
3411
  import { homedir as homedir2, platform } from "os";
@@ -3395,6 +3472,9 @@ var PUBLIC_ERROR_CODES2 = /* @__PURE__ */ new Set([
3395
3472
  "unknown_service"
3396
3473
  ]);
3397
3474
  var ERROR_CODE_PATTERN2 = /^[a-z][a-z0-9_]{0,63}$/;
3475
+ var SERVICE_ERROR_CODE_PATTERN2 = /^[a-z][a-z0-9]*(?:_[a-z][a-z0-9]*){1,9}$/;
3476
+ var SERVICE_MESSAGE_MAX_LENGTH2 = 300;
3477
+ var SERVICE_ISSUE_LIMIT2 = 32;
3398
3478
  var TOPOLO_REQUEST_ID_PATTERN2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
3399
3479
  var CLOUDFLARE_RAY_ID_PATTERN2 = /^[0-9a-f]{16}-[A-Z]{3}$/;
3400
3480
  var PERMISSION_PATTERN2 = /^[a-z][a-z0-9_-]{0,63}(?:\.[a-z][a-z0-9_-]{0,63})*:(?:[a-z][a-z0-9_-]{0,63}|\*)$/;
@@ -3419,6 +3499,24 @@ function canonicalTopoloErrorCode2(value) {
3419
3499
  if (!ERROR_CODE_PATTERN2.test(candidate) || !PUBLIC_ERROR_CODES2.has(candidate)) return null;
3420
3500
  return candidate;
3421
3501
  }
3502
+ function canonicalTopoloServiceErrorCode2(value) {
3503
+ const platform2 = canonicalTopoloErrorCode2(value);
3504
+ if (platform2) return platform2;
3505
+ if (typeof value !== "string") return null;
3506
+ const candidate = value.trim();
3507
+ if (candidate.length > 64 || !SERVICE_ERROR_CODE_PATTERN2.test(candidate)) return null;
3508
+ const wordLike = candidate.split("_").every((segment) => {
3509
+ const digits = segment.replace(/[a-z]/g, "").length;
3510
+ return digits === 0 || digits < segment.length - digits && segment.length <= 8;
3511
+ });
3512
+ return wordLike ? candidate : null;
3513
+ }
3514
+ function sanitizeTopoloServiceMessage2(value) {
3515
+ if (typeof value !== "string") return void 0;
3516
+ const text2 = value.replace(/[\u0000-\u001f\u007f-\u009f\u200b-\u200f\u2028-\u202e\u2066-\u2069\ufeff]/g, " ").replace(/\b[a-z][a-z0-9+.-]*:\/\/\S+/gi, "[url]").replace(/[^\s@<>()[\],;:"']+@[^\s@<>()[\],;:"']+\.[a-z]{2,}/gi, "[email]").replace(/[A-Za-z0-9_\-+/=.]{20,}/g, (run) => /[0-9]/.test(run) && /[A-Za-z]/.test(run) ? "[redacted]" : run).replace(/\s+/g, " ").trim();
3517
+ if (!text2) return void 0;
3518
+ return text2.length > SERVICE_MESSAGE_MAX_LENGTH2 ? `${text2.slice(0, SERVICE_MESSAGE_MAX_LENGTH2 - 1).trimEnd()}\u2026` : text2;
3519
+ }
3422
3520
  function canonicalTopoloRequestId2(value) {
3423
3521
  if (typeof value !== "string") return void 0;
3424
3522
  const candidate = value.trim();
@@ -3443,7 +3541,7 @@ var TopoloAuthError2 = class extends TopoloSdkError2 {
3443
3541
  retryAfter;
3444
3542
  details;
3445
3543
  constructor(message, code = "auth_error", options = {}) {
3446
- super(canonicalTopoloErrorCode2(code) ?? "auth_error", message);
3544
+ super(canonicalTopoloServiceErrorCode2(code) ?? "auth_error", message);
3447
3545
  this.name = "TopoloAuthError";
3448
3546
  this.status = options.status ?? 401;
3449
3547
  this.body = options.body;
@@ -3459,14 +3557,14 @@ var TopoloAuthError2 = class extends TopoloSdkError2 {
3459
3557
  function extractTopoloServiceErrorCode2(body) {
3460
3558
  if (!body || typeof body !== "object" || Array.isArray(body)) return null;
3461
3559
  const record2 = body;
3462
- const topLevel = canonicalTopoloErrorCode2(record2.code);
3560
+ const topLevel = canonicalTopoloServiceErrorCode2(record2.code);
3463
3561
  if (topLevel) return topLevel;
3464
3562
  const nested = record2.error;
3465
- const nestedString = canonicalTopoloErrorCode2(nested);
3563
+ const nestedString = canonicalTopoloServiceErrorCode2(nested);
3466
3564
  if (nestedString) return nestedString;
3467
3565
  if (nested && typeof nested === "object" && !Array.isArray(nested)) {
3468
3566
  const code = nested.code;
3469
- const nestedCode = canonicalTopoloErrorCode2(code);
3567
+ const nestedCode = canonicalTopoloServiceErrorCode2(code);
3470
3568
  if (nestedCode) return nestedCode;
3471
3569
  }
3472
3570
  return null;
@@ -3484,10 +3582,7 @@ function extractTopoloServiceErrorDetails2(body) {
3484
3582
  if (candidate === void 0) candidate = nestedRecord.details ?? nestedRecord;
3485
3583
  }
3486
3584
  if (candidate === void 0) candidate = record2;
3487
- if (Array.isArray(candidate)) {
3488
- const paths = canonicalTopoloValidationPaths2(candidate);
3489
- return paths.length ? { paths } : void 0;
3490
- }
3585
+ if (Array.isArray(candidate)) return validationIssueDetails2(canonicalTopoloValidationIssues2(candidate)) ?? void 0;
3491
3586
  if (!candidate || typeof candidate !== "object") return void 0;
3492
3587
  const source = candidate;
3493
3588
  const safe = {};
@@ -3529,18 +3624,59 @@ function extractTopoloServiceErrorDetails2(body) {
3529
3624
  if (paths.length) safe[key] = paths;
3530
3625
  }
3531
3626
  }
3627
+ const issues = [
3628
+ ...Array.isArray(source.issues) ? canonicalTopoloValidationIssues2(source.issues) : [],
3629
+ ...flattenedValidationIssues2(source.formErrors, source.fieldErrors)
3630
+ ].slice(0, SERVICE_ISSUE_LIMIT2);
3631
+ Object.assign(safe, validationIssueDetails2(issues));
3532
3632
  return Object.keys(safe).length ? safe : void 0;
3533
3633
  }
3534
- function canonicalTopoloValidationPaths2(issues) {
3634
+ function validationIssueDetails2(issues) {
3635
+ if (!issues.length) return null;
3535
3636
  const paths = [];
3536
- for (const issue of issues) {
3537
- if (!issue || typeof issue !== "object" || Array.isArray(issue)) continue;
3538
- const record2 = issue;
3637
+ for (const issue22 of issues) {
3638
+ if (issue22.path && !paths.includes(issue22.path)) paths.push(issue22.path);
3639
+ }
3640
+ return paths.length ? { paths, issues } : { issues };
3641
+ }
3642
+ function issue2(path, message) {
3643
+ const text2 = sanitizeTopoloServiceMessage2(message);
3644
+ if (!path && !text2) return null;
3645
+ return { ...path ? { path } : {}, ...text2 ? { message: text2 } : {} };
3646
+ }
3647
+ function canonicalTopoloValidationIssues2(values) {
3648
+ const issues = [];
3649
+ for (const value of values) {
3650
+ if (!value || typeof value !== "object" || Array.isArray(value)) continue;
3651
+ const record2 = value;
3539
3652
  const path = canonicalTopoloValidationPath2(record2.field) ?? canonicalTopoloValidationPath2(record2.path);
3540
- if (path && !paths.includes(path)) paths.push(path);
3541
- if (paths.length === 32) break;
3653
+ if (!path) continue;
3654
+ const projected = issue2(path, record2.message);
3655
+ if (projected) issues.push(projected);
3656
+ if (issues.length === SERVICE_ISSUE_LIMIT2) break;
3657
+ }
3658
+ return issues;
3659
+ }
3660
+ function flattenedValidationIssues2(formErrors, fieldErrors) {
3661
+ const issues = [];
3662
+ if (Array.isArray(formErrors)) {
3663
+ for (const message of formErrors) {
3664
+ const projected = issue2(void 0, message);
3665
+ if (projected) issues.push(projected);
3666
+ }
3667
+ }
3668
+ if (fieldErrors && typeof fieldErrors === "object" && !Array.isArray(fieldErrors)) {
3669
+ for (const [key, messages] of Object.entries(fieldErrors)) {
3670
+ const path = canonicalTopoloValidationPath2(key);
3671
+ if (!path) continue;
3672
+ const list = Array.isArray(messages) && messages.length ? messages : [void 0];
3673
+ for (const message of list) {
3674
+ const projected = issue2(path, message);
3675
+ if (projected) issues.push(projected);
3676
+ }
3677
+ }
3542
3678
  }
3543
- return paths;
3679
+ return issues;
3544
3680
  }
3545
3681
  function canonicalTopoloValidationPath2(value) {
3546
3682
  if (typeof value === "string") {
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@topolo/mcp",
3
3
  "packageManager": "pnpm@10.17.1",
4
- "version": "0.14.4",
5
- "topoloPublishedVersion": "0.14.4",
4
+ "version": "0.14.5",
5
+ "topoloPublishedVersion": "0.14.5",
6
6
  "description": "Model Context Protocol server for the Topolo platform. Exposes scope-gated tools that third-party agents (Claude, Codex, etc.) can call natively.",
7
7
  "license": "UNLICENSED",
8
8
  "author": "Topolo",
@@ -36,7 +36,7 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@modelcontextprotocol/sdk": "^1.0.0",
39
- "@topolo/sdk": "0.21.4"
39
+ "@topolo/sdk": "0.22.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^20.12.0",