@wootsup/mcp 0.1.0-rc.9 → 0.3.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.
Files changed (240) hide show
  1. package/CHANGELOG.md +148 -83
  2. package/README.md +36 -32
  3. package/SECURITY.md +15 -6
  4. package/dist/auth/keychain.d.ts +27 -1
  5. package/dist/auth/keychain.js +48 -2
  6. package/dist/auth/keychain.js.map +1 -1
  7. package/dist/cli-hint.d.ts +22 -0
  8. package/dist/cli-hint.js +55 -0
  9. package/dist/cli-hint.js.map +1 -0
  10. package/dist/index.d.ts +19 -0
  11. package/dist/index.js +163 -22
  12. package/dist/index.js.map +1 -1
  13. package/dist/install-skill.js +1 -1
  14. package/dist/modules/apimapper/cache.d.ts +2 -2
  15. package/dist/modules/apimapper/cache.js +119 -29
  16. package/dist/modules/apimapper/cache.js.map +1 -1
  17. package/dist/modules/apimapper/client.d.ts +102 -1
  18. package/dist/modules/apimapper/client.js +631 -297
  19. package/dist/modules/apimapper/client.js.map +1 -1
  20. package/dist/modules/apimapper/connections-format.d.ts +51 -0
  21. package/dist/modules/apimapper/connections-format.js +261 -0
  22. package/dist/modules/apimapper/connections-format.js.map +1 -0
  23. package/dist/modules/apimapper/connections-trim.d.ts +82 -0
  24. package/dist/modules/apimapper/connections-trim.js +224 -0
  25. package/dist/modules/apimapper/connections-trim.js.map +1 -0
  26. package/dist/modules/apimapper/connections.d.ts +14 -2
  27. package/dist/modules/apimapper/connections.js +612 -153
  28. package/dist/modules/apimapper/connections.js.map +1 -1
  29. package/dist/modules/apimapper/credential-sanitizer.d.ts +5 -0
  30. package/dist/modules/apimapper/credential-sanitizer.js +60 -1
  31. package/dist/modules/apimapper/credential-sanitizer.js.map +1 -1
  32. package/dist/modules/apimapper/credentials-format.d.ts +21 -0
  33. package/dist/modules/apimapper/credentials-format.js +145 -0
  34. package/dist/modules/apimapper/credentials-format.js.map +1 -0
  35. package/dist/modules/apimapper/credentials.d.ts +12 -2
  36. package/dist/modules/apimapper/credentials.js +226 -73
  37. package/dist/modules/apimapper/credentials.js.map +1 -1
  38. package/dist/modules/apimapper/diagnose.d.ts +54 -2
  39. package/dist/modules/apimapper/diagnose.js +213 -12
  40. package/dist/modules/apimapper/diagnose.js.map +1 -1
  41. package/dist/modules/apimapper/elicitation.d.ts +54 -0
  42. package/dist/modules/apimapper/elicitation.js +90 -0
  43. package/dist/modules/apimapper/elicitation.js.map +1 -0
  44. package/dist/modules/apimapper/flows-format.d.ts +50 -0
  45. package/dist/modules/apimapper/flows-format.js +318 -0
  46. package/dist/modules/apimapper/flows-format.js.map +1 -0
  47. package/dist/modules/apimapper/flows.d.ts +13 -2
  48. package/dist/modules/apimapper/flows.js +312 -122
  49. package/dist/modules/apimapper/flows.js.map +1 -1
  50. package/dist/modules/apimapper/gateway/advanced-tool.d.ts +9 -0
  51. package/dist/modules/apimapper/gateway/advanced-tool.js +265 -0
  52. package/dist/modules/apimapper/gateway/advanced-tool.js.map +1 -0
  53. package/dist/modules/apimapper/gateway/capturing-server.d.ts +81 -0
  54. package/dist/modules/apimapper/gateway/capturing-server.js +87 -0
  55. package/dist/modules/apimapper/gateway/capturing-server.js.map +1 -0
  56. package/dist/modules/apimapper/gateway/essentials.d.ts +4 -0
  57. package/dist/modules/apimapper/gateway/essentials.js +35 -0
  58. package/dist/modules/apimapper/gateway/essentials.js.map +1 -0
  59. package/dist/modules/apimapper/gateway/test-support.d.ts +17 -0
  60. package/dist/modules/apimapper/gateway/test-support.js +43 -0
  61. package/dist/modules/apimapper/gateway/test-support.js.map +1 -0
  62. package/dist/modules/apimapper/get-skill.d.ts +3 -3
  63. package/dist/modules/apimapper/get-skill.js +47 -7
  64. package/dist/modules/apimapper/get-skill.js.map +1 -1
  65. package/dist/modules/apimapper/graph-builder.js +1 -1
  66. package/dist/modules/apimapper/graph-builder.js.map +1 -1
  67. package/dist/modules/apimapper/graph.d.ts +2 -2
  68. package/dist/modules/apimapper/graph.js +170 -35
  69. package/dist/modules/apimapper/graph.js.map +1 -1
  70. package/dist/modules/apimapper/index.d.ts +17 -1
  71. package/dist/modules/apimapper/index.js +68 -17
  72. package/dist/modules/apimapper/index.js.map +1 -1
  73. package/dist/modules/apimapper/inspect.d.ts +3 -2
  74. package/dist/modules/apimapper/inspect.js +97 -13
  75. package/dist/modules/apimapper/inspect.js.map +1 -1
  76. package/dist/modules/apimapper/library.d.ts +2 -2
  77. package/dist/modules/apimapper/library.js +665 -80
  78. package/dist/modules/apimapper/library.js.map +1 -1
  79. package/dist/modules/apimapper/license-format.d.ts +22 -0
  80. package/dist/modules/apimapper/license-format.js +149 -0
  81. package/dist/modules/apimapper/license-format.js.map +1 -0
  82. package/dist/modules/apimapper/license.d.ts +16 -2
  83. package/dist/modules/apimapper/license.js +62 -38
  84. package/dist/modules/apimapper/license.js.map +1 -1
  85. package/dist/modules/apimapper/local-sources.d.ts +2 -2
  86. package/dist/modules/apimapper/local-sources.js +44 -30
  87. package/dist/modules/apimapper/local-sources.js.map +1 -1
  88. package/dist/modules/apimapper/misc.d.ts +30 -2
  89. package/dist/modules/apimapper/misc.js +114 -49
  90. package/dist/modules/apimapper/misc.js.map +1 -1
  91. package/dist/modules/apimapper/node-schema.d.ts +52 -0
  92. package/dist/modules/apimapper/node-schema.js +70 -2
  93. package/dist/modules/apimapper/node-schema.js.map +1 -1
  94. package/dist/modules/apimapper/normalizers.d.ts +1 -0
  95. package/dist/modules/apimapper/normalizers.js +51 -0
  96. package/dist/modules/apimapper/normalizers.js.map +1 -1
  97. package/dist/modules/apimapper/onboarding.d.ts +78 -3
  98. package/dist/modules/apimapper/onboarding.js +428 -26
  99. package/dist/modules/apimapper/onboarding.js.map +1 -1
  100. package/dist/modules/apimapper/read-cache.d.ts +31 -2
  101. package/dist/modules/apimapper/read-cache.js +20 -6
  102. package/dist/modules/apimapper/read-cache.js.map +1 -1
  103. package/dist/modules/apimapper/render/_shared.d.ts +24 -0
  104. package/dist/modules/apimapper/render/_shared.js +84 -0
  105. package/dist/modules/apimapper/render/_shared.js.map +1 -0
  106. package/dist/modules/apimapper/render/dag.d.ts +18 -0
  107. package/dist/modules/apimapper/render/dag.js +70 -0
  108. package/dist/modules/apimapper/render/dag.js.map +1 -0
  109. package/dist/modules/apimapper/render/index.d.ts +2 -0
  110. package/dist/modules/apimapper/render/index.js +112 -0
  111. package/dist/modules/apimapper/render/index.js.map +1 -0
  112. package/dist/modules/apimapper/render/renderers/chart-bar.d.ts +2 -0
  113. package/dist/modules/apimapper/render/renderers/chart-bar.js +70 -0
  114. package/dist/modules/apimapper/render/renderers/chart-bar.js.map +1 -0
  115. package/dist/modules/apimapper/render/renderers/chart-line.d.ts +2 -0
  116. package/dist/modules/apimapper/render/renderers/chart-line.js +71 -0
  117. package/dist/modules/apimapper/render/renderers/chart-line.js.map +1 -0
  118. package/dist/modules/apimapper/render/renderers/diff.d.ts +2 -0
  119. package/dist/modules/apimapper/render/renderers/diff.js +154 -0
  120. package/dist/modules/apimapper/render/renderers/diff.js.map +1 -0
  121. package/dist/modules/apimapper/render/renderers/flow-diagram.d.ts +1 -0
  122. package/dist/modules/apimapper/render/renderers/flow-diagram.js +180 -0
  123. package/dist/modules/apimapper/render/renderers/flow-diagram.js.map +1 -0
  124. package/dist/modules/apimapper/render/renderers/json-tree.d.ts +2 -0
  125. package/dist/modules/apimapper/render/renderers/json-tree.js +87 -0
  126. package/dist/modules/apimapper/render/renderers/json-tree.js.map +1 -0
  127. package/dist/modules/apimapper/render/renderers/schema-diagram.d.ts +2 -0
  128. package/dist/modules/apimapper/render/renderers/schema-diagram.js +83 -0
  129. package/dist/modules/apimapper/render/renderers/schema-diagram.js.map +1 -0
  130. package/dist/modules/apimapper/render/renderers/table.d.ts +2 -0
  131. package/dist/modules/apimapper/render/renderers/table.js +75 -0
  132. package/dist/modules/apimapper/render/renderers/table.js.map +1 -0
  133. package/dist/modules/apimapper/render/schemas.d.ts +23 -0
  134. package/dist/modules/apimapper/render/schemas.js +56 -0
  135. package/dist/modules/apimapper/render/schemas.js.map +1 -0
  136. package/dist/modules/apimapper/render/secret-masking.d.ts +5 -0
  137. package/dist/modules/apimapper/render/secret-masking.js +51 -0
  138. package/dist/modules/apimapper/render/secret-masking.js.map +1 -0
  139. package/dist/modules/apimapper/render/sidecar.d.ts +21 -0
  140. package/dist/modules/apimapper/render/sidecar.js +66 -0
  141. package/dist/modules/apimapper/render/sidecar.js.map +1 -0
  142. package/dist/modules/apimapper/render/token-cap.d.ts +21 -0
  143. package/dist/modules/apimapper/render/token-cap.js +57 -0
  144. package/dist/modules/apimapper/render/token-cap.js.map +1 -0
  145. package/dist/modules/apimapper/schema.d.ts +2 -2
  146. package/dist/modules/apimapper/schema.js +92 -33
  147. package/dist/modules/apimapper/schema.js.map +1 -1
  148. package/dist/modules/apimapper/settings-format.d.ts +23 -0
  149. package/dist/modules/apimapper/settings-format.js +135 -0
  150. package/dist/modules/apimapper/settings-format.js.map +1 -0
  151. package/dist/modules/apimapper/settings.d.ts +2 -2
  152. package/dist/modules/apimapper/settings.js +100 -42
  153. package/dist/modules/apimapper/settings.js.map +1 -1
  154. package/dist/modules/apimapper/sites-tools.d.ts +29 -0
  155. package/dist/modules/apimapper/sites-tools.js +165 -0
  156. package/dist/modules/apimapper/sites-tools.js.map +1 -0
  157. package/dist/modules/apimapper/skill-resources.d.ts +2 -2
  158. package/dist/modules/apimapper/skill-resources.js.map +1 -1
  159. package/dist/modules/apimapper/token-baseline.harness.d.ts +91 -0
  160. package/dist/modules/apimapper/token-baseline.harness.js +291 -0
  161. package/dist/modules/apimapper/token-baseline.harness.js.map +1 -0
  162. package/dist/modules/apimapper/tool-result.d.ts +46 -0
  163. package/dist/modules/apimapper/tool-result.js +63 -0
  164. package/dist/modules/apimapper/tool-result.js.map +1 -0
  165. package/dist/modules/apimapper/toolslist-size.d.ts +56 -0
  166. package/dist/modules/apimapper/toolslist-size.js +192 -0
  167. package/dist/modules/apimapper/toolslist-size.js.map +1 -0
  168. package/dist/modules/apimapper/types.d.ts +44 -8
  169. package/dist/modules/apimapper/types.js +26 -1
  170. package/dist/modules/apimapper/types.js.map +1 -1
  171. package/dist/modules/apimapper/use-profile.d.ts +21 -0
  172. package/dist/modules/apimapper/use-profile.js +56 -2
  173. package/dist/modules/apimapper/use-profile.js.map +1 -1
  174. package/dist/modules/apimapper/whitelist-drift.d.ts +85 -0
  175. package/dist/modules/apimapper/whitelist-drift.js +360 -0
  176. package/dist/modules/apimapper/whitelist-drift.js.map +1 -0
  177. package/dist/modules/apimapper/workflows.d.ts +2 -2
  178. package/dist/modules/apimapper/workflows.js +202 -20
  179. package/dist/modules/apimapper/workflows.js.map +1 -1
  180. package/dist/modules/apimapper/yootheme-binding.d.ts +35 -0
  181. package/dist/modules/apimapper/yootheme-binding.js +186 -0
  182. package/dist/modules/apimapper/yootheme-binding.js.map +1 -0
  183. package/dist/platform/index.d.ts +56 -0
  184. package/dist/platform/index.js +195 -7
  185. package/dist/platform/index.js.map +1 -1
  186. package/dist/setup/detect-clients.d.ts +40 -1
  187. package/dist/setup/detect-clients.js +148 -1
  188. package/dist/setup/detect-clients.js.map +1 -1
  189. package/dist/setup/probe-handshake.js +40 -7
  190. package/dist/setup/probe-handshake.js.map +1 -1
  191. package/dist/setup/remove-config.d.ts +8 -0
  192. package/dist/setup/remove-config.js +145 -0
  193. package/dist/setup/remove-config.js.map +1 -0
  194. package/dist/setup/uninstall.d.ts +34 -0
  195. package/dist/setup/uninstall.js +147 -0
  196. package/dist/setup/uninstall.js.map +1 -0
  197. package/dist/setup-cli.d.ts +60 -0
  198. package/dist/setup-cli.js +155 -5
  199. package/dist/setup-cli.js.map +1 -1
  200. package/dist/sites/loader.d.ts +41 -0
  201. package/dist/sites/loader.js +119 -0
  202. package/dist/sites/loader.js.map +1 -0
  203. package/dist/sites/schema.d.ts +69 -0
  204. package/dist/sites/schema.js +71 -0
  205. package/dist/sites/schema.js.map +1 -0
  206. package/dist/sites/secret-resolver.d.ts +47 -0
  207. package/dist/sites/secret-resolver.js +150 -0
  208. package/dist/sites/secret-resolver.js.map +1 -0
  209. package/dist/skill-instructions.d.ts +1 -1
  210. package/dist/skill-instructions.js +5 -0
  211. package/dist/skill-instructions.js.map +1 -1
  212. package/dist/transports/stdio.js +4 -4
  213. package/dist/transports/stdio.js.map +1 -1
  214. package/dist/uninstall-skill.d.ts +27 -0
  215. package/dist/uninstall-skill.js +89 -0
  216. package/dist/uninstall-skill.js.map +1 -0
  217. package/docs/architecture.md +22 -22
  218. package/docs/customgraph-internal-migration.md +4 -4
  219. package/docs/security.md +2 -21
  220. package/docs/tools.md +40 -12
  221. package/manifest.json +77 -70
  222. package/package.json +68 -60
  223. package/skills/apimapper/SKILL.md +53 -7
  224. package/skills/apimapper/reference/conditional-style-multi-items.md +114 -0
  225. package/skills/apimapper/reference/jmespath-pitfalls.md +108 -0
  226. package/skills/apimapper/reference/joomla.md +1 -1
  227. package/skills/apimapper/reference/library-template-discovery.md +65 -0
  228. package/skills/apimapper/reference/merge-two-sources-on-key.md +99 -0
  229. package/skills/apimapper/reference/render.md +132 -0
  230. package/skills/apimapper/reference/troubleshooting.md +21 -1
  231. package/skills/apimapper/reference/yootheme.md +1 -1
  232. package/dist/auth/oauth-provider.d.ts +0 -68
  233. package/dist/auth/oauth-provider.js +0 -232
  234. package/dist/auth/oauth-provider.js.map +0 -1
  235. package/dist/server-http.d.ts +0 -22
  236. package/dist/server-http.js +0 -159
  237. package/dist/server-http.js.map +0 -1
  238. package/dist/transports/http.d.ts +0 -29
  239. package/dist/transports/http.js +0 -267
  240. package/dist/transports/http.js.map +0 -1
