@wootsup/mcp 0.1.0 → 0.4.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 (208) hide show
  1. package/CHANGELOG.md +157 -83
  2. package/README.md +31 -27
  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/catalog/build-catalog.d.ts +31 -0
  8. package/dist/catalog/build-catalog.js +68 -0
  9. package/dist/catalog/build-catalog.js.map +1 -0
  10. package/dist/cli-hint.d.ts +22 -0
  11. package/dist/cli-hint.js +55 -0
  12. package/dist/cli-hint.js.map +1 -0
  13. package/dist/index.js +129 -22
  14. package/dist/index.js.map +1 -1
  15. package/dist/install-skill.js +1 -1
  16. package/dist/modules/apimapper/auto-layout.d.ts +21 -0
  17. package/dist/modules/apimapper/auto-layout.js +54 -0
  18. package/dist/modules/apimapper/auto-layout.js.map +1 -0
  19. package/dist/modules/apimapper/cache.js +25 -17
  20. package/dist/modules/apimapper/cache.js.map +1 -1
  21. package/dist/modules/apimapper/client.d.ts +115 -4
  22. package/dist/modules/apimapper/client.js +699 -304
  23. package/dist/modules/apimapper/client.js.map +1 -1
  24. package/dist/modules/apimapper/connections-format.d.ts +31 -1
  25. package/dist/modules/apimapper/connections-format.js +97 -5
  26. package/dist/modules/apimapper/connections-format.js.map +1 -1
  27. package/dist/modules/apimapper/connections.d.ts +9 -7
  28. package/dist/modules/apimapper/connections.js +449 -127
  29. package/dist/modules/apimapper/connections.js.map +1 -1
  30. package/dist/modules/apimapper/credential-sanitizer.d.ts +5 -0
  31. package/dist/modules/apimapper/credential-sanitizer.js +60 -1
  32. package/dist/modules/apimapper/credential-sanitizer.js.map +1 -1
  33. package/dist/modules/apimapper/credentials.js +105 -61
  34. package/dist/modules/apimapper/credentials.js.map +1 -1
  35. package/dist/modules/apimapper/diagnose.js +21 -2
  36. package/dist/modules/apimapper/diagnose.js.map +1 -1
  37. package/dist/modules/apimapper/elicitation.d.ts +29 -0
  38. package/dist/modules/apimapper/elicitation.js +62 -0
  39. package/dist/modules/apimapper/elicitation.js.map +1 -1
  40. package/dist/modules/apimapper/example-extract.d.ts +13 -0
  41. package/dist/modules/apimapper/example-extract.js +111 -0
  42. package/dist/modules/apimapper/example-extract.js.map +1 -0
  43. package/dist/modules/apimapper/filter-operators.d.ts +24 -0
  44. package/dist/modules/apimapper/filter-operators.js +103 -0
  45. package/dist/modules/apimapper/filter-operators.js.map +1 -0
  46. package/dist/modules/apimapper/flows-format.js +92 -22
  47. package/dist/modules/apimapper/flows-format.js.map +1 -1
  48. package/dist/modules/apimapper/flows.d.ts +8 -7
  49. package/dist/modules/apimapper/flows.js +275 -120
  50. package/dist/modules/apimapper/flows.js.map +1 -1
  51. package/dist/modules/apimapper/gateway/advanced-read-tool.d.ts +9 -0
  52. package/dist/modules/apimapper/gateway/advanced-read-tool.js +172 -0
  53. package/dist/modules/apimapper/gateway/advanced-read-tool.js.map +1 -0
  54. package/dist/modules/apimapper/gateway/advanced-tool.js +66 -106
  55. package/dist/modules/apimapper/gateway/advanced-tool.js.map +1 -1
  56. package/dist/modules/apimapper/gateway/collect-module-tools.d.ts +17 -0
  57. package/dist/modules/apimapper/gateway/collect-module-tools.js +44 -0
  58. package/dist/modules/apimapper/gateway/collect-module-tools.js.map +1 -0
  59. package/dist/modules/apimapper/gateway/essentials.d.ts +1 -1
  60. package/dist/modules/apimapper/gateway/essentials.js +21 -2
  61. package/dist/modules/apimapper/gateway/essentials.js.map +1 -1
  62. package/dist/modules/apimapper/gateway/gateway-shared.d.ts +21 -0
  63. package/dist/modules/apimapper/gateway/gateway-shared.js +124 -0
  64. package/dist/modules/apimapper/gateway/gateway-shared.js.map +1 -0
  65. package/dist/modules/apimapper/gateway/test-support.d.ts +1 -17
  66. package/dist/modules/apimapper/gateway/test-support.js +4 -33
  67. package/dist/modules/apimapper/gateway/test-support.js.map +1 -1
  68. package/dist/modules/apimapper/get-skill-cores.d.ts +4 -0
  69. package/dist/modules/apimapper/get-skill-cores.js +220 -0
  70. package/dist/modules/apimapper/get-skill-cores.js.map +1 -0
  71. package/dist/modules/apimapper/get-skill.d.ts +1 -1
  72. package/dist/modules/apimapper/get-skill.js +74 -9
  73. package/dist/modules/apimapper/get-skill.js.map +1 -1
  74. package/dist/modules/apimapper/graph-builder.d.ts +85 -2
  75. package/dist/modules/apimapper/graph-builder.js +151 -15
  76. package/dist/modules/apimapper/graph-builder.js.map +1 -1
  77. package/dist/modules/apimapper/graph.js +152 -48
  78. package/dist/modules/apimapper/graph.js.map +1 -1
  79. package/dist/modules/apimapper/index.js +27 -13
  80. package/dist/modules/apimapper/index.js.map +1 -1
  81. package/dist/modules/apimapper/jmespath-test.d.ts +4 -0
  82. package/dist/modules/apimapper/jmespath-test.js +152 -0
  83. package/dist/modules/apimapper/jmespath-test.js.map +1 -0
  84. package/dist/modules/apimapper/library.js +553 -88
  85. package/dist/modules/apimapper/library.js.map +1 -1
  86. package/dist/modules/apimapper/license.js +12 -36
  87. package/dist/modules/apimapper/license.js.map +1 -1
  88. package/dist/modules/apimapper/list-footer.d.ts +27 -0
  89. package/dist/modules/apimapper/list-footer.js +57 -0
  90. package/dist/modules/apimapper/list-footer.js.map +1 -0
  91. package/dist/modules/apimapper/local-sources.js +100 -57
  92. package/dist/modules/apimapper/local-sources.js.map +1 -1
  93. package/dist/modules/apimapper/mcp-client-identity.d.ts +32 -0
  94. package/dist/modules/apimapper/mcp-client-identity.js +70 -0
  95. package/dist/modules/apimapper/mcp-client-identity.js.map +1 -0
  96. package/dist/modules/apimapper/merge-constants.d.ts +6 -0
  97. package/dist/modules/apimapper/merge-constants.js +26 -0
  98. package/dist/modules/apimapper/merge-constants.js.map +1 -0
  99. package/dist/modules/apimapper/misc.js +13 -27
  100. package/dist/modules/apimapper/misc.js.map +1 -1
  101. package/dist/modules/apimapper/node-schema.d.ts +52 -2
  102. package/dist/modules/apimapper/node-schema.js +95 -4
  103. package/dist/modules/apimapper/node-schema.js.map +1 -1
  104. package/dist/modules/apimapper/onboarding.d.ts +59 -1
  105. package/dist/modules/apimapper/onboarding.js +231 -28
  106. package/dist/modules/apimapper/onboarding.js.map +1 -1
  107. package/dist/modules/apimapper/read-cache.d.ts +16 -3
  108. package/dist/modules/apimapper/read-cache.js +59 -4
  109. package/dist/modules/apimapper/read-cache.js.map +1 -1
  110. package/dist/modules/apimapper/render/index.js +26 -5
  111. package/dist/modules/apimapper/render/index.js.map +1 -1
  112. package/dist/modules/apimapper/resource-id.d.ts +13 -0
  113. package/dist/modules/apimapper/resource-id.js +69 -0
  114. package/dist/modules/apimapper/resource-id.js.map +1 -0
  115. package/dist/modules/apimapper/schema.js +9 -18
  116. package/dist/modules/apimapper/schema.js.map +1 -1
  117. package/dist/modules/apimapper/settings.js +49 -52
  118. package/dist/modules/apimapper/settings.js.map +1 -1
  119. package/dist/modules/apimapper/sites-tools.d.ts +29 -0
  120. package/dist/modules/apimapper/sites-tools.js +165 -0
  121. package/dist/modules/apimapper/sites-tools.js.map +1 -0
  122. package/dist/modules/apimapper/tool-result.d.ts +66 -0
  123. package/dist/modules/apimapper/tool-result.js +125 -0
  124. package/dist/modules/apimapper/tool-result.js.map +1 -0
  125. package/dist/modules/apimapper/toolslist-size.d.ts +12 -11
  126. package/dist/modules/apimapper/toolslist-size.js +34 -21
  127. package/dist/modules/apimapper/toolslist-size.js.map +1 -1
  128. package/dist/modules/apimapper/types.d.ts +34 -0
  129. package/dist/modules/apimapper/types.js +1 -1
  130. package/dist/modules/apimapper/types.js.map +1 -1
  131. package/dist/modules/apimapper/whitelist-drift.d.ts +85 -0
  132. package/dist/modules/apimapper/whitelist-drift.js +375 -0
  133. package/dist/modules/apimapper/whitelist-drift.js.map +1 -0
  134. package/dist/modules/apimapper/workflows.js +302 -58
  135. package/dist/modules/apimapper/workflows.js.map +1 -1
  136. package/dist/modules/apimapper/yootheme-binding.d.ts +35 -0
  137. package/dist/modules/apimapper/yootheme-binding.js +267 -0
  138. package/dist/modules/apimapper/yootheme-binding.js.map +1 -0
  139. package/dist/platform/index.d.ts +56 -0
  140. package/dist/platform/index.js +158 -2
  141. package/dist/platform/index.js.map +1 -1
  142. package/dist/proxy/bridge.d.ts +35 -0
  143. package/dist/proxy/bridge.js +129 -0
  144. package/dist/proxy/bridge.js.map +1 -0
  145. package/dist/proxy/mode.d.ts +9 -0
  146. package/dist/proxy/mode.js +20 -0
  147. package/dist/proxy/mode.js.map +1 -0
  148. package/dist/setup/detect-clients.d.ts +40 -1
  149. package/dist/setup/detect-clients.js +148 -1
  150. package/dist/setup/detect-clients.js.map +1 -1
  151. package/dist/setup/probe-auth.d.ts +51 -0
  152. package/dist/setup/probe-auth.js +141 -0
  153. package/dist/setup/probe-auth.js.map +1 -0
  154. package/dist/setup/probe-handshake.js +40 -7
  155. package/dist/setup/probe-handshake.js.map +1 -1
  156. package/dist/setup/remove-config.d.ts +8 -0
  157. package/dist/setup/remove-config.js +145 -0
  158. package/dist/setup/remove-config.js.map +1 -0
  159. package/dist/setup/uninstall.d.ts +34 -0
  160. package/dist/setup/uninstall.js +147 -0
  161. package/dist/setup/uninstall.js.map +1 -0
  162. package/dist/setup-cli.d.ts +16 -0
  163. package/dist/setup-cli.js +63 -1
  164. package/dist/setup-cli.js.map +1 -1
  165. package/dist/sites/loader.d.ts +48 -0
  166. package/dist/sites/loader.js +134 -0
  167. package/dist/sites/loader.js.map +1 -0
  168. package/dist/sites/schema.d.ts +69 -0
  169. package/dist/sites/schema.js +71 -0
  170. package/dist/sites/schema.js.map +1 -0
  171. package/dist/sites/secret-resolver.d.ts +47 -0
  172. package/dist/sites/secret-resolver.js +150 -0
  173. package/dist/sites/secret-resolver.js.map +1 -0
  174. package/dist/skill-instructions.d.ts +14 -1
  175. package/dist/skill-instructions.js +35 -6
  176. package/dist/skill-instructions.js.map +1 -1
  177. package/dist/transports/stdio.js +4 -4
  178. package/dist/transports/stdio.js.map +1 -1
  179. package/dist/uninstall-skill.d.ts +27 -0
  180. package/dist/uninstall-skill.js +89 -0
  181. package/dist/uninstall-skill.js.map +1 -0
  182. package/docs/architecture.md +21 -21
  183. package/docs/customgraph-internal-migration.md +4 -4
  184. package/docs/security.md +2 -21
  185. package/docs/tools.md +40 -12
  186. package/manifest.json +77 -79
  187. package/package.json +69 -65
  188. package/skills/apimapper/SKILL.md +128 -7
  189. package/skills/apimapper/reference/conditional-style-multi-items.md +114 -0
  190. package/skills/apimapper/reference/dynamize-existing-layout.md +158 -0
  191. package/skills/apimapper/reference/jmespath-cookbook.md +241 -0
  192. package/skills/apimapper/reference/jmespath-pitfalls.md +189 -0
  193. package/skills/apimapper/reference/joomla.md +1 -1
  194. package/skills/apimapper/reference/library-template-discovery.md +65 -0
  195. package/skills/apimapper/reference/merge-two-sources-on-key.md +204 -0
  196. package/skills/apimapper/reference/oauth.md +143 -52
  197. package/skills/apimapper/reference/troubleshooting.md +22 -2
  198. package/skills/apimapper/reference/yootheme-source-to-builder-handoff.md +348 -0
  199. package/skills/apimapper/reference/yootheme.md +75 -44
  200. package/dist/auth/oauth-provider.d.ts +0 -68
  201. package/dist/auth/oauth-provider.js +0 -232
  202. package/dist/auth/oauth-provider.js.map +0 -1
  203. package/dist/server-http.d.ts +0 -22
  204. package/dist/server-http.js +0 -159
  205. package/dist/server-http.js.map +0 -1
  206. package/dist/transports/http.d.ts +0 -29
  207. package/dist/transports/http.js +0 -267
  208. package/dist/transports/http.js.map +0 -1
