@topolo/mcp 0.10.0 → 0.10.2
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 +3 -0
- package/dist/dispatch.js +61 -11
- package/dist/http.js +88 -18
- package/dist/index.js +103 -11
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -217,6 +217,9 @@ sent.
|
|
|
217
217
|
catalog. They do not expose the global generated platform catalog.
|
|
218
218
|
- **Credential-scoped action discovery.** `topolo_search_actions` reads only one
|
|
219
219
|
app partition and returns at most 100 permission-filtered actions per page.
|
|
220
|
+
Search, capability discovery, validation, planning, and application audit
|
|
221
|
+
return compact agent guidance by default; pass `detail: true` only when the
|
|
222
|
+
full contracts or findings are needed.
|
|
220
223
|
- **Audit headers.** Every request sends `X-Topolo-Client: topolo-mcp/<ver>`,
|
|
221
224
|
`X-Topolo-Agent: <label>`, `X-Topolo-Request-Id: <uuid>`.
|
|
222
225
|
- **Write-action confirmation.** The SDK refuses mutating HTTP methods unless
|
package/dist/dispatch.js
CHANGED
|
@@ -7,6 +7,10 @@ import {
|
|
|
7
7
|
APPLICATION_REQUIREMENTS_VERSION,
|
|
8
8
|
auditApplicationEntries,
|
|
9
9
|
applicationRequirementScopes,
|
|
10
|
+
compactActionCatalogEntry,
|
|
11
|
+
compactActionPlan,
|
|
12
|
+
compactActionValidation,
|
|
13
|
+
compactApplicationAudit,
|
|
10
14
|
friendlyAppId,
|
|
11
15
|
listApplicationDirectory,
|
|
12
16
|
requirementsForApplication,
|
|
@@ -78,6 +82,17 @@ function optionalResourceContext(args) {
|
|
|
78
82
|
}
|
|
79
83
|
return { resourceType, resourceId };
|
|
80
84
|
}
|
|
85
|
+
function summarizeActionCapabilities(service, actions) {
|
|
86
|
+
return {
|
|
87
|
+
service,
|
|
88
|
+
total: actions.length,
|
|
89
|
+
readOnly: actions.filter((action) => action.readOnly).length,
|
|
90
|
+
mutating: actions.filter((action) => !action.readOnly).length,
|
|
91
|
+
destructive: actions.filter((action) => action.destructive).length,
|
|
92
|
+
confirmationRequired: actions.filter((action) => action.requiresConfirmation).length,
|
|
93
|
+
resourceTypes: [...new Set(actions.map((action) => action.agentContract?.resource?.kind).filter(Boolean))].sort()
|
|
94
|
+
};
|
|
95
|
+
}
|
|
81
96
|
function coerceObjectParam(value, name) {
|
|
82
97
|
let candidate = value;
|
|
83
98
|
if (typeof candidate === "string" && candidate.trim().startsWith("{")) {
|
|
@@ -117,7 +132,8 @@ var TOOLS = [
|
|
|
117
132
|
properties: {
|
|
118
133
|
query: { type: "string" },
|
|
119
134
|
cursor: { type: "string" },
|
|
120
|
-
limit: { type: "integer", minimum: 1, maximum: 100, default: 25 }
|
|
135
|
+
limit: { type: "integer", minimum: 1, maximum: 100, default: 25 },
|
|
136
|
+
detail: { type: "boolean", description: "Return full schemas and agent contracts. Defaults to compact action guidance." }
|
|
121
137
|
},
|
|
122
138
|
additionalProperties: false
|
|
123
139
|
},
|
|
@@ -171,12 +187,13 @@ var TOOLS = [
|
|
|
171
187
|
handler: async (topolo, args) => {
|
|
172
188
|
const service = typeof args["service"] === "string" ? args["service"].trim() : "";
|
|
173
189
|
if (!service) throw new TopoloMcpPublicError("service is required for bounded action discovery.");
|
|
174
|
-
|
|
190
|
+
const result = await topolo.client.searchActions({
|
|
175
191
|
service,
|
|
176
192
|
query: typeof args["query"] === "string" ? args["query"] : void 0,
|
|
177
193
|
cursor: typeof args["cursor"] === "string" ? args["cursor"] : void 0,
|
|
178
194
|
limit: typeof args["limit"] === "number" ? args["limit"] : void 0
|
|
179
195
|
});
|
|
196
|
+
return args["detail"] === true ? result : { actions: result.actions.map(compactActionCatalogEntry), page: result.page };
|
|
180
197
|
}
|
|
181
198
|
},
|
|
182
199
|
{
|
|
@@ -342,7 +359,8 @@ var TOOLS = [
|
|
|
342
359
|
type: "object",
|
|
343
360
|
properties: {
|
|
344
361
|
actionId: { type: "string", minLength: 1 },
|
|
345
|
-
input: { type: "object", additionalProperties: true }
|
|
362
|
+
input: { type: "object", additionalProperties: true },
|
|
363
|
+
detail: { type: "boolean", description: "Include the full action contract. Defaults to a compact validation result." }
|
|
346
364
|
},
|
|
347
365
|
required: ["actionId"],
|
|
348
366
|
additionalProperties: false
|
|
@@ -351,7 +369,8 @@ var TOOLS = [
|
|
|
351
369
|
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
352
370
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
353
371
|
const input = coerceObjectParam(args["input"], "input");
|
|
354
|
-
|
|
372
|
+
const result = await topolo.client.validateActionInput(actionId, input);
|
|
373
|
+
return args["detail"] === true ? result : compactActionValidation(result.action.actionId, result.validation);
|
|
355
374
|
}
|
|
356
375
|
},
|
|
357
376
|
{
|
|
@@ -367,7 +386,8 @@ var TOOLS = [
|
|
|
367
386
|
input: { type: "object", additionalProperties: true },
|
|
368
387
|
resourceType: { type: "string", description: "Optional resource-scoping alias published in the app resource catalog (e.g. workspace, brand, merchant)." },
|
|
369
388
|
resourceId: { type: "string", description: "Resource id. Required when resourceType is provided." },
|
|
370
|
-
confirm: { type: "boolean", description: "Include confirmation in the plan without executing the action." }
|
|
389
|
+
confirm: { type: "boolean", description: "Include confirmation in the plan without executing the action." },
|
|
390
|
+
detail: { type: "boolean", description: "Include the full action contract. Defaults to the executable request and verification plan." }
|
|
371
391
|
},
|
|
372
392
|
required: ["actionId"],
|
|
373
393
|
additionalProperties: false
|
|
@@ -377,7 +397,7 @@ var TOOLS = [
|
|
|
377
397
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
378
398
|
const input = coerceObjectParam(args["input"], "input");
|
|
379
399
|
const resource = optionalResourceContext(args);
|
|
380
|
-
|
|
400
|
+
const plan = await topolo.client.planAction(
|
|
381
401
|
actionId,
|
|
382
402
|
input,
|
|
383
403
|
{
|
|
@@ -385,6 +405,7 @@ var TOOLS = [
|
|
|
385
405
|
...resource ? { resource } : {}
|
|
386
406
|
}
|
|
387
407
|
);
|
|
408
|
+
return args["detail"] === true ? plan : compactActionPlan(plan);
|
|
388
409
|
}
|
|
389
410
|
},
|
|
390
411
|
{
|
|
@@ -413,19 +434,42 @@ var TOOLS = [
|
|
|
413
434
|
{
|
|
414
435
|
name: "topolo_discover_capabilities",
|
|
415
436
|
title: "Discover one Topolo application capability contract",
|
|
416
|
-
description: "Lists every action published by one application \u2014 its full capability contract, straight from the registry-canonical catalog. Use the actionService value returned by topolo_search_applications as service.
|
|
437
|
+
description: "Lists every action published by one application \u2014 its full capability contract, straight from the registry-canonical catalog. Use the actionService value returned by topolo_search_applications as service.",
|
|
417
438
|
requiredScopes: [],
|
|
418
439
|
destructive: false,
|
|
419
440
|
inputSchema: {
|
|
420
441
|
type: "object",
|
|
421
|
-
properties: {
|
|
442
|
+
properties: {
|
|
443
|
+
service: { type: "string", minLength: 1 },
|
|
444
|
+
summary: { type: "boolean", description: "Return compact counts without action rows." },
|
|
445
|
+
detail: { type: "boolean", description: "Return full schemas and agent contracts. Defaults to compact capability guidance." }
|
|
446
|
+
},
|
|
422
447
|
required: ["service"],
|
|
423
448
|
additionalProperties: false
|
|
424
449
|
},
|
|
425
450
|
handler: async (topolo, args) => {
|
|
426
451
|
const service = typeof args["service"] === "string" ? args["service"].trim() : "";
|
|
427
452
|
if (!service) throw new TopoloMcpPublicError("service is required.");
|
|
428
|
-
|
|
453
|
+
if (args["summary"] === true && args["detail"] === true) {
|
|
454
|
+
throw new TopoloMcpPublicError("summary cannot be combined with detail.");
|
|
455
|
+
}
|
|
456
|
+
const actions = [];
|
|
457
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
458
|
+
let cursor;
|
|
459
|
+
for (; ; ) {
|
|
460
|
+
const page = await topolo.client.searchActions({ service, limit: 100, ...cursor ? { cursor } : {} });
|
|
461
|
+
actions.push(...page.actions);
|
|
462
|
+
if (!page.page.hasMore) break;
|
|
463
|
+
const nextCursor = page.page.nextCursor?.trim();
|
|
464
|
+
if (!nextCursor || seenCursors.has(nextCursor)) {
|
|
465
|
+
throw new TopoloMcpPublicError("Capability discovery returned an invalid continuation cursor.");
|
|
466
|
+
}
|
|
467
|
+
seenCursors.add(nextCursor);
|
|
468
|
+
cursor = nextCursor;
|
|
469
|
+
}
|
|
470
|
+
if (args["summary"] === true) return summarizeActionCapabilities(service, actions);
|
|
471
|
+
const result = { actions, page: { nextCursor: null, hasMore: false } };
|
|
472
|
+
return args["detail"] === true ? result : { actions: actions.map(compactActionCatalogEntry), page: result.page };
|
|
429
473
|
}
|
|
430
474
|
},
|
|
431
475
|
{
|
|
@@ -593,6 +637,10 @@ var TOOLS = [
|
|
|
593
637
|
type: "string",
|
|
594
638
|
enum: ["missing", "needs_review", "partial"],
|
|
595
639
|
description: "Optional conformance gate. Returns conformanceGate.passed=false when findings at this severity or worse exist."
|
|
640
|
+
},
|
|
641
|
+
detail: {
|
|
642
|
+
type: "boolean",
|
|
643
|
+
description: "Include every finding and migration item. Defaults to per-app scores and a queue count."
|
|
596
644
|
}
|
|
597
645
|
},
|
|
598
646
|
additionalProperties: false
|
|
@@ -608,11 +656,13 @@ var TOOLS = [
|
|
|
608
656
|
if (application === void 0) {
|
|
609
657
|
const directory = await listApplicationDirectory(topolo.client);
|
|
610
658
|
report = auditApplicationEntries(directory.applications.map((app) => app.application));
|
|
611
|
-
|
|
659
|
+
const output2 = args["detail"] === true ? report : compactApplicationAudit(report);
|
|
660
|
+
return gate ? { ...output2, conformanceGate: evaluateApplicationAuditGate(report, gate) } : output2;
|
|
612
661
|
}
|
|
613
662
|
const resolved = await resolveDirectoryApplication(topolo, application);
|
|
614
663
|
report = auditApplicationEntries([resolved.application]);
|
|
615
|
-
|
|
664
|
+
const output = args["detail"] === true ? report : compactApplicationAudit(report);
|
|
665
|
+
return gate ? { ...output, conformanceGate: evaluateApplicationAuditGate(report, gate) } : output;
|
|
616
666
|
}
|
|
617
667
|
},
|
|
618
668
|
{
|
package/dist/http.js
CHANGED
|
@@ -3098,9 +3098,9 @@ var require_data = __commonJS({
|
|
|
3098
3098
|
}
|
|
3099
3099
|
});
|
|
3100
3100
|
|
|
3101
|
-
// ../../node_modules/.pnpm/fast-uri@3.1.
|
|
3101
|
+
// ../../node_modules/.pnpm/fast-uri@3.1.5/node_modules/fast-uri/lib/utils.js
|
|
3102
3102
|
var require_utils = __commonJS({
|
|
3103
|
-
"../../node_modules/.pnpm/fast-uri@3.1.
|
|
3103
|
+
"../../node_modules/.pnpm/fast-uri@3.1.5/node_modules/fast-uri/lib/utils.js"(exports, module) {
|
|
3104
3104
|
"use strict";
|
|
3105
3105
|
var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
|
|
3106
3106
|
var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
|
|
@@ -3411,9 +3411,9 @@ var require_utils = __commonJS({
|
|
|
3411
3411
|
}
|
|
3412
3412
|
});
|
|
3413
3413
|
|
|
3414
|
-
// ../../node_modules/.pnpm/fast-uri@3.1.
|
|
3414
|
+
// ../../node_modules/.pnpm/fast-uri@3.1.5/node_modules/fast-uri/lib/schemes.js
|
|
3415
3415
|
var require_schemes = __commonJS({
|
|
3416
|
-
"../../node_modules/.pnpm/fast-uri@3.1.
|
|
3416
|
+
"../../node_modules/.pnpm/fast-uri@3.1.5/node_modules/fast-uri/lib/schemes.js"(exports, module) {
|
|
3417
3417
|
"use strict";
|
|
3418
3418
|
var { isUUID } = require_utils();
|
|
3419
3419
|
var URN_REG = /([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-.:;=@]|%[\da-f]{2})+)/iu;
|
|
@@ -3621,9 +3621,9 @@ var require_schemes = __commonJS({
|
|
|
3621
3621
|
}
|
|
3622
3622
|
});
|
|
3623
3623
|
|
|
3624
|
-
// ../../node_modules/.pnpm/fast-uri@3.1.
|
|
3624
|
+
// ../../node_modules/.pnpm/fast-uri@3.1.5/node_modules/fast-uri/index.js
|
|
3625
3625
|
var require_fast_uri = __commonJS({
|
|
3626
|
-
"../../node_modules/.pnpm/fast-uri@3.1.
|
|
3626
|
+
"../../node_modules/.pnpm/fast-uri@3.1.5/node_modules/fast-uri/index.js"(exports, module) {
|
|
3627
3627
|
"use strict";
|
|
3628
3628
|
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3629
3629
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
@@ -3639,7 +3639,12 @@ var require_fast_uri = __commonJS({
|
|
|
3639
3639
|
}
|
|
3640
3640
|
function resolve(baseURI, relativeURI, options) {
|
|
3641
3641
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3642
|
-
const
|
|
3642
|
+
const { parsed: baseParsed, malformedAuthorityOrPort: baseMalformed } = parseWithStatus(baseURI, schemelessOptions);
|
|
3643
|
+
const { parsed: relativeParsed, malformedAuthorityOrPort: relativeMalformed } = parseWithStatus(relativeURI, schemelessOptions);
|
|
3644
|
+
if (baseMalformed || relativeMalformed) {
|
|
3645
|
+
throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
|
|
3646
|
+
}
|
|
3647
|
+
const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
|
|
3643
3648
|
schemelessOptions.skipEscape = true;
|
|
3644
3649
|
return serialize(resolved, schemelessOptions);
|
|
3645
3650
|
}
|
|
@@ -3765,6 +3770,7 @@ var require_fast_uri = __commonJS({
|
|
|
3765
3770
|
}
|
|
3766
3771
|
var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
|
|
3767
3772
|
var AUTHORITY_PREFIX = /^(?:[^#/:?]+:)?\/\/([^/?#]*)/;
|
|
3773
|
+
var AUTHORITY_INTRODUCER_REGION = /^(?:[^#/:?]+:)?([/\\\t\n\r]*)/;
|
|
3768
3774
|
function getParseError(parsed, matches) {
|
|
3769
3775
|
if (matches[2] !== void 0 && parsed.path && parsed.path[0] !== "/") {
|
|
3770
3776
|
return 'URI path must start with "/" when authority is present.';
|
|
@@ -3799,6 +3805,20 @@ var require_fast_uri = __commonJS({
|
|
|
3799
3805
|
parsed.error = "URI authority must not contain a literal backslash.";
|
|
3800
3806
|
malformedAuthorityOrPort = true;
|
|
3801
3807
|
}
|
|
3808
|
+
const introducerMatch = uri.match(AUTHORITY_INTRODUCER_REGION);
|
|
3809
|
+
if (introducerMatch !== null) {
|
|
3810
|
+
const region = introducerMatch[1];
|
|
3811
|
+
const normalizedRegion = region.replace(/[\t\n\r]/g, "");
|
|
3812
|
+
if (normalizedRegion.length >= 2) {
|
|
3813
|
+
if (normalizedRegion.slice(0, 2) !== "//") {
|
|
3814
|
+
parsed.error = parsed.error || "URI authority must not contain a literal backslash.";
|
|
3815
|
+
malformedAuthorityOrPort = true;
|
|
3816
|
+
} else if (region.length !== normalizedRegion.length) {
|
|
3817
|
+
parsed.error = parsed.error || "URI authority introducer must not contain whitespace.";
|
|
3818
|
+
malformedAuthorityOrPort = true;
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
}
|
|
3802
3822
|
const matches = uri.match(URI_PARSE);
|
|
3803
3823
|
if (matches) {
|
|
3804
3824
|
parsed.scheme = matches[1];
|
|
@@ -15832,6 +15852,10 @@ import {
|
|
|
15832
15852
|
APPLICATION_REQUIREMENTS_VERSION,
|
|
15833
15853
|
auditApplicationEntries,
|
|
15834
15854
|
applicationRequirementScopes,
|
|
15855
|
+
compactActionCatalogEntry,
|
|
15856
|
+
compactActionPlan,
|
|
15857
|
+
compactActionValidation,
|
|
15858
|
+
compactApplicationAudit,
|
|
15835
15859
|
friendlyAppId,
|
|
15836
15860
|
listApplicationDirectory,
|
|
15837
15861
|
requirementsForApplication,
|
|
@@ -15892,6 +15916,17 @@ function optionalResourceContext(args) {
|
|
|
15892
15916
|
}
|
|
15893
15917
|
return { resourceType, resourceId };
|
|
15894
15918
|
}
|
|
15919
|
+
function summarizeActionCapabilities(service, actions) {
|
|
15920
|
+
return {
|
|
15921
|
+
service,
|
|
15922
|
+
total: actions.length,
|
|
15923
|
+
readOnly: actions.filter((action) => action.readOnly).length,
|
|
15924
|
+
mutating: actions.filter((action) => !action.readOnly).length,
|
|
15925
|
+
destructive: actions.filter((action) => action.destructive).length,
|
|
15926
|
+
confirmationRequired: actions.filter((action) => action.requiresConfirmation).length,
|
|
15927
|
+
resourceTypes: [...new Set(actions.map((action) => action.agentContract?.resource?.kind).filter(Boolean))].sort()
|
|
15928
|
+
};
|
|
15929
|
+
}
|
|
15895
15930
|
function coerceObjectParam(value, name) {
|
|
15896
15931
|
let candidate = value;
|
|
15897
15932
|
if (typeof candidate === "string" && candidate.trim().startsWith("{")) {
|
|
@@ -15931,7 +15966,8 @@ var TOOLS = [
|
|
|
15931
15966
|
properties: {
|
|
15932
15967
|
query: { type: "string" },
|
|
15933
15968
|
cursor: { type: "string" },
|
|
15934
|
-
limit: { type: "integer", minimum: 1, maximum: 100, default: 25 }
|
|
15969
|
+
limit: { type: "integer", minimum: 1, maximum: 100, default: 25 },
|
|
15970
|
+
detail: { type: "boolean", description: "Return full schemas and agent contracts. Defaults to compact action guidance." }
|
|
15935
15971
|
},
|
|
15936
15972
|
additionalProperties: false
|
|
15937
15973
|
},
|
|
@@ -15985,12 +16021,13 @@ var TOOLS = [
|
|
|
15985
16021
|
handler: async (topolo, args) => {
|
|
15986
16022
|
const service = typeof args["service"] === "string" ? args["service"].trim() : "";
|
|
15987
16023
|
if (!service) throw new TopoloMcpPublicError("service is required for bounded action discovery.");
|
|
15988
|
-
|
|
16024
|
+
const result = await topolo.client.searchActions({
|
|
15989
16025
|
service,
|
|
15990
16026
|
query: typeof args["query"] === "string" ? args["query"] : void 0,
|
|
15991
16027
|
cursor: typeof args["cursor"] === "string" ? args["cursor"] : void 0,
|
|
15992
16028
|
limit: typeof args["limit"] === "number" ? args["limit"] : void 0
|
|
15993
16029
|
});
|
|
16030
|
+
return args["detail"] === true ? result : { actions: result.actions.map(compactActionCatalogEntry), page: result.page };
|
|
15994
16031
|
}
|
|
15995
16032
|
},
|
|
15996
16033
|
{
|
|
@@ -16156,7 +16193,8 @@ var TOOLS = [
|
|
|
16156
16193
|
type: "object",
|
|
16157
16194
|
properties: {
|
|
16158
16195
|
actionId: { type: "string", minLength: 1 },
|
|
16159
|
-
input: { type: "object", additionalProperties: true }
|
|
16196
|
+
input: { type: "object", additionalProperties: true },
|
|
16197
|
+
detail: { type: "boolean", description: "Include the full action contract. Defaults to a compact validation result." }
|
|
16160
16198
|
},
|
|
16161
16199
|
required: ["actionId"],
|
|
16162
16200
|
additionalProperties: false
|
|
@@ -16165,7 +16203,8 @@ var TOOLS = [
|
|
|
16165
16203
|
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
16166
16204
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
16167
16205
|
const input = coerceObjectParam(args["input"], "input");
|
|
16168
|
-
|
|
16206
|
+
const result = await topolo.client.validateActionInput(actionId, input);
|
|
16207
|
+
return args["detail"] === true ? result : compactActionValidation(result.action.actionId, result.validation);
|
|
16169
16208
|
}
|
|
16170
16209
|
},
|
|
16171
16210
|
{
|
|
@@ -16181,7 +16220,8 @@ var TOOLS = [
|
|
|
16181
16220
|
input: { type: "object", additionalProperties: true },
|
|
16182
16221
|
resourceType: { type: "string", description: "Optional resource-scoping alias published in the app resource catalog (e.g. workspace, brand, merchant)." },
|
|
16183
16222
|
resourceId: { type: "string", description: "Resource id. Required when resourceType is provided." },
|
|
16184
|
-
confirm: { type: "boolean", description: "Include confirmation in the plan without executing the action." }
|
|
16223
|
+
confirm: { type: "boolean", description: "Include confirmation in the plan without executing the action." },
|
|
16224
|
+
detail: { type: "boolean", description: "Include the full action contract. Defaults to the executable request and verification plan." }
|
|
16185
16225
|
},
|
|
16186
16226
|
required: ["actionId"],
|
|
16187
16227
|
additionalProperties: false
|
|
@@ -16191,7 +16231,7 @@ var TOOLS = [
|
|
|
16191
16231
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
16192
16232
|
const input = coerceObjectParam(args["input"], "input");
|
|
16193
16233
|
const resource = optionalResourceContext(args);
|
|
16194
|
-
|
|
16234
|
+
const plan = await topolo.client.planAction(
|
|
16195
16235
|
actionId,
|
|
16196
16236
|
input,
|
|
16197
16237
|
{
|
|
@@ -16199,6 +16239,7 @@ var TOOLS = [
|
|
|
16199
16239
|
...resource ? { resource } : {}
|
|
16200
16240
|
}
|
|
16201
16241
|
);
|
|
16242
|
+
return args["detail"] === true ? plan : compactActionPlan(plan);
|
|
16202
16243
|
}
|
|
16203
16244
|
},
|
|
16204
16245
|
{
|
|
@@ -16227,19 +16268,42 @@ var TOOLS = [
|
|
|
16227
16268
|
{
|
|
16228
16269
|
name: "topolo_discover_capabilities",
|
|
16229
16270
|
title: "Discover one Topolo application capability contract",
|
|
16230
|
-
description: "Lists every action published by one application \u2014 its full capability contract, straight from the registry-canonical catalog. Use the actionService value returned by topolo_search_applications as service.
|
|
16271
|
+
description: "Lists every action published by one application \u2014 its full capability contract, straight from the registry-canonical catalog. Use the actionService value returned by topolo_search_applications as service.",
|
|
16231
16272
|
requiredScopes: [],
|
|
16232
16273
|
destructive: false,
|
|
16233
16274
|
inputSchema: {
|
|
16234
16275
|
type: "object",
|
|
16235
|
-
properties: {
|
|
16276
|
+
properties: {
|
|
16277
|
+
service: { type: "string", minLength: 1 },
|
|
16278
|
+
summary: { type: "boolean", description: "Return compact counts without action rows." },
|
|
16279
|
+
detail: { type: "boolean", description: "Return full schemas and agent contracts. Defaults to compact capability guidance." }
|
|
16280
|
+
},
|
|
16236
16281
|
required: ["service"],
|
|
16237
16282
|
additionalProperties: false
|
|
16238
16283
|
},
|
|
16239
16284
|
handler: async (topolo, args) => {
|
|
16240
16285
|
const service = typeof args["service"] === "string" ? args["service"].trim() : "";
|
|
16241
16286
|
if (!service) throw new TopoloMcpPublicError("service is required.");
|
|
16242
|
-
|
|
16287
|
+
if (args["summary"] === true && args["detail"] === true) {
|
|
16288
|
+
throw new TopoloMcpPublicError("summary cannot be combined with detail.");
|
|
16289
|
+
}
|
|
16290
|
+
const actions = [];
|
|
16291
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
16292
|
+
let cursor;
|
|
16293
|
+
for (; ; ) {
|
|
16294
|
+
const page = await topolo.client.searchActions({ service, limit: 100, ...cursor ? { cursor } : {} });
|
|
16295
|
+
actions.push(...page.actions);
|
|
16296
|
+
if (!page.page.hasMore) break;
|
|
16297
|
+
const nextCursor = page.page.nextCursor?.trim();
|
|
16298
|
+
if (!nextCursor || seenCursors.has(nextCursor)) {
|
|
16299
|
+
throw new TopoloMcpPublicError("Capability discovery returned an invalid continuation cursor.");
|
|
16300
|
+
}
|
|
16301
|
+
seenCursors.add(nextCursor);
|
|
16302
|
+
cursor = nextCursor;
|
|
16303
|
+
}
|
|
16304
|
+
if (args["summary"] === true) return summarizeActionCapabilities(service, actions);
|
|
16305
|
+
const result = { actions, page: { nextCursor: null, hasMore: false } };
|
|
16306
|
+
return args["detail"] === true ? result : { actions: actions.map(compactActionCatalogEntry), page: result.page };
|
|
16243
16307
|
}
|
|
16244
16308
|
},
|
|
16245
16309
|
{
|
|
@@ -16407,6 +16471,10 @@ var TOOLS = [
|
|
|
16407
16471
|
type: "string",
|
|
16408
16472
|
enum: ["missing", "needs_review", "partial"],
|
|
16409
16473
|
description: "Optional conformance gate. Returns conformanceGate.passed=false when findings at this severity or worse exist."
|
|
16474
|
+
},
|
|
16475
|
+
detail: {
|
|
16476
|
+
type: "boolean",
|
|
16477
|
+
description: "Include every finding and migration item. Defaults to per-app scores and a queue count."
|
|
16410
16478
|
}
|
|
16411
16479
|
},
|
|
16412
16480
|
additionalProperties: false
|
|
@@ -16422,11 +16490,13 @@ var TOOLS = [
|
|
|
16422
16490
|
if (application === void 0) {
|
|
16423
16491
|
const directory = await listApplicationDirectory(topolo.client);
|
|
16424
16492
|
report = auditApplicationEntries(directory.applications.map((app) => app.application));
|
|
16425
|
-
|
|
16493
|
+
const output2 = args["detail"] === true ? report : compactApplicationAudit(report);
|
|
16494
|
+
return gate ? { ...output2, conformanceGate: evaluateApplicationAuditGate(report, gate) } : output2;
|
|
16426
16495
|
}
|
|
16427
16496
|
const resolved = await resolveDirectoryApplication(topolo, application);
|
|
16428
16497
|
report = auditApplicationEntries([resolved.application]);
|
|
16429
|
-
|
|
16498
|
+
const output = args["detail"] === true ? report : compactApplicationAudit(report);
|
|
16499
|
+
return gate ? { ...output, conformanceGate: evaluateApplicationAuditGate(report, gate) } : output;
|
|
16430
16500
|
}
|
|
16431
16501
|
},
|
|
16432
16502
|
{
|
package/dist/index.js
CHANGED
|
@@ -3908,6 +3908,52 @@ function mergeSignals(a, b) {
|
|
|
3908
3908
|
b.addEventListener("abort", onAbort, { once: true });
|
|
3909
3909
|
return controller.signal;
|
|
3910
3910
|
}
|
|
3911
|
+
function compactActionCatalogEntry(action) {
|
|
3912
|
+
const required = Array.isArray(action.inputSchema["required"]) ? action.inputSchema["required"].filter((value) => typeof value === "string") : [];
|
|
3913
|
+
const examples = action.agentContract?.examples ?? [];
|
|
3914
|
+
return {
|
|
3915
|
+
actionId: action.actionId,
|
|
3916
|
+
title: action.title,
|
|
3917
|
+
description: action.description,
|
|
3918
|
+
method: action.method,
|
|
3919
|
+
readOnly: action.readOnly,
|
|
3920
|
+
requiresConfirmation: action.requiresConfirmation,
|
|
3921
|
+
agentAccess: action.agentAccess ?? (action.requiresConfirmation ? "confirm" : action.readOnly ? "auto" : "confirm"),
|
|
3922
|
+
requiredPermission: action.requiredPermission,
|
|
3923
|
+
requiredInput: required,
|
|
3924
|
+
resourceType: action.agentContract?.resource?.kind ?? null,
|
|
3925
|
+
exampleInput: examples[0]?.input ?? null,
|
|
3926
|
+
docsUrl: action.agentContract?.docsUrl ?? null
|
|
3927
|
+
};
|
|
3928
|
+
}
|
|
3929
|
+
function compactActionValidation(actionId, validation) {
|
|
3930
|
+
return { actionId, valid: validation.valid, errors: validation.errors };
|
|
3931
|
+
}
|
|
3932
|
+
function compactActionPlan(plan) {
|
|
3933
|
+
return {
|
|
3934
|
+
actionId: plan.action.actionId,
|
|
3935
|
+
valid: plan.validation.valid,
|
|
3936
|
+
errors: plan.validation.errors,
|
|
3937
|
+
executable: plan.executable,
|
|
3938
|
+
confirmationRequired: plan.confirmationRequired,
|
|
3939
|
+
confirmationProvided: plan.confirmationProvided,
|
|
3940
|
+
request: plan.request,
|
|
3941
|
+
verification: plan.verification,
|
|
3942
|
+
rollbackActionId: plan.rollbackActionId,
|
|
3943
|
+
nextActionIds: plan.nextActionIds
|
|
3944
|
+
};
|
|
3945
|
+
}
|
|
3946
|
+
function compactApplicationAudit(report) {
|
|
3947
|
+
return {
|
|
3948
|
+
version: report.version,
|
|
3949
|
+
applications: report.applications.map((audit) => ({
|
|
3950
|
+
applicationId: audit.application.id,
|
|
3951
|
+
applicationName: audit.application.name,
|
|
3952
|
+
score: audit.score
|
|
3953
|
+
})),
|
|
3954
|
+
migrationQueueCount: report.migrationQueue.length
|
|
3955
|
+
};
|
|
3956
|
+
}
|
|
3911
3957
|
var CrmModule = class {
|
|
3912
3958
|
constructor(client) {
|
|
3913
3959
|
this.client = client;
|
|
@@ -4479,6 +4525,17 @@ function optionalResourceContext(args) {
|
|
|
4479
4525
|
}
|
|
4480
4526
|
return { resourceType, resourceId };
|
|
4481
4527
|
}
|
|
4528
|
+
function summarizeActionCapabilities(service, actions) {
|
|
4529
|
+
return {
|
|
4530
|
+
service,
|
|
4531
|
+
total: actions.length,
|
|
4532
|
+
readOnly: actions.filter((action) => action.readOnly).length,
|
|
4533
|
+
mutating: actions.filter((action) => !action.readOnly).length,
|
|
4534
|
+
destructive: actions.filter((action) => action.destructive).length,
|
|
4535
|
+
confirmationRequired: actions.filter((action) => action.requiresConfirmation).length,
|
|
4536
|
+
resourceTypes: [...new Set(actions.map((action) => action.agentContract?.resource?.kind).filter(Boolean))].sort()
|
|
4537
|
+
};
|
|
4538
|
+
}
|
|
4482
4539
|
function coerceObjectParam(value, name) {
|
|
4483
4540
|
let candidate = value;
|
|
4484
4541
|
if (typeof candidate === "string" && candidate.trim().startsWith("{")) {
|
|
@@ -4518,7 +4575,8 @@ var TOOLS = [
|
|
|
4518
4575
|
properties: {
|
|
4519
4576
|
query: { type: "string" },
|
|
4520
4577
|
cursor: { type: "string" },
|
|
4521
|
-
limit: { type: "integer", minimum: 1, maximum: 100, default: 25 }
|
|
4578
|
+
limit: { type: "integer", minimum: 1, maximum: 100, default: 25 },
|
|
4579
|
+
detail: { type: "boolean", description: "Return full schemas and agent contracts. Defaults to compact action guidance." }
|
|
4522
4580
|
},
|
|
4523
4581
|
additionalProperties: false
|
|
4524
4582
|
},
|
|
@@ -4572,12 +4630,13 @@ var TOOLS = [
|
|
|
4572
4630
|
handler: async (topolo, args) => {
|
|
4573
4631
|
const service = typeof args["service"] === "string" ? args["service"].trim() : "";
|
|
4574
4632
|
if (!service) throw new TopoloMcpPublicError("service is required for bounded action discovery.");
|
|
4575
|
-
|
|
4633
|
+
const result = await topolo.client.searchActions({
|
|
4576
4634
|
service,
|
|
4577
4635
|
query: typeof args["query"] === "string" ? args["query"] : void 0,
|
|
4578
4636
|
cursor: typeof args["cursor"] === "string" ? args["cursor"] : void 0,
|
|
4579
4637
|
limit: typeof args["limit"] === "number" ? args["limit"] : void 0
|
|
4580
4638
|
});
|
|
4639
|
+
return args["detail"] === true ? result : { actions: result.actions.map(compactActionCatalogEntry), page: result.page };
|
|
4581
4640
|
}
|
|
4582
4641
|
},
|
|
4583
4642
|
{
|
|
@@ -4743,7 +4802,8 @@ var TOOLS = [
|
|
|
4743
4802
|
type: "object",
|
|
4744
4803
|
properties: {
|
|
4745
4804
|
actionId: { type: "string", minLength: 1 },
|
|
4746
|
-
input: { type: "object", additionalProperties: true }
|
|
4805
|
+
input: { type: "object", additionalProperties: true },
|
|
4806
|
+
detail: { type: "boolean", description: "Include the full action contract. Defaults to a compact validation result." }
|
|
4747
4807
|
},
|
|
4748
4808
|
required: ["actionId"],
|
|
4749
4809
|
additionalProperties: false
|
|
@@ -4752,7 +4812,8 @@ var TOOLS = [
|
|
|
4752
4812
|
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
4753
4813
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
4754
4814
|
const input = coerceObjectParam(args["input"], "input");
|
|
4755
|
-
|
|
4815
|
+
const result = await topolo.client.validateActionInput(actionId, input);
|
|
4816
|
+
return args["detail"] === true ? result : compactActionValidation(result.action.actionId, result.validation);
|
|
4756
4817
|
}
|
|
4757
4818
|
},
|
|
4758
4819
|
{
|
|
@@ -4768,7 +4829,8 @@ var TOOLS = [
|
|
|
4768
4829
|
input: { type: "object", additionalProperties: true },
|
|
4769
4830
|
resourceType: { type: "string", description: "Optional resource-scoping alias published in the app resource catalog (e.g. workspace, brand, merchant)." },
|
|
4770
4831
|
resourceId: { type: "string", description: "Resource id. Required when resourceType is provided." },
|
|
4771
|
-
confirm: { type: "boolean", description: "Include confirmation in the plan without executing the action." }
|
|
4832
|
+
confirm: { type: "boolean", description: "Include confirmation in the plan without executing the action." },
|
|
4833
|
+
detail: { type: "boolean", description: "Include the full action contract. Defaults to the executable request and verification plan." }
|
|
4772
4834
|
},
|
|
4773
4835
|
required: ["actionId"],
|
|
4774
4836
|
additionalProperties: false
|
|
@@ -4778,7 +4840,7 @@ var TOOLS = [
|
|
|
4778
4840
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
4779
4841
|
const input = coerceObjectParam(args["input"], "input");
|
|
4780
4842
|
const resource = optionalResourceContext(args);
|
|
4781
|
-
|
|
4843
|
+
const plan = await topolo.client.planAction(
|
|
4782
4844
|
actionId,
|
|
4783
4845
|
input,
|
|
4784
4846
|
{
|
|
@@ -4786,6 +4848,7 @@ var TOOLS = [
|
|
|
4786
4848
|
...resource ? { resource } : {}
|
|
4787
4849
|
}
|
|
4788
4850
|
);
|
|
4851
|
+
return args["detail"] === true ? plan : compactActionPlan(plan);
|
|
4789
4852
|
}
|
|
4790
4853
|
},
|
|
4791
4854
|
{
|
|
@@ -4814,19 +4877,42 @@ var TOOLS = [
|
|
|
4814
4877
|
{
|
|
4815
4878
|
name: "topolo_discover_capabilities",
|
|
4816
4879
|
title: "Discover one Topolo application capability contract",
|
|
4817
|
-
description: "Lists every action published by one application \u2014 its full capability contract, straight from the registry-canonical catalog. Use the actionService value returned by topolo_search_applications as service.
|
|
4880
|
+
description: "Lists every action published by one application \u2014 its full capability contract, straight from the registry-canonical catalog. Use the actionService value returned by topolo_search_applications as service.",
|
|
4818
4881
|
requiredScopes: [],
|
|
4819
4882
|
destructive: false,
|
|
4820
4883
|
inputSchema: {
|
|
4821
4884
|
type: "object",
|
|
4822
|
-
properties: {
|
|
4885
|
+
properties: {
|
|
4886
|
+
service: { type: "string", minLength: 1 },
|
|
4887
|
+
summary: { type: "boolean", description: "Return compact counts without action rows." },
|
|
4888
|
+
detail: { type: "boolean", description: "Return full schemas and agent contracts. Defaults to compact capability guidance." }
|
|
4889
|
+
},
|
|
4823
4890
|
required: ["service"],
|
|
4824
4891
|
additionalProperties: false
|
|
4825
4892
|
},
|
|
4826
4893
|
handler: async (topolo, args) => {
|
|
4827
4894
|
const service = typeof args["service"] === "string" ? args["service"].trim() : "";
|
|
4828
4895
|
if (!service) throw new TopoloMcpPublicError("service is required.");
|
|
4829
|
-
|
|
4896
|
+
if (args["summary"] === true && args["detail"] === true) {
|
|
4897
|
+
throw new TopoloMcpPublicError("summary cannot be combined with detail.");
|
|
4898
|
+
}
|
|
4899
|
+
const actions = [];
|
|
4900
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
4901
|
+
let cursor;
|
|
4902
|
+
for (; ; ) {
|
|
4903
|
+
const page = await topolo.client.searchActions({ service, limit: 100, ...cursor ? { cursor } : {} });
|
|
4904
|
+
actions.push(...page.actions);
|
|
4905
|
+
if (!page.page.hasMore) break;
|
|
4906
|
+
const nextCursor = page.page.nextCursor?.trim();
|
|
4907
|
+
if (!nextCursor || seenCursors.has(nextCursor)) {
|
|
4908
|
+
throw new TopoloMcpPublicError("Capability discovery returned an invalid continuation cursor.");
|
|
4909
|
+
}
|
|
4910
|
+
seenCursors.add(nextCursor);
|
|
4911
|
+
cursor = nextCursor;
|
|
4912
|
+
}
|
|
4913
|
+
if (args["summary"] === true) return summarizeActionCapabilities(service, actions);
|
|
4914
|
+
const result = { actions, page: { nextCursor: null, hasMore: false } };
|
|
4915
|
+
return args["detail"] === true ? result : { actions: actions.map(compactActionCatalogEntry), page: result.page };
|
|
4830
4916
|
}
|
|
4831
4917
|
},
|
|
4832
4918
|
{
|
|
@@ -4994,6 +5080,10 @@ var TOOLS = [
|
|
|
4994
5080
|
type: "string",
|
|
4995
5081
|
enum: ["missing", "needs_review", "partial"],
|
|
4996
5082
|
description: "Optional conformance gate. Returns conformanceGate.passed=false when findings at this severity or worse exist."
|
|
5083
|
+
},
|
|
5084
|
+
detail: {
|
|
5085
|
+
type: "boolean",
|
|
5086
|
+
description: "Include every finding and migration item. Defaults to per-app scores and a queue count."
|
|
4997
5087
|
}
|
|
4998
5088
|
},
|
|
4999
5089
|
additionalProperties: false
|
|
@@ -5009,11 +5099,13 @@ var TOOLS = [
|
|
|
5009
5099
|
if (application === void 0) {
|
|
5010
5100
|
const directory = await listApplicationDirectory(topolo.client);
|
|
5011
5101
|
report = auditApplicationEntries(directory.applications.map((app) => app.application));
|
|
5012
|
-
|
|
5102
|
+
const output2 = args["detail"] === true ? report : compactApplicationAudit(report);
|
|
5103
|
+
return gate ? { ...output2, conformanceGate: evaluateApplicationAuditGate(report, gate) } : output2;
|
|
5013
5104
|
}
|
|
5014
5105
|
const resolved = await resolveDirectoryApplication(topolo, application);
|
|
5015
5106
|
report = auditApplicationEntries([resolved.application]);
|
|
5016
|
-
|
|
5107
|
+
const output = args["detail"] === true ? report : compactApplicationAudit(report);
|
|
5108
|
+
return gate ? { ...output, conformanceGate: evaluateApplicationAuditGate(report, gate) } : output;
|
|
5017
5109
|
}
|
|
5018
5110
|
},
|
|
5019
5111
|
{
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topolo/mcp",
|
|
3
|
-
"version": "0.10.
|
|
4
|
-
"topoloPublishedVersion": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
|
+
"topoloPublishedVersion": "0.10.2",
|
|
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": {
|