@@ -0,0 +1,55 @@
1
+ // src/cli-hint.ts — interactive "this is the MCP stdio server" hint.
2
+ //
3
+ // `npx @wootsup/mcp` with no subcommand boots the stdio MCP server, which
4
+ // then sits silently waiting for JSON-RPC on stdin. An AI client pipes stdin
5
+ // (so the server gets its protocol and works) — but a human running it in a
6
+ // terminal sees nothing and assumes it has hung.
7
+ //
8
+ // We disambiguate purely on `process.stdin.isTTY`:
9
+ // • TTY (interactive human) → no known subcommand means they almost
10
+ // certainly meant `setup` / `uninstall` / `help`; print a hint and exit
11
+ // 0 instead of booting a server they can't talk to.
12
+ // • non-TTY (piped — a real MCP client) → behave EXACTLY as before: boot
13
+ // the server, no hint, no exit. THIS is the load-bearing invariant.
14
+ //
15
+ // The decision is factored out as a pure function so it can be unit-tested
16
+ // without importing index.ts (which boots the server at module load).
17
+ /**
18
+ * Decide whether the bare/unknown-invocation interactive hint should be shown.
19
+ *
20
+ * Returns true ONLY when the invocation is interactive (a TTY on stdin) AND
21
+ * the given subcommand is not a recognised CLI subcommand (either absent —
22
+ * bare `npx @wootsup/mcp` — or an unknown typo).
23
+ *
24
+ * When stdin is NOT a TTY (piped, i.e. a real MCP client) this ALWAYS returns
25
+ * false so the server-boot path is never disturbed.
26
+ *
27
+ * @param subcommand The first positional CLI arg (`process.argv[2]`), or undefined.
28
+ * @param knownSubcommands The set of recognised CLI subcommands.
29
+ * @param isTTY Whether stdin is an interactive terminal (`process.stdin.isTTY`).
30
+ */
31
+ export function shouldShowInteractiveHint(subcommand, knownSubcommands, isTTY) {
32
+ if (!isTTY)
33
+ return false;
34
+ if (subcommand !== undefined && knownSubcommands.has(subcommand))
35
+ return false;
36
+ return true;
37
+ }
38
+ /**
39
+ * Build the human-facing hint message printed to stderr in interactive mode.
40
+ *
41
+ * When `subcommand` is a non-empty unknown token, the message is prefixed with
42
+ * an "unknown command" line so a typo is called out explicitly.
43
+ */
44
+ export function buildInteractiveHint(subcommand) {
45
+ const lines = [];
46
+ if (subcommand !== undefined && subcommand.length > 0) {
47
+ lines.push(`unknown command "${subcommand}".`);
48
+ }
49
+ lines.push("This is the API Mapper MCP server (stdio). It's normally launched by your " +
50
+ "AI client, not run directly — that's why it sits here waiting.");
51
+ lines.push("Did you mean: `npx -y @wootsup/mcp setup`?");
52
+ lines.push("See also: `uninstall`, `help`.");
53
+ return lines.join("\n");
54
+ }
55
+ //# sourceMappingURL=cli-hint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-hint.js","sourceRoot":"","sources":["../src/cli-hint.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,0EAA0E;AAC1E,6EAA6E;AAC7E,4EAA4E;AAC5E,iDAAiD;AACjD,EAAE;AACF,mDAAmD;AACnD,uEAAuE;AACvE,4EAA4E;AAC5E,wDAAwD;AACxD,2EAA2E;AAC3E,wEAAwE;AACxE,EAAE;AACF,2EAA2E;AAC3E,sEAAsE;AAEtE;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,yBAAyB,CACvC,UAA8B,EAC9B,gBAAqC,EACrC,KAAc;IAEd,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,IAAI,UAAU,KAAK,SAAS,IAAI,gBAAgB,CAAC,GAAG,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/E,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,UAA8B;IACjE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtD,KAAK,CAAC,IAAI,CAAC,oBAAoB,UAAU,IAAI,CAAC,CAAC;IACjD,CAAC;IACD,KAAK,CAAC,IAAI,CACR,4EAA4E;QAC1E,gEAAgE,CACnE,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;IACzD,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IAC7C,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { ProfileStore } from "./auth/profiles.js";
3
4
  /**
4
5
  * Constructs the McpServer with bundled skill instructions wired into the
5
6
  * `instructions` field. Extracted as a factory for testability.
@@ -10,4 +11,22 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
11
  */
