@topolo/mcp 0.10.3 → 0.11.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 CHANGED
@@ -11,14 +11,18 @@ tools rather than shelling out.
11
11
  them typed tool schemas, scope-filtered tool advertisement, and structured
12
12
  error responses. Both wrap the same `@topolo/sdk`.
13
13
 
14
- ## Install
14
+ ## Install and register
15
15
 
16
16
  ```bash
17
- npm install -g @topolo/mcp
17
+ npm install -g @topolo/cli
18
+ topolo setup
19
+ topolo auth login
20
+ topolo doctor
18
21
  ```
19
22
 
20
- You don't have to install globally — the registration snippets below use `npx`
21
- so the server downloads on demand.
23
+ Customers install only `@topolo/cli`; it owns an exact compatible MCP and SDK.
24
+ `topolo setup` registers the resolved local Node entry point, so agent startup
25
+ does not depend on `npx`, network access, or a separately synchronized package.
22
26
 
23
27
  ## Get a credential
24
28
 
@@ -33,45 +37,10 @@ Either:
33
37
 
34
38
  ## Register with an MCP client
35
39
 
36
- ### Claude Code
37
-
38
- ```bash
39
- claude mcp add topolo -- npx -y @topolo/mcp
40
- ```
41
-
42
- Then set the credential and (optional) agent label in your shell profile so
43
- Claude Code inherits them when it spawns the server:
44
-
45
- ```bash
46
- export TOPOLO_API_KEY=topo_live_...
47
- export TOPOLO_AGENT_NAME=claude-code
48
- ```
49
-
50
- ### Claude Desktop
51
-
52
- `claude_desktop_config.json`:
53
-
54
- ```json
55
- {
56
- "mcpServers": {
57
- "topolo": {
58
- "command": "npx",
59
- "args": ["-y", "@topolo/mcp"],
60
- "env": {
61
- "TOPOLO_API_KEY": "topo_live_...",
62
- "TOPOLO_AGENT_NAME": "claude-desktop"
63
- }
64
- }
65
- }
66
- }
67
- ```
68
-
69
- ### Codex / Cursor / generic MCP host
70
-
71
- Any MCP host that spawns a stdio subprocess works. Point `command` at
72
- `npx -y @topolo/mcp` and pass the same env vars. Most Codex-style setups also
73
- read `AGENTS.md` files — see `@topolo/cli`'s `skills/codex/AGENTS.md` for a
74
- ready-made agent guide that covers both the CLI and this MCP.
40
+ Run `topolo setup`; it configures Claude Code and Codex with an absolute Node
41
+ entry point resolved from the installed CLI dependency graph. Advanced hosts
42
+ may execute the exported `@topolo/mcp/stdio` entry directly, but customer setup
43
+ must not use an `npx` launcher because that makes startup network-dependent.
75
44
 
76
45
  ## Supported env vars
77
46
 
@@ -147,12 +116,18 @@ deletion, encryption, and audit storage for the data they own.
147
116
  | `topolo_whoami` | (none) | no |
148
117
  | `topolo_search_applications` | (none) | no |
149
118
  | `topolo_get_application` | (none) | no |
150
- | `topolo_list_application_requirements` | (none) | no |
151
- | `topolo_audit_applications` | (none) | no |
119
+ | `topolo_get_resource_types` | credential-scoped | no |
120
+ | `topolo_list_resources` | credential-scoped | no |
152
121
  | `topolo_search_actions` | (credential-scoped) | no |
122
+ | `topolo_discover_capabilities` | credential-scoped | no |
153
123
  | `topolo_get_action` | (credential-scoped) | no |
124
+ | `topolo_get_action_examples` | credential-scoped | no |
125
+ | `topolo_validate_action` | credential-scoped | no |
126
+ | `topolo_plan_action` | credential-scoped | no |
127
+ | `topolo_prepare_action` | credential-scoped | no |
154
128
  | `topolo_read_action` | catalog or target policy | no |
155
129
  | `topolo_call_action` | catalog or target policy | yes |
130
+ | `topolo_upload_action` | catalog or target policy | yes |
156
131
  | `topolo_list_workspaces` | target app runtime policy | no |
157
132
  | `topolo_create_workspace` | target app runtime policy | yes |
158
133
  | `topolo_rename_workspace` | target app runtime policy | yes |
@@ -217,9 +192,8 @@ sent.
217
192
  catalog. They do not expose the global generated platform catalog.
218
193
  - **Credential-scoped action discovery.** `topolo_search_actions` reads only one
219
194
  app partition and returns at most 100 permission-filtered actions per page.
220
- Search, capability discovery, validation, planning, and application audit
221
- return compact agent guidance by default; pass `detail: true` only when the
222
- full contracts or findings are needed.
195
+ Search, capability discovery, validation, and planning return compact agent
196
+ guidance by default; pass `detail: true` only when full contracts are needed.
223
197
  - **Audit headers.** Every request sends `X-Topolo-Client: topolo-mcp/<ver>`,
