@topolo/mcp 0.9.11 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dispatch.js CHANGED
@@ -5,11 +5,12 @@ import { TopoloAuthError, TopoloPermissionError } from "@topolo/sdk";
5
5
  import {
6
6
  APPLICATION_REQUIREMENTS,
7
7
  APPLICATION_REQUIREMENTS_VERSION,
8
- APPLICATIONS,
9
- DEFAULT_APP_URLS,
10
- auditAllApplicationRequirements,
8
+ auditApplicationEntries,
11
9
  applicationRequirementScopes,
10
+ friendlyAppId,
11
+ listApplicationDirectory,
12
12
  requirementsForApplication,
13
+ resolveApplicationDirectoryEntry,
13
14
  resolveCatalogServiceUrl
14
15
  } from "@topolo/sdk";
15
16
 
@@ -62,7 +63,6 @@ function publicMcpErrorMessage(error, fallback) {
62
63
  }
63
64
 
64
65
  // src/tools.ts
65
- var APPLICATION_IDS = Object.keys(APPLICATIONS).sort();
66
66
  var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
67
67
  function requiredString(args, name) {
68
68
  const value = typeof args[name] === "string" ? args[name].trim() : "";
@@ -78,6 +78,20 @@ function optionalResourceContext(args) {
78
78
  }
79
79
  return { resourceType, resourceId };
80
80
  }