11
12
  export declare function createServer(): McpServer;
12
13
  declare const server: McpServer;
14
+ /**
15
+ * Bootstrap the active-profile pointer from `APIMAPPER_PROFILE` env var.
16
+ *
17
+ * F-49 (W1.27) added APIMAPPER_PROFILE to the DXT manifest + setup-cli, but
18
+ * no runtime consumer existed. A customer with multiple MCP-client entries
19
+ * declaring different profiles always landed on whichever was setActive
20
+ * last on disk — defeating the multi-site selection feature.
21
+ *
22
+ * Behaviour (A6-P3-INTEG-02 — pinned by index.bootstrap-profile.test.ts):
23
+ * - unset / whitespace-only → no-op (active pointer unchanged)
24
+ * - "default" → no-op (manifest default is the implicit state)
25
+ * - "<known profile name>" → store.setActive(name) is called
26
+ * - "<unknown profile name>" → no-op, no throw (avoid phantom profiles)
27
+ *
28
+ * Best-effort: any error reading the store is logged + swallowed so the
29
+ * rest of the MCP surface still boots on a disk-locked or torn-write host.
30
+ */
31
+ export declare function bootstrapActiveProfile(store: ProfileStore): Promise<void>;
13
32
  export { server };
package/dist/index.js CHANGED
@@ -1,6 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  // @customgraph/mcp-adapter-apimapper-rest — API Mapper REST MCP Server
3
- // Full coverage of /wp-json/api-mapper/v1/* (~65 tools across 12 modules)
3
+ // Full coverage of /wp-json/api-mapper/v1/* 79 registered tools (15 module
4
+ // essentials + the apimapper_advanced gateway + 60 advanced-registry tools + 3
5
+ // top-level tools registered below). Only 19 are first-class in tools/list; the
6
+ // 60 advanced tools route through apimapper_advanced to stay under Cursor's ~40
7
+ // surface cap. Canonical counts are asserted in gateway/gateway.test.ts (A2).
4
8
  //