224
198
  `X-Topolo-Agent: <label>`, `X-Topolo-Request-Id: <uuid>`.
225
199
  - **Write-action confirmation.** The SDK refuses mutating HTTP methods unless
@@ -242,54 +216,4 @@ sent.
242
216
  disagrees with startup introspection (rare, but possible across scope
243
217
  changes). Re-spawn the server to refresh the cached scope set.
244
218
 
245
- ## Development
246
-
247
- ```bash
248
- cd TopoloMCP
249
- npm install
250
- npm run build
251
- TOPOLO_API_KEY=topo_live_... node dist/index.js
252
- ```
253
-
254
- The server speaks MCP over stdio; when running standalone it just blocks
255
- waiting for JSON-RPC on stdin. To drive it manually, use the MCP Inspector:
256
-
257
- ```bash
258
- npx @modelcontextprotocol/inspector node dist/index.js
259
- ```
260
-
261
- ## Release Flow
262
-
263
- Agent packages are released locally from the `staging` branch after its package
264
- gates pass. Publish in dependency order (`@topolo/sdk`, `@topolo/cli`, then
265
- `@topolo/mcp`) so every public dependency already exists in the registry.
266
-
267
- For each package, run its tests, typecheck, build, and tarball verification:
268
-
269
- ```bash
270
- pnpm --dir packages/topolo-mcp test
271
- pnpm --dir packages/topolo-mcp typecheck
272
- pnpm --dir packages/topolo-mcp build
273
- node tooling/verify-npm-package.mjs packages/topolo-mcp
274
- ```
275
-
276
- The npm token is stored in the macOS Keychain under `registry.npmjs.org`. Use a
277
- temporary npm config so the token is never written into the repository or
278
- printed:
279
-
280
- ```bash
281
- printf '//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}\n' > /tmp/topolo-release.npmrc
282
- NODE_AUTH_TOKEN="$(security find-generic-password -s registry.npmjs.org -w)" \
283
- NPM_CONFIG_USERCONFIG=/tmp/topolo-release.npmrc \
284
- sh -c 'cd packages/topolo-mcp && npm publish --access public'
285
- ```
286
-
287
- After publishing, install exact versions into an empty temporary directory and
288
- exercise the SDK exports, CLI version command, MCP exports, and `topolo-mcp`
289
- executable before updating `topoloPublishedVersion`.
290
-
291
- ## Phase 2 (planned)
292
-
293
- - Hosted action catalog administration in Developers UI.
294
- - HTTP transport in addition to stdio, for hosted (non-subprocess) deployments.
295
219
  - Optional `--provenance` on npm publish once the repo is public.