81
+ function coerceObjectParam(value, name) {
82
+ let candidate = value;
83
+ if (typeof candidate === "string" && candidate.trim().startsWith("{")) {
84
+ try {
85
+ candidate = JSON.parse(candidate);
86
+ } catch {
87
+ }
88
+ }
89
+ if (candidate === void 0) return {};
90
+ if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) {
91
+ throw new TopoloMcpPublicError(`${name} must be an object.`);
92
+ }
93
+ return candidate;
94
+ }
81
95
  var TOOLS = [
82
96
  {
83
97
  name: "topolo_whoami",
@@ -228,14 +242,11 @@ var TOOLS = [
228
242
  handler: async (topolo, args) => {
229
243
  const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
230
244
  if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
231
- const input = args["input"];
232
- if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
233
- throw new TopoloMcpPublicError("input must be an object.");
234
- }
245
+ const input = coerceObjectParam(args["input"], "input");
235
246
  const resource = optionalResourceContext(args);
236
247
  return topolo.client.readAction(
237
248
  actionId,
238
- input ?? {},
249
+ input,
239
250
  resource ? { resource } : {}
240
251
  );
241
252
  }
@@ -261,14 +272,11 @@ var TOOLS = [
261
272
  handler: async (topolo, args) => {
262
273
  const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
263
274
  if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
264
- const input = args["input"];
265
- if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
266
- throw new TopoloMcpPublicError("input must be an object.");
267
- }
275
+ const input = coerceObjectParam(args["input"], "input");
268
276
  const resource = optionalResourceContext(args);
269
277
  return topolo.client.callAction(
270
278
  actionId,
271
- input ?? {},
279
+ input,
272
280
  {
273
281
  confirm: args["confirm"] === true,
274
282
  ...resource ? { resource } : {}
@@ -307,23 +315,17 @@ var TOOLS = [
307
315
  if (!isCanonicalBase64(contentBase64)) throw new TopoloMcpPublicError("contentBase64 must be canonical base64.");
308
316
  if (!contentType) throw new TopoloMcpPublicError("contentType is required.");
309
317
  if (!fileName) throw new TopoloMcpPublicError("fileName is required.");
310
- const input = args["input"];
311
- if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
312
- throw new TopoloMcpPublicError("input must be an object.");
313
- }
314
- const completionInput = args["completionInput"];
315
- if (completionInput !== void 0 && (!completionInput || typeof completionInput !== "object" || Array.isArray(completionInput))) {
316
- throw new TopoloMcpPublicError("completionInput must be an object.");
317
- }
318
+ const input = coerceObjectParam(args["input"], "input");
319
+ const completionInput = coerceObjectParam(args["completionInput"], "completionInput");
318
320
  const resource = optionalResourceContext(args);
319
321
  return topolo.client.uploadActionBase64(
320
322
  actionId,
321
323
  contentBase64,
322
- input ?? {},
324
+ input,
323
325
  {
324
326
  fileName,
325
327
  contentType,
326
- completionInput: completionInput ?? {},
328
+ completionInput,
327
329
  confirm: args["confirm"] === true,
328
330
  ...resource ? { resource } : {}
329
331
  }
@@ -348,11 +350,8 @@ var TOOLS = [
348
350
  handler: async (topolo, args) => {
349
351
  const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
350
352
  if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
351
- const input = args["input"];
352
- if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
353
- throw new TopoloMcpPublicError("input must be an object.");
354
- }
355
- return topolo.client.validateActionInput(actionId, input ?? {});
353
+ const input = coerceObjectParam(args["input"], "input");
354
+ return topolo.client.validateActionInput(actionId, input);
356
355
  }
357
356
  },
358
357
  {
@@ -376,14 +375,11 @@ var TOOLS = [
376
375
  handler: async (topolo, args) => {
377
376
  const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
378
377
  if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
379
- const input = args["input"];
380
- if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
381
- throw new TopoloMcpPublicError("input must be an object.");
382
- }
378
+ const input = coerceObjectParam(args["input"], "input");
383
379
  const resource = optionalResourceContext(args);
384
380
  return topolo.client.planAction(
385
381
  actionId,
386
- input ?? {},
382
+ input,
387
383
  {
388
384
  confirm: args["confirm"] === true,
389
385
  ...resource ? { resource } : {}
@@ -560,7 +556,7 @@ var TOOLS = [
560
556
  },
561
557
  additionalProperties: false
562
558
  },
563
- handler: async (_topolo, args) => {
559
+ handler: async (topolo, args) => {
564
560
  const application = args["application"];
565
561
  if (application === void 0) {
566
562
  return {
@@ -570,12 +566,8 @@ var TOOLS = [
570
566
  requirements: APPLICATION_REQUIREMENTS
571
567
  };
572
568
  }
573
- if (typeof application !== "string" || !APPLICATION_IDS.includes(application)) {
574
- throw new TopoloMcpPublicError(
575
- `Unknown application "${String(application)}". ${formatKnownValues(APPLICATION_IDS, "applications")}`
576
- );
577
- }
578
- const app = APPLICATIONS[application];
569
+ const resolved = await resolveDirectoryApplication(topolo, application);
570
+ const app = resolved.application;
579
571
  return {
580
572
  version: APPLICATION_REQUIREMENTS_VERSION,
581
573
  application: app,
@@ -605,7 +597,7 @@ var TOOLS = [
605
597
  },
606
598
  additionalProperties: false
607
599
  },
608
- handler: async (_topolo, args) => {
600
+ handler: async (topolo, args) => {
609
601
  const application = args["application"];
610
602
  const failOn = args["failOn"];
611
603
  if (failOn !== void 0 && typeof failOn !== "string") {
@@ -614,15 +606,12 @@ var TOOLS = [
614
606
  const gate = failOn ? normalizeFailOn(failOn) : null;
615
607
  let report;
616
608
  if (application === void 0) {
617
- report = auditAllApplicationRequirements();
609
+ const directory = await listApplicationDirectory(topolo.client);
610
+ report = auditApplicationEntries(directory.applications.map((app) => app.application));
618
611
  return gate ? { ...report, conformanceGate: evaluateApplicationAuditGate(report, gate) } : report;
619
612
  }
620
- if (typeof application !== "string" || !APPLICATION_IDS.includes(application)) {
621
- throw new TopoloMcpPublicError(
622
- `Unknown application "${String(application)}". ${formatKnownValues(APPLICATION_IDS, "applications")}`
623
- );
624
- }
625
- report = auditAllApplicationRequirements([application]);
613
+ const resolved = await resolveDirectoryApplication(topolo, application);
614
+ report = auditApplicationEntries([resolved.application]);
626
615
  return gate ? { ...report, conformanceGate: evaluateApplicationAuditGate(report, gate) } : report;
627
616
  }
628
617
  },
@@ -762,31 +751,19 @@ function statusesAtOrWorse(threshold) {
762
751
  return ["missing", "needs_review", "partial"];
763
752
  }
764
753
  function displayAppId(entry) {
765
- for (const value of [entry.slug, entry.name, entry.appId]) {
766
- if (typeof value !== "string" || !value.trim()) continue;
767
- for (const candidate of appIdCandidates(value)) {
768
- if (Object.prototype.hasOwnProperty.call(DEFAULT_APP_URLS, candidate)) {
769
- return candidate;
770
- }
771
- }
772
- }
773
- return appIdCandidates(entry.slug || entry.appId)[0] || entry.appId;
774
- }
775
- function appIdCandidates(value) {
776
- const normalized = value.trim().toLowerCase().replace(/\s+/g, "-");
777
- const withoutTopolo = normalized.startsWith("topolo-") ? normalized.slice("topolo-".length) : normalized;
778
- return [.../* @__PURE__ */ new Set([
779
- normalized,
780
- normalized.replace(/-/g, "_"),
781
- withoutTopolo,
782
- withoutTopolo.replace(/-/g, "_")
783
- ])].filter(Boolean);
754
+ return friendlyAppId(entry);
784
755
  }
785
- function formatKnownValues(values, label) {
786
- const sorted = [...values].sort();
787
- const preview = sorted.slice(0, 25).join(", ");
788
- const suffix = sorted.length > 25 ? `, ... +${sorted.length - 25} more` : "";
789
- return `Run discovery for the full ${label} list. Known snapshot sample: ${preview}${suffix}`;
756
+ async function resolveDirectoryApplication(topolo, application) {
757
+ if (typeof application !== "string" || !application.trim()) {
758
+ throw new TopoloMcpPublicError("`application` must be a non-empty string.");
759
+ }
760
+ try {
761
+ return await resolveApplicationDirectoryEntry(topolo.client, application);
762
+ } catch (error) {
763
+ throw new TopoloMcpPublicError(
764
+ error instanceof Error ? error.message : `Unknown application "${application}".`
765
+ );
766
+ }
790
767
  }
791
768
 
792
769
  // src/dispatch.ts
package/dist/http.js CHANGED
@@ -15830,11 +15830,12 @@ import { TopoloAuthError, TopoloHttpError, TopoloPermissionError } from "@topolo
15830
15830
  import {
15831
15831
  APPLICATION_REQUIREMENTS,
15832
15832
  APPLICATION_REQUIREMENTS_VERSION,
15833
- APPLICATIONS,
15834
- DEFAULT_APP_URLS,
15835
- auditAllApplicationRequirements,
15833
+ auditApplicationEntries,
15836
15834
  applicationRequirementScopes,
15835
+ friendlyAppId,
15836
+ listApplicationDirectory,
15837
15837
  requirementsForApplication,
15838
+ resolveApplicationDirectoryEntry,
15838
15839
  resolveCatalogServiceUrl
15839
15840
  } from "@topolo/sdk";
15840
15841
 
@@ -15876,7 +15877,6 @@ function splitService(servicePart) {
15876
15877
  }
15877
15878
 
15878
15879
  // src/tools.ts
15879
- var APPLICATION_IDS = Object.keys(APPLICATIONS).sort();
15880
15880
  var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
15881
15881
  function requiredString(args, name) {
15882
15882
  const value = typeof args[name] === "string" ? args[name].trim() : "";
@@ -15892,6 +15892,20 @@ function optionalResourceContext(args) {
15892
15892
  }
15893
15893
  return { resourceType, resourceId };
15894
15894
  }
15895
+ function coerceObjectParam(value, name) {
15896
+ let candidate = value;
15897
+ if (typeof candidate === "string" && candidate.trim().startsWith("{")) {
15898
+ try {
15899
+ candidate = JSON.parse(candidate);
15900
+ } catch {
15901
+ }
15902
+ }
15903
+ if (candidate === void 0) return {};
15904
+ if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) {
15905
+ throw new TopoloMcpPublicError(`${name} must be an object.`);
15906
+ }
15907
+ return candidate;
15908
+ }
15895
15909
  var TOOLS = [
15896
15910
  {
15897
15911
  name: "topolo_whoami",
@@ -16042,14 +16056,11 @@ var TOOLS = [
16042
16056
  handler: async (topolo, args) => {
16043
16057
  const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
16044
16058
  if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
16045
- const input = args["input"];
16046
- if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
16047
- throw new TopoloMcpPublicError("input must be an object.");
16048
- }
16059
+ const input = coerceObjectParam(args["input"], "input");
16049
16060
  const resource = optionalResourceContext(args);
16050
16061
  return topolo.client.readAction(
16051
16062
  actionId,
16052
- input ?? {},
16063
+ input,
16053
16064
  resource ? { resource } : {}
16054
16065
  );
16055
16066
  }
@@ -16075,14 +16086,11 @@ var TOOLS = [
16075
16086
  handler: async (topolo, args) => {
16076
16087
  const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
16077
16088
  if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
16078
- const input = args["input"];
16079
- if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
16080
- throw new TopoloMcpPublicError("input must be an object.");
16081
- }
16089
+ const input = coerceObjectParam(args["input"], "input");
16082
16090
  const resource = optionalResourceContext(args);
16083
16091
  return topolo.client.callAction(
16084
16092
  actionId,
16085
- input ?? {},
16093
+ input,
16086
16094
  {
16087
16095
  confirm: args["confirm"] === true,
16088
16096
  ...resource ? { resource } : {}
@@ -16121,23 +16129,17 @@ var TOOLS = [
16121
16129
  if (!isCanonicalBase64(contentBase64)) throw new TopoloMcpPublicError("contentBase64 must be canonical base64.");
16122
16130
  if (!contentType) throw new TopoloMcpPublicError("contentType is required.");
16123
16131
  if (!fileName) throw new TopoloMcpPublicError("fileName is required.");
16124
- const input = args["input"];
16125
- if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
16126
- throw new TopoloMcpPublicError("input must be an object.");
16127
- }
16128
- const completionInput = args["completionInput"];
16129
- if (completionInput !== void 0 && (!completionInput || typeof completionInput !== "object" || Array.isArray(completionInput))) {
16130
- throw new TopoloMcpPublicError("completionInput must be an object.");
16131
- }
16132
+ const input = coerceObjectParam(args["input"], "input");
16133
+ const completionInput = coerceObjectParam(args["completionInput"], "completionInput");
16132
16134
  const resource = optionalResourceContext(args);
16133
16135
  return topolo.client.uploadActionBase64(
16134
16136
  actionId,
16135
16137
  contentBase64,
16136
- input ?? {},
16138
+ input,
16137
16139
  {
16138
16140
  fileName,
16139
16141
  contentType,
16140
- completionInput: completionInput ?? {},
16142
+ completionInput,
16141
16143
  confirm: args["confirm"] === true,
16142
16144
  ...resource ? { resource } : {}
16143
16145
  }
@@ -16162,11 +16164,8 @@ var TOOLS = [
16162
16164
  handler: async (topolo, args) => {
16163
16165
  const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
16164
16166
  if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
16165
- const input = args["input"];
16166
- if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
16167
- throw new TopoloMcpPublicError("input must be an object.");
16168
- }
16169
- return topolo.client.validateActionInput(actionId, input ?? {});
16167
+ const input = coerceObjectParam(args["input"], "input");
16168
+ return topolo.client.validateActionInput(actionId, input);
16170
16169
  }
16171
16170
  },
16172
16171
  {
@@ -16190,14 +16189,11 @@ var TOOLS = [
16190
16189
  handler: async (topolo, args) => {
16191
16190
  const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
16192
16191
  if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
16193
- const input = args["input"];
16194
- if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
16195
- throw new TopoloMcpPublicError("input must be an object.");
16196
- }
16192
+ const input = coerceObjectParam(args["input"], "input");
16197
16193
  const resource = optionalResourceContext(args);
16198
16194
  return topolo.client.planAction(
16199
16195
  actionId,
16200
- input ?? {},
16196
+ input,
16201
16197
  {
16202
16198
  confirm: args["confirm"] === true,
16203
16199
  ...resource ? { resource } : {}
@@ -16374,7 +16370,7 @@ var TOOLS = [
16374
16370
  },
16375
16371
  additionalProperties: false
16376
16372
  },
16377
- handler: async (_topolo, args) => {
16373
+ handler: async (topolo, args) => {
16378
16374
  const application = args["application"];
16379
16375
  if (application === void 0) {
16380
16376
  return {
@@ -16384,12 +16380,8 @@ var TOOLS = [
16384
16380
  requirements: APPLICATION_REQUIREMENTS
16385
16381
  };
16386
16382
  }
16387
- if (typeof application !== "string" || !APPLICATION_IDS.includes(application)) {
16388
- throw new TopoloMcpPublicError(
16389
- `Unknown application "${String(application)}". ${formatKnownValues(APPLICATION_IDS, "applications")}`
16390
- );
16391
- }
16392
- const app = APPLICATIONS[application];
16383
+ const resolved = await resolveDirectoryApplication(topolo, application);
16384
+ const app = resolved.application;
16393
16385
  return {
16394
16386
  version: APPLICATION_REQUIREMENTS_VERSION,
16395
16387
  application: app,
@@ -16419,7 +16411,7 @@ var TOOLS = [
16419
16411
  },
16420
16412
  additionalProperties: false
16421
16413
  },
16422
- handler: async (_topolo, args) => {
16414
+ handler: async (topolo, args) => {
16423
16415
  const application = args["application"];
16424
16416
  const failOn = args["failOn"];
16425
16417
  if (failOn !== void 0 && typeof failOn !== "string") {
@@ -16428,15 +16420,12 @@ var TOOLS = [
16428
16420
  const gate = failOn ? normalizeFailOn(failOn) : null;
16429
16421
  let report;
16430
16422
  if (application === void 0) {
16431
- report = auditAllApplicationRequirements();
16423
+ const directory = await listApplicationDirectory(topolo.client);
16424
+ report = auditApplicationEntries(directory.applications.map((app) => app.application));
16432
16425
  return gate ? { ...report, conformanceGate: evaluateApplicationAuditGate(report, gate) } : report;
16433
16426
  }
16434
- if (typeof application !== "string" || !APPLICATION_IDS.includes(application)) {
16435
- throw new TopoloMcpPublicError(
16436
- `Unknown application "${String(application)}". ${formatKnownValues(APPLICATION_IDS, "applications")}`
16437
- );
16438
- }
16439
- report = auditAllApplicationRequirements([application]);
16427
+ const resolved = await resolveDirectoryApplication(topolo, application);
16428
+ report = auditApplicationEntries([resolved.application]);
16440
16429
  return gate ? { ...report, conformanceGate: evaluateApplicationAuditGate(report, gate) } : report;
16441
16430
  }
16442
16431
  },
@@ -16576,31 +16565,19 @@ function statusesAtOrWorse(threshold) {
16576
16565
  return ["missing", "needs_review", "partial"];
16577
16566
  }
16578
16567
  function displayAppId(entry) {
16579
- for (const value of [entry.slug, entry.name, entry.appId]) {
16580
- if (typeof value !== "string" || !value.trim()) continue;
16581
- for (const candidate of appIdCandidates(value)) {
16582
- if (Object.prototype.hasOwnProperty.call(DEFAULT_APP_URLS, candidate)) {
16583
- return candidate;
16584
- }
16585
- }
16586
- }
16587
- return appIdCandidates(entry.slug || entry.appId)[0] || entry.appId;
16568
+ return friendlyAppId(entry);
16588
16569
  }
16589
- function appIdCandidates(value) {
16590
- const normalized = value.trim().toLowerCase().replace(/\s+/g, "-");
16591
- const withoutTopolo = normalized.startsWith("topolo-") ? normalized.slice("topolo-".length) : normalized;
16592
- return [.../* @__PURE__ */ new Set([
16593
- normalized,
16594
- normalized.replace(/-/g, "_"),
16595
- withoutTopolo,
16596
- withoutTopolo.replace(/-/g, "_")
16597
- ])].filter(Boolean);
16598
- }
16599
- function formatKnownValues(values, label) {
16600
- const sorted = [...values].sort();
16601
- const preview = sorted.slice(0, 25).join(", ");
16602
- const suffix = sorted.length > 25 ? `, ... +${sorted.length - 25} more` : "";
16603
- return `Run discovery for the full ${label} list. Known snapshot sample: ${preview}${suffix}`;
16570
+ async function resolveDirectoryApplication(topolo, application) {
16571
+ if (typeof application !== "string" || !application.trim()) {
16572
+ throw new TopoloMcpPublicError("`application` must be a non-empty string.");
16573
+ }
16574
+ try {
16575
+ return await resolveApplicationDirectoryEntry(topolo.client, application);
16576
+ } catch (error2) {
16577
+ throw new TopoloMcpPublicError(
16578
+ error2 instanceof Error ? error2.message : `Unknown application "${application}".`
16579
+ );
16580
+ }
16604
16581
  }
16605
16582
 
16606
16583
  // src/version.ts
package/dist/index.js CHANGED
@@ -104,57 +104,8 @@ var TopoloHttpError = class extends TopoloSdkError {
104
104
  }
105
105
  };
106
106
  var APP_API_URLS = {
107
- agent: "https://agent.topolo.app",
108
107
  auth: "https://auth.topolo.app",
109
- backup: "https://backup.topolo.app",
110
- blog: "https://blog.topolo.app",
111
- books: "https://books.topolo.app",
112
- brand: "https://brand.topolo.app",
113
- bugfix: "https://bugfix.topolo.app",
114
- bytes: "https://bytes.topolo.app",
115
- calendar: "https://calendar.topolo.app",
116
- campaigns: "https://campaigns.topolo.app",
117
- capacity: "https://capacity.topolo.app",
118
- chat: "https://chat.topolo.app",
119
- commerce: "https://commerce.topolo.app",
120
- compose: "https://compose.topolo.app",
121
- consent: "https://consent.topolo.app",
122
- crm: "https://crm.topolo.app",
123
- design: "https://design.topolo.app",
124
- developers: "https://developers.topolo.app",
125
- director: "https://director.topolo.app",
126
- feed: "https://feed.topolo.app",
127
- flow: "https://flow.topolo.app",
128
- forecast: "https://forecast.topolo.app",
129
- forms: "https://forms.topolo.app",
130
- home: "https://home.topolo.app",
131
- insights: "https://insights.topolo.app",
132
- inventory: "https://inventory.topolo.app",
133
- learn: "https://learn.topolo.app",
134
- localize: "https://localize.topolo.app",
135
- mail: "https://mail.topolo.app",
136
- mdm: "https://mdm.topolo.app",
137
- messages: "https://messages.topolo.app",
138
- nexus: "https://nexus.topolo.app",
139
- notify: "https://notify.topolo.app",
140
- observability_watch: "https://observability-watch.topolo.app",
141
- one: "https://www.topolo.app",
142
- p2p: "https://p2p.topolo.app",
143
- pay: "https://pay.topolo.app",
144
- people: "https://people.topolo.app",
145
- "quro.api": "https://api.ol0.me",
146
- "quro.redirect": "https://ol0.me",
147
- roadmapper: "https://roadmapper.topolo.app",
148
- sign: "https://sign.topolo.app",
149
- social_studio: "https://studio.topolo.app",
150
- socialize: "https://socialize.topolo.app",
151
- spaces: "https://spaces.topolo.app",
152
- status: "https://status.topolo.app",
153
- success: "https://success.topolo.app",
154
- support: "https://support.topolo.app",
155
- survey: "https://survey.topolo.app",
156
- voice: "https://voice.topolo.app",
157
- web: "https://web.topolo.app"
108
+ developers: "https://developers.topolo.app"
158
109
  };
159
110
  var APPLICATIONS = {
160
111
  "admin": {
@@ -1880,7 +1831,145 @@ var APPLICATIONS = {
1880
1831
  ]
1881
1832
  }
1882
1833
  };
1883
- var APPLICATION_REQUIREMENTS_VERSION = "2026-06-07.1";
1834
+ function friendlyAppId(entry) {
1835
+ for (const value of [entry.slug, entry.name, entry.appId]) {
1836
+ if (typeof value !== "string" || !value.trim()) continue;
1837
+ const normalized = value.trim().toLowerCase().replace(/\s+/g, "-");
1838
+ const withoutPrefix = normalized.replace(/^(?:app[_-])?topolo[-_]+/, "");
1839
+ if (withoutPrefix) return withoutPrefix;
1840
+ }
1841
+ return entry.appId;
1842
+ }
1843
+ function idVariants(value) {
1844
+ const normalized = value.trim().toLowerCase().replace(/\s+/g, "-");
1845
+ return [.../* @__PURE__ */ new Set([
1846
+ normalized,
1847
+ normalized.replace(/-/g, "_"),
1848
+ normalized.replace(/_/g, "-")
1849
+ ])].filter(Boolean);
1850
+ }
1851
+ var STATIC_APPLICATIONS = APPLICATIONS;
1852
+ function staticApplicationForId(id) {
1853
+ for (const variant of idVariants(id)) {
1854
+ const entry = STATIC_APPLICATIONS[variant];
1855
+ if (entry) return entry;
1856
+ }
1857
+ return null;
1858
+ }
1859
+ function applicationEntryFromCatalog(live) {
1860
+ const id = friendlyAppId(live);
1861
+ return {
1862
+ id,
1863
+ appDir: "-",
1864
+ name: live.name ?? live.slug ?? live.appId,
1865
+ packageName: null,
1866
+ productionUrl: live.launchUrl ?? live.apiBaseUrl ?? null,
1867
+ services: live.apiBaseUrl ? [id] : [],
1868
+ deployTargets: []
1869
+ };
1870
+ }
1871
+ var DIRECTORY_PAGE_LIMIT = 100;
1872
+ var DIRECTORY_MAX_PAGES = 100;
1873
+ function staticApplicationDirectory() {
1874
+ const applications = Object.entries(STATIC_APPLICATIONS).map(([id, application]) => ({
1875
+ id,
1876
+ application,
1877
+ source: "static",
1878
+ live: null
1879
+ })).sort((left, right) => left.id.localeCompare(right.id));
1880
+ return { source: "static_fallback", applications };
1881
+ }
1882
+ function directoryApplicationFromLive(live) {
1883
+ const id = friendlyAppId(live);
1884
+ return {
1885
+ id,
1886
+ // Prefer the static snapshot's richer repo/deploy metadata when the live
1887
+ // registry confirms the app; synthesize from the live entry otherwise.
1888
+ application: staticApplicationForId(id) ?? applicationEntryFromCatalog(live),
1889
+ source: "live",
1890
+ live
1891
+ };
1892
+ }
1893
+ async function listApplicationDirectory(client) {
1894
+ if (!client) return staticApplicationDirectory();
1895
+ let services;
1896
+ try {
1897
+ services = [];
1898
+ let cursor;
1899
+ for (let page = 0; page < DIRECTORY_MAX_PAGES; page += 1) {
1900
+ const result = await client.searchServices({
1901
+ ...cursor ? { cursor } : {},
1902
+ limit: DIRECTORY_PAGE_LIMIT
1903
+ });
1904
+ services.push(...result.services);
1905
+ if (!result.page.nextCursor) break;
1906
+ cursor = result.page.nextCursor;
1907
+ }
1908
+ } catch {
1909
+ return staticApplicationDirectory();
1910
+ }
1911
+ const seen = /* @__PURE__ */ new Map();
1912
+ for (const live of services) {
1913
+ const entry = directoryApplicationFromLive(live);
1914
+ if (!seen.has(entry.id)) seen.set(entry.id, entry);
1915
+ }
1916
+ return {
1917
+ source: "live",
1918
+ applications: [...seen.values()].sort((left, right) => left.id.localeCompare(right.id))
1919
+ };
1920
+ }
1921
+ function matchesDirectoryApplication(app, needle) {
1922
+ const candidates = new Set(idVariants(needle));
1923
+ const keys = [
1924
+ app.id,
1925
+ app.application.id,
1926
+ app.application.name,
1927
+ app.live?.appId,
1928
+ app.live?.slug,
1929
+ app.live?.name
1930
+ ];
1931
+ for (const key of keys) {
1932
+ if (typeof key !== "string" || !key.trim()) continue;
1933
+ for (const variant of idVariants(key)) {
1934
+ if (candidates.has(variant)) return true;
1935
+ }
1936
+ for (const variant of idVariants(friendlyAppId({ appId: key }))) {
1937
+ if (candidates.has(variant)) return true;
1938
+ }
1939
+ }
1940
+ return false;
1941
+ }
1942
+ function formatDirectoryApplicationIds(directory) {
1943
+ const ids = directory.applications.map((app) => app.id).sort();
1944
+ const preview = ids.slice(0, 50).join(", ");
1945
+ const suffix = ids.length > 50 ? `, ... +${ids.length - 50} more` : "";
1946
+ const label = directory.source === "live" ? "Applications available to this credential" : "Applications in the bundled static snapshot (live registry unreachable)";
1947
+ return `${label}: ${preview}${suffix}`;
1948
+ }
1949
+ async function resolveApplicationDirectoryEntry(client, application) {
1950
+ const needle = typeof application === "string" ? application.trim() : "";
1951
+ if (!needle) {
1952
+ throw new TopoloSdkError("unknown_application", "application is required");
1953
+ }
1954
+ if (client) {
1955
+ let live = null;
1956
+ try {
1957
+ live = await client.getService(needle);
1958
+ } catch {
1959
+ live = null;
1960
+ }
1961
+ if (live) return directoryApplicationFromLive(live);
1962
+ }
1963
+ const directory = await listApplicationDirectory(client);
1964
+ const match = directory.applications.find((app) => matchesDirectoryApplication(app, needle));
1965
+ if (match) return match;
1966
+ throw new TopoloSdkError(
1967
+ "unknown_application",
1968
+ `Unknown application "${application}". ${formatDirectoryApplicationIds(directory)}`
1969
+ );
1970
+ }
1971
+ var STATIC_APPLICATIONS2 = APPLICATIONS;
1972
+ var APPLICATION_REQUIREMENTS_VERSION = "2026-08-11.1";
1884
1973
  var APPLICATION_REQUIREMENTS = [
1885
1974
  {
1886
1975
  id: "platform-metadata",
@@ -1890,10 +1979,10 @@ var APPLICATION_REQUIREMENTS = [
1890
1979
  evidence: [
1891
1980
  "topolo.cloudcontrol.json exists for every deployed app surface",
1892
1981
  "package.json names the package or app when the repo ships code",
1893
- "The SDK application catalog exposes the app through topolo apps and MCP discovery"
1982
+ "The live platform registry exposes the app through topolo apps and MCP discovery"
1894
1983
  ],
1895
1984
  implementation: [
1896
- "Add the app to the SDK application catalog generator before exposing it to agents",
1985
+ "Register the app in the live platform registry (Auth service catalog) before exposing it to agents",
1897
1986
  "Keep production URLs, Worker names, Pages projects, routes, domains, and bindings current in CloudControl metadata",
1898
1987
  "Do not leave a new Topolo* app directory without an explicit application ID"
1899
1988
  ]
@@ -1968,7 +2057,7 @@ var APPLICATION_REQUIREMENTS = [
1968
2057
  implementation: [
1969
2058
  "Add production Worker api_url metadata and sdk_app_id for every agent-callable API target",
1970
2059
  "Mark browser, documentation, and runtime-only Worker targets with agent_callable:false",
1971
- "Expose stable app IDs through generated DEFAULT_APP_URLS and live catalog discovery",
2060
+ "Expose stable app IDs through live catalog discovery",
1972
2061
  "Keep typed SDK/CLI/MCP surfaces in sync when an API contract stabilizes"
1973
2062
  ]
1974
2063
  },
@@ -2088,15 +2177,24 @@ function applicationRequirementScopes(application) {
2088
2177
  }
2089
2178
  return Array.from(scopes);
2090
2179
  }
2180
+ function fallbackApplication(id) {
2181
+ const entry = STATIC_APPLICATIONS2[id];
2182
+ if (!entry) {
2183
+ throw new Error(
2184
+ `Unknown application "${id}" in the static fallback snapshot. Resolve applications from the live registry (resolveApplicationDirectoryEntry) and pass the entry directly.`
2185
+ );
2186
+ }
2187
+ return entry;
2188
+ }
2091
2189
  function requirementsForApplication(applicationOrId) {
2092
- const application = typeof applicationOrId === "string" ? APPLICATIONS[applicationOrId] : applicationOrId;
2190
+ const application = typeof applicationOrId === "string" ? fallbackApplication(applicationOrId) : applicationOrId;
2093
2191
  const scopes = new Set(applicationRequirementScopes(application));
2094
2192
  return APPLICATION_REQUIREMENTS.filter(
2095
2193
  (requirement) => requirement.appliesTo.some((scope) => scopes.has(scope))
2096
2194
  );
2097
2195
  }
2098
2196
  function auditApplicationRequirements(applicationOrId) {
2099
- const application = typeof applicationOrId === "string" ? APPLICATIONS[applicationOrId] : applicationOrId;
2197
+ const application = typeof applicationOrId === "string" ? fallbackApplication(applicationOrId) : applicationOrId;
2100
2198
  const scopes = applicationRequirementScopes(application);
2101
2199
  const findings = requirementsForApplication(application).map(
2102
2200
  (requirement) => evaluateRequirement(application, requirement)
@@ -2109,10 +2207,12 @@ function auditApplicationRequirements(applicationOrId) {
2109
2207
  findings
2110
2208
  };
2111
2209
  }
2112
- function auditAllApplicationRequirements(applicationIds = Object.keys(APPLICATIONS).sort()) {
2113
- const applications = applicationIds.map(
2114
- (applicationId) => auditApplicationRequirements(applicationId)
2210
+ function auditApplicationEntries(applications) {
2211
+ return buildAuditReport(
2212
+ applications.map((application) => auditApplicationRequirements(application))
2115
2213
  );
2214
+ }
2215
+ function buildAuditReport(applications) {
2116
2216
  const migrationQueue = applications.flatMap(
2117
2217
  (audit) => audit.findings.filter((finding2) => finding2.status !== "met").map((finding2) => ({
2118
2218
  applicationId: audit.application.id,
@@ -3415,8 +3515,9 @@ var TopoloClient = class _TopoloClient {
3415
3515
  });
3416
3516
  }
3417
3517
  /**
3418
- * Bundled generated registry for tooling that audits platform packaging, not
3419
- * for deciding what the current credential may use.
3518
+ * @deprecated Static fallback snapshot only. Use `searchServices()` (the
3519
+ * live credential-scoped registry) for anything that decides behavior; this
3520
+ * exists for offline packaging audits when the registry is unreachable.
3420
3521
  */
3421
3522
  listBundledServices() {
3422
3523
  const apps = Object.values(APPLICATIONS);
@@ -3995,57 +4096,8 @@ var TopoloHttpError2 = class extends TopoloSdkError2 {
3995
4096
  }
3996
4097
  };
3997
4098
  var APP_API_URLS2 = {
3998
- agent: "https://agent.topolo.app",
3999
4099
  auth: "https://auth.topolo.app",
4000
- backup: "https://backup.topolo.app",
4001
- blog: "https://blog.topolo.app",
4002
- books: "https://books.topolo.app",
4003
- brand: "https://brand.topolo.app",
4004
- bugfix: "https://bugfix.topolo.app",
4005
- bytes: "https://bytes.topolo.app",
4006
- calendar: "https://calendar.topolo.app",
4007
- campaigns: "https://campaigns.topolo.app",
4008
- capacity: "https://capacity.topolo.app",
4009
- chat: "https://chat.topolo.app",
4010
- commerce: "https://commerce.topolo.app",
4011
- compose: "https://compose.topolo.app",
4012
- consent: "https://consent.topolo.app",
4013
- crm: "https://crm.topolo.app",
4014
- design: "https://design.topolo.app",
4015
- developers: "https://developers.topolo.app",
4016
- director: "https://director.topolo.app",
4017
- feed: "https://feed.topolo.app",
4018
- flow: "https://flow.topolo.app",
4019
- forecast: "https://forecast.topolo.app",
4020
- forms: "https://forms.topolo.app",
4021
- home: "https://home.topolo.app",
4022
- insights: "https://insights.topolo.app",
4023
- inventory: "https://inventory.topolo.app",
4024
- learn: "https://learn.topolo.app",
4025
- localize: "https://localize.topolo.app",
4026
- mail: "https://mail.topolo.app",
4027
- mdm: "https://mdm.topolo.app",
4028
- messages: "https://messages.topolo.app",
4029
- nexus: "https://nexus.topolo.app",
4030
- notify: "https://notify.topolo.app",
4031
- observability_watch: "https://observability-watch.topolo.app",
4032
- one: "https://www.topolo.app",
4033
- p2p: "https://p2p.topolo.app",
4034
- pay: "https://pay.topolo.app",
4035
- people: "https://people.topolo.app",
4036
- "quro.api": "https://api.ol0.me",
4037
- "quro.redirect": "https://ol0.me",
4038
- roadmapper: "https://roadmapper.topolo.app",
4039
- sign: "https://sign.topolo.app",
4040
- social_studio: "https://studio.topolo.app",
4041
- socialize: "https://socialize.topolo.app",
4042
- spaces: "https://spaces.topolo.app",
4043
- status: "https://status.topolo.app",
4044
- success: "https://success.topolo.app",
4045
- support: "https://support.topolo.app",
4046
- survey: "https://survey.topolo.app",
4047
- voice: "https://voice.topolo.app",
4048
- web: "https://web.topolo.app"
4100
+ developers: "https://developers.topolo.app"
4049
4101
  };
4050
4102
  var DEFAULT_APP_URLS2 = APP_API_URLS2;
4051
4103
  function resolveServiceUrl2(service, overrides) {
@@ -4412,7 +4464,6 @@ function publicMcpErrorMessage(error, fallback) {
4412
4464
  }
4413
4465
 
4414
4466
  // src/tools.ts
4415
- var APPLICATION_IDS = Object.keys(APPLICATIONS).sort();
4416
4467
  var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
4417
4468
  function requiredString(args, name) {
4418
4469
  const value = typeof args[name] === "string" ? args[name].trim() : "";
@@ -4428,6 +4479,20 @@ function optionalResourceContext(args) {
4428
4479
  }
4429
4480
  return { resourceType, resourceId };
4430
4481
  }
4482
+ function coerceObjectParam(value, name) {
4483
+ let candidate = value;
4484
+ if (typeof candidate === "string" && candidate.trim().startsWith("{")) {
4485
+ try {
4486
+ candidate = JSON.parse(candidate);
4487
+ } catch {
4488
+ }
4489
+ }
4490
+ if (candidate === void 0) return {};
4491
+ if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) {
4492
+ throw new TopoloMcpPublicError(`${name} must be an object.`);
4493
+ }
4494
+ return candidate;
4495
+ }
4431
4496
  var TOOLS = [
4432
4497
  {
4433
4498
  name: "topolo_whoami",
@@ -4578,14 +4643,11 @@ var TOOLS = [
4578
4643
  handler: async (topolo, args) => {
4579
4644
  const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
4580
4645
  if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
4581
- const input = args["input"];
4582
- if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
4583
- throw new TopoloMcpPublicError("input must be an object.");
4584
- }
4646
+ const input = coerceObjectParam(args["input"], "input");
4585
4647
  const resource = optionalResourceContext(args);
4586
4648
  return topolo.client.readAction(
4587
4649
  actionId,
4588
- input ?? {},
4650
+ input,
4589
4651
  resource ? { resource } : {}
4590
4652
  );
4591
4653
  }
@@ -4611,14 +4673,11 @@ var TOOLS = [
4611
4673
  handler: async (topolo, args) => {
4612
4674
  const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
4613
4675
  if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
4614
- const input = args["input"];
4615
- if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
4616
- throw new TopoloMcpPublicError("input must be an object.");
4617
- }
4676
+ const input = coerceObjectParam(args["input"], "input");
4618
4677
  const resource = optionalResourceContext(args);
4619
4678
  return topolo.client.callAction(
4620
4679
  actionId,
4621
- input ?? {},
4680
+ input,
4622
4681
  {
4623
4682
  confirm: args["confirm"] === true,
4624
4683
  ...resource ? { resource } : {}
@@ -4657,23 +4716,17 @@ var TOOLS = [
4657
4716
  if (!isCanonicalBase642(contentBase64)) throw new TopoloMcpPublicError("contentBase64 must be canonical base64.");
4658
4717
  if (!contentType) throw new TopoloMcpPublicError("contentType is required.");
4659
4718
  if (!fileName) throw new TopoloMcpPublicError("fileName is required.");
4660
- const input = args["input"];
4661
- if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
4662
- throw new TopoloMcpPublicError("input must be an object.");
4663
- }
4664
- const completionInput = args["completionInput"];
4665
- if (completionInput !== void 0 && (!completionInput || typeof completionInput !== "object" || Array.isArray(completionInput))) {
4666
- throw new TopoloMcpPublicError("completionInput must be an object.");
4667
- }
4719
+ const input = coerceObjectParam(args["input"], "input");
4720
+ const completionInput = coerceObjectParam(args["completionInput"], "completionInput");
4668
4721
  const resource = optionalResourceContext(args);
4669
4722
  return topolo.client.uploadActionBase64(
4670
4723
  actionId,
4671
4724
  contentBase64,
4672
- input ?? {},
4725
+ input,
4673
4726
  {
4674
4727
  fileName,
4675
4728
  contentType,
4676
- completionInput: completionInput ?? {},
4729
+ completionInput,
4677
4730
  confirm: args["confirm"] === true,
4678
4731
  ...resource ? { resource } : {}
4679
4732
  }
@@ -4698,11 +4751,8 @@ var TOOLS = [
4698
4751
  handler: async (topolo, args) => {
4699
4752
  const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
4700
4753
  if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
4701
- const input = args["input"];
4702
- if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
4703
- throw new TopoloMcpPublicError("input must be an object.");
4704
- }
4705
- return topolo.client.validateActionInput(actionId, input ?? {});
4754
+ const input = coerceObjectParam(args["input"], "input");
4755
+ return topolo.client.validateActionInput(actionId, input);
4706
4756
  }
4707
4757
  },
4708
4758
  {
@@ -4726,14 +4776,11 @@ var TOOLS = [
4726
4776
  handler: async (topolo, args) => {
4727
4777
  const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
4728
4778
  if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
4729
- const input = args["input"];
4730
- if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
4731
- throw new TopoloMcpPublicError("input must be an object.");
4732
- }
4779
+ const input = coerceObjectParam(args["input"], "input");
4733
4780
  const resource = optionalResourceContext(args);
4734
4781
  return topolo.client.planAction(
4735
4782
  actionId,
4736
- input ?? {},
4783
+ input,
4737
4784
  {
4738
4785
  confirm: args["confirm"] === true,
4739
4786
  ...resource ? { resource } : {}
@@ -4910,7 +4957,7 @@ var TOOLS = [
4910
4957
  },
4911
4958
  additionalProperties: false
4912
4959
  },
4913
- handler: async (_topolo, args) => {
4960
+ handler: async (topolo, args) => {
4914
4961
  const application = args["application"];
4915
4962
  if (application === void 0) {
4916
4963
  return {
@@ -4920,12 +4967,8 @@ var TOOLS = [
4920
4967
  requirements: APPLICATION_REQUIREMENTS
4921
4968
  };
4922
4969
  }
4923
- if (typeof application !== "string" || !APPLICATION_IDS.includes(application)) {
4924
- throw new TopoloMcpPublicError(
4925
- `Unknown application "${String(application)}". ${formatKnownValues(APPLICATION_IDS, "applications")}`
4926
- );
4927
- }
4928
- const app = APPLICATIONS[application];
4970
+ const resolved = await resolveDirectoryApplication(topolo, application);
4971
+ const app = resolved.application;
4929
4972
  return {
4930
4973
  version: APPLICATION_REQUIREMENTS_VERSION,
4931
4974
  application: app,
@@ -4955,7 +4998,7 @@ var TOOLS = [
4955
4998
  },
4956
4999
  additionalProperties: false
4957
5000
  },
4958
- handler: async (_topolo, args) => {
5001
+ handler: async (topolo, args) => {
4959
5002
  const application = args["application"];
4960
5003
  const failOn = args["failOn"];
4961
5004
  if (failOn !== void 0 && typeof failOn !== "string") {
@@ -4964,15 +5007,12 @@ var TOOLS = [
4964
5007
  const gate = failOn ? normalizeFailOn(failOn) : null;
4965
5008
  let report;
4966
5009
  if (application === void 0) {
4967
- report = auditAllApplicationRequirements();
5010
+ const directory = await listApplicationDirectory(topolo.client);
5011
+ report = auditApplicationEntries(directory.applications.map((app) => app.application));
4968
5012
  return gate ? { ...report, conformanceGate: evaluateApplicationAuditGate(report, gate) } : report;
4969
5013
  }
4970
- if (typeof application !== "string" || !APPLICATION_IDS.includes(application)) {
4971
- throw new TopoloMcpPublicError(
4972
- `Unknown application "${String(application)}". ${formatKnownValues(APPLICATION_IDS, "applications")}`
4973
- );
4974
- }
4975
- report = auditAllApplicationRequirements([application]);
5014
+ const resolved = await resolveDirectoryApplication(topolo, application);
5015
+ report = auditApplicationEntries([resolved.application]);
4976
5016
  return gate ? { ...report, conformanceGate: evaluateApplicationAuditGate(report, gate) } : report;
4977
5017
  }
4978
5018
  },
@@ -5112,31 +5152,19 @@ function statusesAtOrWorse(threshold) {
5112
5152
  return ["missing", "needs_review", "partial"];
5113
5153
  }
5114
5154
  function displayAppId(entry) {
5115
- for (const value of [entry.slug, entry.name, entry.appId]) {
5116
- if (typeof value !== "string" || !value.trim()) continue;
5117
- for (const candidate of appIdCandidates(value)) {
5118
- if (Object.prototype.hasOwnProperty.call(DEFAULT_APP_URLS, candidate)) {
5119
- return candidate;
5120
- }
5121
- }
5122
- }
5123
- return appIdCandidates(entry.slug || entry.appId)[0] || entry.appId;
5124
- }
5125
- function appIdCandidates(value) {
5126
- const normalized = value.trim().toLowerCase().replace(/\s+/g, "-");
5127
- const withoutTopolo = normalized.startsWith("topolo-") ? normalized.slice("topolo-".length) : normalized;
5128
- return [.../* @__PURE__ */ new Set([
5129
- normalized,
5130
- normalized.replace(/-/g, "_"),
5131
- withoutTopolo,
5132
- withoutTopolo.replace(/-/g, "_")
5133
- ])].filter(Boolean);
5155
+ return friendlyAppId(entry);
5134
5156
  }
5135
- function formatKnownValues(values, label) {
5136
- const sorted = [...values].sort();
5137
- const preview = sorted.slice(0, 25).join(", ");
5138
- const suffix = sorted.length > 25 ? `, ... +${sorted.length - 25} more` : "";
5139
- return `Run discovery for the full ${label} list. Known snapshot sample: ${preview}${suffix}`;
5157
+ async function resolveDirectoryApplication(topolo, application) {
5158
+ if (typeof application !== "string" || !application.trim()) {
5159
+ throw new TopoloMcpPublicError("`application` must be a non-empty string.");
5160
+ }
5161
+ try {
5162
+ return await resolveApplicationDirectoryEntry(topolo.client, application);
5163
+ } catch (error) {
5164
+ throw new TopoloMcpPublicError(
5165
+ error instanceof Error ? error.message : `Unknown application "${application}".`
5166
+ );
5167
+ }
5140
5168
  }
5141
5169
 
5142
5170
  // src/version.ts
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@topolo/mcp",
3
- "version": "0.9.11",
4
- "topoloPublishedVersion": "0.9.11",
3
+ "version": "0.10.0",
4
+ "topoloPublishedVersion": "0.10.0",
5
5
  "description": "Model Context Protocol server for the Topolo platform. Exposes scope-gated tools that third-party agents (Claude, Codex, etc.) can call natively.",
6
6
  "type": "module",
7
7
  "bin": {
@@ -37,7 +37,7 @@
37
37
  "@modelcontextprotocol/sdk": "^1.0.0"
38
38
  },
39
39
  "peerDependencies": {
40
- "@topolo/sdk": "^0.9.10"
40
+ "@topolo/sdk": "^0.10.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@topolo/sdk": "file:../topolo-sdk",