@topolo/mcp 0.9.10 → 0.9.11
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 +10 -0
- package/dist/dispatch.js +107 -26
- package/dist/http.js +107 -26
- package/dist/index.js +167 -26
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -153,6 +153,10 @@ deletion, encryption, and audit storage for the data they own.
|
|
|
153
153
|
| `topolo_get_action` | (credential-scoped) | no |
|
|
154
154
|
| `topolo_read_action` | catalog or target policy | no |
|
|
155
155
|
| `topolo_call_action` | catalog or target policy | yes |
|
|
156
|
+
| `topolo_list_workspaces` | target app runtime policy | no |
|
|
157
|
+
| `topolo_create_workspace` | target app runtime policy | yes |
|
|
158
|
+
| `topolo_rename_workspace` | target app runtime policy | yes |
|
|
159
|
+
| `topolo_set_default_workspace` | target app runtime policy | yes |
|
|
156
160
|
| `topolo_api_call` | (service-enforced) | yes |
|
|
157
161
|
|
|
158
162
|
Applications publish machine-action definitions through Topolo Developers.
|
|
@@ -171,6 +175,12 @@ capability without inventing a global permission, and the target service checks
|
|
|
171
175
|
the current database-backed policy for the supplied organization/application on
|
|
172
176
|
every call.
|
|
173
177
|
|
|
178
|
+
Workspace lifecycle is first-class so agents do not have to know that Auth is
|
|
179
|
+
the canonical owner. The tools accept the target application, derive the
|
|
180
|
+
organization from the credential, and retain Auth's per-app runtime decision.
|
|
181
|
+
`topolo_list_workspaces` exposes `policy.canCreate` and `policy.reason`; the
|
|
182
|
+
write tools never infer access from organization ownership.
|
|
183
|
+
|
|
174
184
|
`topolo_api_call` is the escape hatch for endpoints without typed MCP tools
|
|
175
185
|
yet. GET requests work without confirmation; mutating HTTP methods must pass
|
|
176
186
|
`confirm: true` or the SDK rejects the call. Backing services still enforce
|
package/dist/dispatch.js
CHANGED
|
@@ -64,6 +64,11 @@ function publicMcpErrorMessage(error, fallback) {
|
|
|
64
64
|
// src/tools.ts
|
|
65
65
|
var APPLICATION_IDS = Object.keys(APPLICATIONS).sort();
|
|
66
66
|
var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
67
|
+
function requiredString(args, name) {
|
|
68
|
+
const value = typeof args[name] === "string" ? args[name].trim() : "";
|
|
69
|
+
if (!value) throw new TopoloMcpPublicError(`${name} is required.`);
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
67
72
|
function optionalResourceContext(args) {
|
|
68
73
|
const resourceType = typeof args["resourceType"] === "string" ? args["resourceType"].trim() : "";
|
|
69
74
|
const resourceId = typeof args["resourceId"] === "string" ? args["resourceId"].trim() : "";
|
|
@@ -73,20 +78,6 @@ function optionalResourceContext(args) {
|
|
|
73
78
|
}
|
|
74
79
|
return { resourceType, resourceId };
|
|
75
80
|
}
|
|
76
|
-
function coerceObjectParam(value, name) {
|
|
77
|
-
let candidate = value;
|
|
78
|
-
if (typeof candidate === "string" && candidate.trim().startsWith("{")) {
|
|
79
|
-
try {
|
|
80
|
-
candidate = JSON.parse(candidate);
|
|
81
|
-
} catch {
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
if (candidate === void 0) return {};
|
|
85
|
-
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) {
|
|
86
|
-
throw new TopoloMcpPublicError(`${name} must be an object.`);
|
|
87
|
-
}
|
|
88
|
-
return candidate;
|
|
89
|
-
}
|
|
90
81
|
var TOOLS = [
|
|
91
82
|
{
|
|
92
83
|
name: "topolo_whoami",
|
|
@@ -237,11 +228,14 @@ var TOOLS = [
|
|
|
237
228
|
handler: async (topolo, args) => {
|
|
238
229
|
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
239
230
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
240
|
-
const input =
|
|
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
|
+
}
|
|
241
235
|
const resource = optionalResourceContext(args);
|
|
242
236
|
return topolo.client.readAction(
|
|
243
237
|
actionId,
|
|
244
|
-
input,
|
|
238
|
+
input ?? {},
|
|
245
239
|
resource ? { resource } : {}
|
|
246
240
|
);
|
|
247
241
|
}
|
|
@@ -267,11 +261,14 @@ var TOOLS = [
|
|
|
267
261
|
handler: async (topolo, args) => {
|
|
268
262
|
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
269
263
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
270
|
-
const input =
|
|
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
|
+
}
|
|
271
268
|
const resource = optionalResourceContext(args);
|
|
272
269
|
return topolo.client.callAction(
|
|
273
270
|
actionId,
|
|
274
|
-
input,
|
|
271
|
+
input ?? {},
|
|
275
272
|
{
|
|
276
273
|
confirm: args["confirm"] === true,
|
|
277
274
|
...resource ? { resource } : {}
|
|
@@ -310,17 +307,23 @@ var TOOLS = [
|
|
|
310
307
|
if (!isCanonicalBase64(contentBase64)) throw new TopoloMcpPublicError("contentBase64 must be canonical base64.");
|
|
311
308
|
if (!contentType) throw new TopoloMcpPublicError("contentType is required.");
|
|
312
309
|
if (!fileName) throw new TopoloMcpPublicError("fileName is required.");
|
|
313
|
-
const input =
|
|
314
|
-
|
|
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
|
+
}
|
|
315
318
|
const resource = optionalResourceContext(args);
|
|
316
319
|
return topolo.client.uploadActionBase64(
|
|
317
320
|
actionId,
|
|
318
321
|
contentBase64,
|
|
319
|
-
input,
|
|
322
|
+
input ?? {},
|
|
320
323
|
{
|
|
321
324
|
fileName,
|
|
322
325
|
contentType,
|
|
323
|
-
completionInput,
|
|
326
|
+
completionInput: completionInput ?? {},
|
|
324
327
|
confirm: args["confirm"] === true,
|
|
325
328
|
...resource ? { resource } : {}
|
|
326
329
|
}
|
|
@@ -345,8 +348,11 @@ var TOOLS = [
|
|
|
345
348
|
handler: async (topolo, args) => {
|
|
346
349
|
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
347
350
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
348
|
-
const input =
|
|
349
|
-
|
|
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 ?? {});
|
|
350
356
|
}
|
|
351
357
|
},
|
|
352
358
|
{
|
|
@@ -370,11 +376,14 @@ var TOOLS = [
|
|
|
370
376
|
handler: async (topolo, args) => {
|
|
371
377
|
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
372
378
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
373
|
-
const input =
|
|
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
|
+
}
|
|
374
383
|
const resource = optionalResourceContext(args);
|
|
375
384
|
return topolo.client.planAction(
|
|
376
385
|
actionId,
|
|
377
|
-
input,
|
|
386
|
+
input ?? {},
|
|
378
387
|
{
|
|
379
388
|
confirm: args["confirm"] === true,
|
|
380
389
|
...resource ? { resource } : {}
|
|
@@ -463,6 +472,78 @@ var TOOLS = [
|
|
|
463
472
|
return topolo.client.listBindableResources(application);
|
|
464
473
|
}
|
|
465
474
|
},
|
|
475
|
+
{
|
|
476
|
+
name: "topolo_list_workspaces",
|
|
477
|
+
title: "List workspaces for one Topolo application",
|
|
478
|
+
description: "Lists caller-visible workspaces and the caller-specific creation policy for one target application. Use this before creating a workspace; organization ownership alone does not imply creation rights for every app.",
|
|
479
|
+
requiredScopes: [],
|
|
480
|
+
destructive: false,
|
|
481
|
+
inputSchema: {
|
|
482
|
+
type: "object",
|
|
483
|
+
properties: { application: { type: "string", minLength: 1 } },
|
|
484
|
+
required: ["application"],
|
|
485
|
+
additionalProperties: false
|
|
486
|
+
},
|
|
487
|
+
handler: async (topolo, args) => {
|
|
488
|
+
const application = requiredString(args, "application");
|
|
489
|
+
return topolo.workspaces.list(application);
|
|
490
|
+
}
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
name: "topolo_create_workspace",
|
|
494
|
+
title: "Create a workspace for one Topolo application",
|
|
495
|
+
description: "Creates a workspace only after reading the target application policy and confirming it permits this caller. The canonical Auth runtime still authorizes the concrete app and organization. Set confirm:true only after approval.",
|
|
496
|
+
requiredScopes: [],
|
|
497
|
+
destructive: true,
|
|
498
|
+
inputSchema: {
|
|
499
|
+
type: "object",
|
|
500
|
+
properties: { application: { type: "string", minLength: 1 }, name: { type: "string", minLength: 1, maxLength: 120 }, isDefault: { type: "boolean" }, confirm: { type: "boolean" } },
|
|
501
|
+
required: ["application", "name"],
|
|
502
|
+
additionalProperties: false
|
|
503
|
+
},
|
|
504
|
+
handler: async (topolo, args) => topolo.workspaces.create(requiredString(args, "application"), {
|
|
505
|
+
name: requiredString(args, "name"),
|
|
506
|
+
...typeof args["isDefault"] === "boolean" ? { isDefault: args["isDefault"] } : {},
|
|
507
|
+
confirm: args["confirm"] === true
|
|
508
|
+
})
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
name: "topolo_rename_workspace",
|
|
512
|
+
title: "Rename one Topolo application workspace",
|
|
513
|
+
description: "Renames a caller-authorized workspace without changing its stable id, slug, ownership, membership, or app data.",
|
|
514
|
+
requiredScopes: [],
|
|
515
|
+
destructive: true,
|
|
516
|
+
inputSchema: {
|
|
517
|
+
type: "object",
|
|
518
|
+
properties: { application: { type: "string", minLength: 1 }, workspaceId: { type: "string", minLength: 1 }, name: { type: "string", minLength: 1, maxLength: 120 }, confirm: { type: "boolean" } },
|
|
519
|
+
required: ["application", "workspaceId", "name"],
|
|
520
|
+
additionalProperties: false
|
|
521
|
+
},
|
|
522
|
+
handler: async (topolo, args) => topolo.workspaces.rename(
|
|
523
|
+
requiredString(args, "application"),
|
|
524
|
+
requiredString(args, "workspaceId"),
|
|
525
|
+
requiredString(args, "name"),
|
|
526
|
+
args["confirm"] === true
|
|
527
|
+
)
|
|
528
|
+
},
|
|
529
|
+
{
|
|
530
|
+
name: "topolo_set_default_workspace",
|
|
531
|
+
title: "Set an application default workspace",
|
|
532
|
+
description: "Sets exactly one caller-authorized workspace as the default for the target application and current organization.",
|
|
533
|
+
requiredScopes: [],
|
|
534
|
+
destructive: true,
|
|
535
|
+
inputSchema: {
|
|
536
|
+
type: "object",
|
|
537
|
+
properties: { application: { type: "string", minLength: 1 }, workspaceId: { type: "string", minLength: 1 }, confirm: { type: "boolean" } },
|
|
538
|
+
required: ["application", "workspaceId"],
|
|
539
|
+
additionalProperties: false
|
|
540
|
+
},
|
|
541
|
+
handler: async (topolo, args) => topolo.workspaces.setDefault(
|
|
542
|
+
requiredString(args, "application"),
|
|
543
|
+
requiredString(args, "workspaceId"),
|
|
544
|
+
args["confirm"] === true
|
|
545
|
+
)
|
|
546
|
+
},
|
|
466
547
|
{
|
|
467
548
|
name: "topolo_list_application_requirements",
|
|
468
549
|
title: "List Topolo application build requirements",
|
package/dist/http.js
CHANGED
|
@@ -15878,6 +15878,11 @@ function splitService(servicePart) {
|
|
|
15878
15878
|
// src/tools.ts
|
|
15879
15879
|
var APPLICATION_IDS = Object.keys(APPLICATIONS).sort();
|
|
15880
15880
|
var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
15881
|
+
function requiredString(args, name) {
|
|
15882
|
+
const value = typeof args[name] === "string" ? args[name].trim() : "";
|
|
15883
|
+
if (!value) throw new TopoloMcpPublicError(`${name} is required.`);
|
|
15884
|
+
return value;
|
|
15885
|
+
}
|
|
15881
15886
|
function optionalResourceContext(args) {
|
|
15882
15887
|
const resourceType = typeof args["resourceType"] === "string" ? args["resourceType"].trim() : "";
|
|
15883
15888
|
const resourceId = typeof args["resourceId"] === "string" ? args["resourceId"].trim() : "";
|
|
@@ -15887,20 +15892,6 @@ function optionalResourceContext(args) {
|
|
|
15887
15892
|
}
|
|
15888
15893
|
return { resourceType, resourceId };
|
|
15889
15894
|
}
|
|
15890
|
-
function coerceObjectParam(value, name) {
|
|
15891
|
-
let candidate = value;
|
|
15892
|
-
if (typeof candidate === "string" && candidate.trim().startsWith("{")) {
|
|
15893
|
-
try {
|
|
15894
|
-
candidate = JSON.parse(candidate);
|
|
15895
|
-
} catch {
|
|
15896
|
-
}
|
|
15897
|
-
}
|
|
15898
|
-
if (candidate === void 0) return {};
|
|
15899
|
-
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) {
|
|
15900
|
-
throw new TopoloMcpPublicError(`${name} must be an object.`);
|
|
15901
|
-
}
|
|
15902
|
-
return candidate;
|
|
15903
|
-
}
|
|
15904
15895
|
var TOOLS = [
|
|
15905
15896
|
{
|
|
15906
15897
|
name: "topolo_whoami",
|
|
@@ -16051,11 +16042,14 @@ var TOOLS = [
|
|
|
16051
16042
|
handler: async (topolo, args) => {
|
|
16052
16043
|
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
16053
16044
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
16054
|
-
const input =
|
|
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
|
+
}
|
|
16055
16049
|
const resource = optionalResourceContext(args);
|
|
16056
16050
|
return topolo.client.readAction(
|
|
16057
16051
|
actionId,
|
|
16058
|
-
input,
|
|
16052
|
+
input ?? {},
|
|
16059
16053
|
resource ? { resource } : {}
|
|
16060
16054
|
);
|
|
16061
16055
|
}
|
|
@@ -16081,11 +16075,14 @@ var TOOLS = [
|
|
|
16081
16075
|
handler: async (topolo, args) => {
|
|
16082
16076
|
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
16083
16077
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
16084
|
-
const input =
|
|
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
|
+
}
|
|
16085
16082
|
const resource = optionalResourceContext(args);
|
|
16086
16083
|
return topolo.client.callAction(
|
|
16087
16084
|
actionId,
|
|
16088
|
-
input,
|
|
16085
|
+
input ?? {},
|
|
16089
16086
|
{
|
|
16090
16087
|
confirm: args["confirm"] === true,
|
|
16091
16088
|
...resource ? { resource } : {}
|
|
@@ -16124,17 +16121,23 @@ var TOOLS = [
|
|
|
16124
16121
|
if (!isCanonicalBase64(contentBase64)) throw new TopoloMcpPublicError("contentBase64 must be canonical base64.");
|
|
16125
16122
|
if (!contentType) throw new TopoloMcpPublicError("contentType is required.");
|
|
16126
16123
|
if (!fileName) throw new TopoloMcpPublicError("fileName is required.");
|
|
16127
|
-
const input =
|
|
16128
|
-
|
|
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
|
+
}
|
|
16129
16132
|
const resource = optionalResourceContext(args);
|
|
16130
16133
|
return topolo.client.uploadActionBase64(
|
|
16131
16134
|
actionId,
|
|
16132
16135
|
contentBase64,
|
|
16133
|
-
input,
|
|
16136
|
+
input ?? {},
|
|
16134
16137
|
{
|
|
16135
16138
|
fileName,
|
|
16136
16139
|
contentType,
|
|
16137
|
-
completionInput,
|
|
16140
|
+
completionInput: completionInput ?? {},
|
|
16138
16141
|
confirm: args["confirm"] === true,
|
|
16139
16142
|
...resource ? { resource } : {}
|
|
16140
16143
|
}
|
|
@@ -16159,8 +16162,11 @@ var TOOLS = [
|
|
|
16159
16162
|
handler: async (topolo, args) => {
|
|
16160
16163
|
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
16161
16164
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
16162
|
-
const input =
|
|
16163
|
-
|
|
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 ?? {});
|
|
16164
16170
|
}
|
|
16165
16171
|
},
|
|
16166
16172
|
{
|
|
@@ -16184,11 +16190,14 @@ var TOOLS = [
|
|
|
16184
16190
|
handler: async (topolo, args) => {
|
|
16185
16191
|
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
16186
16192
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
16187
|
-
const input =
|
|
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
|
+
}
|
|
16188
16197
|
const resource = optionalResourceContext(args);
|
|
16189
16198
|
return topolo.client.planAction(
|
|
16190
16199
|
actionId,
|
|
16191
|
-
input,
|
|
16200
|
+
input ?? {},
|
|
16192
16201
|
{
|
|
16193
16202
|
confirm: args["confirm"] === true,
|
|
16194
16203
|
...resource ? { resource } : {}
|
|
@@ -16277,6 +16286,78 @@ var TOOLS = [
|
|
|
16277
16286
|
return topolo.client.listBindableResources(application);
|
|
16278
16287
|
}
|
|
16279
16288
|
},
|
|
16289
|
+
{
|
|
16290
|
+
name: "topolo_list_workspaces",
|
|
16291
|
+
title: "List workspaces for one Topolo application",
|
|
16292
|
+
description: "Lists caller-visible workspaces and the caller-specific creation policy for one target application. Use this before creating a workspace; organization ownership alone does not imply creation rights for every app.",
|
|
16293
|
+
requiredScopes: [],
|
|
16294
|
+
destructive: false,
|
|
16295
|
+
inputSchema: {
|
|
16296
|
+
type: "object",
|
|
16297
|
+
properties: { application: { type: "string", minLength: 1 } },
|
|
16298
|
+
required: ["application"],
|
|
16299
|
+
additionalProperties: false
|
|
16300
|
+
},
|
|
16301
|
+
handler: async (topolo, args) => {
|
|
16302
|
+
const application = requiredString(args, "application");
|
|
16303
|
+
return topolo.workspaces.list(application);
|
|
16304
|
+
}
|
|
16305
|
+
},
|
|
16306
|
+
{
|
|
16307
|
+
name: "topolo_create_workspace",
|
|
16308
|
+
title: "Create a workspace for one Topolo application",
|
|
16309
|
+
description: "Creates a workspace only after reading the target application policy and confirming it permits this caller. The canonical Auth runtime still authorizes the concrete app and organization. Set confirm:true only after approval.",
|
|
16310
|
+
requiredScopes: [],
|
|
16311
|
+
destructive: true,
|
|
16312
|
+
inputSchema: {
|
|
16313
|
+
type: "object",
|
|
16314
|
+
properties: { application: { type: "string", minLength: 1 }, name: { type: "string", minLength: 1, maxLength: 120 }, isDefault: { type: "boolean" }, confirm: { type: "boolean" } },
|
|
16315
|
+
required: ["application", "name"],
|
|
16316
|
+
additionalProperties: false
|
|
16317
|
+
},
|
|
16318
|
+
handler: async (topolo, args) => topolo.workspaces.create(requiredString(args, "application"), {
|
|
16319
|
+
name: requiredString(args, "name"),
|
|
16320
|
+
...typeof args["isDefault"] === "boolean" ? { isDefault: args["isDefault"] } : {},
|
|
16321
|
+
confirm: args["confirm"] === true
|
|
16322
|
+
})
|
|
16323
|
+
},
|
|
16324
|
+
{
|
|
16325
|
+
name: "topolo_rename_workspace",
|
|
16326
|
+
title: "Rename one Topolo application workspace",
|
|
16327
|
+
description: "Renames a caller-authorized workspace without changing its stable id, slug, ownership, membership, or app data.",
|
|
16328
|
+
requiredScopes: [],
|
|
16329
|
+
destructive: true,
|
|
16330
|
+
inputSchema: {
|
|
16331
|
+
type: "object",
|
|
16332
|
+
properties: { application: { type: "string", minLength: 1 }, workspaceId: { type: "string", minLength: 1 }, name: { type: "string", minLength: 1, maxLength: 120 }, confirm: { type: "boolean" } },
|
|
16333
|
+
required: ["application", "workspaceId", "name"],
|
|
16334
|
+
additionalProperties: false
|
|
16335
|
+
},
|
|
16336
|
+
handler: async (topolo, args) => topolo.workspaces.rename(
|
|
16337
|
+
requiredString(args, "application"),
|
|
16338
|
+
requiredString(args, "workspaceId"),
|
|
16339
|
+
requiredString(args, "name"),
|
|
16340
|
+
args["confirm"] === true
|
|
16341
|
+
)
|
|
16342
|
+
},
|
|
16343
|
+
{
|
|
16344
|
+
name: "topolo_set_default_workspace",
|
|
16345
|
+
title: "Set an application default workspace",
|
|
16346
|
+
description: "Sets exactly one caller-authorized workspace as the default for the target application and current organization.",
|
|
16347
|
+
requiredScopes: [],
|
|
16348
|
+
destructive: true,
|
|
16349
|
+
inputSchema: {
|
|
16350
|
+
type: "object",
|
|
16351
|
+
properties: { application: { type: "string", minLength: 1 }, workspaceId: { type: "string", minLength: 1 }, confirm: { type: "boolean" } },
|
|
16352
|
+
required: ["application", "workspaceId"],
|
|
16353
|
+
additionalProperties: false
|
|
16354
|
+
},
|
|
16355
|
+
handler: async (topolo, args) => topolo.workspaces.setDefault(
|
|
16356
|
+
requiredString(args, "application"),
|
|
16357
|
+
requiredString(args, "workspaceId"),
|
|
16358
|
+
args["confirm"] === true
|
|
16359
|
+
)
|
|
16360
|
+
},
|
|
16280
16361
|
{
|
|
16281
16362
|
name: "topolo_list_application_requirements",
|
|
16282
16363
|
title: "List Topolo application build requirements",
|
package/dist/index.js
CHANGED
|
@@ -3865,11 +3865,71 @@ var IdentityModule = class {
|
|
|
3865
3865
|
return this.client.introspect();
|
|
3866
3866
|
}
|
|
3867
3867
|
};
|
|
3868
|
+
var ACTIONS = {
|
|
3869
|
+
list: "app_topolo_auth.workspaces.list",
|
|
3870
|
+
create: "app_topolo_auth.workspaces.create",
|
|
3871
|
+
rename: "app_topolo_auth.workspaces.rename",
|
|
3872
|
+
setDefault: "app_topolo_auth.workspaces.default.set"
|
|
3873
|
+
};
|
|
3874
|
+
var WorkspacesModule = class {
|
|
3875
|
+
constructor(client) {
|
|
3876
|
+
this.client = client;
|
|
3877
|
+
}
|
|
3878
|
+
client;
|
|
3879
|
+
async list(application) {
|
|
3880
|
+
const context = await this.resolveContext(application);
|
|
3881
|
+
return this.client.callAction(ACTIONS.list, {
|
|
3882
|
+
org_id: context.organizationId,
|
|
3883
|
+
app_id: context.appId
|
|
3884
|
+
});
|
|
3885
|
+
}
|
|
3886
|
+
async create(application, input) {
|
|
3887
|
+
const current = await this.list(application);
|
|
3888
|
+
if (!current.data.policy.canCreate) {
|
|
3889
|
+
throw new TopoloSdkError(
|
|
3890
|
+
"workspace_creation_not_allowed",
|
|
3891
|
+
`Workspace creation is not allowed for ${current.data.appId}: ${current.data.policy.reason}`
|
|
3892
|
+
);
|
|
3893
|
+
}
|
|
3894
|
+
return this.client.callAction(ACTIONS.create, {
|
|
3895
|
+
organizationId: current.data.organizationId,
|
|
3896
|
+
appId: current.data.appId,
|
|
3897
|
+
name: input.name,
|
|
3898
|
+
...input.isDefault === void 0 ? {} : { isDefault: input.isDefault }
|
|
3899
|
+
}, { confirm: input.confirm === true });
|
|
3900
|
+
}
|
|
3901
|
+
async rename(application, workspaceId, name, confirm = false) {
|
|
3902
|
+
const context = await this.resolveContext(application);
|
|
3903
|
+
return this.client.callAction(ACTIONS.rename, {
|
|
3904
|
+
workspaceId,
|
|
3905
|
+
organizationId: context.organizationId,
|
|
3906
|
+
appId: context.appId,
|
|
3907
|
+
name
|
|
3908
|
+
}, { confirm });
|
|
3909
|
+
}
|
|
3910
|
+
async setDefault(application, workspaceId, confirm = false) {
|
|
3911
|
+
const context = await this.resolveContext(application);
|
|
3912
|
+
return this.client.callAction(ACTIONS.setDefault, {
|
|
3913
|
+
workspaceId,
|
|
3914
|
+
organizationId: context.organizationId,
|
|
3915
|
+
appId: context.appId
|
|
3916
|
+
}, { confirm });
|
|
3917
|
+
}
|
|
3918
|
+
async resolveContext(application) {
|
|
3919
|
+
const identity = await this.client.introspect();
|
|
3920
|
+
if (!identity.organization?.id) {
|
|
3921
|
+
throw new TopoloSdkError("organization_required", "Workspace lifecycle requires an organization-scoped credential.");
|
|
3922
|
+
}
|
|
3923
|
+
const service = await this.client.getService(application);
|
|
3924
|
+
return { organizationId: identity.organization.id, appId: service.appId };
|
|
3925
|
+
}
|
|
3926
|
+
};
|
|
3868
3927
|
function createTopolo(options) {
|
|
3869
3928
|
const client = new TopoloClient(options);
|
|
3870
3929
|
return {
|
|
3871
3930
|
client,
|
|
3872
3931
|
identity: new IdentityModule(client),
|
|
3932
|
+
workspaces: new WorkspacesModule(client),
|
|
3873
3933
|
crm: new CrmModule(client)
|
|
3874
3934
|
};
|
|
3875
3935
|
}
|
|
@@ -4354,6 +4414,11 @@ function publicMcpErrorMessage(error, fallback) {
|
|
|
4354
4414
|
// src/tools.ts
|
|
4355
4415
|
var APPLICATION_IDS = Object.keys(APPLICATIONS).sort();
|
|
4356
4416
|
var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
4417
|
+
function requiredString(args, name) {
|
|
4418
|
+
const value = typeof args[name] === "string" ? args[name].trim() : "";
|
|
4419
|
+
if (!value) throw new TopoloMcpPublicError(`${name} is required.`);
|
|
4420
|
+
return value;
|
|
4421
|
+
}
|
|
4357
4422
|
function optionalResourceContext(args) {
|
|
4358
4423
|
const resourceType = typeof args["resourceType"] === "string" ? args["resourceType"].trim() : "";
|
|
4359
4424
|
const resourceId = typeof args["resourceId"] === "string" ? args["resourceId"].trim() : "";
|
|
@@ -4363,20 +4428,6 @@ function optionalResourceContext(args) {
|
|
|
4363
4428
|
}
|
|
4364
4429
|
return { resourceType, resourceId };
|
|
4365
4430
|
}
|
|
4366
|
-
function coerceObjectParam(value, name) {
|
|
4367
|
-
let candidate = value;
|
|
4368
|
-
if (typeof candidate === "string" && candidate.trim().startsWith("{")) {
|
|
4369
|
-
try {
|
|
4370
|
-
candidate = JSON.parse(candidate);
|
|
4371
|
-
} catch {
|
|
4372
|
-
}
|
|
4373
|
-
}
|
|
4374
|
-
if (candidate === void 0) return {};
|
|
4375
|
-
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) {
|
|
4376
|
-
throw new TopoloMcpPublicError(`${name} must be an object.`);
|
|
4377
|
-
}
|
|
4378
|
-
return candidate;
|
|
4379
|
-
}
|
|
4380
4431
|
var TOOLS = [
|
|
4381
4432
|
{
|
|
4382
4433
|
name: "topolo_whoami",
|
|
@@ -4527,11 +4578,14 @@ var TOOLS = [
|
|
|
4527
4578
|
handler: async (topolo, args) => {
|
|
4528
4579
|
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
4529
4580
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
4530
|
-
const input =
|
|
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
|
+
}
|
|
4531
4585
|
const resource = optionalResourceContext(args);
|
|
4532
4586
|
return topolo.client.readAction(
|
|
4533
4587
|
actionId,
|
|
4534
|
-
input,
|
|
4588
|
+
input ?? {},
|
|
4535
4589
|
resource ? { resource } : {}
|
|
4536
4590
|
);
|
|
4537
4591
|
}
|
|
@@ -4557,11 +4611,14 @@ var TOOLS = [
|
|
|
4557
4611
|
handler: async (topolo, args) => {
|
|
4558
4612
|
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
4559
4613
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
4560
|
-
const input =
|
|
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
|
+
}
|
|
4561
4618
|
const resource = optionalResourceContext(args);
|
|
4562
4619
|
return topolo.client.callAction(
|
|
4563
4620
|
actionId,
|
|
4564
|
-
input,
|
|
4621
|
+
input ?? {},
|
|
4565
4622
|
{
|
|
4566
4623
|
confirm: args["confirm"] === true,
|
|
4567
4624
|
...resource ? { resource } : {}
|
|
@@ -4600,17 +4657,23 @@ var TOOLS = [
|
|
|
4600
4657
|
if (!isCanonicalBase642(contentBase64)) throw new TopoloMcpPublicError("contentBase64 must be canonical base64.");
|
|
4601
4658
|
if (!contentType) throw new TopoloMcpPublicError("contentType is required.");
|
|
4602
4659
|
if (!fileName) throw new TopoloMcpPublicError("fileName is required.");
|
|
4603
|
-
const input =
|
|
4604
|
-
|
|
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
|
+
}
|
|
4605
4668
|
const resource = optionalResourceContext(args);
|
|
4606
4669
|
return topolo.client.uploadActionBase64(
|
|
4607
4670
|
actionId,
|
|
4608
4671
|
contentBase64,
|
|
4609
|
-
input,
|
|
4672
|
+
input ?? {},
|
|
4610
4673
|
{
|
|
4611
4674
|
fileName,
|
|
4612
4675
|
contentType,
|
|
4613
|
-
completionInput,
|
|
4676
|
+
completionInput: completionInput ?? {},
|
|
4614
4677
|
confirm: args["confirm"] === true,
|
|
4615
4678
|
...resource ? { resource } : {}
|
|
4616
4679
|
}
|
|
@@ -4635,8 +4698,11 @@ var TOOLS = [
|
|
|
4635
4698
|
handler: async (topolo, args) => {
|
|
4636
4699
|
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
4637
4700
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
4638
|
-
const input =
|
|
4639
|
-
|
|
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 ?? {});
|
|
4640
4706
|
}
|
|
4641
4707
|
},
|
|
4642
4708
|
{
|
|
@@ -4660,11 +4726,14 @@ var TOOLS = [
|
|
|
4660
4726
|
handler: async (topolo, args) => {
|
|
4661
4727
|
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
4662
4728
|
if (!actionId) throw new TopoloMcpPublicError("actionId is required.");
|
|
4663
|
-
const input =
|
|
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
|
+
}
|
|
4664
4733
|
const resource = optionalResourceContext(args);
|
|
4665
4734
|
return topolo.client.planAction(
|
|
4666
4735
|
actionId,
|
|
4667
|
-
input,
|
|
4736
|
+
input ?? {},
|
|
4668
4737
|
{
|
|
4669
4738
|
confirm: args["confirm"] === true,
|
|
4670
4739
|
...resource ? { resource } : {}
|
|
@@ -4753,6 +4822,78 @@ var TOOLS = [
|
|
|
4753
4822
|
return topolo.client.listBindableResources(application);
|
|
4754
4823
|
}
|
|
4755
4824
|
},
|
|
4825
|
+
{
|
|
4826
|
+
name: "topolo_list_workspaces",
|
|
4827
|
+
title: "List workspaces for one Topolo application",
|
|
4828
|
+
description: "Lists caller-visible workspaces and the caller-specific creation policy for one target application. Use this before creating a workspace; organization ownership alone does not imply creation rights for every app.",
|
|
4829
|
+
requiredScopes: [],
|
|
4830
|
+
destructive: false,
|
|
4831
|
+
inputSchema: {
|
|
4832
|
+
type: "object",
|
|
4833
|
+
properties: { application: { type: "string", minLength: 1 } },
|
|
4834
|
+
required: ["application"],
|
|
4835
|
+
additionalProperties: false
|
|
4836
|
+
},
|
|
4837
|
+
handler: async (topolo, args) => {
|
|
4838
|
+
const application = requiredString(args, "application");
|
|
4839
|
+
return topolo.workspaces.list(application);
|
|
4840
|
+
}
|
|
4841
|
+
},
|
|
4842
|
+
{
|
|
4843
|
+
name: "topolo_create_workspace",
|
|
4844
|
+
title: "Create a workspace for one Topolo application",
|
|
4845
|
+
description: "Creates a workspace only after reading the target application policy and confirming it permits this caller. The canonical Auth runtime still authorizes the concrete app and organization. Set confirm:true only after approval.",
|
|
4846
|
+
requiredScopes: [],
|
|
4847
|
+
destructive: true,
|
|
4848
|
+
inputSchema: {
|
|
4849
|
+
type: "object",
|
|
4850
|
+
properties: { application: { type: "string", minLength: 1 }, name: { type: "string", minLength: 1, maxLength: 120 }, isDefault: { type: "boolean" }, confirm: { type: "boolean" } },
|
|
4851
|
+
required: ["application", "name"],
|
|
4852
|
+
additionalProperties: false
|
|
4853
|
+
},
|
|
4854
|
+
handler: async (topolo, args) => topolo.workspaces.create(requiredString(args, "application"), {
|
|
4855
|
+
name: requiredString(args, "name"),
|
|
4856
|
+
...typeof args["isDefault"] === "boolean" ? { isDefault: args["isDefault"] } : {},
|
|
4857
|
+
confirm: args["confirm"] === true
|
|
4858
|
+
})
|
|
4859
|
+
},
|
|
4860
|
+
{
|
|
4861
|
+
name: "topolo_rename_workspace",
|
|
4862
|
+
title: "Rename one Topolo application workspace",
|
|
4863
|
+
description: "Renames a caller-authorized workspace without changing its stable id, slug, ownership, membership, or app data.",
|
|
4864
|
+
requiredScopes: [],
|
|
4865
|
+
destructive: true,
|
|
4866
|
+
inputSchema: {
|
|
4867
|
+
type: "object",
|
|
4868
|
+
properties: { application: { type: "string", minLength: 1 }, workspaceId: { type: "string", minLength: 1 }, name: { type: "string", minLength: 1, maxLength: 120 }, confirm: { type: "boolean" } },
|
|
4869
|
+
required: ["application", "workspaceId", "name"],
|
|
4870
|
+
additionalProperties: false
|
|
4871
|
+
},
|
|
4872
|
+
handler: async (topolo, args) => topolo.workspaces.rename(
|
|
4873
|
+
requiredString(args, "application"),
|
|
4874
|
+
requiredString(args, "workspaceId"),
|
|
4875
|
+
requiredString(args, "name"),
|
|
4876
|
+
args["confirm"] === true
|
|
4877
|
+
)
|
|
4878
|
+
},
|
|
4879
|
+
{
|
|
4880
|
+
name: "topolo_set_default_workspace",
|
|
4881
|
+
title: "Set an application default workspace",
|
|
4882
|
+
description: "Sets exactly one caller-authorized workspace as the default for the target application and current organization.",
|
|
4883
|
+
requiredScopes: [],
|
|
4884
|
+
destructive: true,
|
|
4885
|
+
inputSchema: {
|
|
4886
|
+
type: "object",
|
|
4887
|
+
properties: { application: { type: "string", minLength: 1 }, workspaceId: { type: "string", minLength: 1 }, confirm: { type: "boolean" } },
|
|
4888
|
+
required: ["application", "workspaceId"],
|
|
4889
|
+
additionalProperties: false
|
|
4890
|
+
},
|
|
4891
|
+
handler: async (topolo, args) => topolo.workspaces.setDefault(
|
|
4892
|
+
requiredString(args, "application"),
|
|
4893
|
+
requiredString(args, "workspaceId"),
|
|
4894
|
+
args["confirm"] === true
|
|
4895
|
+
)
|
|
4896
|
+
},
|
|
4756
4897
|
{
|
|
4757
4898
|
name: "topolo_list_application_requirements",
|
|
4758
4899
|
title: "List Topolo application build requirements",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topolo/mcp",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"topoloPublishedVersion": "0.9.
|
|
3
|
+
"version": "0.9.11",
|
|
4
|
+
"topoloPublishedVersion": "0.9.11",
|
|
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.
|
|
40
|
+
"@topolo/sdk": "^0.9.10"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@topolo/sdk": "file:../topolo-sdk",
|