@topolo/mcp 0.7.2 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -1
- package/dist/dispatch.js +142 -0
- package/dist/http.js +314 -172
- package/dist/index.js +642 -27
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -79,15 +79,43 @@ ready-made agent guide that covers both the CLI and this MCP.
|
|
|
79
79
|
| ---------------------------- | ----------------------------------------------------- |
|
|
80
80
|
| `TOPOLO_API_KEY` | Platform API key (preferred) |
|
|
81
81
|
| `TOPOLO_ACCESS_TOKEN` | Short-lived JWT (dev/testing) |
|
|
82
|
+
| `TOPOLO_ENV` | Credential environment (production by default) |
|
|
83
|
+
| `TOPOLO_CONTEXT` | Pin one stored personal/org context without activating it |
|
|
82
84
|
| `TOPOLO_AGENT_NAME` | Human-readable agent label for audit logs |
|
|
83
85
|
| `TOPOLO_SERVICE_URL_<ID>` | Override a service base URL (e.g. `_AUTH`, `_MAIL`) |
|
|
84
86
|
|
|
85
87
|
Exactly one credential var must be set. If both are present, `TOPOLO_API_KEY`
|
|
86
88
|
wins.
|
|
87
89
|
|
|
90
|
+
For concurrent organization or environment operation, run one named MCP server
|
|
91
|
+
per stored context. `TOPOLO_CONTEXT` accepts an exact key from `topolo context
|
|
92
|
+
list --json` (for example `personal` or `org:org_topolo`) or a unique stored
|
|
93
|
+
organization id, slug, or name. The server reads and refreshes that credential
|
|
94
|
+
without changing the CLI's active context, so separate agent processes cannot
|
|
95
|
+
race one shared context pointer:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"mcpServers": {
|
|
100
|
+
"topolo-topolo": {
|
|
101
|
+
"command": "topolo-mcp",
|
|
102
|
+
"env": { "TOPOLO_ENV": "production", "TOPOLO_CONTEXT": "org:org_topolo" }
|
|
103
|
+
},
|
|
104
|
+
"topolo-personal": {
|
|
105
|
+
"command": "topolo-mcp",
|
|
106
|
+
"env": { "TOPOLO_ENV": "production", "TOPOLO_CONTEXT": "personal" }
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Do not combine `TOPOLO_CONTEXT` with an injected API key or access token: those
|
|
113
|
+
credentials already carry their own immutable context.
|
|
114
|
+
|
|
88
115
|
## Startup sequence
|
|
89
116
|
|
|
90
|
-
1. Resolve
|
|
117
|
+
1. Resolve an injected credential, a pinned stored context, or the environment's
|
|
118
|
+
active stored credential. **Refuse to start** if none is available.
|
|
91
119
|
2. Call `GET /api/me` to load the user's granted scopes + role.
|
|
92
120
|
3. Connect the stdio transport and begin serving MCP requests.
|
|
93
121
|
4. Advertise a fixed, bounded discovery/invocation surface. Agents search one
|
package/dist/dispatch.js
CHANGED
|
@@ -260,6 +260,148 @@ var TOOLS = [
|
|
|
260
260
|
);
|
|
261
261
|
}
|
|
262
262
|
},
|
|
263
|
+
{
|
|
264
|
+
name: "topolo_validate_action",
|
|
265
|
+
title: "Validate Topolo action input",
|
|
266
|
+
description: "Validates input locally against the exact JSON Schema published for one credential-scoped action. Does not invoke the action.",
|
|
267
|
+
requiredScopes: [],
|
|
268
|
+
destructive: false,
|
|
269
|
+
inputSchema: {
|
|
270
|
+
type: "object",
|
|
271
|
+
properties: {
|
|
272
|
+
actionId: { type: "string", minLength: 1 },
|
|
273
|
+
input: { type: "object", additionalProperties: true }
|
|
274
|
+
},
|
|
275
|
+
required: ["actionId"],
|
|
276
|
+
additionalProperties: false
|
|
277
|
+
},
|
|
278
|
+
handler: async (topolo, args) => {
|
|
279
|
+
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
280
|
+
if (!actionId) throw new Error("actionId is required.");
|
|
281
|
+
const input = args["input"];
|
|
282
|
+
if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
|
|
283
|
+
throw new Error("input must be an object.");
|
|
284
|
+
}
|
|
285
|
+
return topolo.client.validateActionInput(actionId, input ?? {});
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
name: "topolo_plan_action",
|
|
290
|
+
title: "Plan one Topolo action",
|
|
291
|
+
description: "Validates one credential-scoped action and returns its exact request, confirmation state, verification steps, rollback action, and next actions without executing it.",
|
|
292
|
+
requiredScopes: [],
|
|
293
|
+
destructive: false,
|
|
294
|
+
inputSchema: {
|
|
295
|
+
type: "object",
|
|
296
|
+
properties: {
|
|
297
|
+
actionId: { type: "string", minLength: 1 },
|
|
298
|
+
input: { type: "object", additionalProperties: true },
|
|
299
|
+
resourceType: { type: "string", description: "Optional app-local resource alias, such as workspace." },
|
|
300
|
+
resourceId: { type: "string", description: "Resource id. Required when resourceType is provided." },
|
|
301
|
+
confirm: { type: "boolean", description: "Include confirmation in the plan without executing the action." }
|
|
302
|
+
},
|
|
303
|
+
required: ["actionId"],
|
|
304
|
+
additionalProperties: false
|
|
305
|
+
},
|
|
306
|
+
handler: async (topolo, args) => {
|
|
307
|
+
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
308
|
+
if (!actionId) throw new Error("actionId is required.");
|
|
309
|
+
const input = args["input"];
|
|
310
|
+
if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input))) {
|
|
311
|
+
throw new Error("input must be an object.");
|
|
312
|
+
}
|
|
313
|
+
const resource = optionalResourceContext(args);
|
|
314
|
+
return topolo.client.planAction(
|
|
315
|
+
actionId,
|
|
316
|
+
input ?? {},
|
|
317
|
+
{
|
|
318
|
+
confirm: args["confirm"] === true,
|
|
319
|
+
...resource ? { resource } : {}
|
|
320
|
+
}
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
name: "topolo_get_action_examples",
|
|
326
|
+
title: "Get Topolo action examples and documentation",
|
|
327
|
+
description: "Returns the public documentation URL and inline examples published for one action.",
|
|
328
|
+
requiredScopes: [],
|
|
329
|
+
destructive: false,
|
|
330
|
+
inputSchema: {
|
|
331
|
+
type: "object",
|
|
332
|
+
properties: { actionId: { type: "string", minLength: 1 } },
|
|
333
|
+
required: ["actionId"],
|
|
334
|
+
additionalProperties: false
|
|
335
|
+
},
|
|
336
|
+
handler: async (topolo, args) => {
|
|
337
|
+
const actionId = typeof args["actionId"] === "string" ? args["actionId"].trim() : "";
|
|
338
|
+
if (!actionId) throw new Error("actionId is required.");
|
|
339
|
+
const action = await topolo.client.getAction(actionId);
|
|
340
|
+
return {
|
|
341
|
+
actionId: action.actionId,
|
|
342
|
+
docsUrl: action.agentContract?.docsUrl ?? null,
|
|
343
|
+
examples: action.agentContract?.examples ?? []
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
name: "topolo_discover_capabilities",
|
|
349
|
+
title: "Discover one Topolo application capability contract",
|
|
350
|
+
description: "Discovers capability and schema actions published by one application. Use the actionService value returned by topolo_search_applications as service.",
|
|
351
|
+
requiredScopes: [],
|
|
352
|
+
destructive: false,
|
|
353
|
+
inputSchema: {
|
|
354
|
+
type: "object",
|
|
355
|
+
properties: { service: { type: "string", minLength: 1 } },
|
|
356
|
+
required: ["service"],
|
|
357
|
+
additionalProperties: false
|
|
358
|
+
},
|
|
359
|
+
handler: async (topolo, args) => {
|
|
360
|
+
const service = typeof args["service"] === "string" ? args["service"].trim() : "";
|
|
361
|
+
if (!service) throw new Error("service is required.");
|
|
362
|
+
return topolo.client.searchActions({ service, query: "capabilities", limit: 100 });
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
name: "topolo_get_resource_types",
|
|
367
|
+
title: "Get application resource-scoping types",
|
|
368
|
+
description: "Returns the canonical resource-scoping metadata published for one application, including aliases accepted by resource-scoped API keys and action calls.",
|
|
369
|
+
requiredScopes: [],
|
|
370
|
+
destructive: false,
|
|
371
|
+
inputSchema: {
|
|
372
|
+
type: "object",
|
|
373
|
+
properties: { application: { type: "string", minLength: 1 } },
|
|
374
|
+
required: ["application"],
|
|
375
|
+
additionalProperties: false
|
|
376
|
+
},
|
|
377
|
+
handler: async (topolo, args) => {
|
|
378
|
+
const application = typeof args["application"] === "string" ? args["application"].trim() : "";
|
|
379
|
+
if (!application) throw new Error("application is required.");
|
|
380
|
+
const entry = await topolo.client.getService(application);
|
|
381
|
+
return {
|
|
382
|
+
application: { appId: entry.appId, slug: entry.slug, name: entry.name },
|
|
383
|
+
resourceTypes: entry.apiKeyResources
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
name: "topolo_list_resources",
|
|
389
|
+
title: "List bindable Topolo resource ids",
|
|
390
|
+
description: "Returns credential-scoped resource ids for one application. OAuth credentials use the published Auth resource catalog; API keys return only their own bound resources.",
|
|
391
|
+
requiredScopes: [],
|
|
392
|
+
destructive: false,
|
|
393
|
+
inputSchema: {
|
|
394
|
+
type: "object",
|
|
395
|
+
properties: { application: { type: "string", minLength: 1 } },
|
|
396
|
+
required: ["application"],
|
|
397
|
+
additionalProperties: false
|
|
398
|
+
},
|
|
399
|
+
handler: async (topolo, args) => {
|
|
400
|
+
const application = typeof args["application"] === "string" ? args["application"].trim() : "";
|
|
401
|
+
if (!application) throw new Error("application is required.");
|
|
402
|
+
return topolo.client.listBindableResources(application);
|
|
403
|
+
}
|
|
404
|
+
},
|
|
263
405
|
{
|
|
264
406
|
name: "topolo_list_application_requirements",
|
|
265
407
|
title: "List Topolo application build requirements",
|