package/dist/dispatch.js CHANGED
@@ -9,28 +9,16 @@ import {
9
9
 
10
10
  // src/tools.ts
11
11
  import {
12
- APPLICATION_REQUIREMENTS,
13
- APPLICATION_REQUIREMENTS_VERSION,
14
- auditApplicationEntries,
15
- applicationRequirementScopes,
16
12
  compactActionCatalogEntry,
17
13
  compactActionPreparation,
18
14
  compactActionPlan,
19
15
  compactActionValidation,
20
- compactApplicationAudit,
21
16
  friendlyAppId,
22
- listApplicationDirectory,
23
- requirementsForApplication,
24
- resolveApplicationDirectoryEntry,
25
17
  resolveCatalogServiceUrl
26
18
  } from "@topolo/sdk";
27
19
 
28
20
  // src/gating.ts
29
- function hasPlatformAccess(set) {
30
- return (set.role === "platform_super_admin" || set.role === "platform_admin") && set.orgSlug === "admin";
31
- }
32
21
  function hasScope(set, required) {
33
- if (hasPlatformAccess(set)) return true;
34
22
  if (set.permissions.includes("*")) return true;
35
23
  const [servicePart, actionPart] = splitPermission(required);
36
24
  if (!servicePart) return set.permissions.includes(required);
@@ -623,87 +611,6 @@ var TOOLS = [
623
611
  args["confirm"] === true
624
612
  )
625
613
  },
626
- {
627
- name: "topolo_list_application_requirements",
628
- title: "List Topolo application build requirements",
629
- description: "Returns the current versioned Topolo application-build contract, optionally filtered to one application. Use this before creating or expanding a Topolo app so the agent follows shared metadata, docs, auth, shell, service registration, deployment, observability, and verification requirements.",
630
- requiredScopes: [],
631
- destructive: false,
632
- inputSchema: {
633
- type: "object",
634
- properties: {
635
- application: {
636
- type: "string",
637
- description: "Optional application ID from topolo_search_applications."
638
- }
639
- },
640
- additionalProperties: false
641
- },
642
- handler: async (topolo, args) => {
643
- const application = args["application"];
644
- if (application === void 0) {
645
- return {
646
- version: APPLICATION_REQUIREMENTS_VERSION,
647
- application: null,
648
- scopes: ["all", "browser", "api", "tooling", "agent_surface"],
649
- requirements: APPLICATION_REQUIREMENTS
650
- };
651
- }
652
- const resolved = await resolveDirectoryApplication(topolo, application);
653
- const app = resolved.application;
654
- return {
655
- version: APPLICATION_REQUIREMENTS_VERSION,
656
- application: app,
657
- scopes: applicationRequirementScopes(app),
658
- requirements: requirementsForApplication(app)
659
- };
660
- }
661
- },
662
- {
663
- name: "topolo_audit_applications",
664
- title: "Audit Topolo applications against platform requirements",
665
- description: "Returns catalog-backed conformance scores and migration-queue items for all Topolo apps, or one application when provided. Use this to see which shared platform requirements need implementation, verification, or deeper review.",
666
- requiredScopes: [],
667
- destructive: false,
668
- inputSchema: {
669
- type: "object",
670
- properties: {
671
- application: {
672
- type: "string",
673
- description: "Optional application ID from topolo_search_applications."
674
- },
675
- failOn: {
676
- type: "string",
677
- enum: ["missing", "needs_review", "partial"],
678
- description: "Optional conformance gate. Returns conformanceGate.passed=false when findings at this severity or worse exist."
679
- },
680
- detail: {
681
- type: "boolean",
682
- description: "Include every finding and migration item. Defaults to per-app scores and a queue count."
683
- }
684
- },
685
- additionalProperties: false
686
- },
687
- handler: async (topolo, args) => {
688
- const application = args["application"];
689
- const failOn = args["failOn"];
690
- if (failOn !== void 0 && typeof failOn !== "string") {
691
- throw new TopoloMcpPublicError("failOn must be one of: missing, needs_review, partial");
692
- }
693
- const gate = failOn ? normalizeFailOn(failOn) : null;
694
- let report;
695
- if (application === void 0) {
696
- const directory = await listApplicationDirectory(topolo.client);
697
- report = auditApplicationEntries(directory.applications.map((app) => app.application));
698
- const output2 = args["detail"] === true ? report : compactApplicationAudit(report);
699
- return gate ? { ...output2, conformanceGate: evaluateApplicationAuditGate(report, gate) } : output2;
700
- }
701
- const resolved = await resolveDirectoryApplication(topolo, application);
702
- report = auditApplicationEntries([resolved.application]);
703
- const output = args["detail"] === true ? report : compactApplicationAudit(report);
704
- return gate ? { ...output, conformanceGate: evaluateApplicationAuditGate(report, gate) } : output;
705
- }
706
- },
707
614
  {
708
615
  name: "topolo_api_call",
709
616
  title: "Call any Topolo platform service",
@@ -803,57 +710,9 @@ async function buildTopoloTools(topolo, scopes, tools = TOOLS) {
803
710
  void topolo;
804
711
  return filterToolsByScopes(tools, scopes);
805
712
  }
806
- function evaluateApplicationAuditGate(report, threshold) {
807
- const counts = {
808
- met: 0,
809
- partial: 0,
810
- missing: 0,
811
- needs_review: 0
812
- };
813
- for (const audit of report.applications) {
814
- for (const finding of audit.findings) {
815
- counts[finding.status] += 1;
816
- }
817
- }
818
- const failingFindings = statusesAtOrWorse(threshold).reduce(
819
- (total, status) => total + counts[status],
820
- 0
821
- );
822
- return {
823
- threshold,
824
- passed: failingFindings === 0,
825
- message: failingFindings === 0 ? `No findings at or above ${threshold}.` : `${failingFindings} finding(s) at or above ${threshold}.`,
826
- failingFindings,
827
- counts
828
- };
829
- }
830
- function normalizeFailOn(value) {
831
- const normalized = value.trim().toLowerCase().replace(/-/g, "_");
832
- if (normalized === "missing" || normalized === "needs_review" || normalized === "partial") {
833
- return normalized;
834
- }
835
- throw new TopoloMcpPublicError("failOn must be one of: missing, needs_review, partial");
836
- }
837
- function statusesAtOrWorse(threshold) {
838
- if (threshold === "missing") return ["missing"];
839
- if (threshold === "needs_review") return ["missing", "needs_review"];
840
- return ["missing", "needs_review", "partial"];
841
- }
842
713
  function displayAppId(entry) {
843
714
  return friendlyAppId(entry);
844
715
  }
845
- async function resolveDirectoryApplication(topolo, application) {
846
- if (typeof application !== "string" || !application.trim()) {
847
- throw new TopoloMcpPublicError("`application` must be a non-empty string.");
848
- }
849
- try {
850
- return await resolveApplicationDirectoryEntry(topolo.client, application);
851
- } catch (error) {
852
- throw new TopoloMcpPublicError(
853
- error instanceof Error ? error.message : `Unknown application "${application}".`
854
- );
855
- }
856
- }
857
716
 
858
717
  // src/dispatch.ts
859
718
  function listAvailableTopoloTools(scopes, tools = TOOLS) {