@@ -0,0 +1,134 @@
1
+ // src/sites/loader.ts — Phase 3.
2
+ //
3
+ // Load + validate the on-disk sites file pointed at by APIMAPPER_SITES_FILE and
4
+ // wrap it in a small read-only registry. This is the multi-site "agency / .dxt
5
+ // one-click" path: a plaintext JSON file listing several WordPress/Joomla sites,
6
+ // each with its own URL + token + platform. The keychain ProfileStore path
7
+ // (src/auth/profiles.ts) remains the secure wizard default for single-machine
8
+ // setups — the two mechanisms coexist; the sites-file takes priority in
9
+ // client.ts ONLY when APIMAPPER_SITES_FILE is set and the file is non-empty.
10
+ //
11
+ // Read-only by design: this loader never writes the sites file. Editing is an
12
+ // operator / wizard concern, kept out of the hot request path.
13
+ import { existsSync, readFileSync } from "node:fs";
14
+ import { homedir } from "node:os";
15
+ import { join } from "node:path";
16
+ import { SitesFile } from "./schema.js";
17
+ /** Base class for any sites-file IO / parse / validation failure. */
18
+ export class SitesFileError extends Error {
19
+ cause;
20
+ constructor(message, cause) {
21
+ super(message);
22
+ this.cause = cause;
23
+ this.name = "SitesFileError";
24
+ Object.setPrototypeOf(this, SitesFileError.prototype);
25
+ }
26
+ }
27
+ /**
28
+ * Read-only registry around a parsed, non-empty sites file. Provides O(1)-ish
29
+ * lookups for the active-site resolution in client.ts. Never mutates the input.
30
+ */
31
+ export class SitesRegistry {
32
+ file;
33
+ constructor(file) {
34
+ this.file = file;
35
+ }
36
+ /** Entries in insertion order (stable for list-tool UX). */
37
+ list() {
38
+ return this.file.sites;
39
+ }
40
+ /** Site_id list in insertion order. */
41
+ listIds() {
42
+ return this.file.sites.map((s) => s.site_id);
43
+ }
44
+ /** Raw entry for a site_id, or null when unknown. */
45
+ get(siteId) {
46
+ return this.file.sites.find((s) => s.site_id === siteId) ?? null;
47
+ }
48
+ /** True when the registry contains the given site_id. */
49
+ has(siteId) {
50
+ return this.file.sites.some((s) => s.site_id === siteId);
51
+ }
52
+ /**
53
+ * The default site entry. Resolution order:
54
+ * 1. `default_site_id` (when it points at an existing entry).
55
+ * 2. The lone `is_default:true` entry (schema guarantees at most one).
56
+ * 3. The first entry (the file is guaranteed non-empty by the loader).
57
+ */
58
+ getDefault() {
59
+ const explicit = this.file.default_site_id;
60
+ if (explicit !== null) {
61
+ const hit = this.get(explicit);
62
+ if (hit)
63
+ return hit;
64
+ }
65
+ const flagged = this.file.sites.find((s) => s.is_default);
66
+ if (flagged)
67
+ return flagged;
68
+ // Loader guarantees sites.length > 0 (empty → null, never a registry).
69
+ return this.file.sites[0];
70
+ }
71
+ }
72
+ /**
73
+ * Load the sites file at `path` and return a {@link SitesRegistry}, or `null`
74
+ * when there is no usable multi-site config (so the caller falls through to the
75
+ * env / keychain single-site path).
76
+ *
77
+ * - `path` unset / empty / whitespace → null
78
+ * - file does not exist → null
79
+ * - file parses but has zero sites → null
80
+ * - malformed JSON / schema-invalid /
81
+ * unknown schema_version → throws {@link SitesFileError}
82
+ */
83
+ /**
84
+ * F190 (2026-06-12): expand a leading `~` to the user's home directory.
85
+ * Node's fs does NOT do this — a `~/...` path typed into the Claude Desktop
86
+ * DXT settings silently failed (existsSync false → no sites). Only `~` and
87
+ * `~/...` are expanded; `~user/...` is left untouched (not supported).
88
+ */
89
+ export function expandTilde(p) {
90
+ if (p === "~")
91
+ return homedir();
92
+ if (p.startsWith("~/"))
93
+ return join(homedir(), p.slice(2));
94
+ return p;
95
+ }
96
+ export function loadSitesRegistry(path) {
97
+ const trimmed = expandTilde((path ?? "").trim());
98
+ if (trimmed.length === 0)
99
+ return null;
100
+ if (!existsSync(trimmed))
101
+ return null;
102
+ let raw;
103
+ try {
104
+ raw = readFileSync(trimmed, "utf8");
105
+ }
106
+ catch (e) {
107
+ throw new SitesFileError(`Failed to read sites file at ${trimmed}`, e);
108
+ }
109
+ let parsed;
110
+ try {
111
+ parsed = JSON.parse(raw);
112
+ }
113
+ catch (e) {
114
+ throw new SitesFileError(`Sites file at ${trimmed} is not valid JSON`, e);
115
+ }
116
+ // Explicit schema-version gate: reject a known-unknown version with a clear
117
+ // message rather than letting the Zod literal check surface a cryptic issue.
118
+ if (typeof parsed === "object" &&
119
+ parsed !== null &&
120
+ "schema_version" in parsed &&
121
+ parsed.schema_version !== 1) {
122
+ throw new SitesFileError(`Unsupported sites-file schema_version: ${String(parsed.schema_version)}. This build supports schema_version: 1.`);
123
+ }
124
+ const result = SitesFile.safeParse(parsed);
125
+ if (!result.success) {
126
+ throw new SitesFileError(`Sites file at ${trimmed} failed schema validation: ` +
127
+ result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; "));
128
+ }
129
+ // Empty sites list → no usable multi-site config; fall through to env.
130
+ if (result.data.sites.length === 0)
131
+ return null;
132
+ return new SitesRegistry(result.data);
133
+ }
134
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/sites/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Allowed character set for a `site_id`. Letters, digits, underscore, dash —
4
+ * no spaces, no path separators, no shell metacharacters. Filename-safe,
5
+ * URL-path-safe, log-safe.
6
+ */
7
+ export declare const SITE_ID_REGEX: RegExp;
8
+ /**
9
+ * 1Password Secret Reference shape (`op://<vault>/<item>/<field>` and deeper).
10
+ * Letters, digits, underscore, slash, dot, dash only. The negative lookahead
11
+ * `(?!.*\/\.\.\/)` rejects any ref containing a `/../` traversal segment while
12
+ * still allowing legitimate `.` in vault/item names (e.g. `op://team.acme/...`).
13
+ * Re-validated at the secret-resolver call site as defence-in-depth before the
14
+ * ref ever reaches a subprocess argv.
15
+ */
16
+ export declare const OP_REF_REGEX: RegExp;
17
+ /**
18
+ * API Mapper MCP-key shape (canonical — mirrors core `KeyService.php`):
19
+ * `amk_(live|test)_<payloadB64url>.<signatureB64url>` — the payload and the
20
+ * signature are base64url (`A-Za-z0-9_-`) joined by exactly ONE dot. The earlier
21
+ * pattern dropped the `.<sig>` arm, so it rejected every REAL token (which always
22
+ * carries the dot) — a sites.json with a valid key failed schema validation.
23
+ * Re-validated here so a hand-edited sites.json can never inject a token shape the
24
+ * server would reject anyway.
25
+ */
26
+ export declare const BEARER_REGEX: RegExp;
27
+ /**
28
+ * One site entry. Carries identity (`site_id`), reachability (`url` +
29
+ * `platform`), credential (exactly one of `bearer`/`bearer_ref`), and
30
+ * presentation metadata (`is_default`, `label`, `added_at`).
31
+ */
32
+ export declare const SiteEntry: z.ZodObject<{
33
+ site_id: z.ZodString;
34
+ url: z.ZodString;
35
+ platform: z.ZodDefault<z.ZodEnum<{
36
+ wordpress: "wordpress";
37
+ joomla: "joomla";
38
+ auto: "auto";
39
+ }>>;
40
+ bearer: z.ZodOptional<z.ZodString>;
41
+ bearer_ref: z.ZodOptional<z.ZodString>;
42
+ is_default: z.ZodDefault<z.ZodBoolean>;
43
+ label: z.ZodOptional<z.ZodString>;
44
+ added_at: z.ZodOptional<z.ZodString>;
45
+ }, z.core.$strip>;
46
+ /**
47
+ * The on-disk sites-file root. `schema_version` is a literal `1` for now;
48
+ * future schema migrations bump it AND add a migration step in the loader.
49
+ */
50
+ export declare const SitesFile: z.ZodObject<{
51
+ schema_version: z.ZodLiteral<1>;
52
+ default_site_id: z.ZodNullable<z.ZodString>;
53
+ sites: z.ZodArray<z.ZodObject<{
54
+ site_id: z.ZodString;
55
+ url: z.ZodString;
56
+ platform: z.ZodDefault<z.ZodEnum<{
57
+ wordpress: "wordpress";
58
+ joomla: "joomla";
59
+ auto: "auto";
60
+ }>>;
61
+ bearer: z.ZodOptional<z.ZodString>;
62
+ bearer_ref: z.ZodOptional<z.ZodString>;
63
+ is_default: z.ZodDefault<z.ZodBoolean>;
64
+ label: z.ZodOptional<z.ZodString>;
65
+ added_at: z.ZodOptional<z.ZodString>;
66
+ }, z.core.$strip>>;
67
+ }, z.core.$strip>;
68
+ export type SiteEntryT = z.infer<typeof SiteEntry>;
69
+ export type SitesFileT = z.infer<typeof SitesFile>;
@@ -0,0 +1,71 @@
1
+ // src/sites/schema.ts — Zod schemas for the on-disk API Mapper sites file.
2
+ //
3
+ // Phase 3 (2026-06-03): the multi-site sites-file mechanism. Mirrors the YT
4
+ // Builder reference shape (yt-builder-mcp/packages/mcp/src/sites/schema.ts) so
5
+ // both MCP servers expose the SAME multi-site concept, adapted for API Mapper:
6
+ // - token shape is `amk_(live|test)_…` (API Mapper MCP key), not `ytb_…`.
7
+ // - per-site `platform` is 'wordpress' | 'joomla' | 'auto' (default 'auto').
8
+ //
9
+ // The on-disk format is JSON. Each entry is one connected WordPress/Joomla site
10
+ // running API Mapper. A site MUST carry either an inline `bearer` (plain text)
11
+ // OR an `op://` 1Password Secret Reference (`bearer_ref`), never both — enforced
12
+ // via the SiteEntry refine().
13
+ import { z } from "zod";
14
+ /**
15
+ * Allowed character set for a `site_id`. Letters, digits, underscore, dash —
16
+ * no spaces, no path separators, no shell metacharacters. Filename-safe,
17
+ * URL-path-safe, log-safe.
18
+ */
19
+ export const SITE_ID_REGEX = /^[a-zA-Z0-9_-]+$/;
20
+ /**
21
+ * 1Password Secret Reference shape (`op://<vault>/<item>/<field>` and deeper).
22
+ * Letters, digits, underscore, slash, dot, dash only. The negative lookahead
23
+ * `(?!.*\/\.\.\/)` rejects any ref containing a `/../` traversal segment while
24
+ * still allowing legitimate `.` in vault/item names (e.g. `op://team.acme/...`).
25
+ * Re-validated at the secret-resolver call site as defence-in-depth before the
26
+ * ref ever reaches a subprocess argv.
27
+ */
28
+ export const OP_REF_REGEX = /^op:\/\/(?!.*\/\.\.\/)[A-Za-z0-9_/.-]+$/;
29
+ /**
30
+ * API Mapper MCP-key shape (canonical — mirrors core `KeyService.php`):
31
+ * `amk_(live|test)_<payloadB64url>.<signatureB64url>` — the payload and the
32
+ * signature are base64url (`A-Za-z0-9_-`) joined by exactly ONE dot. The earlier
33
+ * pattern dropped the `.<sig>` arm, so it rejected every REAL token (which always
34
+ * carries the dot) — a sites.json with a valid key failed schema validation.
35
+ * Re-validated here so a hand-edited sites.json can never inject a token shape the
36
+ * server would reject anyway.
37
+ */
38
+ export const BEARER_REGEX = /^amk_(live|test)_[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/;
39
+ /**
40
+ * One site entry. Carries identity (`site_id`), reachability (`url` +
41
+ * `platform`), credential (exactly one of `bearer`/`bearer_ref`), and
42
+ * presentation metadata (`is_default`, `label`, `added_at`).
43
+ */
44
+ export const SiteEntry = z
45
+ .object({
46
+ site_id: z.string().min(1).max(64).regex(SITE_ID_REGEX),
47
+ url: z.string().url(),
48
+ platform: z.enum(["wordpress", "joomla", "auto"]).default("auto"),
49
+ bearer: z.string().regex(BEARER_REGEX).optional(),
50
+ bearer_ref: z.string().regex(OP_REF_REGEX).optional(),
51
+ is_default: z.boolean().default(false),
52
+ label: z.string().max(120).optional(),
53
+ added_at: z.string().datetime().optional(),
54
+ })
55
+ .refine((s) => (s.bearer !== undefined) !== (s.bearer_ref !== undefined), {
56
+ message: "Exactly one of bearer or bearer_ref must be set",
57
+ });
58
+ /**
59
+ * The on-disk sites-file root. `schema_version` is a literal `1` for now;
60
+ * future schema migrations bump it AND add a migration step in the loader.
61
+ */
62
+ export const SitesFile = z
63
+ .object({
64
+ schema_version: z.literal(1),
65
+ default_site_id: z.string().regex(SITE_ID_REGEX).nullable(),
66
+ sites: z.array(SiteEntry),
67
+ })
68
+ .refine((f) => f.sites.filter((s) => s.is_default).length <= 1, {
69
+ message: "At most one site can have is_default:true",
70
+ });
71
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/sites/schema.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,EAAE;AACF,4EAA4E;AAC5E,+EAA+E;AAC/E,+EAA+E;AAC/E,4EAA4E;AAC5E,+EAA+E;AAC/E,EAAE;AACF,gFAAgF;AAChF,+EAA+E;AAC/E,iFAAiF;AACjF,8BAA8B;AAE9B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,kBAAkB,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,yCAAyC,CAAC;AAEtE;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,YAAY,GACvB,kDAAkD,CAAC;AAErD;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC;KACvB,MAAM,CAAC;IACN,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC;IACvD,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACrB,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACjE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE;IACjD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE;IACrD,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACtC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IACrC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CAC3C,CAAC;KACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC,EAAE;IACxE,OAAO,EAAE,iDAAiD;CAC3D,CAAC,CAAC;AAEL;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC;KACvB,MAAM,CAAC;IACN,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5B,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE;IAC3D,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;CAC1B,CAAC;KACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM,IAAI,CAAC,EAAE;IAC9D,OAAO,EAAE,2CAA2C;CACrD,CAAC,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { type SiteEntryT } from "./schema.js";
2
+ /**
3
+ * Resolve the `op` binary to an absolute path so it works under a stripped-down
4
+ * GUI PATH. Precedence: explicit `APIMAPPER_OP_BINARY` env override → first
5
+ * existing well-known absolute path → bare `op` (PATH).
6
+ */
7
+ export declare function resolveOpBinary(env?: NodeJS.ProcessEnv): string;
8
+ /** Resolved bearer + its provenance for downstream logs (never the token). */
9
+ export interface ResolvedBearer {
10
+ readonly token: string;
11
+ readonly source: "plain" | "op";
12
+ }
13
+ /** Domain-tagged error so callers can branch on `code`. */
14
+ export declare class SecretResolverError extends Error {
15
+ readonly code: string;
16
+ constructor(code: string, message: string);
17
+ }
18
+ /**
19
+ * Signature of `node:child_process.execFile` reduced to the callback we rely
20
+ * on. Injecting this lets tests provide a deterministic substitute without a
21
+ * `vi.mock('node:child_process')` side-effect.
22
+ */
23
+ export type ExecFileLike = (file: string, args: readonly string[], options: {
24
+ timeout?: number;
25
+ maxBuffer?: number;
26
+ }, callback: (error: (Error & {
27
+ code?: string | number;
28
+ signal?: string;
29
+ }) | null, stdout: string, stderr: string) => void) => void;
30
+ export interface ResolveSiteBearerOptions {
31
+ /** Injected execFile for tests. Defaults to Node's real execFile. */
32
+ execFile?: ExecFileLike;
33
+ /** Resolved `op` binary path. Defaults to {@link resolveOpBinary}. */
34
+ opBinary?: string;
35
+ /** Per-call timeout override. Defaults to {@link OP_TIMEOUT_MS}. */
36
+ timeoutMs?: number;
37
+ }
38
+ /**
39
+ * Resolve the bearer token for a site entry.
40
+ *
41
+ * - `bearer` present → returned verbatim (`source:'plain'`).
42
+ * - `bearer_ref` set → `op read <ref>` via execFile (`source:'op'`).
43
+ * - neither → throws SecretResolverError('BEARER_MISSING').
44
+ *
45
+ * Never logs the token; never mutates the input site.
46
+ */
47
+ export declare function resolveSiteBearer(site: SiteEntryT, opts?: ResolveSiteBearerOptions): Promise<ResolvedBearer>;
@@ -0,0 +1,150 @@
1
+ // src/sites/secret-resolver.ts — Phase 3.
2
+ //
3
+ // Produce a bearer token for a SiteEntryT at call time, supporting either a
4
+ // plain in-file token (`bearer`) or a 1Password Secret Reference (`bearer_ref`)
5
+ // resolved through the `op` CLI. Mirrors the YT Builder defence model
6
+ // (yt-builder-mcp/packages/mcp/src/sites/secret-resolver.ts), kept simple:
7
+ //
8
+ // - `execFile`, NEVER `exec`/`spawn` with `shell:true`. `op read <ref>` runs
9
+ // as a direct argv invocation — no shell, no metacharacter expansion. The
10
+ // schema enforces OP_REF_REGEX on load; we re-enforce it here as
11
+ // defence-in-depth (a hand-edited sites.json could otherwise sneak a
12
+ // payload past validation).
13
+ // - Hard timeout so a biometric-stalled `op` can't wedge the agent loop.
14
+ // - Pluggable `execFile` for testing — no global child_process monkey-patch.
15
+ import { execFile as nodeExecFile } from "node:child_process";
16
+ import { existsSync } from "node:fs";
17
+ import { OP_REF_REGEX } from "./schema.js";
18
+ /** Hard cap for any single `op read` invocation. */
19
+ const OP_TIMEOUT_MS = 5_000;
20
+ /**
21
+ * Common absolute install locations for the 1Password CLI. GUI-spawned MCP
22
+ * hosts (Claude Desktop, etc.) launch the server subprocess with a minimal
23
+ * PATH that usually omits `/opt/homebrew/bin` and `/usr/local/bin`, so a bare
24
+ * `op` resolves to ENOENT even when `op` works in the user's shell. Probe these
25
+ * absolute paths before falling back to PATH.
26
+ */
27
+ const OP_BINARY_CANDIDATES = [
28
+ "/opt/homebrew/bin/op",
29
+ "/usr/local/bin/op",
30
+ "/usr/bin/op",
31
+ ];
32
+ /**
33
+ * Resolve the `op` binary to an absolute path so it works under a stripped-down
34
+ * GUI PATH. Precedence: explicit `APIMAPPER_OP_BINARY` env override → first
35
+ * existing well-known absolute path → bare `op` (PATH).
36
+ */
37
+ export function resolveOpBinary(env = process.env) {
38
+ const override = (env.APIMAPPER_OP_BINARY ?? "").trim();
39
+ if (override.length > 0)
40
+ return override;
41
+ for (const candidate of OP_BINARY_CANDIDATES) {
42
+ try {
43
+ if (existsSync(candidate))
44
+ return candidate;
45
+ }
46
+ catch {
47
+ // ignore stat errors and keep probing
48
+ }
49
+ }
50
+ return "op";
51
+ }
52
+ /** Domain-tagged error so callers can branch on `code`. */
53
+ export class SecretResolverError extends Error {
54
+ code;
55
+ constructor(code, message) {
56
+ super(message);
57
+ this.code = code;
58
+ this.name = "SecretResolverError";
59
+ Object.setPrototypeOf(this, SecretResolverError.prototype);
60
+ }
61
+ }
62
+ /** Default adapter wrapping Node's real `execFile` with utf8 encoding. */
63
+ const defaultExecFile = (file, args, options, callback) => {
64
+ nodeExecFile(file, args, { ...options, encoding: "utf8" }, (err, stdout, stderr) => {
65
+ callback(err, stdout, stderr);
66
+ });
67
+ };
68
+ const OP_EXIT_CODE_HINTS = {
69
+ 6: "Not signed in to 1Password CLI. Run `op signin` and retry.",
70
+ 1: "Generic op CLI error — verify the secret reference exists and the vault is accessible.",
71
+ };
72
+ /**
73
+ * Resolve the bearer token for a site entry.
74
+ *
75
+ * - `bearer` present → returned verbatim (`source:'plain'`).
76
+ * - `bearer_ref` set → `op read <ref>` via execFile (`source:'op'`).
77
+ * - neither → throws SecretResolverError('BEARER_MISSING').
78
+ *
79
+ * Never logs the token; never mutates the input site.
80
+ */
81
+ export async function resolveSiteBearer(site, opts = {}) {
82
+ if (site.bearer !== undefined && site.bearer.length > 0) {
83
+ return { token: site.bearer, source: "plain" };
84
+ }
85
+ const ref = site.bearer_ref;
86
+ if (ref === undefined || ref.length === 0) {
87
+ throw new SecretResolverError("BEARER_MISSING", `Site '${site.site_id}' has neither an inline 'bearer' nor a 'bearer_ref'.`);
88
+ }
89
+ // Defence-in-depth: re-validate the ref shape BEFORE it reaches a subprocess
90
+ // argv. The schema enforces this on load; a hand-edited sites.json could
91
+ // bypass that.
92
+ if (!OP_REF_REGEX.test(ref)) {
93
+ throw new SecretResolverError("OP_REF_INVALID", `Site '${site.site_id}' has an invalid 'bearer_ref' shape — must match op://<vault>/<item>/<field>.`);
94
+ }
95
+ const execFile = opts.execFile ?? defaultExecFile;
96
+ const opBinary = opts.opBinary ?? resolveOpBinary();
97
+ const timeoutMs = opts.timeoutMs ?? OP_TIMEOUT_MS;
98
+ const stdout = await runOpRead(execFile, opBinary, ref, timeoutMs, site.site_id);
99
+ const token = stdout.trim();
100
+ if (token.length === 0) {
101
+ throw new SecretResolverError("OP_EMPTY_OUTPUT", `op returned empty output for '${ref}' — verify the field exists and is non-empty.`);
102
+ }
103
+ return { token, source: "op" };
104
+ }
105
+ /** Invoke `op read <ref>` with a hard timeout that survives a stalled child. */
106
+ function runOpRead(execFile, opBinary, ref, timeoutMs, siteId) {
107
+ return new Promise((resolve, reject) => {
108
+ let settled = false;
109
+ const timer = setTimeout(() => {
110
+ if (settled)
111
+ return;
112
+ settled = true;
113
+ reject(new SecretResolverError("OP_TIMEOUT", `op read '${ref}' exceeded ${timeoutMs}ms — is 1Password CLI hung on a biometric prompt?`));
114
+ }, timeoutMs);
115
+ if (typeof timer.unref === "function")
116
+ timer.unref();
117
+ execFile(opBinary, ["read", ref], { timeout: timeoutMs, maxBuffer: 1024 * 64 }, (err, stdout, stderr) => {
118
+ if (settled)
119
+ return;
120
+ settled = true;
121
+ clearTimeout(timer);
122
+ if (err) {
123
+ reject(mapExecError(err, stderr, ref, siteId));
124
+ return;
125
+ }
126
+ resolve(stdout);
127
+ });
128
+ });
129
+ }
130
+ function mapExecError(err, stderr, ref, siteId) {
131
+ const codeStr = typeof err.code === "string" ? err.code : "";
132
+ const codeNum = typeof err.code === "number" ? err.code : NaN;
133
+ if (codeStr === "ENOENT") {
134
+ return new SecretResolverError("OP_CLI_MISSING", `op CLI not found for site '${siteId}' — install 1Password CLI (or set APIMAPPER_OP_BINARY), ` +
135
+ "or use an inline 'bearer' field instead of 'bearer_ref'.");
136
+ }
137
+ const stderrLower = (stderr || "").toLowerCase();
138
+ if (stderrLower.includes("isn't an item") || stderrLower.includes("item not found")) {
139
+ return new SecretResolverError("OP_ITEM_NOT_FOUND", `1Password item not found at '${ref}'. Verify the ref points to an existing item.`);
140
+ }
141
+ if (Number.isFinite(codeNum)) {
142
+ const hint = OP_EXIT_CODE_HINTS[codeNum];
143
+ if (codeNum === 6) {
144
+ return new SecretResolverError("OP_NOT_SIGNED_IN", hint ?? "op exited 6 — not signed in.");
145
+ }
146
+ return new SecretResolverError("OP_EXEC_FAILED", `op read '${ref}' failed with exit ${codeNum}: ${(stderr || "").trim() || (hint ?? "no stderr")}`);
147
+ }
148
+ return new SecretResolverError("OP_EXEC_FAILED", `op read '${ref}' failed: ${err.message}`);
149
+ }
150
+ //# sourceMappingURL=secret-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-resolver.js","sourceRoot":"","sources":["../../src/sites/secret-resolver.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,17 @@
1
1
  export declare const FALLBACK_INSTRUCTIONS = "Use this MCP to manage API Mapper flows, connections, and sources across WordPress + Joomla.";
2
+ /**
3
+ * F134 / F118 — load-bearing operational rules that MUST survive into the
4
+ * server `instructions` field regardless of SKILL.md body length. The body is
5
+ * truncated to MAX_LENGTH chars, and its opening prose (intro + `npx setup`)
6
+ * pushes the rules a cold agent actually needs PAST that window. We front-load
7
+ * this compact preamble so the rules are always present, then append a bounded
8
+ * slice of the body and the topic pointer.
9
+ *
10
+ * Keep this TERSE — every char competes with the body for the instructions
11
+ * budget. Each line encodes one P0-prevention rule found by the cold-agent
12
+ * friction audit.
13
+ */
14
+ export declare const CRITICAL_RULES = "## Critical rules (read first)\n\n- Most tools are reachable via the gateway: apimapper_advanced({ tool: \"<name>\", arguments: {...} }). The arg key is `arguments` (NOT `input`). Omit `arguments` to discover a tool's schema.\n- If a call returns \"Unknown tool\", it is gateway-only \u2014 wrap it as apimapper_advanced({ tool, arguments }).\n- Verify connectivity with apimapper_health({}) \u2014 it is first-class in tools/list (call it directly, NOT via the gateway). Recover auth/config errors via apimapper_diagnose; deeper guidance via apimapper_get_skill({ topic }).\n";
2
15
  /**
3
16
  * Agent-discoverable skill-topic pointer appended to every loaded instructions
4
17
  * string. Documents the canonical entrypoint for deeper guidance via the
@@ -8,7 +21,7 @@ export declare const FALLBACK_INSTRUCTIONS = "Use this MCP to manage API Mapper
8
21
  *
9
22
  * Topics MUST stay in sync with SKILL_TOPICS in modules/apimapper/get-skill.ts.
10
23
  */
11
- export declare const SKILL_TOPIC_POINTER = "\n\n## Available skill topics\n\nFor deeper guidance on specific aspects of API Mapper, call:\n apimapper_get_skill({ topic })\n\nAvailable topics:\n- getting-started \u2014 Quickstart, common tools, common pitfalls\n- oauth \u2014 Wiring OAuth-protected sources (Google, Pexels, Instagram, Notion, ...)\n- yootheme \u2014 Publish flows as YOOtheme sources; Save-vs-Publish\n- joomla \u2014 Joomla 3-tier auth, com_ajax envelope, system plugin layout\n- troubleshooting \u2014 HTTP status triage, flow issues, credential states\n";
24
+ export declare const SKILL_TOPIC_POINTER = "\n\n## Available skill topics\n\nFor deeper guidance on specific aspects of API Mapper, call:\n apimapper_get_skill({ topic })\n\nAvailable topics:\n- getting-started \u2014 Quickstart, common tools, common pitfalls\n- oauth \u2014 Wiring OAuth-protected sources (Google, Pexels, Instagram, Notion, ...)\n- yootheme \u2014 Publish flows as YOOtheme sources; Save-vs-Publish\n- joomla \u2014 Joomla 3-tier auth, com_ajax envelope, system plugin layout\n- troubleshooting \u2014 HTTP status triage, flow issues, credential states\n- render \u2014 Render a flow as a diagram (viz-type, flow-diagram output)\n- jmespath-pitfalls \u2014 The 9 traps + date-primitive functions (date_weekday, date_iso_to_time, date_iso_to_date, time_in_window) + depth-cap warning\n- jmespath-cookbook \u2014 Copy-paste JMESPath recipes (ternary, join, conditions, sort_by, coordinates, format_number, dates, two-transform split) + a GIBT-ES-NICHT list (arithmetic/split/regex/if-else) with workarounds; iterate via apimapper_jmespath_test\n- merge-two-sources-on-key \u2014 Joining two sources on a shared key, including date-primitive bridging for weekday-name \u2194 ISO-datetime joins\n- conditional-style-multi-items \u2014 Per-row YOOtheme styles driven by a row field (text_color, panel_style)\n- library-template-discovery \u2014 Inspect a library template's contract before activating\n- yootheme-source-to-builder-handoff \u2014 Bind a published flow into a Builder element. Two shapes: field_mappings (fresh element; binding_for_flow \u2192 element_bind_source; map_item, bindingLevel) AND the theme-canonical #parent repeater form to dynamize an EXISTING designed layout (swap source.query.name to apiMapperFlow<Id>List; _condition '!'/'!!'; named-section discovery; article-context width)\n- dynamize-existing-layout \u2014 READ FIRST when the customer says \"keep the design exactly as it is\" / \"bind onto my existing section/page\": ONE call does it \u2014 template_summary (find the named section) \u2192 binding_for_flow (source name + flat fields) \u2192 yootheme_builder_page_dynamize({ template_id, section_path, source_name, leaf_map, publish: true }) \u2192 visual row check. The tool copies the subtree byte-identically and swaps only leaf_map names by construction (insert nothing, rebuild nothing)\n";
12
25
  /**
13
26
  * Loads MCP server instructions from skills/apimapper/SKILL.md.
14
27
  *
@@ -7,6 +7,24 @@ import { readFileSync, existsSync } from "node:fs";
7
7
  import { fileURLToPath } from "node:url";
8
8
  import { dirname, join, resolve } from "node:path";
9
9
  export const FALLBACK_INSTRUCTIONS = "Use this MCP to manage API Mapper flows, connections, and sources across WordPress + Joomla.";
10
+ /**
11
+ * F134 / F118 — load-bearing operational rules that MUST survive into the
12
+ * server `instructions` field regardless of SKILL.md body length. The body is
13
+ * truncated to MAX_LENGTH chars, and its opening prose (intro + `npx setup`)
14
+ * pushes the rules a cold agent actually needs PAST that window. We front-load
15
+ * this compact preamble so the rules are always present, then append a bounded
16
+ * slice of the body and the topic pointer.
17
+ *
18
+ * Keep this TERSE — every char competes with the body for the instructions
19
+ * budget. Each line encodes one P0-prevention rule found by the cold-agent
20
+ * friction audit.
21
+ */
22
+ export const CRITICAL_RULES = `## Critical rules (read first)
23
+
24
+ - Most tools are reachable via the gateway: apimapper_advanced({ tool: "<name>", arguments: {...} }). The arg key is \`arguments\` (NOT \`input\`). Omit \`arguments\` to discover a tool's schema.
25
+ - If a call returns "Unknown tool", it is gateway-only — wrap it as apimapper_advanced({ tool, arguments }).
26
+ - Verify connectivity with apimapper_health({}) — it is first-class in tools/list (call it directly, NOT via the gateway). Recover auth/config errors via apimapper_diagnose; deeper guidance via apimapper_get_skill({ topic }).
27
+ `;
10
28
  const MAX_LENGTH = 500;
11
29
  /**
12
30
  * Agent-discoverable skill-topic pointer appended to every loaded instructions
@@ -30,6 +48,14 @@ Available topics:
30
48
  - yootheme — Publish flows as YOOtheme sources; Save-vs-Publish
31
49
  - joomla — Joomla 3-tier auth, com_ajax envelope, system plugin layout
32
50
  - troubleshooting — HTTP status triage, flow issues, credential states
51
+ - render — Render a flow as a diagram (viz-type, flow-diagram output)
52
+ - jmespath-pitfalls — The 9 traps + date-primitive functions (date_weekday, date_iso_to_time, date_iso_to_date, time_in_window) + depth-cap warning
53
+ - jmespath-cookbook — Copy-paste JMESPath recipes (ternary, join, conditions, sort_by, coordinates, format_number, dates, two-transform split) + a GIBT-ES-NICHT list (arithmetic/split/regex/if-else) with workarounds; iterate via apimapper_jmespath_test
54
+ - merge-two-sources-on-key — Joining two sources on a shared key, including date-primitive bridging for weekday-name ↔ ISO-datetime joins
55
+ - conditional-style-multi-items — Per-row YOOtheme styles driven by a row field (text_color, panel_style)
56
+ - library-template-discovery — Inspect a library template's contract before activating
57
+ - yootheme-source-to-builder-handoff — Bind a published flow into a Builder element. Two shapes: field_mappings (fresh element; binding_for_flow → element_bind_source; map_item, bindingLevel) AND the theme-canonical #parent repeater form to dynamize an EXISTING designed layout (swap source.query.name to apiMapperFlow<Id>List; _condition '!'/'!!'; named-section discovery; article-context width)
58
+ - dynamize-existing-layout — READ FIRST when the customer says "keep the design exactly as it is" / "bind onto my existing section/page": ONE call does it — template_summary (find the named section) → binding_for_flow (source name + flat fields) → yootheme_builder_page_dynamize({ template_id, section_path, source_name, leaf_map, publish: true }) → visual row check. The tool copies the subtree byte-identically and swaps only leaf_map names by construction (insert nothing, rebuild nothing)
33
59
  `;
34
60
  /**
35
61
  * Loads MCP server instructions from skills/apimapper/SKILL.md.
@@ -43,22 +69,25 @@ export function loadSkillInstructions(rootDir) {
43
69
  const baseDir = rootDir ?? defaultRoot();
44
70
  const skillPath = join(baseDir, "skills", "apimapper", "SKILL.md");
45
71
  if (!existsSync(skillPath)) {
46
- return FALLBACK_INSTRUCTIONS + SKILL_TOPIC_POINTER;
72
+ return CRITICAL_RULES + FALLBACK_INSTRUCTIONS + SKILL_TOPIC_POINTER;
47
73
  }
48
74
  let raw;
49
75
  try {
50
76
  raw = readFileSync(skillPath, "utf8");
51
77
  }
52
78
  catch {
53
- return FALLBACK_INSTRUCTIONS + SKILL_TOPIC_POINTER;
79
+ return CRITICAL_RULES + FALLBACK_INSTRUCTIONS + SKILL_TOPIC_POINTER;
54
80
  }
55
81
  const body = stripFrontmatter(raw).trim();
56
82
  if (body.length === 0) {
57
- return FALLBACK_INSTRUCTIONS + SKILL_TOPIC_POINTER;
83
+ return CRITICAL_RULES + FALLBACK_INSTRUCTIONS + SKILL_TOPIC_POINTER;
58
84
  }
59
- // Append the skill-topic pointer AFTER truncation so the topic discovery
60
- // surface is always present, regardless of the SKILL.md body length.
61
- return body.slice(0, MAX_LENGTH) + SKILL_TOPIC_POINTER;
85
+ // Front-load the load-bearing rules (F134/F118) so they always survive
86
+ // truncation, then a bounded slice of the SKILL.md body, then the topic
87
+ // pointer. The body keeps its own MAX_LENGTH window; the rules + pointer are
88
+ // never truncated. (Pre-F134 the body opened the instructions and its intro
89
+ // prose pushed these rules past the window — a cold agent never saw them.)
90
+ return CRITICAL_RULES + body.slice(0, MAX_LENGTH) + SKILL_TOPIC_POINTER;
62
91
  }
63
92
  /**
64
93
  * Strips a YAML frontmatter block (`---\n...\n---\n`) from the start of the
@@ -1 +1 @@
1
- {"version":3,"file":"skill-instructions.js","sourceRoot":"","sources":["../src/skill-instructions.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,0EAA0E;AAC1E,yCAAyC;AACzC,EAAE;AACF,yEAAyE;AAEzE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,MAAM,CAAC,MAAM,qBAAqB,GAChC,8FAA8F,CAAC;AAEjG,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;CAalC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,MAAM,OAAO,GAAG,OAAO,IAAI,WAAW,EAAE,CAAC;IACzC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;IAEnE,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,OAAO,qBAAqB,GAAG,mBAAmB,CAAC;IACrD,CAAC;IAED,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,qBAAqB,GAAG,mBAAmB,CAAC;IACrD,CAAC;IAED,MAAM,IAAI,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,qBAAqB,GAAG,mBAAmB,CAAC;IACrD,CAAC;IACD,yEAAyE;IACzE,qEAAqE;IACrE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG,mBAAmB,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,SAAS,gBAAgB,CAAC,KAAa;IACrC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,iDAAiD;IACjD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC1C,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,kEAAkE;IAClE,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;IAC/C,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,qDAAqD;QACrD,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,WAAW;IAClB,8DAA8D;IAC9D,qEAAqE;IACrE,wCAAwC;IACxC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,OAAO,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"skill-instructions.js","sourceRoot":"","sources":["../src/skill-instructions.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,0EAA0E;AAC1E,yCAAyC;AACzC,EAAE;AACF,yEAAyE;AAEzE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,MAAM,CAAC,MAAM,qBAAqB,GAChC,8FAA8F,CAAC;AAEjG;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;CAK7B,CAAC;AAEF,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;CAqBlC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,MAAM,OAAO,GAAG,OAAO,IAAI,WAAW,EAAE,CAAC;IACzC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;IAEnE,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,OAAO,cAAc,GAAG,qBAAqB,GAAG,mBAAmB,CAAC;IACtE,CAAC;IAED,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,cAAc,GAAG,qBAAqB,GAAG,mBAAmB,CAAC;IACtE,CAAC;IAED,MAAM,IAAI,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,cAAc,GAAG,qBAAqB,GAAG,mBAAmB,CAAC;IACtE,CAAC;IACD,uEAAuE;IACvE,wEAAwE;IACxE,6EAA6E;IAC7E,4EAA4E;IAC5E,2EAA2E;IAC3E,OAAO,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG,mBAAmB,CAAC;AAC1E,CAAC;AAED;;;;;GAKG;AACH,SAAS,gBAAgB,CAAC,KAAa;IACrC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,iDAAiD;IACjD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC1C,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,kEAAkE;IAClE,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;IAC/C,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,qDAAqD;QACrD,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,WAAW;IAClB,8DAA8D;IAC9D,qEAAqE;IACrE,wCAAwC;IACxC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,OAAO,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC7B,CAAC"}
@@ -1,9 +1,9 @@
1
- // src/transports/stdio.ts — Phase 9.1.
1
+ // src/transports/stdio.ts
2
2
  //
3
3
  // Thin factory that connects an McpServer to a StdioServerTransport so the
4
- // process speaks JSON-RPC over stdin/stdout. Extracted from src/index.ts as
5
- // part of the multi-transport split Task 9.2 introduces an HTTP variant
6
- // using the same `connect*` shape.
4
+ // process speaks JSON-RPC over stdin/stdout. stdio is the only transport the
5
+ // MCP server ships it runs over stdio for both the npm/npx path and the
6
+ // Claude Desktop DXT bundle.
7
7
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8
8
  /**
9
9
  * Connect the given McpServer to a fresh `StdioServerTransport`.
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/transports/stdio.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,EAAE;AACF,2EAA2E;AAC3E,4EAA4E;AAC5E,0EAA0E;AAC1E,mCAAmC;AAGnC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAiB;IAClD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC"}
1
+ {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/transports/stdio.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,EAAE;AACF,2EAA2E;AAC3E,6EAA6E;AAC7E,0EAA0E;AAC1E,6BAA6B;AAG7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAiB;IAClD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC"}