@topolo/mcp 0.13.2 → 0.14.1
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 +8 -0
- package/dist/dispatch.js +89 -0
- package/dist/http.js +89 -0
- package/dist/index.js +97 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -145,6 +145,7 @@ deletion, encryption, and audit storage for the data they own.
|
|
|
145
145
|
| `topolo_prepare_action` | credential-scoped | no |
|
|
146
146
|
| `topolo_read_action` | catalog or target policy | no |
|
|
147
147
|
| `topolo_call_action` | catalog or target policy | yes |
|
|
148
|
+
| `topolo_run_agent` | Agent runtime policy | yes |
|
|
148
149
|
| `topolo_upload_action` | catalog or target policy | yes |
|
|
149
150
|
| `topolo_list_workspaces` | target app runtime policy | no |
|
|
150
151
|
| `topolo_create_workspace` | target app runtime policy | yes |
|
|
@@ -194,6 +195,13 @@ personal or organization context. This lets agents address many workspaces
|
|
|
194
195
|
independently; providing only one of the pair is rejected before the request is
|
|
195
196
|
sent.
|
|
196
197
|
|
|
198
|
+
`topolo_run_agent` is the bounded external-harness path for Codex, Claude, and
|
|
199
|
+
other MCP clients. It creates or replays one invocation using the caller's
|
|
200
|
+
stable `idempotencyKey`, polls the same invocation, and returns either its
|
|
201
|
+
terminal result or `state: "approval_required"` with the exact Topolo
|
|
202
|
+
verification URL. Calling it again with the same input resumes the durable
|
|
203
|
+
invocation instead of starting duplicate work.
|
|
204
|
+
|
|
197
205
|
## Safety rails
|
|
198
206
|
|
|
199
207
|
- **No `orgId` parameter** on any tool. The organization is derived entirely
|
package/dist/dispatch.js
CHANGED
|
@@ -65,6 +65,8 @@ function publicMcpErrorMessage(error, fallback) {
|
|
|
65
65
|
|
|
66
66
|
// src/tools.ts
|
|
67
67
|
var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
68
|
+
var AGENT_INVOCATIONS_CREATE = "app_topolo_agent.agent_invocations.create";
|
|
69
|
+
var AGENT_INVOCATIONS_GET = "app_topolo_agent.agent_invocations.get";
|
|
68
70
|
function requiredString(args, name) {
|
|
69
71
|
const value = typeof args[name] === "string" ? args[name].trim() : "";
|
|
70
72
|
if (!value) throw new TopoloMcpPublicError(`${name} is required.`);
|
|
@@ -104,6 +106,35 @@ function coerceObjectParam(value, name) {
|
|
|
104
106
|
}
|
|
105
107
|
return candidate;
|
|
106
108
|
}
|
|
109
|
+
function recordValue(value) {
|
|
110
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
111
|
+
}
|
|
112
|
+
function invocationFrom(value) {
|
|
113
|
+
const invocation = recordValue(recordValue(value)?.["invocation"]);
|
|
114
|
+
if (!invocation || typeof invocation["invocationId"] !== "string") {
|
|
115
|
+
throw new TopoloMcpPublicError("Topolo Agent returned an invalid invocation response.");
|
|
116
|
+
}
|
|
117
|
+
return invocation;
|
|
118
|
+
}
|
|
119
|
+
function agentRunResult(invocation) {
|
|
120
|
+
const status = typeof invocation["status"] === "string" ? invocation["status"] : "running";
|
|
121
|
+
const terminal = invocation["terminal"] === true;
|
|
122
|
+
const approval = recordValue(invocation["approval"]);
|
|
123
|
+
if (status === "awaiting_approval" && approval) {
|
|
124
|
+
return {
|
|
125
|
+
state: "approval_required",
|
|
126
|
+
invocationId: invocation["invocationId"],
|
|
127
|
+
verificationUrl: approval["verificationUrl"],
|
|
128
|
+
approval,
|
|
129
|
+
invocation
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
state: terminal ? status : "running",
|
|
134
|
+
invocationId: invocation["invocationId"],
|
|
135
|
+
invocation
|
|
136
|
+
};
|
|
137
|
+
}
|
|
107
138
|
var TOOLS = [
|
|
108
139
|
{
|
|
109
140
|
name: "topolo_whoami",
|
|
@@ -351,6 +382,64 @@ var TOOLS = [
|
|
|
351
382
|
);
|
|
352
383
|
}
|
|
353
384
|
},
|
|
385
|
+
{
|
|
386
|
+
name: "topolo_run_agent",
|
|
387
|
+
title: "Run a Topolo agent to a durable checkpoint",
|
|
388
|
+
description: "Creates or replays one idempotent Topolo Agent invocation, polls its published status, and returns either the terminal result or an approval_required handoff with the exact Topolo verification URL. Reusing the same idempotencyKey never starts a duplicate invocation.",
|
|
389
|
+
requiredScopes: [],
|
|
390
|
+
destructive: true,
|
|
391
|
+
inputSchema: {
|
|
392
|
+
type: "object",
|
|
393
|
+
properties: {
|
|
394
|
+
invocation: {
|
|
395
|
+
type: "object",
|
|
396
|
+
description: "Input for app_topolo_agent.agent_invocations.create, including a stable idempotencyKey.",
|
|
397
|
+
additionalProperties: true
|
|
398
|
+
},
|
|
399
|
+
resourceType: { type: "string", description: "Optional resource-scoping alias for the Agent workspace." },
|
|
400
|
+
resourceId: { type: "string", description: "Resource id. Required when resourceType is provided." },
|
|
401
|
+
waitSeconds: {
|
|
402
|
+
type: "integer",
|
|
403
|
+
minimum: 0,
|
|
404
|
+
maximum: 120,
|
|
405
|
+
default: 30,
|
|
406
|
+
description: "Maximum time to poll. Returns state=running when the bounded wait elapses."
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
required: ["invocation"],
|
|
410
|
+
additionalProperties: false
|
|
411
|
+
},
|
|
412
|
+
handler: async (topolo, args) => {
|
|
413
|
+
const invocationInput = coerceObjectParam(args["invocation"], "invocation");
|
|
414
|
+
const idempotencyKey = typeof invocationInput["idempotencyKey"] === "string" ? invocationInput["idempotencyKey"].trim() : "";
|
|
415
|
+
if (!idempotencyKey) {
|
|
416
|
+
throw new TopoloMcpPublicError("invocation.idempotencyKey is required.");
|
|
417
|
+
}
|
|
418
|
+
const resource = optionalResourceContext(args);
|
|
419
|
+
const waitSeconds = typeof args["waitSeconds"] === "number" ? Math.max(0, Math.min(120, Math.floor(args["waitSeconds"]))) : 30;
|
|
420
|
+
const createResult = await topolo.client.callAction(
|
|
421
|
+
AGENT_INVOCATIONS_CREATE,
|
|
422
|
+
invocationInput,
|
|
423
|
+
{ confirm: true, ...resource ? { resource } : {} }
|
|
424
|
+
);
|
|
425
|
+
let invocation = invocationFrom(createResult);
|
|
426
|
+
const deadline = Date.now() + waitSeconds * 1e3;
|
|
427
|
+
while (invocation["terminal"] !== true && invocation["status"] !== "awaiting_approval" && Date.now() < deadline) {
|
|
428
|
+
const recommended = typeof invocation["recommendedPollAfterSeconds"] === "number" ? invocation["recommendedPollAfterSeconds"] : 2;
|
|
429
|
+
const delayMs = Math.min(
|
|
430
|
+
Math.max(250, recommended * 1e3),
|
|
431
|
+
Math.max(0, deadline - Date.now())
|
|
432
|
+
);
|
|
433
|
+
if (delayMs > 0) await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
434
|
+
invocation = invocationFrom(await topolo.client.readAction(
|
|
435
|
+
AGENT_INVOCATIONS_GET,
|
|
436
|
+
{ invocationId: invocation["invocationId"] },
|
|
437
|
+
resource ? { resource } : {}
|
|
438
|
+
));
|
|
439
|
+
}
|
|
440
|
+
return agentRunResult(invocation);
|
|
441
|
+
}
|
|
442
|
+
},
|
|
354
443
|
{
|
|
355
444
|
name: "topolo_validate_action",
|
|
356
445
|
title: "Validate Topolo action input",
|
package/dist/http.js
CHANGED
|
@@ -17792,6 +17792,8 @@ function splitService(servicePart) {
|
|
|
17792
17792
|
|
|
17793
17793
|
// src/tools.ts
|
|
17794
17794
|
var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
17795
|
+
var AGENT_INVOCATIONS_CREATE = "app_topolo_agent.agent_invocations.create";
|
|
17796
|
+
var AGENT_INVOCATIONS_GET = "app_topolo_agent.agent_invocations.get";
|
|
17795
17797
|
function requiredString(args, name) {
|
|
17796
17798
|
const value = typeof args[name] === "string" ? args[name].trim() : "";
|
|
17797
17799
|
if (!value) throw new TopoloMcpPublicError(`${name} is required.`);
|
|
@@ -17831,6 +17833,35 @@ function coerceObjectParam(value, name) {
|
|
|
17831
17833
|
}
|
|
17832
17834
|
return candidate;
|
|
17833
17835
|
}
|
|
17836
|
+
function recordValue(value) {
|
|
17837
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
17838
|
+
}
|
|
17839
|
+
function invocationFrom(value) {
|
|
17840
|
+
const invocation = recordValue(recordValue(value)?.["invocation"]);
|
|
17841
|
+
if (!invocation || typeof invocation["invocationId"] !== "string") {
|
|
17842
|
+
throw new TopoloMcpPublicError("Topolo Agent returned an invalid invocation response.");
|
|
17843
|
+
}
|
|
17844
|
+
return invocation;
|
|
17845
|
+
}
|
|
17846
|
+
function agentRunResult(invocation) {
|
|
17847
|
+
const status = typeof invocation["status"] === "string" ? invocation["status"] : "running";
|
|
17848
|
+
const terminal = invocation["terminal"] === true;
|
|
17849
|
+
const approval = recordValue(invocation["approval"]);
|
|
17850
|
+
if (status === "awaiting_approval" && approval) {
|
|
17851
|
+
return {
|
|
17852
|
+
state: "approval_required",
|
|
17853
|
+
invocationId: invocation["invocationId"],
|
|
17854
|
+
verificationUrl: approval["verificationUrl"],
|
|
17855
|
+
approval,
|
|
17856
|
+
invocation
|
|
17857
|
+
};
|
|
17858
|
+
}
|
|
17859
|
+
return {
|
|
17860
|
+
state: terminal ? status : "running",
|
|
17861
|
+
invocationId: invocation["invocationId"],
|
|
17862
|
+
invocation
|
|
17863
|
+
};
|
|
17864
|
+
}
|
|
17834
17865
|
var TOOLS = [
|
|
17835
17866
|
{
|
|
17836
17867
|
name: "topolo_whoami",
|
|
@@ -18078,6 +18109,64 @@ var TOOLS = [
|
|
|
18078
18109
|
);
|
|
18079
18110
|
}
|
|
18080
18111
|
},
|
|
18112
|
+
{
|
|
18113
|
+
name: "topolo_run_agent",
|
|
18114
|
+
title: "Run a Topolo agent to a durable checkpoint",
|
|
18115
|
+
description: "Creates or replays one idempotent Topolo Agent invocation, polls its published status, and returns either the terminal result or an approval_required handoff with the exact Topolo verification URL. Reusing the same idempotencyKey never starts a duplicate invocation.",
|
|
18116
|
+
requiredScopes: [],
|
|
18117
|
+
destructive: true,
|
|
18118
|
+
inputSchema: {
|
|
18119
|
+
type: "object",
|
|
18120
|
+
properties: {
|
|
18121
|
+
invocation: {
|
|
18122
|
+
type: "object",
|
|
18123
|
+
description: "Input for app_topolo_agent.agent_invocations.create, including a stable idempotencyKey.",
|
|
18124
|
+
additionalProperties: true
|
|
18125
|
+
},
|
|
18126
|
+
resourceType: { type: "string", description: "Optional resource-scoping alias for the Agent workspace." },
|
|
18127
|
+
resourceId: { type: "string", description: "Resource id. Required when resourceType is provided." },
|
|
18128
|
+
waitSeconds: {
|
|
18129
|
+
type: "integer",
|
|
18130
|
+
minimum: 0,
|
|
18131
|
+
maximum: 120,
|
|
18132
|
+
default: 30,
|
|
18133
|
+
description: "Maximum time to poll. Returns state=running when the bounded wait elapses."
|
|
18134
|
+
}
|
|
18135
|
+
},
|
|
18136
|
+
required: ["invocation"],
|
|
18137
|
+
additionalProperties: false
|
|
18138
|
+
},
|
|
18139
|
+
handler: async (topolo, args) => {
|
|
18140
|
+
const invocationInput = coerceObjectParam(args["invocation"], "invocation");
|
|
18141
|
+
const idempotencyKey = typeof invocationInput["idempotencyKey"] === "string" ? invocationInput["idempotencyKey"].trim() : "";
|
|
18142
|
+
if (!idempotencyKey) {
|
|
18143
|
+
throw new TopoloMcpPublicError("invocation.idempotencyKey is required.");
|
|
18144
|
+
}
|
|
18145
|
+
const resource = optionalResourceContext(args);
|
|
18146
|
+
const waitSeconds = typeof args["waitSeconds"] === "number" ? Math.max(0, Math.min(120, Math.floor(args["waitSeconds"]))) : 30;
|
|
18147
|
+
const createResult = await topolo.client.callAction(
|
|
18148
|
+
AGENT_INVOCATIONS_CREATE,
|
|
18149
|
+
invocationInput,
|
|
18150
|
+
{ confirm: true, ...resource ? { resource } : {} }
|
|
18151
|
+
);
|
|
18152
|
+
let invocation = invocationFrom(createResult);
|
|
18153
|
+
const deadline = Date.now() + waitSeconds * 1e3;
|
|
18154
|
+
while (invocation["terminal"] !== true && invocation["status"] !== "awaiting_approval" && Date.now() < deadline) {
|
|
18155
|
+
const recommended = typeof invocation["recommendedPollAfterSeconds"] === "number" ? invocation["recommendedPollAfterSeconds"] : 2;
|
|
18156
|
+
const delayMs = Math.min(
|
|
18157
|
+
Math.max(250, recommended * 1e3),
|
|
18158
|
+
Math.max(0, deadline - Date.now())
|
|
18159
|
+
);
|
|
18160
|
+
if (delayMs > 0) await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
18161
|
+
invocation = invocationFrom(await topolo.client.readAction(
|
|
18162
|
+
AGENT_INVOCATIONS_GET,
|
|
18163
|
+
{ invocationId: invocation["invocationId"] },
|
|
18164
|
+
resource ? { resource } : {}
|
|
18165
|
+
));
|
|
18166
|
+
}
|
|
18167
|
+
return agentRunResult(invocation);
|
|
18168
|
+
}
|
|
18169
|
+
},
|
|
18081
18170
|
{
|
|
18082
18171
|
name: "topolo_validate_action",
|
|
18083
18172
|
title: "Validate Topolo action input",
|
package/dist/index.js
CHANGED
|
@@ -4154,6 +4154,8 @@ function publicMcpErrorMessage(error, fallback) {
|
|
|
4154
4154
|
|
|
4155
4155
|
// src/tools.ts
|
|
4156
4156
|
var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
4157
|
+
var AGENT_INVOCATIONS_CREATE = "app_topolo_agent.agent_invocations.create";
|
|
4158
|
+
var AGENT_INVOCATIONS_GET = "app_topolo_agent.agent_invocations.get";
|
|
4157
4159
|
function requiredString(args, name) {
|
|
4158
4160
|
const value = typeof args[name] === "string" ? args[name].trim() : "";
|
|
4159
4161
|
if (!value) throw new TopoloMcpPublicError(`${name} is required.`);
|
|
@@ -4193,6 +4195,35 @@ function coerceObjectParam(value, name) {
|
|
|
4193
4195
|
}
|
|
4194
4196
|
return candidate;
|
|
4195
4197
|
}
|
|
4198
|
+
function recordValue(value) {
|
|
4199
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
4200
|
+
}
|
|
4201
|
+
function invocationFrom(value) {
|
|
4202
|
+
const invocation = recordValue(recordValue(value)?.["invocation"]);
|
|
4203
|
+
if (!invocation || typeof invocation["invocationId"] !== "string") {
|
|
4204
|
+
throw new TopoloMcpPublicError("Topolo Agent returned an invalid invocation response.");
|
|
4205
|
+
}
|
|
4206
|
+
return invocation;
|
|
4207
|
+
}
|
|
4208
|
+
function agentRunResult(invocation) {
|
|
4209
|
+
const status = typeof invocation["status"] === "string" ? invocation["status"] : "running";
|
|
4210
|
+
const terminal = invocation["terminal"] === true;
|
|
4211
|
+
const approval = recordValue(invocation["approval"]);
|
|
4212
|
+
if (status === "awaiting_approval" && approval) {
|
|
4213
|
+
return {
|
|
4214
|
+
state: "approval_required",
|
|
4215
|
+
invocationId: invocation["invocationId"],
|
|
4216
|
+
verificationUrl: approval["verificationUrl"],
|
|
4217
|
+
approval,
|
|
4218
|
+
invocation
|
|
4219
|
+
};
|
|
4220
|
+
}
|
|
4221
|
+
return {
|
|
4222
|
+
state: terminal ? status : "running",
|
|
4223
|
+
invocationId: invocation["invocationId"],
|
|
4224
|
+
invocation
|
|
4225
|
+
};
|
|
4226
|
+
}
|
|
4196
4227
|
var TOOLS = [
|
|
4197
4228
|
{
|
|
4198
4229
|
name: "topolo_whoami",
|
|
@@ -4440,6 +4471,64 @@ var TOOLS = [
|
|
|
4440
4471
|
);
|
|
4441
4472
|
}
|
|
4442
4473
|
},
|
|
4474
|
+
{
|
|
4475
|
+
name: "topolo_run_agent",
|
|
4476
|
+
title: "Run a Topolo agent to a durable checkpoint",
|
|
4477
|
+
description: "Creates or replays one idempotent Topolo Agent invocation, polls its published status, and returns either the terminal result or an approval_required handoff with the exact Topolo verification URL. Reusing the same idempotencyKey never starts a duplicate invocation.",
|
|
4478
|
+
requiredScopes: [],
|
|
4479
|
+
destructive: true,
|
|
4480
|
+
inputSchema: {
|
|
4481
|
+
type: "object",
|
|
4482
|
+
properties: {
|
|
4483
|
+
invocation: {
|
|
4484
|
+
type: "object",
|
|
4485
|
+
description: "Input for app_topolo_agent.agent_invocations.create, including a stable idempotencyKey.",
|
|
4486
|
+
additionalProperties: true
|
|
4487
|
+
},
|
|
4488
|
+
resourceType: { type: "string", description: "Optional resource-scoping alias for the Agent workspace." },
|
|
4489
|
+
resourceId: { type: "string", description: "Resource id. Required when resourceType is provided." },
|
|
4490
|
+
waitSeconds: {
|
|
4491
|
+
type: "integer",
|
|
4492
|
+
minimum: 0,
|
|
4493
|
+
maximum: 120,
|
|
4494
|
+
default: 30,
|
|
4495
|
+
description: "Maximum time to poll. Returns state=running when the bounded wait elapses."
|
|
4496
|
+
}
|
|
4497
|
+
},
|
|
4498
|
+
required: ["invocation"],
|
|
4499
|
+
additionalProperties: false
|
|
4500
|
+
},
|
|
4501
|
+
handler: async (topolo, args) => {
|
|
4502
|
+
const invocationInput = coerceObjectParam(args["invocation"], "invocation");
|
|
4503
|
+
const idempotencyKey = typeof invocationInput["idempotencyKey"] === "string" ? invocationInput["idempotencyKey"].trim() : "";
|
|
4504
|
+
if (!idempotencyKey) {
|
|
4505
|
+
throw new TopoloMcpPublicError("invocation.idempotencyKey is required.");
|
|
4506
|
+
}
|
|
4507
|
+
const resource = optionalResourceContext(args);
|
|
4508
|
+
const waitSeconds = typeof args["waitSeconds"] === "number" ? Math.max(0, Math.min(120, Math.floor(args["waitSeconds"]))) : 30;
|
|
4509
|
+
const createResult = await topolo.client.callAction(
|
|
4510
|
+
AGENT_INVOCATIONS_CREATE,
|
|
4511
|
+
invocationInput,
|
|
4512
|
+
{ confirm: true, ...resource ? { resource } : {} }
|
|
4513
|
+
);
|
|
4514
|
+
let invocation = invocationFrom(createResult);
|
|
4515
|
+
const deadline = Date.now() + waitSeconds * 1e3;
|
|
4516
|
+
while (invocation["terminal"] !== true && invocation["status"] !== "awaiting_approval" && Date.now() < deadline) {
|
|
4517
|
+
const recommended = typeof invocation["recommendedPollAfterSeconds"] === "number" ? invocation["recommendedPollAfterSeconds"] : 2;
|
|
4518
|
+
const delayMs = Math.min(
|
|
4519
|
+
Math.max(250, recommended * 1e3),
|
|
4520
|
+
Math.max(0, deadline - Date.now())
|
|
4521
|
+
);
|
|
4522
|
+
if (delayMs > 0) await new Promise((resolve2) => setTimeout(resolve2, delayMs));
|
|
4523
|
+
invocation = invocationFrom(await topolo.client.readAction(
|
|
4524
|
+
AGENT_INVOCATIONS_GET,
|
|
4525
|
+
{ invocationId: invocation["invocationId"] },
|
|
4526
|
+
resource ? { resource } : {}
|
|
4527
|
+
));
|
|
4528
|
+
}
|
|
4529
|
+
return agentRunResult(invocation);
|
|
4530
|
+
}
|
|
4531
|
+
},
|
|
4443
4532
|
{
|
|
4444
4533
|
name: "topolo_validate_action",
|
|
4445
4534
|
title: "Validate Topolo action input",
|
|
@@ -4968,6 +5057,10 @@ function audienceFor(context) {
|
|
|
4968
5057
|
}
|
|
4969
5058
|
return `app_topolo_${service.replace(/-/g, "_")}`;
|
|
4970
5059
|
}
|
|
5060
|
+
function scopeFor(context, audience) {
|
|
5061
|
+
if (context.service === "auth" && context.path === "/api/auth/me") return "app_topolo_auth:identity";
|
|
5062
|
+
return `${audience}:actions:execute`;
|
|
5063
|
+
}
|
|
4971
5064
|
function responseData(value) {
|
|
4972
5065
|
if (!value || typeof value !== "object") return {};
|
|
4973
5066
|
const record2 = value;
|
|
@@ -4985,22 +5078,24 @@ async function resolveExternalAgentInstallationCredential(environment, installat
|
|
|
4985
5078
|
const fetchImpl = options.fetch ?? fetch;
|
|
4986
5079
|
const now = options.now ?? Date.now;
|
|
4987
5080
|
const authBaseUrl = resolveServiceUrl("auth", options.serviceUrls);
|
|
4988
|
-
const tokenUrl = new URL("/
|
|
5081
|
+
const tokenUrl = new URL("/oauth/token", authBaseUrl).toString();
|
|
4989
5082
|
const cache = /* @__PURE__ */ new Map();
|
|
4990
5083
|
const credentialProvider = async (context) => {
|
|
4991
5084
|
const audience = audienceFor(context);
|
|
5085
|
+
const scope = scopeFor(context, audience);
|
|
4992
5086
|
const resource = context.resource ?? {
|
|
4993
5087
|
resourceType: "organization",
|
|
4994
5088
|
resourceId: stored.installation.organizationId
|
|
4995
5089
|
};
|
|
4996
5090
|
const boundTaskId = context.taskId?.trim() || taskId;
|
|
4997
|
-
const key = JSON.stringify({ audience, taskId: boundTaskId, resource });
|
|
5091
|
+
const key = JSON.stringify({ audience, scope, taskId: boundTaskId, resource });
|
|
4998
5092
|
const cached = cache.get(key);
|
|
4999
5093
|
if (cached && cached.expiresAt - 15e3 > now()) return cached.credential;
|
|
5000
5094
|
const body = new URLSearchParams({
|
|
5001
5095
|
grant_type: "client_credentials",
|
|
5002
5096
|
client_id: stored.installation.clientId,
|
|
5003
5097
|
client_secret: stored.secret.clientSecret,
|
|
5098
|
+
scope,
|
|
5004
5099
|
audience,
|
|
5005
5100
|
task_id: boundTaskId,
|
|
5006
5101
|
resource_type: resource.resourceType,
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topolo/mcp",
|
|
3
3
|
"packageManager": "pnpm@10.17.1",
|
|
4
|
-
"version": "0.
|
|
5
|
-
"topoloPublishedVersion": "0.
|
|
4
|
+
"version": "0.14.1",
|
|
5
|
+
"topoloPublishedVersion": "0.14.1",
|
|
6
6
|
"description": "Model Context Protocol server for the Topolo platform. Exposes scope-gated tools that third-party agents (Claude, Codex, etc.) can call natively.",
|
|
7
7
|
"license": "UNLICENSED",
|
|
8
8
|
"author": "Topolo",
|