@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.
- package/CHANGELOG.md +157 -83
- package/README.md +31 -27
- package/SECURITY.md +15 -6
- package/dist/auth/keychain.d.ts +27 -1
- package/dist/auth/keychain.js +48 -2
- package/dist/auth/keychain.js.map +1 -1
- package/dist/catalog/build-catalog.d.ts +31 -0
- package/dist/catalog/build-catalog.js +68 -0
- package/dist/catalog/build-catalog.js.map +1 -0
- package/dist/cli-hint.d.ts +22 -0
- package/dist/cli-hint.js +55 -0
- package/dist/cli-hint.js.map +1 -0
- package/dist/index.js +129 -22
- package/dist/index.js.map +1 -1
- package/dist/install-skill.js +1 -1
- package/dist/modules/apimapper/auto-layout.d.ts +21 -0
- package/dist/modules/apimapper/auto-layout.js +54 -0
- package/dist/modules/apimapper/auto-layout.js.map +1 -0
- package/dist/modules/apimapper/cache.js +25 -17
- package/dist/modules/apimapper/cache.js.map +1 -1
- package/dist/modules/apimapper/client.d.ts +115 -4
- package/dist/modules/apimapper/client.js +699 -304
- package/dist/modules/apimapper/client.js.map +1 -1
- package/dist/modules/apimapper/connections-format.d.ts +31 -1
- package/dist/modules/apimapper/connections-format.js +97 -5
- package/dist/modules/apimapper/connections-format.js.map +1 -1
- package/dist/modules/apimapper/connections.d.ts +9 -7
- package/dist/modules/apimapper/connections.js +449 -127
- package/dist/modules/apimapper/connections.js.map +1 -1
- package/dist/modules/apimapper/credential-sanitizer.d.ts +5 -0
- package/dist/modules/apimapper/credential-sanitizer.js +60 -1
- package/dist/modules/apimapper/credential-sanitizer.js.map +1 -1
- package/dist/modules/apimapper/credentials.js +105 -61
- package/dist/modules/apimapper/credentials.js.map +1 -1
- package/dist/modules/apimapper/diagnose.js +21 -2
- package/dist/modules/apimapper/diagnose.js.map +1 -1
- package/dist/modules/apimapper/elicitation.d.ts +29 -0
- package/dist/modules/apimapper/elicitation.js +62 -0
- package/dist/modules/apimapper/elicitation.js.map +1 -1
- package/dist/modules/apimapper/example-extract.d.ts +13 -0
- package/dist/modules/apimapper/example-extract.js +111 -0
- package/dist/modules/apimapper/example-extract.js.map +1 -0
- package/dist/modules/apimapper/filter-operators.d.ts +24 -0
- package/dist/modules/apimapper/filter-operators.js +103 -0
- package/dist/modules/apimapper/filter-operators.js.map +1 -0
- package/dist/modules/apimapper/flows-format.js +92 -22
- package/dist/modules/apimapper/flows-format.js.map +1 -1
- package/dist/modules/apimapper/flows.d.ts +8 -7
- package/dist/modules/apimapper/flows.js +275 -120
- package/dist/modules/apimapper/flows.js.map +1 -1
- package/dist/modules/apimapper/gateway/advanced-read-tool.d.ts +9 -0
- package/dist/modules/apimapper/gateway/advanced-read-tool.js +172 -0
- package/dist/modules/apimapper/gateway/advanced-read-tool.js.map +1 -0
- package/dist/modules/apimapper/gateway/advanced-tool.js +66 -106
- package/dist/modules/apimapper/gateway/advanced-tool.js.map +1 -1
- package/dist/modules/apimapper/gateway/collect-module-tools.d.ts +17 -0
- package/dist/modules/apimapper/gateway/collect-module-tools.js +44 -0
- package/dist/modules/apimapper/gateway/collect-module-tools.js.map +1 -0
- package/dist/modules/apimapper/gateway/essentials.d.ts +1 -1
- package/dist/modules/apimapper/gateway/essentials.js +21 -2
- package/dist/modules/apimapper/gateway/essentials.js.map +1 -1
- package/dist/modules/apimapper/gateway/gateway-shared.d.ts +21 -0
- package/dist/modules/apimapper/gateway/gateway-shared.js +124 -0
- package/dist/modules/apimapper/gateway/gateway-shared.js.map +1 -0
- package/dist/modules/apimapper/gateway/test-support.d.ts +1 -17
- package/dist/modules/apimapper/gateway/test-support.js +4 -33
- package/dist/modules/apimapper/gateway/test-support.js.map +1 -1
- package/dist/modules/apimapper/get-skill-cores.d.ts +4 -0
- package/dist/modules/apimapper/get-skill-cores.js +220 -0
- package/dist/modules/apimapper/get-skill-cores.js.map +1 -0
- package/dist/modules/apimapper/get-skill.d.ts +1 -1
- package/dist/modules/apimapper/get-skill.js +74 -9
- package/dist/modules/apimapper/get-skill.js.map +1 -1
- package/dist/modules/apimapper/graph-builder.d.ts +85 -2
- package/dist/modules/apimapper/graph-builder.js +151 -15
- package/dist/modules/apimapper/graph-builder.js.map +1 -1
- package/dist/modules/apimapper/graph.js +152 -48
- package/dist/modules/apimapper/graph.js.map +1 -1
- package/dist/modules/apimapper/index.js +27 -13
- package/dist/modules/apimapper/index.js.map +1 -1
- package/dist/modules/apimapper/jmespath-test.d.ts +4 -0
- package/dist/modules/apimapper/jmespath-test.js +152 -0
- package/dist/modules/apimapper/jmespath-test.js.map +1 -0
- package/dist/modules/apimapper/library.js +553 -88
- package/dist/modules/apimapper/library.js.map +1 -1
- package/dist/modules/apimapper/license.js +12 -36
- package/dist/modules/apimapper/license.js.map +1 -1
- package/dist/modules/apimapper/list-footer.d.ts +27 -0
- package/dist/modules/apimapper/list-footer.js +57 -0
- package/dist/modules/apimapper/list-footer.js.map +1 -0
- package/dist/modules/apimapper/local-sources.js +100 -57
- package/dist/modules/apimapper/local-sources.js.map +1 -1
- package/dist/modules/apimapper/mcp-client-identity.d.ts +32 -0
- package/dist/modules/apimapper/mcp-client-identity.js +70 -0
- package/dist/modules/apimapper/mcp-client-identity.js.map +1 -0
- package/dist/modules/apimapper/merge-constants.d.ts +6 -0
- package/dist/modules/apimapper/merge-constants.js +26 -0
- package/dist/modules/apimapper/merge-constants.js.map +1 -0
- package/dist/modules/apimapper/misc.js +13 -27
- package/dist/modules/apimapper/misc.js.map +1 -1
- package/dist/modules/apimapper/node-schema.d.ts +52 -2
- package/dist/modules/apimapper/node-schema.js +95 -4
- package/dist/modules/apimapper/node-schema.js.map +1 -1
- package/dist/modules/apimapper/onboarding.d.ts +59 -1
- package/dist/modules/apimapper/onboarding.js +231 -28
- package/dist/modules/apimapper/onboarding.js.map +1 -1
- package/dist/modules/apimapper/read-cache.d.ts +16 -3
- package/dist/modules/apimapper/read-cache.js +59 -4
- package/dist/modules/apimapper/read-cache.js.map +1 -1
- package/dist/modules/apimapper/render/index.js +26 -5
- package/dist/modules/apimapper/render/index.js.map +1 -1
- package/dist/modules/apimapper/resource-id.d.ts +13 -0
- package/dist/modules/apimapper/resource-id.js +69 -0
- package/dist/modules/apimapper/resource-id.js.map +1 -0
- package/dist/modules/apimapper/schema.js +9 -18
- package/dist/modules/apimapper/schema.js.map +1 -1
- package/dist/modules/apimapper/settings.js +49 -52
- package/dist/modules/apimapper/settings.js.map +1 -1
- package/dist/modules/apimapper/sites-tools.d.ts +29 -0
- package/dist/modules/apimapper/sites-tools.js +165 -0
- package/dist/modules/apimapper/sites-tools.js.map +1 -0
- package/dist/modules/apimapper/tool-result.d.ts +66 -0
- package/dist/modules/apimapper/tool-result.js +125 -0
- package/dist/modules/apimapper/tool-result.js.map +1 -0
- package/dist/modules/apimapper/toolslist-size.d.ts +12 -11
- package/dist/modules/apimapper/toolslist-size.js +34 -21
- package/dist/modules/apimapper/toolslist-size.js.map +1 -1
- package/dist/modules/apimapper/types.d.ts +34 -0
- package/dist/modules/apimapper/types.js +1 -1
- package/dist/modules/apimapper/types.js.map +1 -1
- package/dist/modules/apimapper/whitelist-drift.d.ts +85 -0
- package/dist/modules/apimapper/whitelist-drift.js +375 -0
- package/dist/modules/apimapper/whitelist-drift.js.map +1 -0
- package/dist/modules/apimapper/workflows.js +302 -58
- package/dist/modules/apimapper/workflows.js.map +1 -1
- package/dist/modules/apimapper/yootheme-binding.d.ts +35 -0
- package/dist/modules/apimapper/yootheme-binding.js +267 -0
- package/dist/modules/apimapper/yootheme-binding.js.map +1 -0
- package/dist/platform/index.d.ts +56 -0
- package/dist/platform/index.js +158 -2
- package/dist/platform/index.js.map +1 -1
- package/dist/proxy/bridge.d.ts +35 -0
- package/dist/proxy/bridge.js +129 -0
- package/dist/proxy/bridge.js.map +1 -0
- package/dist/proxy/mode.d.ts +9 -0
- package/dist/proxy/mode.js +20 -0
- package/dist/proxy/mode.js.map +1 -0
- package/dist/setup/detect-clients.d.ts +40 -1
- package/dist/setup/detect-clients.js +148 -1
- package/dist/setup/detect-clients.js.map +1 -1
- package/dist/setup/probe-auth.d.ts +51 -0
- package/dist/setup/probe-auth.js +141 -0
- package/dist/setup/probe-auth.js.map +1 -0
- package/dist/setup/probe-handshake.js +40 -7
- package/dist/setup/probe-handshake.js.map +1 -1
- package/dist/setup/remove-config.d.ts +8 -0
- package/dist/setup/remove-config.js +145 -0
- package/dist/setup/remove-config.js.map +1 -0
- package/dist/setup/uninstall.d.ts +34 -0
- package/dist/setup/uninstall.js +147 -0
- package/dist/setup/uninstall.js.map +1 -0
- package/dist/setup-cli.d.ts +16 -0
- package/dist/setup-cli.js +63 -1
- package/dist/setup-cli.js.map +1 -1
- package/dist/sites/loader.d.ts +48 -0
- package/dist/sites/loader.js +134 -0
- package/dist/sites/loader.js.map +1 -0
- package/dist/sites/schema.d.ts +69 -0
- package/dist/sites/schema.js +71 -0
- package/dist/sites/schema.js.map +1 -0
- package/dist/sites/secret-resolver.d.ts +47 -0
- package/dist/sites/secret-resolver.js +150 -0
- package/dist/sites/secret-resolver.js.map +1 -0
- package/dist/skill-instructions.d.ts +14 -1
- package/dist/skill-instructions.js +35 -6
- package/dist/skill-instructions.js.map +1 -1
- package/dist/transports/stdio.js +4 -4
- package/dist/transports/stdio.js.map +1 -1
- package/dist/uninstall-skill.d.ts +27 -0
- package/dist/uninstall-skill.js +89 -0
- package/dist/uninstall-skill.js.map +1 -0
- package/docs/architecture.md +21 -21
- package/docs/customgraph-internal-migration.md +4 -4
- package/docs/security.md +2 -21
- package/docs/tools.md +40 -12
- package/manifest.json +77 -79
- package/package.json +69 -65
- package/skills/apimapper/SKILL.md +128 -7
- package/skills/apimapper/reference/conditional-style-multi-items.md +114 -0
- package/skills/apimapper/reference/dynamize-existing-layout.md +158 -0
- package/skills/apimapper/reference/jmespath-cookbook.md +241 -0
- package/skills/apimapper/reference/jmespath-pitfalls.md +189 -0
- package/skills/apimapper/reference/joomla.md +1 -1
- package/skills/apimapper/reference/library-template-discovery.md +65 -0
- package/skills/apimapper/reference/merge-two-sources-on-key.md +204 -0
- package/skills/apimapper/reference/oauth.md +143 -52
- package/skills/apimapper/reference/troubleshooting.md +22 -2
- package/skills/apimapper/reference/yootheme-source-to-builder-handoff.md +348 -0
- package/skills/apimapper/reference/yootheme.md +75 -44
- package/dist/auth/oauth-provider.d.ts +0 -68
- package/dist/auth/oauth-provider.js +0 -232
- package/dist/auth/oauth-provider.js.map +0 -1
- package/dist/server-http.d.ts +0 -22
- package/dist/server-http.js +0 -159
- package/dist/server-http.js.map +0 -1
- package/dist/transports/http.d.ts +0 -29
- package/dist/transports/http.js +0 -267
- package/dist/transports/http.js.map +0 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// packages/apimapper-mcp/src/catalog/build-catalog.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { loadModules } from "@getimo/mcp-toolkit";
|
|
5
|
+
import { apimapperRestModule } from "../modules/apimapper/index.js";
|
|
6
|
+
import { collectModuleTools } from "../modules/apimapper/gateway/collect-module-tools.js";
|
|
7
|
+
/**
|
|
8
|
+
* Convert a captured tool inputSchema to JSON Schema. collectModuleTools yields a
|
|
9
|
+
* RAW Zod shape for advanced tools (entry.config.inputSchema) but a constructed Zod
|
|
10
|
+
* OBJECT for essentials (server._registeredTools[name].inputSchema, SDK mcp.js:611).
|
|
11
|
+
* Branch on the Zod-4 internal marker `_zod`. Native z.toJSONSchema (zod 4.4.3).
|
|
12
|
+
*/
|
|
13
|
+
export function toJsonSchema(inputSchema) {
|
|
14
|
+
try {
|
|
15
|
+
if (inputSchema && typeof inputSchema === "object") {
|
|
16
|
+
const isZodObject = "_zod" in inputSchema;
|
|
17
|
+
const schema = isZodObject
|
|
18
|
+
? inputSchema
|
|
19
|
+
: z.object(inputSchema);
|
|
20
|
+
return z.toJSONSchema(schema);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
/* malformed/unsupported shape → safe fallback */
|
|
25
|
+
}
|
|
26
|
+
return { type: "object" };
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Fail loud if module registration degraded. `loadModules` is graceful by
|
|
30
|
+
* design — when a module's `register()` throws it logs and records
|
|
31
|
+
* `{ status: "error" }` but RETURNS normally, so a registration failure would
|
|
32
|
+
* otherwise yield an empty/partial catalog that still resolves successfully.
|
|
33
|
+
* The catalog is a release artifact (SSOT for a future PHP MCP surface), so a
|
|
34
|
+
* silently-degraded export is worse than a hard failure — mirror the repo's
|
|
35
|
+
* fail-loud discipline (encryption golden-master, deploy key-survival).
|
|
36
|
+
*/
|
|
37
|
+
export function assertModulesLoaded(statuses) {
|
|
38
|
+
const failed = statuses.filter((s) => s.status === "error");
|
|
39
|
+
if (failed.length) {
|
|
40
|
+
const detail = failed
|
|
41
|
+
.map((f) => `${f.name}: ${f.error ?? "unknown error"}`)
|
|
42
|
+
.join(", ");
|
|
43
|
+
throw new Error(`buildCatalog: module registration failed: ${detail}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export async function buildCatalog() {
|
|
47
|
+
const server = new McpServer({ name: "API Mapper MCP", version: "0.0.0" });
|
|
48
|
+
const statuses = await loadModules(server, [apimapperRestModule]);
|
|
49
|
+
assertModulesLoaded(statuses);
|
|
50
|
+
const collected = collectModuleTools(server, apimapperRestModule); // 78 module tools
|
|
51
|
+
const advancedKeys = new Set(apimapperRestModule.getAdvancedRegistry()?.keys() ?? []);
|
|
52
|
+
const tools = Object.entries(collected).map(([name, t]) => ({
|
|
53
|
+
name,
|
|
54
|
+
description: t.description ?? "",
|
|
55
|
+
jsonSchema: toJsonSchema(t.inputSchema),
|
|
56
|
+
annotations: t.annotations ?? {},
|
|
57
|
+
tier: advancedKeys.has(name) ? "advanced" : "essential",
|
|
58
|
+
}));
|
|
59
|
+
if (tools.length === 0) {
|
|
60
|
+
throw new Error("buildCatalog produced 0 tools — registration likely failed");
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
version: process.env.npm_package_version ?? "0.0.0",
|
|
64
|
+
generatedFrom: "zod",
|
|
65
|
+
tools,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=build-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-catalog.js","sourceRoot":"","sources":["../../src/catalog/build-catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decide whether the bare/unknown-invocation interactive hint should be shown.
|
|
3
|
+
*
|
|
4
|
+
* Returns true ONLY when the invocation is interactive (a TTY on stdin) AND
|
|
5
|
+
* the given subcommand is not a recognised CLI subcommand (either absent —
|
|
6
|
+
* bare `npx @wootsup/mcp` — or an unknown typo).
|
|
7
|
+
*
|
|
8
|
+
* When stdin is NOT a TTY (piped, i.e. a real MCP client) this ALWAYS returns
|
|
9
|
+
* false so the server-boot path is never disturbed.
|
|
10
|
+
*
|
|
11
|
+
* @param subcommand The first positional CLI arg (`process.argv[2]`), or undefined.
|
|
12
|
+
* @param knownSubcommands The set of recognised CLI subcommands.
|
|
13
|
+
* @param isTTY Whether stdin is an interactive terminal (`process.stdin.isTTY`).
|
|
14
|
+
*/
|
|
15
|
+
export declare function shouldShowInteractiveHint(subcommand: string | undefined, knownSubcommands: ReadonlySet<string>, isTTY: boolean): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Build the human-facing hint message printed to stderr in interactive mode.
|
|
18
|
+
*
|
|
19
|
+
* When `subcommand` is a non-empty unknown token, the message is prefixed with
|
|
20
|
+
* an "unknown command" line so a typo is called out explicitly.
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildInteractiveHint(subcommand: string | undefined): string;
|
package/dist/cli-hint.js
ADDED
|
@@ -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.js
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
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/*
|
|
3
|
+
// Full coverage of /wp-json/api-mapper/v1/* — 81 registered tools (16 module
|
|
4
|
+
// essentials + the apimapper_advanced gateway + the apimapper_advanced_read
|
|
5
|
+
// gateway + 60 advanced-registry tools + 3 top-level tools registered below).
|
|
6
|
+
// Only 21 are first-class in tools/list; the 60 advanced tools route through
|
|
7
|
+
// the gateways to stay under Cursor's ~40 surface cap. Canonical counts are
|
|
8
|
+
// asserted in gateway/gateway.test.ts (A2).
|
|
9
|
+
// F115 (2026-06-11): apimapper_health promoted advanced→essential (15→16
|
|
10
|
+
// essentials, 60→59 advanced, surface 19→20, total then 79).
|
|
11
|
+
// F200b (2026-06-12): apimapper_advanced_read read-only gateway added
|
|
12
|
+
// (module-real 17→18, surface 20→21, total 80→81).
|
|
4
13
|
//
|
|
5
14
|
// Auth: API Mapper MCP-key (amk_live_...) generated via the API Mapper
|
|
6
15
|
// admin UI → Settings → MCP Access. The legacy WordPress Application
|
|
@@ -33,10 +42,12 @@ if (process.env.APIMAPPER_SITE_URL && !process.env.APIMAPPER_WP_BASE) {
|
|
|
33
42
|
if (process.env.APIMAPPER_BASE_URL && !process.env.APIMAPPER_WP_BASE) {
|
|
34
43
|
process.env.APIMAPPER_WP_BASE = process.env.APIMAPPER_BASE_URL;
|
|
35
44
|
}
|
|
36
|
-
// APIMAPPER_PLATFORM is consumed by
|
|
37
|
-
// (
|
|
38
|
-
//
|
|
39
|
-
//
|
|
45
|
+
// APIMAPPER_PLATFORM is consumed by client.ts (Phase 1, 2026-06-03): the
|
|
46
|
+
// legacy `request()` path reads it as the explicit env→kind HINT
|
|
47
|
+
// (PLATFORM_KIND) and, when it is unset or "auto", layers a network
|
|
48
|
+
// identity probe on top to auto-detect WordPress vs Joomla. Kept as an
|
|
49
|
+
// explicit no-op read here too so the build-dxt grep gate confirms every
|
|
50
|
+
// user_config key has a runtime consumer — see scripts/build-dxt.js.
|
|
40
51
|
void process.env.APIMAPPER_PLATFORM;
|
|
41
52
|
// APIMAPPER_PROFILE (F-49 / W1.27) — optional profile label for multi-site
|
|
42
53
|
// setups. The setup-cli writes it into the MCP client entry env; the
|
|
@@ -45,6 +56,13 @@ void process.env.APIMAPPER_PLATFORM;
|
|
|
45
56
|
// bridge runs inside main() once the ProfileStore is constructed; see
|
|
46
57
|
// `bootstrapActiveProfile` below for the A6-P3-INTEG-02 wiring + tests.
|
|
47
58
|
void process.env.APIMAPPER_PROFILE;
|
|
59
|
+
// APIMAPPER_SITES_FILE (Phase 3, 2026-06-03) — optional path to a multi-site
|
|
60
|
+
// sites.json (the .dxt one-click / agency path). client.ts reads it lazily
|
|
61
|
+
// (getSitesRegistry) to drive the ACTIVE site's URL/token/platform in
|
|
62
|
+
// request(); main() wires the sites-file-backed profile tools when it loads
|
|
63
|
+
// non-empty. Explicit no-op read here too so the build-dxt grep gate confirms
|
|
64
|
+
// every user_config key has a runtime consumer — see scripts/build-dxt.js.
|
|
65
|
+
void process.env.APIMAPPER_SITES_FILE;
|
|
48
66
|
import { createRequire } from "node:module";
|
|
49
67
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
50
68
|
import { loadModules, formatResult, readOnly } from "@getimo/mcp-toolkit";
|
|
@@ -54,6 +72,10 @@ import { connectStdio } from "./transports/stdio.js";
|
|
|
54
72
|
import { createKeychain } from "./auth/keychain.js";
|
|
55
73
|
import { ProfileStore, resolveConfigDir } from "./auth/profiles.js";
|
|
56
74
|
import { registerUseProfileTool, registerListProfilesTool, } from "./modules/apimapper/use-profile.js";
|
|
75
|
+
import { registerSitesUseProfileTool, registerSitesListProfilesTool, } from "./modules/apimapper/sites-tools.js";
|
|
76
|
+
import { getSitesRegistry, getActiveSiteId, setActiveSite, } from "./modules/apimapper/client.js";
|
|
77
|
+
import { shouldShowInteractiveHint, buildInteractiveHint } from "./cli-hint.js";
|
|
78
|
+
import { setMcpClient } from "./modules/apimapper/mcp-client-identity.js";
|
|
57
79
|
// Single source of truth for the package version (F-41 / W1.23).
|
|
58
80
|
// Reads ../package.json at runtime so we never drift between the manifest
|
|
59
81
|
// version (used by npm + DXT) and what we advertise to MCP clients.
|
|
@@ -140,26 +162,84 @@ server.registerTool("apimapper_rest_modules_status", {
|
|
|
140
162
|
}, false, { maxChars: 2000 });
|
|
141
163
|
});
|
|
142
164
|
async function main() {
|
|
165
|
+
// Proxy mode: forward stdio 1:1 to the plugin-served PHP MCP endpoint and stop
|
|
166
|
+
// here — the fat catalog below is bypassed entirely. Default (fat) is unchanged.
|
|
167
|
+
// The dynamic import is gated on the env so the fat path never loads the proxy
|
|
168
|
+
// module (and the SDK client transport it pulls in) — keeps fat-mode startup
|
|
169
|
+
// lean and avoids loading proxy code (incl. under test) when it can't apply.
|
|
170
|
+
if (process.env.APIMAPPER_MODE === "proxy") {
|
|
171
|
+
const { maybeRunProxy } = await import("./proxy/bridge.js");
|
|
172
|
+
if (await maybeRunProxy(process.env))
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
143
175
|
moduleStatuses = await loadModules(server, [apimapperRestModule]);
|
|
144
|
-
// Profile
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
// file
|
|
148
|
-
//
|
|
149
|
-
//
|
|
176
|
+
// Profile tools for apimapper_use_profile / apimapper_list_profiles.
|
|
177
|
+
//
|
|
178
|
+
// Phase 3 (2026-06-03) — TWO multi-site mechanisms, branched on presence of a
|
|
179
|
+
// sites-file:
|
|
180
|
+
// • APIMAPPER_SITES_FILE set + non-empty → the sites-file IS the profile
|
|
181
|
+
// registry. The tools list its entries and switch the active site via the
|
|
182
|
+
// client's setActiveSite() (which retargets request()). No keychain.
|
|
183
|
+
// • otherwise → the legacy keychain ProfileStore path (the secure
|
|
184
|
+
// single-machine wizard default), unchanged.
|
|
185
|
+
//
|
|
186
|
+
// Best-effort: log + skip if init throws on a locked-down host so the rest of
|
|
187
|
+
// the MCP surface still boots.
|
|
188
|
+
let sitesFileActive = false;
|
|
150
189
|
try {
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
190
|
+
const registry = getSitesRegistry();
|
|
191
|
+
if (registry) {
|
|
192
|
+
sitesFileActive = true;
|
|
193
|
+
// A sites-file is present → honour APIMAPPER_PROFILE as the initial
|
|
194
|
+
// active-site selection (a site_id). Unknown / "default" / unset → leave
|
|
195
|
+
// the file's default entry active. setActiveSite throws on an unknown id,
|
|
196
|
+
// so guard with has() to avoid a phantom selection on a stale env var.
|
|
197
|
+
const desired = process.env.APIMAPPER_PROFILE?.trim();
|
|
198
|
+
if (desired && desired !== "default" && registry.has(desired)) {
|
|
199
|
+
setActiveSite(desired);
|
|
200
|
+
}
|
|
201
|
+
registerSitesListProfilesTool(server, {
|
|
202
|
+
getRegistry: () => {
|
|
203
|
+
const r = getSitesRegistry();
|
|
204
|
+
if (!r)
|
|
205
|
+
throw new Error("sites-file unloaded since boot");
|
|
206
|
+
return r;
|
|
207
|
+
},
|
|
208
|
+
getActiveSiteId,
|
|
209
|
+
});
|
|
210
|
+
registerSitesUseProfileTool(server, {
|
|
211
|
+
getRegistry: () => {
|
|
212
|
+
const r = getSitesRegistry();
|
|
213
|
+
if (!r)
|
|
214
|
+
throw new Error("sites-file unloaded since boot");
|
|
215
|
+
return r;
|
|
216
|
+
},
|
|
217
|
+
setActiveSite,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
160
220
|
}
|
|
161
221
|
catch (err) {
|
|
162
|
-
console.error("[apimapper-rest]
|
|
222
|
+
console.error("[apimapper-rest] sites-file profile tools disabled — sites-file init failed:", err instanceof Error ? err.message : err);
|
|
223
|
+
}
|
|
224
|
+
if (!sitesFileActive) {
|
|
225
|
+
// Keychain ProfileStore path (legacy single-machine default). Phase 5
|
|
226
|
+
// deferred this to the server entrypoint because constructing the keychain
|
|
227
|
+
// is async (probes the OS Secret-Service, falling back to a file impl) and
|
|
228
|
+
// the module-level register() signature is sync.
|
|
229
|
+
try {
|
|
230
|
+
const configDir = resolveConfigDir();
|
|
231
|
+
const keychain = await createKeychain({ configDir });
|
|
232
|
+
const profileStore = new ProfileStore(configDir);
|
|
233
|
+
// A6-P3-INTEG-02: honour APIMAPPER_PROFILE env var. Must run AFTER the
|
|
234
|
+
// ProfileStore is constructed but BEFORE the tools register so any
|
|
235
|
+
// subsequent tool call sees the corrected active pointer.
|
|
236
|
+
await bootstrapActiveProfile(profileStore);
|
|
237
|
+
registerUseProfileTool(server, { store: profileStore, keychain });
|
|
238
|
+
registerListProfilesTool(server, { store: profileStore, keychain });
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
console.error("[apimapper-rest] use-profile tool disabled — keychain/profile init failed:", err instanceof Error ? err.message : err);
|
|
242
|
+
}
|
|
163
243
|
}
|
|
164
244
|
process.stdout.on("error", (err) => {
|
|
165
245
|
if (err.code === "EPIPE" || err.code === "ERR_STREAM_DESTROYED")
|
|
@@ -167,6 +247,22 @@ async function main() {
|
|
|
167
247
|
throw err;
|
|
168
248
|
});
|
|
169
249
|
await connectStdio(server);
|
|
250
|
+
// Q1 (2026-06-14): capture the connected AI client's identity for the
|
|
251
|
+
// X-MCP-Client header. The SDK only knows the client name+version AFTER the
|
|
252
|
+
// handshake completes, so this read must follow connectStdio(). Stashed in a
|
|
253
|
+
// module-scoped slot (mcp-client-identity.ts) that the outbound REST
|
|
254
|
+
// chokepoint (client.ts performFetch) reads per request. Empty/missing
|
|
255
|
+
// clientInfo → null → no header attached.
|
|
256
|
+
//
|
|
257
|
+
// Defensive: `server.server` / `getClientVersion` are SDK internals; guard
|
|
258
|
+
// against a transport/SDK shape that doesn't expose them so a missing client
|
|
259
|
+
// identity degrades to "no header" and NEVER crashes server startup.
|
|
260
|
+
try {
|
|
261
|
+
setMcpClient(server.server?.getClientVersion?.());
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
setMcpClient(undefined);
|
|
265
|
+
}
|
|
170
266
|
const ok = moduleStatuses.filter((m) => m.status === "ok").length;
|
|
171
267
|
console.error(`[apimapper-rest] MCP Server v${PKG_VERSION} running — ${ok}/${moduleStatuses.length} modules loaded`);
|
|
172
268
|
}
|
|
@@ -180,7 +276,7 @@ async function main() {
|
|
|
180
276
|
// lazily inside the subcommand branch so the AI-client startup path
|
|
181
277
|
// stays free of clack/prompts side-effects.
|
|
182
278
|
const subcommand = process.argv[2];
|
|
183
|
-
const CLI_SUBCOMMANDS = new Set(["setup", "install-skill", "install", "help", "--help", "-h"]);
|
|
279
|
+
const CLI_SUBCOMMANDS = new Set(["setup", "install-skill", "install", "uninstall", "remove", "help", "--help", "-h"]);
|
|
184
280
|
if (subcommand && CLI_SUBCOMMANDS.has(subcommand)) {
|
|
185
281
|
void (async () => {
|
|
186
282
|
try {
|
|
@@ -194,6 +290,17 @@ if (subcommand && CLI_SUBCOMMANDS.has(subcommand)) {
|
|
|
194
290
|
}
|
|
195
291
|
})();
|
|
196
292
|
}
|
|
293
|
+
else if (shouldShowInteractiveHint(subcommand, CLI_SUBCOMMANDS, !!process.stdin.isTTY)) {
|
|
294
|
+
// Interactive human ran `npx @wootsup/mcp` (bare) or a typo'd subcommand in
|
|
295
|
+
// a terminal. Booting the stdio server here would just sit waiting for
|
|
296
|
+
// JSON-RPC on stdin and LOOK hung. Print a one-screen hint and exit 0.
|
|
297
|
+
//
|
|
298
|
+
// Load-bearing invariant: when stdin is NOT a TTY (an MCP client pipes it),
|
|
299
|
+
// shouldShowInteractiveHint() returns false and we fall through to main()
|
|
300
|
+
// below — the server-boot path is byte-for-byte unchanged.
|
|
301
|
+
console.error(buildInteractiveHint(subcommand));
|
|
302
|
+
process.exit(0);
|
|
303
|
+
}
|
|
197
304
|
else {
|
|
198
305
|
main().catch((error) => {
|
|
199
306
|
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,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/install-skill.js
CHANGED
|
@@ -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.
|
|
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.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Minimal node shape the layout needs; every other field is preserved. */
|
|
2
|
+
interface LayoutNode {
|
|
3
|
+
id: string;
|
|
4
|
+
type?: string;
|
|
5
|
+
position?: {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
interface LayoutEdge {
|
|
11
|
+
source: string;
|
|
12
|
+
target: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Re-position every node into a clean layered grid derived from the edges.
|
|
16
|
+
* Returns a NEW array; each node keeps its id/type/data and gets a fresh
|
|
17
|
+
* `position`. Pure + deterministic (same graph → same positions). An empty
|
|
18
|
+
* `nodes` array is returned untouched.
|
|
19
|
+
*/
|
|
20
|
+
export declare function autoLayoutNodes<T extends LayoutNode>(nodes: T[], edges: ReadonlyArray<LayoutEdge>): T[];
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// auto-layout.ts — deterministic layered left-to-right layout for AI-authored
|
|
2
|
+
// flow graphs (Task X).
|
|
3
|
+
//
|
|
4
|
+
// Why: when the AI builds/edits a flow it should not have to compute pixel
|
|
5
|
+
// positions, and the customer wants the canvas tidy after every AI touch — no
|
|
6
|
+
// overlaps, logical source→…→output flow. This re-flows positions from the
|
|
7
|
+
// graph's topology so every AI write lands clean.
|
|
8
|
+
//
|
|
9
|
+
// IMPORTANT scope: this runs ONLY on the MCP (AI) flow-write path
|
|
10
|
+
// (flow_create / flow_update). It is deliberately NOT in the generic backend
|
|
11
|
+
// save, so a human's manual node positions (persisted by the admin-ui autosave,
|
|
12
|
+
// Task W) are never clobbered — only the AI tidies.
|
|
13
|
+
//
|
|
14
|
+
// Layout: topological layers become columns (left→right); nodes within a layer
|
|
15
|
+
// stack vertically. Orphan / cycle members (never reached) get their own
|
|
16
|
+
// trailing column so they stay visible and non-overlapping — the exact same
|
|
17
|
+
// "unreachable as a trailing layer" treatment the flow-diagram renderer uses.
|
|
18
|
+
import { topoLayers } from "./render/dag.js";
|
|
19
|
+
// Pitch must exceed the admin-ui BaseNode card box (min-w-[220px]
|
|
20
|
+
// max-w-[300px]) so programmatically-placed nodes never crowd — identical to
|
|
21
|
+
// the graph-builder constants (300 max card + 100 gutter; stacked-card height +
|
|
22
|
+
// gutter).
|
|
23
|
+
const BASE_X = 100;
|
|
24
|
+
const BASE_Y = 100;
|
|
25
|
+
const COL_WIDTH = 400;
|
|
26
|
+
const ROW_HEIGHT = 240;
|
|
27
|
+
/**
|
|
28
|
+
* Re-position every node into a clean layered grid derived from the edges.
|
|
29
|
+
* Returns a NEW array; each node keeps its id/type/data and gets a fresh
|
|
30
|
+
* `position`. Pure + deterministic (same graph → same positions). An empty
|
|
31
|
+
* `nodes` array is returned untouched.
|
|
32
|
+
*/
|
|
33
|
+
export function autoLayoutNodes(nodes, edges) {
|
|
34
|
+
if (nodes.length === 0)
|
|
35
|
+
return nodes;
|
|
36
|
+
const { layers, unreachable } = topoLayers(nodes.map((n) => ({ id: n.id, type: n.type })), edges.map((e) => ({ source: e.source, target: e.target })));
|
|
37
|
+
// Orphans + cycle members trail in their own column so they remain visible
|
|
38
|
+
// (this is exactly the node the AI must be able to see to tidy — Task W).
|
|
39
|
+
const columns = unreachable.length > 0 ? [...layers, unreachable] : layers;
|
|
40
|
+
const positionById = new Map();
|
|
41
|
+
columns.forEach((column, colIndex) => {
|
|
42
|
+
column.forEach((id, rowIndex) => {
|
|
43
|
+
positionById.set(id, {
|
|
44
|
+
x: BASE_X + colIndex * COL_WIDTH,
|
|
45
|
+
y: BASE_Y + rowIndex * ROW_HEIGHT,
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
return nodes.map((node) => {
|
|
50
|
+
const position = positionById.get(node.id);
|
|
51
|
+
return position ? { ...node, position } : node;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=auto-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-layout.js","sourceRoot":"","sources":["../../../src/modules/apimapper/auto-layout.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,wBAAwB;AACxB,EAAE;AACF,2EAA2E;AAC3E,8EAA8E;AAC9E,2EAA2E;AAC3E,kDAAkD;AAClD,EAAE;AACF,kEAAkE;AAClE,6EAA6E;AAC7E,gFAAgF;AAChF,oDAAoD;AACpD,EAAE;AACF,+EAA+E;AAC/E,yEAAyE;AACzE,4EAA4E;AAC5E,8EAA8E;AAE9E,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAc7C,kEAAkE;AAClE,6EAA6E;AAC7E,gFAAgF;AAChF,WAAW;AACX,MAAM,MAAM,GAAG,GAAG,CAAC;AACnB,MAAM,MAAM,GAAG,GAAG,CAAC;AACnB,MAAM,SAAS,GAAG,GAAG,CAAC;AACtB,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAU,EACV,KAAgC;IAEhC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAErC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,UAAU,CACxC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAC9C,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAC3D,CAAC;IAEF,2EAA2E;IAC3E,0EAA0E;IAC1E,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAE3E,MAAM,YAAY,GAAG,IAAI,GAAG,EAAoC,CAAC;IACjE,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;QACnC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE;YAC9B,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE;gBACnB,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;gBAChC,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU;aAClC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACxB,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3C,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { formatResult, statsResult,
|
|
3
|
-
import { request
|
|
2
|
+
import { formatResult, statsResult, readOnly, destructive, } from "@getimo/mcp-toolkit";
|
|
3
|
+
import { request } from "./client.js";
|
|
4
|
+
import { restErrorResult } from "./tool-result.js";
|
|
4
5
|
// rc.13 Welle 3 (2026-05-20) — cache_stats migrated to the toolkit's
|
|
5
6
|
// statsResult builder; both tools' error branches upgraded to errorResult.
|
|
6
7
|
// The migration is purely additive (text `content` block preserved, `_meta.ui`
|
|
@@ -12,6 +13,16 @@ import { request, hintFor } from "./client.js";
|
|
|
12
13
|
// F-A6-07: canonical PHP enum from CacheInvalidateController::scopeToEvent.
|
|
13
14
|
// Legacy aliases (`flow`, `connection`, `credential`, `user`) are accepted
|
|
14
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.
|
|
15
26
|
const CACHE_INVALIDATE_SCOPES = [
|
|
16
27
|
"connection.updated",
|
|
17
28
|
"connection.deleted",
|
|
@@ -19,6 +30,7 @@ const CACHE_INVALIDATE_SCOPES = [
|
|
|
19
30
|
"flow.published",
|
|
20
31
|
"user.refresh",
|
|
21
32
|
"user.fetch_data",
|
|
33
|
+
"yootheme.schema",
|
|
22
34
|
];
|
|
23
35
|
// W1.15 (F-27): cap top_keys envelope size — PHP can return arbitrary
|
|
24
36
|
// counts but the MCP response stays bounded for AI-client legibility.
|
|
@@ -30,15 +42,21 @@ export function registerCacheTools(server) {
|
|
|
30
42
|
description: "Publish a cache-invalidation event to the InvalidationBus (Admin-UI BroadcastChannel + render cache). " +
|
|
31
43
|
"Scope is the dotted event id matching the PHP CacheInvalidationEvent subclass. " +
|
|
32
44
|
"Legacy aliases (`flow`, `connection`, `credential`, `user`) are accepted server-side " +
|
|
33
|
-
"but the canonical scopes are documented here." +
|
|
34
|
-
"
|
|
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",
|
|
35
52
|
inputSchema: {
|
|
36
53
|
scope: z
|
|
37
54
|
.enum(CACHE_INVALIDATE_SCOPES)
|
|
38
55
|
.describe("Cache invalidation scope (dotted event id). " +
|
|
39
56
|
"Required payload fields: connection.updated→{connection_id, credential_id?}, " +
|
|
40
57
|
"connection.deleted→{connection_id}, credential.reauth→{credential_id, affected_connection_ids?}, " +
|
|
41
|
-
"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)."),
|
|
42
60
|
payload: z
|
|
43
61
|
.record(z.string(), z.unknown())
|
|
44
62
|
.optional()
|
|
@@ -54,12 +72,7 @@ export function registerCacheTools(server) {
|
|
|
54
72
|
body.payload = payload;
|
|
55
73
|
const r = await request("/cache/admin/invalidate", { method: "POST", body: JSON.stringify(body) });
|
|
56
74
|
if (!r.success) {
|
|
57
|
-
return
|
|
58
|
-
message: r.error ?? "cache invalidation failed",
|
|
59
|
-
code: r.errorCode ?? (r.status ? String(r.status) : undefined),
|
|
60
|
-
suggestion: hintFor(r.errorCode),
|
|
61
|
-
details: { scope, payload_keys: payload ? Object.keys(payload) : [] },
|
|
62
|
-
});
|
|
75
|
+
return restErrorResult(r, { scope, payload_keys: payload ? Object.keys(payload) : [] }, { message: "cache invalidation failed" });
|
|
63
76
|
}
|
|
64
77
|
const ok = r.data?.ok === true;
|
|
65
78
|
return formatResult({
|
|
@@ -83,12 +96,7 @@ export function registerCacheTools(server) {
|
|
|
83
96
|
}, async () => {
|
|
84
97
|
const r = await request("/cache-stats");
|
|
85
98
|
if (!r.success) {
|
|
86
|
-
return
|
|
87
|
-
message: r.error ?? "cache stats failed",
|
|
88
|
-
code: r.errorCode ?? (r.status ? String(r.status) : undefined),
|
|
89
|
-
suggestion: hintFor(r.errorCode),
|
|
90
|
-
details: {},
|
|
91
|
-
});
|
|
99
|
+
return restErrorResult(r, {}, { message: "cache stats failed" });
|
|
92
100
|
}
|
|
93
101
|
const tiers = r.data?.tiers ?? {};
|
|
94
102
|
const admin = tiers.admin ?? {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/modules/apimapper/cache.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,YAAY,EACZ,WAAW,EACX,
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/modules/apimapper/cache.ts"],"names":[],"mappings":"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"}
|