@wootsup/mcp 0.3.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 +14 -5
- 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/index.js +37 -5
- package/dist/index.js.map +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/client.d.ts +54 -4
- package/dist/modules/apimapper/client.js +145 -14
- 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 +225 -58
- package/dist/modules/apimapper/connections.js.map +1 -1
- package/dist/modules/apimapper/credentials.js +86 -14
- package/dist/modules/apimapper/credentials.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 +216 -44
- 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 +39 -130
- 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 +19 -7
- 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 +30 -3
- 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 +115 -15
- package/dist/modules/apimapper/graph.js.map +1 -1
- package/dist/modules/apimapper/index.js +25 -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 +131 -8
- package/dist/modules/apimapper/library.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 +88 -31
- 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/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 +29 -0
- package/dist/modules/apimapper/onboarding.js +117 -9
- 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/tool-result.d.ts +20 -0
- package/dist/modules/apimapper/tool-result.js +67 -5
- package/dist/modules/apimapper/tool-result.js.map +1 -1
- package/dist/modules/apimapper/toolslist-size.d.ts +10 -10
- package/dist/modules/apimapper/toolslist-size.js +29 -18
- package/dist/modules/apimapper/toolslist-size.js.map +1 -1
- package/dist/modules/apimapper/types.d.ts +13 -0
- package/dist/modules/apimapper/types.js +1 -1
- package/dist/modules/apimapper/types.js.map +1 -1
- package/dist/modules/apimapper/whitelist-drift.js +16 -1
- package/dist/modules/apimapper/whitelist-drift.js.map +1 -1
- package/dist/modules/apimapper/workflows.js +221 -32
- package/dist/modules/apimapper/workflows.js.map +1 -1
- package/dist/modules/apimapper/yootheme-binding.js +103 -22
- package/dist/modules/apimapper/yootheme-binding.js.map +1 -1
- package/dist/platform/index.js +7 -0
- 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/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-cli.d.ts +9 -0
- package/dist/setup-cli.js +34 -0
- package/dist/setup-cli.js.map +1 -1
- package/dist/sites/loader.d.ts +7 -0
- package/dist/sites/loader.js +16 -1
- package/dist/sites/loader.js.map +1 -1
- package/dist/skill-instructions.d.ts +14 -1
- package/dist/skill-instructions.js +30 -6
- package/dist/skill-instructions.js.map +1 -1
- package/manifest.json +2 -2
- package/package.json +3 -2
- package/skills/apimapper/SKILL.md +78 -3
- 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 +81 -0
- package/skills/apimapper/reference/library-template-discovery.md +1 -1
- package/skills/apimapper/reference/merge-two-sources-on-key.md +117 -12
- package/skills/apimapper/reference/oauth.md +143 -52
- package/skills/apimapper/reference/troubleshooting.md +2 -2
- package/skills/apimapper/reference/yootheme-source-to-builder-handoff.md +348 -0
- package/skills/apimapper/reference/yootheme.md +75 -44
package/CHANGELOG.md
CHANGED
|
@@ -5,13 +5,20 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project follows [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
-
## [0.
|
|
8
|
+
## [0.4.0] `Latest` - 2026-06-21
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Proxy mode: the server now connects through your site's plugin-served MCP endpoint. New setups use it automatically; existing installs keep working unchanged.**
|
|
13
|
+
- **Smoother client setup: tool-catalog export and a Connect to Claude handoff.**
|
|
14
|
+
|
|
15
|
+
## [0.3.0] - 2026-06-08
|
|
9
16
|
|
|
10
17
|
### Added
|
|
11
18
|
|
|
12
19
|
- **Library-first workflow: creating a custom connection for an API a curated library template already covers now returns a 409 that steers you to activate the template instead. Override with acknowledge_no_library:true for genuinely uncovered endpoints.**
|
|
13
|
-
- **New tool apimapper_yootheme_binding_for_flow
|
|
14
|
-
- **New tool apimapper_connection_recover
|
|
20
|
+
- **New tool apimapper_yootheme_binding_for_flow: inspect the exact YOOtheme binding a published flow exposes.**
|
|
21
|
+
- **New tool apimapper_connection_recover: repair stuck or corrupted connections.**
|
|
15
22
|
- **JMESPath date primitives (date_weekday, date_iso_to_time, date_iso_to_date, time_in_window) plus a depth-overflow guard for deeply nested expressions.**
|
|
16
23
|
- **Connection reads now explain why they returned 0 items instead of failing silently.**
|
|
17
24
|
- **MCP keys can be minted from a permission level (read / write / admin) with additive scopes.**
|
|
@@ -20,8 +27,9 @@ and this project follows [Semantic Versioning](https://semver.org/).
|
|
|
20
27
|
|
|
21
28
|
### Changed
|
|
22
29
|
|
|
23
|
-
- **library_activate is resource-aware: it never silently mutates a healthy existing connection
|
|
30
|
+
- **library_activate is resource-aware: it never silently mutates a healthy existing connection: reuse, heal, or fork is explicit (force_new + reused/mutated/healed semantics).**
|
|
24
31
|
- **Recompile/publish auto-fix is on by default.**
|
|
32
|
+
- **Version history note: the public npm line goes 0.1.0 → 0.3.0. The intermediate 0.2.0 / 0.2.1 bumps were internal build/test cuts and were never published to npm (npm registry: 0.1.0-rc.1…rc.12, rc.13-w3.0, rc.13-w3.1, 0.1.0, 0.3.0), so there is no 0.2.x release to upgrade from: 0.3.0 is the direct successor to 0.1.0.**
|
|
25
33
|
|
|
26
34
|
### Fixed
|
|
27
35
|
|
|
@@ -137,7 +145,8 @@ and this project follows [Semantic Versioning](https://semver.org/).
|
|
|
137
145
|
- **Fixed** - Bug fixes
|
|
138
146
|
- **Security** - Security updates
|
|
139
147
|
|
|
140
|
-
[0.
|
|
148
|
+
[0.4.0]: https://github.com/wootsup/api-mapper/compare/v0.3.0...HEAD
|
|
149
|
+
[0.3.0]: https://github.com/wootsup/api-mapper/compare/v0.1.0...v0.3.0
|
|
141
150
|
[0.1.0]: https://github.com/wootsup/api-mapper/compare/v0.1.0-rc.13-w3.1...v0.1.0
|
|
142
151
|
[0.1.0-rc.13-w3.1]: https://github.com/wootsup/api-mapper/compare/v0.1.0-rc.13-w3.0...v0.1.0-rc.13-w3.1
|
|
143
152
|
[0.1.0-rc.13-w3.0]: https://github.com/wootsup/api-mapper/compare/v0.1.0-rc.12...v0.1.0-rc.13-w3.0
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type ModuleStatus } from "@getimo/mcp-toolkit";
|
|
2
|
+
/**
|
|
3
|
+
* Convert a captured tool inputSchema to JSON Schema. collectModuleTools yields a
|
|
4
|
+
* RAW Zod shape for advanced tools (entry.config.inputSchema) but a constructed Zod
|
|
5
|
+
* OBJECT for essentials (server._registeredTools[name].inputSchema, SDK mcp.js:611).
|
|
6
|
+
* Branch on the Zod-4 internal marker `_zod`. Native z.toJSONSchema (zod 4.4.3).
|
|
7
|
+
*/
|
|
8
|
+
export declare function toJsonSchema(inputSchema: unknown): object;
|
|
9
|
+
/**
|
|
10
|
+
* Fail loud if module registration degraded. `loadModules` is graceful by
|
|
11
|
+
* design — when a module's `register()` throws it logs and records
|
|
12
|
+
* `{ status: "error" }` but RETURNS normally, so a registration failure would
|
|
13
|
+
* otherwise yield an empty/partial catalog that still resolves successfully.
|
|
14
|
+
* The catalog is a release artifact (SSOT for a future PHP MCP surface), so a
|
|
15
|
+
* silently-degraded export is worse than a hard failure — mirror the repo's
|
|
16
|
+
* fail-loud discipline (encryption golden-master, deploy key-survival).
|
|
17
|
+
*/
|
|
18
|
+
export declare function assertModulesLoaded(statuses: ModuleStatus[]): void;
|
|
19
|
+
export interface CatalogTool {
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
jsonSchema: object;
|
|
23
|
+
annotations: Record<string, unknown>;
|
|
24
|
+
tier: "essential" | "advanced";
|
|
25
|
+
}
|
|
26
|
+
export interface Catalog {
|
|
27
|
+
version: string;
|
|
28
|
+
generatedFrom: "zod";
|
|
29
|
+
tools: CatalogTool[];
|
|
30
|
+
}
|
|
31
|
+
export declare function buildCatalog(): Promise<Catalog>;
|
|
@@ -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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"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +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/* —
|
|
4
|
-
// essentials + the apimapper_advanced gateway +
|
|
5
|
-
// top-level tools registered below).
|
|
6
|
-
//
|
|
7
|
-
// surface cap. Canonical counts are
|
|
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).
|
|
8
13
|
//
|
|
9
14
|
// Auth: API Mapper MCP-key (amk_live_...) generated via the API Mapper
|
|
10
15
|
// admin UI → Settings → MCP Access. The legacy WordPress Application
|
|
@@ -70,6 +75,7 @@ import { registerUseProfileTool, registerListProfilesTool, } from "./modules/api
|
|
|
70
75
|
import { registerSitesUseProfileTool, registerSitesListProfilesTool, } from "./modules/apimapper/sites-tools.js";
|
|
71
76
|
import { getSitesRegistry, getActiveSiteId, setActiveSite, } from "./modules/apimapper/client.js";
|
|
72
77
|
import { shouldShowInteractiveHint, buildInteractiveHint } from "./cli-hint.js";
|
|
78
|
+
import { setMcpClient } from "./modules/apimapper/mcp-client-identity.js";
|
|
73
79
|
// Single source of truth for the package version (F-41 / W1.23).
|
|
74
80
|
// Reads ../package.json at runtime so we never drift between the manifest
|
|
75
81
|
// version (used by npm + DXT) and what we advertise to MCP clients.
|
|
@@ -156,6 +162,16 @@ server.registerTool("apimapper_rest_modules_status", {
|
|
|
156
162
|
}, false, { maxChars: 2000 });
|
|
157
163
|
});
|
|
158
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
|
+
}
|
|
159
175
|
moduleStatuses = await loadModules(server, [apimapperRestModule]);
|
|
160
176
|
// Profile tools for apimapper_use_profile / apimapper_list_profiles.
|
|
161
177
|
//
|
|
@@ -231,6 +247,22 @@ async function main() {
|
|
|
231
247
|
throw err;
|
|
232
248
|
});
|
|
233
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
|
+
}
|
|
234
266
|
const ok = moduleStatuses.filter((m) => m.status === "ok").length;
|
|
235
267
|
console.error(`[apimapper-rest] MCP Server v${PKG_VERSION} running — ${ok}/${moduleStatuses.length} modules loaded`);
|
|
236
268
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,uEAAuE;AACvE,6EAA6E;AAC7E
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -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"}
|
|
@@ -46,7 +46,7 @@ export declare function sanitizeErrorString(s: string): string;
|
|
|
46
46
|
* The underlying toolkit `ApiResponse` only carries `{success, data?, error?}`.
|
|
47
47
|
* We wrap each call so we capture the HTTP code via `fetch` and merge.
|
|
48
48
|
*/
|
|
49
|
-
export type ApiErrorCode = "auth" | "not_found" | "conflict" | "rate_limit" | "server" | "network" | "unknown";
|
|
49
|
+
export type ApiErrorCode = "auth" | "not_found" | "conflict" | "rate_limit" | "server" | "network" | "credential_expired" | "tier_limit_reached" | "unknown";
|
|
50
50
|
export interface ExtApiResponse<T = unknown> extends ApiResponse<T> {
|
|
51
51
|
status?: number;
|
|
52
52
|
errorCode?: ApiErrorCode;
|
|
@@ -181,11 +181,61 @@ export declare function __resetPlatformResolutionForTests(): void;
|
|
|
181
181
|
*/
|
|
182
182
|
export declare function request<T = unknown>(path: string, init?: RequestInit, opts?: RequestOpts): Promise<ExtApiResponse<T>>;
|
|
183
183
|
/**
|
|
184
|
-
*
|
|
185
|
-
*
|
|
184
|
+
* Optional second argument to {@link hintFor}, used to route a hint more
|
|
185
|
+
* precisely than the coarse `ApiErrorCode` alone allows. Both fields are
|
|
186
|
+
* optional and every legacy `hintFor(code)` call keeps its exact prior
|
|
187
|
+
* output (back-compat), so the ~12 call sites need not change.
|
|
188
|
+
*
|
|
189
|
+
* Welle 2 (F112 + F113, 2026-06-11):
|
|
190
|
+
* - `message`: the upstream error string. Lets the `unknown` branch route
|
|
191
|
+
* a config/validation/argument error to a "fix the field / fix the flow
|
|
192
|
+
* shape / detect schema" hint instead of the catch-all HEALTH_HINT
|
|
193
|
+
* (which sends the agent on a connectivity probe that always passes).
|
|
194
|
+
* It is also the channel for the F83 JMESPath depth-limit detection
|
|
195
|
+
* (see {@link DEPTH_SPLIT_HINT}).
|
|
196
|
+
* - `origin`: WHERE a 401/403 came from. `classify()` maps every 401/403
|
|
197
|
+
* to `'auth'`, but a 401/403 raised by a *connection* / *credential*
|
|
198
|
+
* fetch is an EXPIRED UPSTREAM token, not a broken MCP key. With
|
|
199
|
+
* `origin: 'connection' | 'credential'` the auth branch steers to
|
|
200
|
+
* re-authorising the upstream credential (`oauth_authorize_begin`)
|
|
201
|
+
* rather than rotating the still-valid MCP bearer key.
|
|
186
202
|
*/
|
|
187
|
-
export
|
|
203
|
+
export interface HintContext {
|
|
204
|
+
/** The upstream error message, used for message-pattern routing of `unknown`. */
|
|
205
|
+
message?: string;
|
|
206
|
+
/**
|
|
207
|
+
* The origin of an auth (401/403) failure. `connection` / `credential`
|
|
208
|
+
* mean an expired upstream token; `mcp_transport` (or omitted) means the
|
|
209
|
+
* MCP bearer key itself.
|
|
210
|
+
*/
|
|
211
|
+
origin?: "connection" | "credential" | "mcp_transport";
|
|
212
|
+
}
|
|
213
|
+
export declare const DEPTH_SPLIT_HINT: string;
|
|
214
|
+
/**
|
|
215
|
+
* Map an `errorCode` (and optional {@link HintContext}) to a focused hint
|
|
216
|
+
* string for the caller. Falls back to the generic health-tool hint only for
|
|
217
|
+
* genuinely connectivity-shaped failures.
|
|
218
|
+
*
|
|
219
|
+
* The second argument is a UNION: a bare `string` is treated as
|
|
220
|
+
* `{ message }` so the ~12 legacy call sites that pass the upstream error
|
|
221
|
+
* string verbatim (`hintFor(code, r.error)`) keep working unchanged, while
|
|
222
|
+
* the richer `{ message, origin }` form drives F112/F113 routing. Omit it to
|
|
223
|
+
* keep the legacy code-only behaviour byte-for-byte.
|
|
224
|
+
*/
|
|
225
|
+
export declare function hintFor(code?: ApiErrorCode, context?: string | HintContext): string;
|
|
188
226
|
export declare const HEALTH_HINT = "Use apimapper_health to check connectivity and auth.";
|
|
227
|
+
/**
|
|
228
|
+
* Recovery hint for an auth failure on the MCP transport itself (the bearer
|
|
229
|
+
* key is wrong/revoked/expired). Kept verbatim for the legacy `hintFor('auth')`
|
|
230
|
+
* contract.
|
|
231
|
+
*/
|
|
232
|
+
export declare const MCP_KEY_AUTH_HINT: string;
|
|
233
|
+
/**
|
|
234
|
+
* F113 — recovery hint for an EXPIRED UPSTREAM credential surfaced as a
|
|
235
|
+
* connection/credential 401/403. The fix is to re-authorise the credential in
|
|
236
|
+
* place (preserving the refresh_token), NOT to rotate the MCP key.
|
|
237
|
+
*/
|
|
238
|
+
export declare const CREDENTIAL_EXPIRED_HINT: string;
|
|
189
239
|
export declare function authConfigured(): boolean;
|
|
190
240
|
export declare const api: {
|
|
191
241
|
request: <T>(path: string, init?: RequestInit, _retryCount?: number, responseSchema?: import("zod").ZodType<T>) => Promise<ApiResponse<T>>;
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
import { createHttpClient } from "@getimo/mcp-toolkit";
|
|
26
26
|
import { Agent, setGlobalDispatcher } from "undici";
|
|
27
27
|
import { sanitizeSecrets } from "./credential-sanitizer.js";
|
|
28
|
+
import { getMcpClient } from "./mcp-client-identity.js";
|
|
28
29
|
import { getCached, setCached, isCacheableRequest, invalidateByPath, clearCache, } from "./read-cache.js";
|
|
29
30
|
import { WordPressPlatform, JoomlaPlatform, isPlatformResponseError, isJoomlaUnsupportedPathError } from "../../platform/index.js";
|
|
30
31
|
import { loadSitesRegistry } from "../../sites/loader.js";
|
|
@@ -207,10 +208,19 @@ async function performFetch(cfg) {
|
|
|
207
208
|
const { url, headers, init, opts, parseResponse, preferMessageKey = true, attachErrorBody = false, textSuccessFalseGuard = false, } = cfg;
|
|
208
209
|
let status;
|
|
209
210
|
const timeoutMs = resolveTimeout(opts);
|
|
211
|
+
// Q1 (2026-06-14): performFetch is the ONE outbound chokepoint shared by the
|
|
212
|
+
// WP, Joomla, and absolute request paths. Attaching X-MCP-Client here means
|
|
213
|
+
// every REST call carries the connected AI client's identity (set once
|
|
214
|
+
// post-handshake in index.ts) without touching three caller header builders.
|
|
215
|
+
// Null when no client info → header omitted entirely.
|
|
216
|
+
const mcpClient = getMcpClient();
|
|
210
217
|
try {
|
|
211
218
|
const res = await fetch(url, {
|
|
212
219
|
...init,
|
|
213
|
-
headers
|
|
220
|
+
headers: {
|
|
221
|
+
...headers,
|
|
222
|
+
...(mcpClient ? { "X-MCP-Client": mcpClient } : {}),
|
|
223
|
+
},
|
|
214
224
|
signal: AbortSignal.timeout(timeoutMs),
|
|
215
225
|
});
|
|
216
226
|
status = res.status;
|
|
@@ -855,33 +865,154 @@ async function rawAbsoluteRequest(url, init, opts) {
|
|
|
855
865
|
});
|
|
856
866
|
}
|
|
857
867
|
/**
|
|
858
|
-
*
|
|
859
|
-
*
|
|
868
|
+
* F83 (2026-06-10, C3 cold-agent): the JMESPath depth-limit failure surfaced
|
|
869
|
+
* on the flow-write path. The PHP backend emits it as a 422 with one of two
|
|
870
|
+
* frozen wordings:
|
|
871
|
+
* - FlowHandler::validateJmesPathDepth → "N JMESPath expression(s) exceeded
|
|
872
|
+
* the depth limit of M"
|
|
873
|
+
* - TransformException → "JMESPath expression too deeply nested (N levels).
|
|
874
|
+
* Maximum: M"
|
|
875
|
+
* Neither carries a body-level `error_code`/`suggestion`, so `classify(422)`
|
|
876
|
+
* lands on "unknown" and the bare-code hint is HEALTH_HINT — the WRONG remedy
|
|
877
|
+
* (a cold agent literally got "Use apimapper_health to check connectivity").
|
|
878
|
+
* The actual cure is the two-transform split: a pipe `|` resets the depth
|
|
879
|
+
* counter. We detect the depth-limit message text (not the coarse code) so the
|
|
880
|
+
* remedy fires regardless of how the wire status classifies. This is the
|
|
881
|
+
* canonical depth remedy — the PHP `TransformException::expressionTooDeepWithRemedy`
|
|
882
|
+
* superset emits the same intent; the MCP-side detection here covers the
|
|
883
|
+
* write-path 422s that arrive without a body-level error_code.
|
|
860
884
|
*/
|
|
861
|
-
|
|
885
|
+
const DEPTH_LIMIT_MESSAGE_RE = /depth limit|too deeply nested/i;
|
|
886
|
+
export const DEPTH_SPLIT_HINT = "JMESPath depth limit hit. This is NOT a connectivity problem — do not run " +
|
|
887
|
+
"apimapper_health. Multi-stage reshape? Pass `transform` as an ARRAY of stages " +
|
|
888
|
+
"— each stage gets its own depth budget. SPLIT the over-nested expression into " +
|
|
889
|
+
"TWO Transform nodes piped together: a pipe `|` resets the depth counter, so " +
|
|
890
|
+
"each half stays under the cap of 10. Move the inner projection/merge into a " +
|
|
891
|
+
"first Transform, then do the per-row shaping in a second Transform reading its " +
|
|
892
|
+
"output. Iterate each half risk-free with apimapper_jmespath_test before " +
|
|
893
|
+
"wiring, and read the copy-paste recipes via " +
|
|
894
|
+
"apimapper_get_skill({ topic: 'jmespath-cookbook' }) → \"Two-Transform split\".";
|
|
895
|
+
/**
|
|
896
|
+
* Map an `errorCode` (and optional {@link HintContext}) to a focused hint
|
|
897
|
+
* string for the caller. Falls back to the generic health-tool hint only for
|
|
898
|
+
* genuinely connectivity-shaped failures.
|
|
899
|
+
*
|
|
900
|
+
* The second argument is a UNION: a bare `string` is treated as
|
|
901
|
+
* `{ message }` so the ~12 legacy call sites that pass the upstream error
|
|
902
|
+
* string verbatim (`hintFor(code, r.error)`) keep working unchanged, while
|
|
903
|
+
* the richer `{ message, origin }` form drives F112/F113 routing. Omit it to
|
|
904
|
+
* keep the legacy code-only behaviour byte-for-byte.
|
|
905
|
+
*/
|
|
906
|
+
export function hintFor(code, context) {
|
|
907
|
+
// Normalise the union: a bare string IS the upstream message.
|
|
908
|
+
const ctx = typeof context === "string" ? { message: context } : context;
|
|
909
|
+
// F83: message-driven depth-limit detection wins over the coarse code, so a
|
|
910
|
+
// 422 that classify()s to "unknown" still gets the split remedy.
|
|
911
|
+
if (ctx?.message && DEPTH_LIMIT_MESSAGE_RE.test(ctx.message)) {
|
|
912
|
+
return DEPTH_SPLIT_HINT;
|
|
913
|
+
}
|
|
862
914
|
switch (code) {
|
|
863
915
|
case "auth":
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
916
|
+
// F113: separate upstream-credential auth from MCP-transport auth.
|
|
917
|
+
// A 401/403 carried back from a connection/credential fetch is an
|
|
918
|
+
// EXPIRED UPSTREAM token — re-authorise it in place; do NOT send the
|
|
919
|
+
// agent to rotate the (valid) MCP key + re-run the setup wizard.
|
|
920
|
+
if (ctx?.origin === "connection" || ctx?.origin === "credential") {
|
|
921
|
+
return CREDENTIAL_EXPIRED_HINT;
|
|
922
|
+
}
|
|
923
|
+
return MCP_KEY_AUTH_HINT;
|
|
872
924
|
case "not_found":
|
|
873
925
|
return "Resource not found. Use the matching `*_list` tool to find a valid id.";
|
|
874
926
|
case "rate_limit":
|
|
875
|
-
|
|
927
|
+
// F59 (2026-06-10): a 429 is often recoverable WITHOUT waiting — many
|
|
928
|
+
// providers have a same-schema MIRROR connection (same template, a
|
|
929
|
+
// different upstream serving identical data). Point the agent there.
|
|
930
|
+
return ("Rate-limited (HTTP 429). Retry after a few seconds, and raise " +
|
|
931
|
+
"cache_ttl / use apimapper_cache_invalidate to reduce churn. If the " +
|
|
932
|
+
"throttle persists, run apimapper_connection_list and look for a " +
|
|
933
|
+
"same-schema / mirror connection (same library template or a " +
|
|
934
|
+
"duplicate pointing at an alternative upstream) that serves the same " +
|
|
935
|
+
"data — bind the flow to that mirror instead of the throttled source.");
|
|
936
|
+
case "credential_expired":
|
|
937
|
+
// A11: re-authorize the EXISTING credential in place; never delete +
|
|
938
|
+
// recreate (that drops the OAuth refresh token).
|
|
939
|
+
return ("An OAuth credential expired. Re-authorize it IN PLACE with " +
|
|
940
|
+
"apimapper_oauth_authorize_begin({ credential_id }), open the returned " +
|
|
941
|
+
"authorize_url, complete consent, then retry. Keep the same credential " +
|
|
942
|
+
"— recreating it from scratch drops the refresh token. Use " +
|
|
943
|
+
"apimapper_credential_list to find the credential_id.");
|
|
944
|
+
case "tier_limit_reached":
|
|
945
|
+
// A12: the plan's connection / auth-method limit is hit.
|
|
946
|
+
return ("Your plan's limit was reached (connections or auth methods). " +
|
|
947
|
+
"Upgrade the license to raise the limit, or free a slot by deleting an " +
|
|
948
|
+
"unused connection (apimapper_connection_list to review). Check the " +
|
|
949
|
+
"current tier + limits with apimapper_license_status.");
|
|
876
950
|
case "server":
|
|
877
951
|
return "Upstream server error. Try again, then run apimapper_health and check WP error logs.";
|
|
878
952
|
case "network":
|
|
879
953
|
return "Network/timeout error. Verify APIMAPPER_WP_BASE is reachable from this host.";
|
|
880
954
|
default:
|
|
881
|
-
|
|
955
|
+
// F112: an `unknown`/config error must NOT blanket-route to the
|
|
956
|
+
// connectivity probe. Route on the message shape when we have one.
|
|
957
|
+
return routeUnknownHint(ctx?.message);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* F112 — message-pattern router for the `unknown` (config/validation) branch.
|
|
962
|
+
* Returns a hint that points at the ACTUAL fix (fill a field, repair the flow
|
|
963
|
+
* shape, detect a schema) instead of the catch-all HEALTH_HINT. Only a
|
|
964
|
+
* genuinely connectivity-shaped message (or no message at all) keeps the
|
|
965
|
+
* health hint.
|
|
966
|
+
*/
|
|
967
|
+
function routeUnknownHint(message) {
|
|
968
|
+
if (!message)
|
|
969
|
+
return HEALTH_HINT;
|
|
970
|
+
const m = message.toLowerCase();
|
|
971
|
+
// Connectivity-shaped failures keep pointing at apimapper_health.
|
|
972
|
+
if (/econnrefused|enotfound|etimedout|fetch failed|network|timeout|unreachable|connection refused/.test(m)) {
|
|
973
|
+
return HEALTH_HINT;
|
|
974
|
+
}
|
|
975
|
+
// Empty/stale schema → detect the schema.
|
|
976
|
+
if (/schema (is )?empty|no schema|empty schema|run detect|detect[- ]schema/.test(m)) {
|
|
977
|
+
return "The source schema is empty — run apimapper_flow_detect_schema (or apimapper_flow_full_recompile_publish) to populate it before binding fields.";
|
|
978
|
+
}
|
|
979
|
+
// Flow-SHAPE errors (wiring / nodes / edges) → inspect the flow graph.
|
|
980
|
+
if (/no (target|source|output) node|target node|source node|\bedges?\b|\bnode\b|connect|wiring|no nodes/.test(m)) {
|
|
981
|
+
return "The flow shape is incomplete (missing node, edge, or target). Run apimapper_flow_get to inspect the graph, then fix the node/edge wiring with apimapper_flow_update.";
|
|
982
|
+
}
|
|
983
|
+
// Missing-field / configure errors → supply the field.
|
|
984
|
+
if (/missing required field|missing field|please configure|required field|is required|required:/.test(m)) {
|
|
985
|
+
return "A required argument is missing — supply the named field(s) and call the tool again. Check the tool's input schema for the exact key(s).";
|
|
882
986
|
}
|
|
987
|
+
// Default: still a config error, not a connectivity one — keep the agent
|
|
988
|
+
// out of the health probe and tell it to recheck its arguments.
|
|
989
|
+
return "Check the tool arguments against its input schema and retry; this is a request/config error, not a connectivity problem.";
|
|
883
990
|
}
|
|
884
991
|
export const HEALTH_HINT = "Use apimapper_health to check connectivity and auth.";
|
|
992
|
+
/**
|
|
993
|
+
* Recovery hint for an auth failure on the MCP transport itself (the bearer
|
|
994
|
+
* key is wrong/revoked/expired). Kept verbatim for the legacy `hintFor('auth')`
|
|
995
|
+
* contract.
|
|
996
|
+
*/
|
|
997
|
+
export const MCP_KEY_AUTH_HINT = "Auth failed (HTTP 401/403). Your MCP key (APIMAPPER_TOKEN) is " +
|
|
998
|
+
"invalid, revoked, or expired. Recovery steps: " +
|
|
999
|
+
"(1) Open API Mapper → ⋮ menu → Settings → MCP Access. " +
|
|
1000
|
+
"(2) Revoke the old key if you suspect it was leaked. " +
|
|
1001
|
+
"(3) Click 'New API key' and copy the value. " +
|
|
1002
|
+
"(4) Re-run `npx -y @wootsup/mcp setup` and paste the new key — " +
|
|
1003
|
+
"the wizard rewrites your AI client config in place. " +
|
|
1004
|
+
"(5) Restart your AI client (Claude Desktop / Cursor / etc.).";
|
|
1005
|
+
/**
|
|
1006
|
+
* F113 — recovery hint for an EXPIRED UPSTREAM credential surfaced as a
|
|
1007
|
+
* connection/credential 401/403. The fix is to re-authorise the credential in
|
|
1008
|
+
* place (preserving the refresh_token), NOT to rotate the MCP key.
|
|
1009
|
+
*/
|
|
1010
|
+
export const CREDENTIAL_EXPIRED_HINT = "The upstream API rejected the request (HTTP 401/403) because the " +
|
|
1011
|
+
"connection's credential has expired or was revoked — this is the " +
|
|
1012
|
+
"external service's token, NOT your MCP key. Re-authorise it: call " +
|
|
1013
|
+
"apimapper_oauth_authorize_begin with the connection's credential_id to " +
|
|
1014
|
+
"get a fresh consent URL (this preserves the refresh_token). Do NOT " +
|
|
1015
|
+
"rotate your MCP key for this error.";
|
|
885
1016
|
export function authConfigured() {
|
|
886
1017
|
// Bearer token (amk_live_…) is sufficient on its own; legacy App-Password
|
|
887
1018
|
// auth still requires both user + password.
|