@topolo/mcp 0.4.0 → 0.4.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 +9 -5
- package/dist/dispatch.js +14 -12
- package/dist/index.js +462 -201
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -112,7 +112,10 @@ clients surface that as a failed server launch.
|
|
|
112
112
|
`topolo_api_call` is the escape hatch for endpoints without typed MCP tools
|
|
113
113
|
yet. GET requests work without confirmation; mutating HTTP methods must pass
|
|
114
114
|
`confirm: true` or the SDK rejects the call. Backing services still enforce
|
|
115
|
-
permissions for every request.
|
|
115
|
+
permissions for every request. The tool schema intentionally does not embed a
|
|
116
|
+
large service enum; agents should call `topolo_list_services` first, then pass a
|
|
117
|
+
service ID/slug. The SDK can resolve live Auth-catalog API/technical service
|
|
118
|
+
surfaces for newly registered services before the next MCP package release.
|
|
116
119
|
|
|
117
120
|
## Safety rails
|
|
118
121
|
|
|
@@ -159,11 +162,12 @@ waiting for JSON-RPC on stdin. To drive it manually, use the MCP Inspector:
|
|
|
159
162
|
npx @modelcontextprotocol/inspector node dist/index.js
|
|
160
163
|
```
|
|
161
164
|
|
|
162
|
-
## Release
|
|
165
|
+
## Release Flow
|
|
163
166
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
`NPM_TOKEN` secret.
|
|
167
|
+
Preferred flow: push a `v<x.y.z>` tag to `main`; GitHub Actions typechecks,
|
|
168
|
+
tests, builds, verifies the tag matches `package.json`, and publishes to npm via
|
|
169
|
+
the `NPM_TOKEN` secret. Operators may publish directly with an npm token only
|
|
170
|
+
after running the same package checks and `npm pack --dry-run`.
|
|
167
171
|
|
|
168
172
|
## Phase 2 (planned)
|
|
169
173
|
|
package/dist/dispatch.js
CHANGED
|
@@ -52,7 +52,6 @@ function splitService(servicePart) {
|
|
|
52
52
|
|
|
53
53
|
// src/tools.ts
|
|
54
54
|
var APPLICATION_IDS = Object.keys(APPLICATIONS).sort();
|
|
55
|
-
var SERVICE_IDS = Object.keys(DEFAULT_SERVICE_URLS).sort();
|
|
56
55
|
var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
57
56
|
var TOOLS = [
|
|
58
57
|
{
|
|
@@ -131,9 +130,9 @@ var TOOLS = [
|
|
|
131
130
|
(e) => e.serviceId.toLowerCase() === needle || e.slug && e.slug.toLowerCase() === needle || e.name && e.name.toLowerCase() === needle
|
|
132
131
|
);
|
|
133
132
|
if (!match) {
|
|
134
|
-
const known = catalog.map((e) => e.slug || e.serviceId).sort().
|
|
133
|
+
const known = catalog.map((e) => e.slug || e.serviceId).sort().filter((value) => typeof value === "string" && value.length > 0);
|
|
135
134
|
throw new Error(
|
|
136
|
-
`Unknown application "${application}".
|
|
135
|
+
`Unknown application "${application}". ${formatKnownValues(known, "applications")}`
|
|
137
136
|
);
|
|
138
137
|
}
|
|
139
138
|
return { application: match };
|
|
@@ -150,7 +149,6 @@ var TOOLS = [
|
|
|
150
149
|
properties: {
|
|
151
150
|
application: {
|
|
152
151
|
type: "string",
|
|
153
|
-
enum: APPLICATION_IDS,
|
|
154
152
|
description: "Optional application ID from topolo_list_applications."
|
|
155
153
|
}
|
|
156
154
|
},
|
|
@@ -168,7 +166,7 @@ var TOOLS = [
|
|
|
168
166
|
}
|
|
169
167
|
if (typeof application !== "string" || !APPLICATION_IDS.includes(application)) {
|
|
170
168
|
throw new Error(
|
|
171
|
-
`Unknown application "${String(application)}".
|
|
169
|
+
`Unknown application "${String(application)}". ${formatKnownValues(APPLICATION_IDS, "applications")}`
|
|
172
170
|
);
|
|
173
171
|
}
|
|
174
172
|
const app = APPLICATIONS[application];
|
|
@@ -191,7 +189,6 @@ var TOOLS = [
|
|
|
191
189
|
properties: {
|
|
192
190
|
application: {
|
|
193
191
|
type: "string",
|
|
194
|
-
enum: APPLICATION_IDS,
|
|
195
192
|
description: "Optional application ID from topolo_list_applications."
|
|
196
193
|
},
|
|
197
194
|
failOn: {
|
|
@@ -216,7 +213,7 @@ var TOOLS = [
|
|
|
216
213
|
}
|
|
217
214
|
if (typeof application !== "string" || !APPLICATION_IDS.includes(application)) {
|
|
218
215
|
throw new Error(
|
|
219
|
-
`Unknown application "${String(application)}".
|
|
216
|
+
`Unknown application "${String(application)}". ${formatKnownValues(APPLICATION_IDS, "applications")}`
|
|
220
217
|
);
|
|
221
218
|
}
|
|
222
219
|
report = auditAllApplicationRequirements([application]);
|
|
@@ -249,7 +246,7 @@ var TOOLS = [
|
|
|
249
246
|
{
|
|
250
247
|
name: "topolo_api_call",
|
|
251
248
|
title: "Call any Topolo platform service",
|
|
252
|
-
description:
|
|
249
|
+
description: "Low-level passthrough to any Topolo service. Use when no domain-specific tool exists for the operation you need. The request is signed with the current credential and scoped to the caller's organization \u2014 the target service will return 403 if your scopes do not permit the operation, even though this tool is advertised. Mutating calls (non-GET methods) require confirm:true. Call topolo_list_services first to discover callable service IDs; the SDK can also resolve live Auth-catalog service ids/slugs for newly registered API surfaces.",
|
|
253
250
|
requiredScopes: [],
|
|
254
251
|
destructive: true,
|
|
255
252
|
inputSchema: {
|
|
@@ -257,7 +254,6 @@ var TOOLS = [
|
|
|
257
254
|
properties: {
|
|
258
255
|
service: {
|
|
259
256
|
type: "string",
|
|
260
|
-
enum: SERVICE_IDS,
|
|
261
257
|
description: "Target service ID from the platform registry."
|
|
262
258
|
},
|
|
263
259
|
method: {
|
|
@@ -290,8 +286,8 @@ var TOOLS = [
|
|
|
290
286
|
handler: async (topolo, args) => {
|
|
291
287
|
const service = args["service"];
|
|
292
288
|
const path = args["path"];
|
|
293
|
-
if (typeof service !== "string" || !
|
|
294
|
-
throw new Error(
|
|
289
|
+
if (typeof service !== "string" || !service.trim()) {
|
|
290
|
+
throw new Error("service is required. Call topolo_list_services first to discover callable services.");
|
|
295
291
|
}
|
|
296
292
|
if (typeof path !== "string" || !path) {
|
|
297
293
|
throw new Error("path is required");
|
|
@@ -306,7 +302,7 @@ var TOOLS = [
|
|
|
306
302
|
Object.entries(query).map(([k, v]) => [k, String(v)])
|
|
307
303
|
) : void 0;
|
|
308
304
|
return topolo.client.request({
|
|
309
|
-
service,
|
|
305
|
+
service: service.trim(),
|
|
310
306
|
method,
|
|
311
307
|
path,
|
|
312
308
|
body: args["body"],
|
|
@@ -379,6 +375,12 @@ function statusesAtOrWorse(threshold) {
|
|
|
379
375
|
if (threshold === "needs_review") return ["missing", "needs_review"];
|
|
380
376
|
return ["missing", "needs_review", "partial"];
|
|
381
377
|
}
|
|
378
|
+
function formatKnownValues(values, label) {
|
|
379
|
+
const sorted = [...values].sort();
|
|
380
|
+
const preview = sorted.slice(0, 25).join(", ");
|
|
381
|
+
const suffix = sorted.length > 25 ? `, ... +${sorted.length - 25} more` : "";
|
|
382
|
+
return `Run discovery for the full ${label} list. Known snapshot sample: ${preview}${suffix}`;
|
|
383
|
+
}
|
|
382
384
|
|
|
383
385
|
// src/dispatch.ts
|
|
384
386
|
function listAvailableTopoloTools(scopes, tools = TOOLS) {
|