@topolo/mcp 0.4.8 → 0.4.10

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/dist/index.js CHANGED
@@ -86,7 +86,7 @@ var SERVICES = {
86
86
  mail: "https://mail.topolo.app",
87
87
  mdm: "https://mdm.topolo.app",
88
88
  messages: "https://messages.topolo.app",
89
- nexus: "https://nexus-api.topolo.app",
89
+ nexus: "https://nexus.topolo.app",
90
90
  notify: "https://notify.topolo.app",
91
91
  observability_watch: "https://observability-watch.topolo.app",
92
92
  one: "https://www.topolo.app",
@@ -635,8 +635,10 @@ var APPLICATIONS = {
635
635
  {
636
636
  "name": "topolo-feed-api",
637
637
  "kind": "worker",
638
- "apiUrl": null,
639
- "domains": [],
638
+ "apiUrl": "https://feed-api.topolo.app",
639
+ "domains": [
640
+ "feed-api.topolo.app"
641
+ ],
640
642
  "routes": [],
641
643
  "serviceId": null
642
644
  },
@@ -1007,9 +1009,9 @@ var APPLICATIONS = {
1007
1009
  {
1008
1010
  "name": "topolo-nexus-gateway",
1009
1011
  "kind": "worker",
1010
- "apiUrl": "https://nexus-api.topolo.app",
1012
+ "apiUrl": "https://nexus.topolo.app",
1011
1013
  "domains": [
1012
- "nexus-api.topolo.app"
1014
+ "nexus.topolo.app"
1013
1015
  ],
1014
1016
  "routes": [],
1015
1017
  "serviceId": "nexus"
@@ -1369,8 +1371,10 @@ var APPLICATIONS = {
1369
1371
  {
1370
1372
  "name": "topolo-socialize-api",
1371
1373
  "kind": "worker",
1372
- "apiUrl": null,
1373
- "domains": [],
1374
+ "apiUrl": "https://socialize-api.topolo.app",
1375
+ "domains": [
1376
+ "socialize-api.topolo.app"
1377
+ ],
1374
1378
  "routes": [],
1375
1379
  "serviceId": null
1376
1380
  },
@@ -2214,10 +2218,14 @@ var TopoloClient = class _TopoloClient {
2214
2218
  if (!serviceKey) {
2215
2219
  throw new TopoloSdkError("unknown_service", "service is required");
2216
2220
  }
2217
- if (serviceKey === "auth") {
2221
+ if (serviceKey === "auth" || serviceKey === "developers") {
2218
2222
  const overrideUrl = resolveConfiguredServiceUrl(serviceKey, this.serviceUrls);
2219
2223
  if (overrideUrl) return { serviceKey, baseUrl: overrideUrl };
2220
- return { serviceKey, baseUrl: DEFAULT_SERVICE_URLS.auth };
2224
+ if (serviceKey === "developers") {
2225
+ const derived = deriveDevelopersFromAuth(resolveConfiguredServiceUrl("auth", this.serviceUrls));
2226
+ if (derived) return { serviceKey, baseUrl: derived };
2227
+ }
2228
+ return { serviceKey, baseUrl: DEFAULT_SERVICE_URLS[serviceKey] };
2221
2229
  }
2222
2230
  const live = await this.resolveLiveCallableService(serviceKey);
2223
2231
  if (live) {
@@ -2257,7 +2265,7 @@ var TopoloClient = class _TopoloClient {
2257
2265
  if (!normalized) return null;
2258
2266
  const configuredServiceId = resolveConfiguredServiceId(normalized, this.serviceIds);
2259
2267
  if (configuredServiceId) return configuredServiceId;
2260
- const authBase = resolveServiceUrl("auth", this.serviceUrls);
2268
+ const authBase = resolveServiceUrl("developers", this.serviceUrls);
2261
2269
  const cacheKey = `${authBase}|${normalized}`;
2262
2270
  const now = Date.now();
2263
2271
  const cached = _TopoloClient.serviceIdCache.get(cacheKey);
@@ -2311,7 +2319,7 @@ var TopoloClient = class _TopoloClient {
2311
2319
  if (this.serviceCatalogCache && this.serviceCatalogCache.expiresAt > now) {
2312
2320
  return this.serviceCatalogCache.entries;
2313
2321
  }
2314
- const res = await this.request({ service: "auth", method: "GET", path: "/api/services/catalog" });
2322
+ const res = await this.request({ service: "developers", method: "GET", path: "/api/services/catalog" });
2315
2323
  const raw = res.data?.services ?? res.services;
2316
2324
  if (!Array.isArray(raw)) {
2317
2325
  throw new TopoloSdkError(
@@ -2352,8 +2360,9 @@ var TopoloClient = class _TopoloClient {
2352
2360
  return entries;
2353
2361
  }
2354
2362
  /**
2355
- * List callable actions from the live Auth catalog. The response is scoped to
2356
- * the caller's organization and effective permissions; no bundled/static app
2363
+ * List callable actions from the live registry-canonical catalog (definitions
2364
+ * from the Catalog registry, scoping from Auth). The response is scoped to the
2365
+ * caller's organization and effective permissions; no bundled/static app
2357
2366
  * action list is used as an authorization source.
2358
2367
  */
2359
2368
  async listActions(options = {}) {
@@ -2362,7 +2371,7 @@ var TopoloClient = class _TopoloClient {
2362
2371
  return this.actionCatalogCache.entries;
2363
2372
  }
2364
2373
  const res = await this.request({
2365
- service: "auth",
2374
+ service: "developers",
2366
2375
  method: "GET",
2367
2376
  path: "/api/actions/catalog",
2368
2377
  ...options.service ? { query: { service: options.service } } : {}
@@ -2542,6 +2551,17 @@ function serviceKeyCandidates2(slug) {
2542
2551
  function normalizeLookupKey(value) {
2543
2552
  return String(value || "").trim().toLowerCase().replace(/\s+/g, "-");
2544
2553
  }
2554
+ function deriveDevelopersFromAuth(authUrl) {
2555
+ if (!authUrl) return null;
2556
+ try {
2557
+ const url = new URL(authUrl);
2558
+ if (!/^auth\./i.test(url.hostname)) return null;
2559
+ url.hostname = url.hostname.replace(/^auth\./i, "developers.");
2560
+ return url.origin;
2561
+ } catch {
2562
+ return null;
2563
+ }
2564
+ }
2545
2565
  function catalogEntryMatches(entry, needle) {
2546
2566
  return catalogEntryLookupKeys(entry).includes(needle);
2547
2567
  }
@@ -2586,6 +2606,7 @@ function normalizeActionCatalogEntry(item) {
2586
2606
  readOnly: Boolean(a.read_only ?? a.readOnly),
2587
2607
  destructive: Boolean(a.destructive),
2588
2608
  requiresConfirmation: Boolean(a.requires_confirmation ?? a.requiresConfirmation),
2609
+ agentAccess: pickAgentAccess(a.agent_access ?? a.agentAccess),
2589
2610
  status: pickActionString(a.status),
2590
2611
  sourceRevision: pickActionString(a.source_revision) ?? pickActionString(a.sourceRevision)
2591
2612
  };
@@ -2596,6 +2617,9 @@ function isHttpMethod(value) {
2596
2617
  function pickActionString(value) {
2597
2618
  return typeof value === "string" && value.trim() ? value.trim() : null;
2598
2619
  }
2620
+ function pickAgentAccess(value) {
2621
+ return value === "auto" || value === "confirm" || value === "off" ? value : null;
2622
+ }
2599
2623
  function plainObject(value) {
2600
2624
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
2601
2625
  }
@@ -2687,7 +2711,6 @@ var CrmModule = class {
2687
2711
  constructor(client) {
2688
2712
  this.client = client;
2689
2713
  }
2690
- client;
2691
2714
  async listContacts(options = {}) {
2692
2715
  const res = await this.client.request({
2693
2716
  service: "crm",
@@ -2733,7 +2756,6 @@ var IdentityModule = class {
2733
2756
  constructor(client) {
2734
2757
  this.client = client;
2735
2758
  }
2736
- client;
2737
2759
  /** Returns the resolved user, organization, and permission set for the
2738
2760
  * current credential. Equivalent to `TopoloClient.introspect()` — exposed
2739
2761
  * on this module for symmetry with the other domain modules. */
@@ -3109,14 +3131,20 @@ async function buildTopoloTools(topolo, scopes, tools = TOOLS) {
3109
3131
  const actionTools = actionsToToolDefs(actions);
3110
3132
  return filterToolsByScopes([...baseTools, ...actionTools], scopes);
3111
3133
  }
3134
+ function effectiveAgentAccess(a) {
3135
+ if (a.agentAccess) return a.agentAccess;
3136
+ if (a.destructive) return "off";
3137
+ if (a.readOnly && !a.requiresConfirmation) return "auto";
3138
+ return "confirm";
3139
+ }
3112
3140
  function actionsToToolDefs(actions) {
3113
- return actions.map((action) => ({
3141
+ return actions.map((action) => ({ action, access: effectiveAgentAccess(action) })).filter(({ access }) => access !== "off").map(({ action, access }) => ({
3114
3142
  name: action.toolName || toolNameForAction(action),
3115
3143
  title: action.title,
3116
3144
  description: action.description,
3117
3145
  requiredScopes: action.requiredPermission ? [action.requiredPermission] : [],
3118
- destructive: action.destructive || action.requiresConfirmation || action.method !== "GET",
3119
- inputSchema: actionInputSchema(action),
3146
+ destructive: access === "confirm",
3147
+ inputSchema: actionInputSchema(action, access),
3120
3148
  handler: async (topolo, args) => {
3121
3149
  const confirm = Boolean(args["confirm"]);
3122
3150
  const input = { ...args };
@@ -3130,7 +3158,7 @@ function toolNameForAction(action) {
3130
3158
  const name = action.name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
3131
3159
  return ["topolo", service, name].filter(Boolean).join("_").slice(0, 96);
3132
3160
  }
3133
- function actionInputSchema(action) {
3161
+ function actionInputSchema(action, access = "auto") {
3134
3162
  const schema = {
3135
3163
  type: "object",
3136
3164
  properties: {},
@@ -3138,7 +3166,7 @@ function actionInputSchema(action) {
3138
3166
  ...action.inputSchema
3139
3167
  };
3140
3168
  const properties = schema.properties && typeof schema.properties === "object" && !Array.isArray(schema.properties) ? { ...schema.properties } : {};
3141
- if (action.requiresConfirmation || action.method !== "GET") {
3169
+ if (access === "confirm") {
3142
3170
  properties.confirm = {
3143
3171
  type: "boolean",
3144
3172
  description: "Required for mutating actions. Explicit human-in-the-loop acknowledgement."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topolo/mcp",
3
- "version": "0.4.8",
3
+ "version": "0.4.10",
4
4
  "description": "Model Context Protocol server for the Topolo platform. Exposes scope-gated tools that third-party agents (Claude, Codex, etc.) can call natively.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,32 +10,36 @@
10
10
  "./dispatch": {
11
11
  "types": "./dist/dispatch.d.ts",
12
12
  "import": "./dist/dispatch.js"
13
+ },
14
+ "./http": {
15
+ "types": "./dist/http.d.ts",
16
+ "import": "./dist/http.js"
13
17
  }
14
18
  },
15
19
  "files": [
16
20
  "dist"
17
21
  ],
22
+ "scripts": {
23
+ "build": "tsup",
24
+ "dev": "tsup --watch",
25
+ "typecheck": "tsc --noEmit",
26
+ "start": "node dist/index.js",
27
+ "test": "vitest run",
28
+ "test:watch": "vitest",
29
+ "coverage": "vitest run --coverage"
30
+ },
18
31
  "dependencies": {
19
32
  "@modelcontextprotocol/sdk": "^1.0.0"
20
33
  },
21
34
  "devDependencies": {
35
+ "@topolo/sdk": "workspace:*",
22
36
  "@types/node": "^20.12.0",
23
37
  "@vitest/coverage-v8": "^2.1.0",
24
38
  "tsup": "^8.0.0",
25
39
  "typescript": "^5.4.0",
26
- "vitest": "^2.1.0",
27
- "@topolo/sdk": "0.4.8"
40
+ "vitest": "^2.1.0"
28
41
  },
29
42
  "engines": {
30
43
  "node": ">=20"
31
- },
32
- "scripts": {
33
- "build": "tsup",
34
- "dev": "tsup --watch",
35
- "typecheck": "tsc --noEmit",
36
- "start": "node dist/index.js",
37
- "test": "vitest run",
38
- "test:watch": "vitest",
39
- "coverage": "vitest run --coverage"
40
44
  }
41
- }
45
+ }