5
9
  // Auth: API Mapper MCP-key (amk_live_...) generated via the API Mapper
6
10
  // admin UI → Settings → MCP Access. The legacy WordPress Application
@@ -21,11 +25,40 @@ if (process.env.APIMAPPER_TOKEN && !process.env.APIMAPPER_WP_APP_PASS) {
21
25
  if (process.env.APIMAPPER_SITE_URL && !process.env.APIMAPPER_WP_BASE) {
22
26
  process.env.APIMAPPER_WP_BASE = process.env.APIMAPPER_SITE_URL;
23
27
  }
24
- // APIMAPPER_PLATFORM is consumed by the platform factory once wired
25
- // (Phase 4 abstraction lands per-tool). Surfaced as a no-op read here so
26
- // the build-dxt grep gate verifies every user_config key has a runtime
27
- // consumer see scripts/build-dxt.js.
28
+ // M-9 (2026-05-28) accept the documented `APIMAPPER_BASE_URL` alias.
29
+ // The original API Mapper docs referred to this variable name; the DXT
30
+ // bundle later standardised on `APIMAPPER_SITE_URL`. Customers who set
31
+ // `APIMAPPER_BASE_URL` (manual setups, custom container images) had
32
+ // their value silently ignored. Bridge it through here so all three
33
+ // names (`APIMAPPER_BASE_URL`, `APIMAPPER_SITE_URL`, `APIMAPPER_WP_BASE`)
34
+ // resolve to the same underlying value. Precedence order:
35
+ // `APIMAPPER_WP_BASE` (legacy canonical) > `APIMAPPER_SITE_URL` (DXT) >
36
+ // `APIMAPPER_BASE_URL` (documentation alias). First-set wins.
37
+ if (process.env.APIMAPPER_BASE_URL && !process.env.APIMAPPER_WP_BASE) {
38
+ process.env.APIMAPPER_WP_BASE = process.env.APIMAPPER_BASE_URL;
39
+ }
40
+ // APIMAPPER_PLATFORM is consumed by client.ts (Phase 1, 2026-06-03): the
41
+ // legacy `request()` path reads it as the explicit env→kind HINT
42
+ // (PLATFORM_KIND) and, when it is unset or "auto", layers a network
43
+ // identity probe on top to auto-detect WordPress vs Joomla. Kept as an
44
+ // explicit no-op read here too so the build-dxt grep gate confirms every
45
+ // user_config key has a runtime consumer — see scripts/build-dxt.js.
28
46
  void process.env.APIMAPPER_PLATFORM;
47
+ // APIMAPPER_PROFILE (F-49 / W1.27) — optional profile label for multi-site
48
+ // setups. The setup-cli writes it into the MCP client entry env; the
49
+ // profile-aware tools (apimapper_use_profile / apimapper_list_profiles)
50
+ // consume the underlying ProfileStore. The actual env-var → setActive
51
+ // bridge runs inside main() once the ProfileStore is constructed; see
52
+ // `bootstrapActiveProfile` below for the A6-P3-INTEG-02 wiring + tests.
53
+ void process.env.APIMAPPER_PROFILE;
54
+ // APIMAPPER_SITES_FILE (Phase 3, 2026-06-03) — optional path to a multi-site
55
+ // sites.json (the .dxt one-click / agency path). client.ts reads it lazily
56
+ // (getSitesRegistry) to drive the ACTIVE site's URL/token/platform in
57
+ // request(); main() wires the sites-file-backed profile tools when it loads
58
+ // non-empty. Explicit no-op read here too so the build-dxt grep gate confirms
59
+ // every user_config key has a runtime consumer — see scripts/build-dxt.js.
60
+ void process.env.APIMAPPER_SITES_FILE;
61
+ import { createRequire } from "node:module";
29
62
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
30
63
  import { loadModules, formatResult, readOnly } from "@getimo/mcp-toolkit";
31
64
  import { apimapperRestModule } from "./modules/apimapper/index.js";
@@ -33,7 +66,16 @@ import { loadSkillInstructions } from "./skill-instructions.js";
33
66
  import { connectStdio } from "./transports/stdio.js";
34
67
  import { createKeychain } from "./auth/keychain.js";
35
68
  import { ProfileStore, resolveConfigDir } from "./auth/profiles.js";
36
- import { registerUseProfileTool } from "./modules/apimapper/use-profile.js";
69
+ import { registerUseProfileTool, registerListProfilesTool, } from "./modules/apimapper/use-profile.js";
70
+ import { registerSitesUseProfileTool, registerSitesListProfilesTool, } from "./modules/apimapper/sites-tools.js";
71
+ import { getSitesRegistry, getActiveSiteId, setActiveSite, } from "./modules/apimapper/client.js";
72
+ import { shouldShowInteractiveHint, buildInteractiveHint } from "./cli-hint.js";
73
+ // Single source of truth for the package version (F-41 / W1.23).
74
+ // Reads ../package.json at runtime so we never drift between the manifest
75
+ // version (used by npm + DXT) and what we advertise to MCP clients.
76
+ const require = createRequire(import.meta.url);
77
+ const pkg = require("../package.json");
78
+ const PKG_VERSION = pkg.version;
37
79
  /**
38
80
  * Constructs the McpServer with bundled skill instructions wired into the
39
81
  * `instructions` field. Extracted as a factory for testability.
@@ -45,13 +87,48 @@ import { registerUseProfileTool } from "./modules/apimapper/use-profile.js";
45
87
  export function createServer() {
46
88
  return new McpServer({
47
89
  name: "API Mapper MCP",
48
- version: "0.2.0",
90
+ version: PKG_VERSION,
49
91
  }, {
50
92
  instructions: loadSkillInstructions(),
51
93
  });
52
94
  }
53
95
  const server = createServer();
54
96
  let moduleStatuses = [];
97
+ /**
98
+ * Bootstrap the active-profile pointer from `APIMAPPER_PROFILE` env var.
99
+ *
100
+ * F-49 (W1.27) added APIMAPPER_PROFILE to the DXT manifest + setup-cli, but
101
+ * no runtime consumer existed. A customer with multiple MCP-client entries
102
+ * declaring different profiles always landed on whichever was setActive
103
+ * last on disk — defeating the multi-site selection feature.
104
+ *
105
+ * Behaviour (A6-P3-INTEG-02 — pinned by index.bootstrap-profile.test.ts):
106
+ * - unset / whitespace-only → no-op (active pointer unchanged)
107
+ * - "default" → no-op (manifest default is the implicit state)
108
+ * - "<known profile name>" → store.setActive(name) is called
109
+ * - "<unknown profile name>" → no-op, no throw (avoid phantom profiles)
110
+ *
111
+ * Best-effort: any error reading the store is logged + swallowed so the
112
+ * rest of the MCP surface still boots on a disk-locked or torn-write host.
113
+ */
114
+ export async function bootstrapActiveProfile(store) {
115
+ const desired = process.env.APIMAPPER_PROFILE?.trim();
116
+ if (!desired || desired === "default")
117
+ return;
118
+ try {
119
+ const all = await store.list();
120
+ const known = all.some((p) => p.name === desired);
121
+ if (known) {
122
+ await store.setActive(desired);
123
+ }
124
+ // unknown profile: swallow silently to avoid creating phantom profiles
125
+ // or surfacing confusing errors on a fresh install where the profile
126
+ // env var was inherited from a different host.
127
+ }
128
+ catch (err) {
129
+ console.error("[apimapper-rest] APIMAPPER_PROFILE bootstrap skipped — profile store unreadable:", err instanceof Error ? err.message : err);
130
+ }
131
+ }
55
132
  // Root tool: module-loading status. Distinct from `apimapper_health` (which
56
133
  // probes connectivity + auth against the live REST surface). Names diverge
57
134
  // to avoid agent confusion.
@@ -60,12 +137,12 @@ server.registerTool("apimapper_rest_modules_status", {
60
137
  description: "Module-loading status for this MCP adapter (which sub-modules registered cleanly). " +
61
138
  "For runtime connectivity + auth checks against the API Mapper REST surface, use apimapper_health.",
62
139
  inputSchema: {},
63
- annotations: readOnly(),
140
+ annotations: readOnly({ title: "MCP Modules Status", openWorld: false }),
64
141
  }, async () => {
65
142
  const ok = moduleStatuses.filter((m) => m.status === "ok").length;
66
143
  const failed = moduleStatuses.filter((m) => m.status === "error").length;
67
144
  return formatResult({
68
- version: "0.2.0",
145
+ version: PKG_VERSION,
69
146
  modules_loaded: ok,
70
147
  modules_total: moduleStatuses.length,
71
148
  modules_failed: failed,
@@ -80,20 +157,73 @@ server.registerTool("apimapper_rest_modules_status", {
80
157
  });
81
158
  async function main() {
82
159
  moduleStatuses = await loadModules(server, [apimapperRestModule]);
83
- // Profile + keychain wiring for apimapper_use_profile.
84
- // Phase 5 deferred this to the server entrypoint because constructing the
85
- // keychain is async (it probes the OS Secret-Service, falling back to a
86
- // file impl) and the module-level register() signature is sync.
87
- // Best-effort: log + skip if the keychain init throws on a locked-down host
88
- // so the rest of the MCP surface still boots.
160
+ // Profile tools for apimapper_use_profile / apimapper_list_profiles.
161
+ //
162
+ // Phase 3 (2026-06-03) TWO multi-site mechanisms, branched on presence of a
163
+ // sites-file:
164
+ // APIMAPPER_SITES_FILE set + non-empty the sites-file IS the profile
165
+ // registry. The tools list its entries and switch the active site via the
166
+ // client's setActiveSite() (which retargets request()). No keychain.
167
+ // • otherwise → the legacy keychain ProfileStore path (the secure
168
+ // single-machine wizard default), unchanged.
169
+ //
170
+ // Best-effort: log + skip if init throws on a locked-down host so the rest of
171
+ // the MCP surface still boots.
172
+ let sitesFileActive = false;
89
173
  try {
90
- const configDir = resolveConfigDir();
91
- const keychain = await createKeychain({ configDir });
92
- const profileStore = new ProfileStore(configDir);
93
- registerUseProfileTool(server, { store: profileStore, keychain });
174
+ const registry = getSitesRegistry();
175
+ if (registry) {
176
+ sitesFileActive = true;
177
+ // A sites-file is present → honour APIMAPPER_PROFILE as the initial
178
+ // active-site selection (a site_id). Unknown / "default" / unset → leave
179
+ // the file's default entry active. setActiveSite throws on an unknown id,
180
+ // so guard with has() to avoid a phantom selection on a stale env var.
181
+ const desired = process.env.APIMAPPER_PROFILE?.trim();
182
+ if (desired && desired !== "default" && registry.has(desired)) {
183
+ setActiveSite(desired);
184
+ }
185
+ registerSitesListProfilesTool(server, {
186
+ getRegistry: () => {
187
+ const r = getSitesRegistry();
188
+ if (!r)
189
+ throw new Error("sites-file unloaded since boot");
190
+ return r;
191
+ },
192
+ getActiveSiteId,
193
+ });
194
+ registerSitesUseProfileTool(server, {
195
+ getRegistry: () => {
196
+ const r = getSitesRegistry();
197
+ if (!r)
198
+ throw new Error("sites-file unloaded since boot");
199
+ return r;
200
+ },
201
+ setActiveSite,
202
+ });
203
+ }
94
204
  }
95
205
  catch (err) {
96
- console.error("[apimapper-rest] use-profile tool disabled — keychain/profile init failed:", err instanceof Error ? err.message : err);
206
+ console.error("[apimapper-rest] sites-file profile tools disabled — sites-file init failed:", err instanceof Error ? err.message : err);
207
+ }
208
+ if (!sitesFileActive) {
209
+ // Keychain ProfileStore path (legacy single-machine default). Phase 5
210
+ // deferred this to the server entrypoint because constructing the keychain
211
+ // is async (probes the OS Secret-Service, falling back to a file impl) and
212
+ // the module-level register() signature is sync.
213
+ try {
214
+ const configDir = resolveConfigDir();
215
+ const keychain = await createKeychain({ configDir });
216
+ const profileStore = new ProfileStore(configDir);
217
+ // A6-P3-INTEG-02: honour APIMAPPER_PROFILE env var. Must run AFTER the
218
+ // ProfileStore is constructed but BEFORE the tools register so any
219
+ // subsequent tool call sees the corrected active pointer.
220
+ await bootstrapActiveProfile(profileStore);
221
+ registerUseProfileTool(server, { store: profileStore, keychain });
222
+ registerListProfilesTool(server, { store: profileStore, keychain });
223
+ }
224
+ catch (err) {
225
+ console.error("[apimapper-rest] use-profile tool disabled — keychain/profile init failed:", err instanceof Error ? err.message : err);
226
+ }
97
227
  }
98
228
  process.stdout.on("error", (err) => {
99
229
  if (err.code === "EPIPE" || err.code === "ERR_STREAM_DESTROYED")
@@ -102,7 +232,7 @@ async function main() {
102
232
  });
103
233
  await connectStdio(server);
104
234
  const ok = moduleStatuses.filter((m) => m.status === "ok").length;
105
- console.error(`[apimapper-rest] MCP Server v0.2.0 running — ${ok}/${moduleStatuses.length} modules loaded`);
235
+ console.error(`[apimapper-rest] MCP Server v${PKG_VERSION} running — ${ok}/${moduleStatuses.length} modules loaded`);
106
236
  }
107
237
  // ── Subcommand dispatch (Phase 6 setup CLI integration) ──────────────
108
238
  // AI clients invoke `apimapper-mcp` with stdio piped and no subcommand;
@@ -114,7 +244,7 @@ async function main() {
114
244
  // lazily inside the subcommand branch so the AI-client startup path
115
245
  // stays free of clack/prompts side-effects.
116
246
  const subcommand = process.argv[2];
117
- const CLI_SUBCOMMANDS = new Set(["setup", "install-skill", "install", "help", "--help", "-h"]);
247
+ const CLI_SUBCOMMANDS = new Set(["setup", "install-skill", "install", "uninstall", "remove", "help", "--help", "-h"]);
118
248
  if (subcommand && CLI_SUBCOMMANDS.has(subcommand)) {
119
249
  void (async () => {
120
250
  try {
@@ -128,6 +258,17 @@ if (subcommand && CLI_SUBCOMMANDS.has(subcommand)) {
128
258
  }
129
259
  })();
130
260
  }
261
+ else if (shouldShowInteractiveHint(subcommand, CLI_SUBCOMMANDS, !!process.stdin.isTTY)) {
262
+ // Interactive human ran `npx @wootsup/mcp` (bare) or a typo'd subcommand in
263
+ // a terminal. Booting the stdio server here would just sit waiting for
264
+ // JSON-RPC on stdin and LOOK hung. Print a one-screen hint and exit 0.
265
+ //
266
+ // Load-bearing invariant: when stdin is NOT a TTY (an MCP client pipes it),
267
+ // shouldShowInteractiveHint() returns false and we fall through to main()
268
+ // below — the server-boot path is byte-for-byte unchanged.
269
+ console.error(buildInteractiveHint(subcommand));
270
+ process.exit(0);
271
+ }
131
272
  else {
132
273
  main().catch((error) => {
133
274
  console.error("[apimapper-rest] Fatal error:", error);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,uEAAuE;AACvE,0EAA0E;AAC1E,EAAE;AACF,uEAAuE;AACvE,qEAAqE;AACrE,iEAAiE;AACjE,wCAAwC;AAExC,yEAAyE;AACzE,sEAAsE;AACtE,2CAA2C;AAC3C,+CAA+C;AAC/C,8DAA8D;AAC9D,iDAAiD;AACjD,sEAAsE;AACtE,mEAAmE;AACnE,oEAAoE;AACpE,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,qBAAqB,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;AAClE,CAAC;AACD,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;IACrE,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;AACjE,CAAC;AACD,oEAAoE;AACpE,yEAAyE;AACzE,uEAAuE;AACvE,uCAAuC;AACvC,KAAK,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;AAEpC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAqB,MAAM,qBAAqB,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAE5E;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,SAAS,CAClB;QACE,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EAAE,qBAAqB,EAAE;KACtC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;AAE9B,IAAI,cAAc,GAAmB,EAAE,CAAC;AAExC,4EAA4E;AAC5E,2EAA2E;AAC3E,4BAA4B;AAC5B,MAAM,CAAC,YAAY,CACjB,+BAA+B,EAC/B;IACE,KAAK,EAAE,wBAAwB;IAC/B,WAAW,EACT,qFAAqF;QACrF,mGAAmG;IACrG,WAAW,EAAE,EAAE;IACf,WAAW,EAAE,QAAQ,EAAE;CACxB,EACD,KAAK,IAAI,EAAE;IACT,MAAM,EAAE,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,MAAM,CAAC;IAClE,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC;IACzE,OAAO,YAAY,CACjB;QACE,OAAO,EAAE,OAAO;QAChB,cAAc,EAAE,EAAE;QAClB,aAAa,EAAE,cAAc,CAAC,MAAM;QACpC,cAAc,EAAE,MAAM;QACtB,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAClC,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,KAAK,EAAE,CAAC,CAAC,KAAK;SACf,CAAC,CAAC;QACH,IAAI,EAAE,0DAA0D;KACjE,EACD,KAAK,EACL,EAAE,QAAQ,EAAE,IAAI,EAAE,CACnB,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,cAAc,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAElE,uDAAuD;IACvD,0EAA0E;IAC1E,wEAAwE;IACxE,gEAAgE;IAChE,4EAA4E;IAC5E,8CAA8C;IAC9C,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;QACrD,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC;QACjD,sBAAsB,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAC;IACpE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,4EAA4E,EAC5E,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CACzC,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;QACxD,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,IAAI,KAAK,sBAAsB;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjF,MAAM,GAAG,CAAC;IACZ,CAAC,CAAC,CAAC;IACH,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,MAAM,CAAC;IAClE,OAAO,CAAC,KAAK,CACX,gDAAgD,EAAE,IAAI,cAAc,CAAC,MAAM,iBAAiB,CAC7F,CAAC;AACJ,CAAC;AAED,wEAAwE;AACxE,wEAAwE;AACxE,8DAA8D;AAC9D,qEAAqE;AACrE,iEAAiE;AACjE,EAAE;AACF,uEAAuE;AACvE,oEAAoE;AACpE,4CAA4C;AAC5C,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;AAE/F,IAAI,UAAU,IAAI,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;IAClD,KAAK,CAAC,KAAK,IAAmB,EAAE;QAC9B,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;YAClD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,GAAG,CAAC,CAAC;YACvD,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;AACP,CAAC;KAAM,CAAC;IACN,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACrB,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,OAAO,EAAE,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -18,7 +18,7 @@ const MARKER_BLOCK = `
18
18
  ## API Mapper MCP
19
19
 
20
20
  ${MARKER_LINE}
21
- The API Mapper skill is installed at \`~/.claude/skills/apimapper/\`. Refer to it for flow, connection, OAuth, YOOtheme, and Joomla guidance. Source: https://github.com/wootsup/api-mapper.
21
+ The API Mapper skill is installed at \`~/.claude/skills/apimapper/\`. Refer to it for flow, connection, OAuth, YOOtheme, and Joomla guidance. Docs: https://wootsup.com/docs/mcp/api-mapper/.
22
22
  `;
23
23
  function defaultPkgRoot() {
24
24
  // <pkg-root>/src/install-skill.ts → up one.
@@ -1,2 +1,2 @@
1
- import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- export declare function registerCacheTools(server: McpServer): void;
1
+ import type { ToolRegistrar } from "./gateway/capturing-server.js";
2
+ export declare function registerCacheTools(server: ToolRegistrar): void;
@@ -1,9 +1,28 @@
1
1
  import { z } from "zod";
2
- import { formatResult, readOnly, mutating } from "@getimo/mcp-toolkit";
3
- import { request, hintFor } from "./client.js";
2
+ import { formatResult, statsResult, readOnly, destructive, } from "@getimo/mcp-toolkit";
3
+ import { request } from "./client.js";
4
+ import { restErrorResult } from "./tool-result.js";
5
+ // rc.13 Welle 3 (2026-05-20) — cache_stats migrated to the toolkit's
6
+ // statsResult builder; both tools' error branches upgraded to errorResult.
7
+ // The migration is purely additive (text `content` block preserved, `_meta.ui`
8
+ // added). cache_stats' headline metrics (hits / misses / hit_rate / storage /
9
+ // window / rt_avoidance) become the statsResult `stats[]`; the per-tier
10
+ // breakdown + the (W1.15-capped) top_keys list move into the statsResult
11
+ // `description` text so the LLM still reads them. cache_invalidate keeps its
12
+ // formatResult success payload — a small confirmation.
4
13
  // F-A6-07: canonical PHP enum from CacheInvalidateController::scopeToEvent.
5
14
  // Legacy aliases (`flow`, `connection`, `credential`, `user`) are accepted
6
15
  // by Wave 1B PHP but the dotted form is the documented contract.
16
+ //
17
+ // Wave-12 F12 (2026-05-31): `yootheme.schema` is a direct-file flush scope
18
+ // that bypasses the InvalidationBus. PHP invokes
19
+ // `YOOthemeSchemaCacheBuster::flushNow()` directly when this scope arrives,
20
+ // deleting `schema-*.{php,gql,error.gql}` from the active YOOtheme theme
21
+ // cache directory. Pairs with Wave-12 F8 — that fix closes the auto-flush
22
+ // gap on flow publish; this scope is the manual escape hatch when a
23
+ // customer hits a stale schema and wants to recompile without re-publishing
24
+ // every flow. See `skills/apimapper/reference/troubleshooting.md` for
25
+ // triage.
7
26
  const CACHE_INVALIDATE_SCOPES = [
8
27
  "connection.updated",
9
28
  "connection.deleted",
@@ -11,7 +30,11 @@ const CACHE_INVALIDATE_SCOPES = [
11
30
  "flow.published",
12
31
  "user.refresh",
13
32
  "user.fetch_data",
33
+ "yootheme.schema",
14
34
  ];
35
+ // W1.15 (F-27): cap top_keys envelope size — PHP can return arbitrary
36
+ // counts but the MCP response stays bounded for AI-client legibility.
37
+ const CACHE_STATS_TOP_KEYS_CAP = 20;
15
38
  export function registerCacheTools(server) {
16
39
  // ── apimapper_cache_invalidate ─────────────────────────────────────
17
40
  server.registerTool("apimapper_cache_invalidate", {
@@ -19,34 +42,37 @@ export function registerCacheTools(server) {
19
42
  description: "Publish a cache-invalidation event to the InvalidationBus (Admin-UI BroadcastChannel + render cache). " +
20
43
  "Scope is the dotted event id matching the PHP CacheInvalidationEvent subclass. " +
21
44
  "Legacy aliases (`flow`, `connection`, `credential`, `user`) are accepted server-side " +
22
- "but the canonical scopes are documented here." +
23
- "\n\nExample:\n apimapper_cache_invalidate({ scope: 'connection.updated', payload: { connection_id: 'con_abc' } })",
45
+ "but the canonical scopes are documented here. " +
46
+ "`yootheme.schema` is a manual escape hatch that directly flushes the YOOtheme GraphQL schema " +
47
+ "cache files (`schema-*.{php,gql,error.gql}`) — use it when a newly-published flow is missing " +
48
+ "from the YOOtheme Builder source list. See troubleshooting topic for triage." +
49
+ "\n\nExamples:" +
50
+ "\n apimapper_cache_invalidate({ scope: 'connection.updated', payload: { connection_id: 'con_abc' } })" +
51
+ "\n apimapper_cache_invalidate({ scope: 'yootheme.schema' }) // force-flush the YT schema cache",
24
52
  inputSchema: {
25
53
  scope: z
26
54
  .enum(CACHE_INVALIDATE_SCOPES)
27
55
  .describe("Cache invalidation scope (dotted event id). " +
28
56
  "Required payload fields: connection.updated→{connection_id, credential_id?}, " +
29
57
  "connection.deleted→{connection_id}, credential.reauth→{credential_id, affected_connection_ids?}, " +
30
- "flow.published→{flow_id, connection_ids?}, user.refresh→{}, user.fetch_data→{node_id?, connection_id?}."),
58
+ "flow.published→{flow_id, connection_ids?}, user.refresh→{}, user.fetch_data→{node_id?, connection_id?}, " +
59
+ "yootheme.schema→{} (no payload — direct-file flush, bypasses the InvalidationBus)."),
31
60
  payload: z
32
61
  .record(z.string(), z.unknown())
33
62
  .optional()
34
63
  .describe("Event-specific payload (see scope description for required keys)."),
35
64
  },
36
- annotations: mutating(),
65
+ // W1.26 (IA-1): cache_invalidate evicts state (destructive), not idempotent
66
+ // re-write of same payload. Aligns with the rest of the destructive() family
67
+ // (connection_delete, flow_delete, library_deactivate, ...).
68
+ annotations: destructive({ title: "Invalidate Admin Cache", openWorld: false }),
37
69
  }, async ({ scope, payload }) => {
38
70
  const body = { scope };
39
71
  if (payload)
40
72
  body.payload = payload;
41
73
  const r = await request("/cache/admin/invalidate", { method: "POST", body: JSON.stringify(body) });
42
74
  if (!r.success) {
43
- return formatResult({
44
- error: r.error,
45
- status: r.status,
46
- errorCode: r.errorCode,
47
- context: { scope, payload_keys: payload ? Object.keys(payload) : [] },
48
- hint: hintFor(r.errorCode),
49
- }, true);
75
+ return restErrorResult(r, { scope, payload_keys: payload ? Object.keys(payload) : [] }, { message: "cache invalidation failed" });
50
76
  }
51
77
  const ok = r.data?.ok === true;
52
78
  return formatResult({
@@ -62,14 +88,15 @@ export function registerCacheTools(server) {
62
88
  // events.
63
89
  server.registerTool("apimapper_cache_stats", {
64
90
  title: "Get Cache Stats",
65
- description: "Fetch cache observability stats (per-tier hits/misses, storage size, invalidation events)." +
91
+ description: "Fetch cache observability stats (per-tier hits/misses, storage size, invalidation events, " +
92
+ `top_keys capped at ${CACHE_STATS_TOP_KEYS_CAP}).` +
66
93
  "\n\nExample:\n apimapper_cache_stats({})",
67
94
  inputSchema: {},
68
- annotations: readOnly(),
95
+ annotations: readOnly({ title: "Get Cache Stats", openWorld: false }),
69
96
  }, async () => {
70
97
  const r = await request("/cache-stats");
71
98
  if (!r.success) {
72
- return formatResult({ error: r.error, status: r.status, errorCode: r.errorCode, context: {}, hint: hintFor(r.errorCode) }, true);
99
+ return restErrorResult(r, {}, { message: "cache stats failed" });
73
100
  }
74
101
  const tiers = r.data?.tiers ?? {};
75
102
  const admin = tiers.admin ?? {};
@@ -82,20 +109,83 @@ export function registerCacheTools(server) {
82
109
  const totalMisses = adminMisses + renderMisses;
83
110
  const denom = totalHits + totalMisses;
84
111
  const hitRate = denom > 0 ? `${((totalHits / denom) * 100).toFixed(1)}%` : "n/a";
85
- return formatResult({
86
- timestamp: r.data?.timestamp,
87
- hits: totalHits,
88
- misses: totalMisses,
89
- hit_rate: hitRate,
90
- tiers: {
91
- admin: { hits: adminHits, misses: adminMisses, sets: admin.sets ?? 0 },
92
- render: { hits: renderHits, misses: renderMisses, sets: render.sets ?? 0 },
112
+ // W3.1 — statsResult: every metric becomes a flat `stats[]` entry so it
113
+ // is BOTH LLM-visible (rendered as text by statsResult) and structured
114
+ // for the StatsDisplay card. The headline metrics, the per-tier
115
+ // breakdown, storage and the (W1.15-capped) top_keys all render as stat
116
+ // entries — statsResult.stats[] holds flat scalars, and the top_keys
117
+ // list is joined into a single string-valued stat.
118
+ const storage = r.data?.storage;
119
+ const topKeys = Array.isArray(r.data?.top_keys)
120
+ ? r.data.top_keys.slice(0, CACHE_STATS_TOP_KEYS_CAP)
121
+ : [];
122
+ const stats = [
123
+ { key: "hits", label: "Hits", value: totalHits, format: "number" },
124
+ { key: "misses", label: "Misses", value: totalMisses, format: "number" },
125
+ { key: "hit_rate", label: "Hit rate", value: hitRate },
126
+ {
127
+ key: "admin_tier",
128
+ label: "Tier admin",
129
+ value: `${adminHits} hits / ${adminMisses} misses / ${admin.sets ?? 0} sets`,
130
+ },
131
+ {
132
+ key: "render_tier",
133
+ label: "Tier render",
134
+ value: `${renderHits} hits / ${renderMisses} misses / ${render.sets ?? 0} sets`,
93
135
  },
94
- storage: r.data?.storage,
95
- invalidation: r.data?.invalidation,
96
- window_seconds: r.data?.window_seconds,
97
- rt_avoidance_ms_p50: r.data?.rt_avoidance_ms_p50,
98
- }, false, { maxChars: 3000 });
136
+ ];
137
+ if (storage && typeof storage.entries === "number") {
138
+ stats.push({
139
+ key: "storage_entries",
140
+ label: "Storage entries",
141
+ value: storage.entries,
142
+ format: "number",
143
+ });
144
+ }
145
+ if (storage && typeof storage.bytes === "number") {
146
+ stats.push({
147
+ key: "storage_bytes",
148
+ label: "Storage bytes",
149
+ value: storage.bytes,
150
+ format: "number",
151
+ });
152
+ }
153
+ if (typeof r.data?.window_seconds === "number") {
154
+ stats.push({
155
+ key: "window_seconds",
156
+ label: "Window (s)",
157
+ value: r.data.window_seconds,
158
+ format: "number",
159
+ });
160
+ }
161
+ if (typeof r.data?.rt_avoidance_ms_p50 === "number") {
162
+ stats.push({
163
+ key: "rt_avoidance_ms_p50",
164
+ label: "RT avoidance p50 (ms)",
165
+ value: r.data.rt_avoidance_ms_p50,
166
+ format: "number",
167
+ });
168
+ }
169
+ if (r.data?.invalidation && typeof r.data.invalidation === "object") {
170
+ stats.push({
171
+ key: "invalidation",
172
+ label: "Invalidation",
173
+ value: JSON.stringify(r.data.invalidation),
174
+ });
175
+ }
176
+ if (topKeys.length > 0) {
177
+ stats.push({
178
+ key: "top_keys",
179
+ label: `Top keys (capped ${CACHE_STATS_TOP_KEYS_CAP})`,
180
+ value: topKeys.map((k) => String(k)).join(", "),
181
+ });
182
+ }
183
+ return statsResult({
184
+ title: "Cache Stats",
185
+ description: "Per-tier cache observability — hit/miss counters, storage size, " +
186
+ "invalidation throughput and the hottest keys.",
187
+ stats,
188
+ });
99
189
  });
100
190
  }
101
191
  //# sourceMappingURL=cache.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/modules/apimapper/cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/modules/apimapper/cache.ts"],"names":[],"mappings":"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"}