@wootsup/mcp 0.1.0-rc.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +148 -83
- package/README.md +36 -32
- 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/cli-hint.d.ts +22 -0
- package/dist/cli-hint.js +55 -0
- package/dist/cli-hint.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +163 -22
- package/dist/index.js.map +1 -1
- package/dist/install-skill.js +1 -1
- package/dist/modules/apimapper/cache.d.ts +2 -2
- package/dist/modules/apimapper/cache.js +119 -29
- package/dist/modules/apimapper/cache.js.map +1 -1
- package/dist/modules/apimapper/client.d.ts +102 -1
- package/dist/modules/apimapper/client.js +631 -297
- package/dist/modules/apimapper/client.js.map +1 -1
- package/dist/modules/apimapper/connections-format.d.ts +51 -0
- package/dist/modules/apimapper/connections-format.js +261 -0
- package/dist/modules/apimapper/connections-format.js.map +1 -0
- package/dist/modules/apimapper/connections-trim.d.ts +82 -0
- package/dist/modules/apimapper/connections-trim.js +224 -0
- package/dist/modules/apimapper/connections-trim.js.map +1 -0
- package/dist/modules/apimapper/connections.d.ts +14 -2
- package/dist/modules/apimapper/connections.js +612 -153
- 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-format.d.ts +21 -0
- package/dist/modules/apimapper/credentials-format.js +145 -0
- package/dist/modules/apimapper/credentials-format.js.map +1 -0
- package/dist/modules/apimapper/credentials.d.ts +12 -2
- package/dist/modules/apimapper/credentials.js +226 -73
- package/dist/modules/apimapper/credentials.js.map +1 -1
- package/dist/modules/apimapper/diagnose.d.ts +54 -2
- package/dist/modules/apimapper/diagnose.js +213 -12
- package/dist/modules/apimapper/diagnose.js.map +1 -1
- package/dist/modules/apimapper/elicitation.d.ts +54 -0
- package/dist/modules/apimapper/elicitation.js +90 -0
- package/dist/modules/apimapper/elicitation.js.map +1 -0
- package/dist/modules/apimapper/flows-format.d.ts +50 -0
- package/dist/modules/apimapper/flows-format.js +318 -0
- package/dist/modules/apimapper/flows-format.js.map +1 -0
- package/dist/modules/apimapper/flows.d.ts +13 -2
- package/dist/modules/apimapper/flows.js +312 -122
- package/dist/modules/apimapper/flows.js.map +1 -1
- package/dist/modules/apimapper/gateway/advanced-tool.d.ts +9 -0
- package/dist/modules/apimapper/gateway/advanced-tool.js +265 -0
- package/dist/modules/apimapper/gateway/advanced-tool.js.map +1 -0
- package/dist/modules/apimapper/gateway/capturing-server.d.ts +81 -0
- package/dist/modules/apimapper/gateway/capturing-server.js +87 -0
- package/dist/modules/apimapper/gateway/capturing-server.js.map +1 -0
- package/dist/modules/apimapper/gateway/essentials.d.ts +4 -0
- package/dist/modules/apimapper/gateway/essentials.js +35 -0
- package/dist/modules/apimapper/gateway/essentials.js.map +1 -0
- package/dist/modules/apimapper/gateway/test-support.d.ts +17 -0
- package/dist/modules/apimapper/gateway/test-support.js +43 -0
- package/dist/modules/apimapper/gateway/test-support.js.map +1 -0
- package/dist/modules/apimapper/get-skill.d.ts +3 -3
- package/dist/modules/apimapper/get-skill.js +47 -7
- package/dist/modules/apimapper/get-skill.js.map +1 -1
- package/dist/modules/apimapper/graph-builder.js +1 -1
- package/dist/modules/apimapper/graph-builder.js.map +1 -1
- package/dist/modules/apimapper/graph.d.ts +2 -2
- package/dist/modules/apimapper/graph.js +170 -35
- package/dist/modules/apimapper/graph.js.map +1 -1
- package/dist/modules/apimapper/index.d.ts +17 -1
- package/dist/modules/apimapper/index.js +68 -17
- package/dist/modules/apimapper/index.js.map +1 -1
- package/dist/modules/apimapper/inspect.d.ts +3 -2
- package/dist/modules/apimapper/inspect.js +97 -13
- package/dist/modules/apimapper/inspect.js.map +1 -1
- package/dist/modules/apimapper/library.d.ts +2 -2
- package/dist/modules/apimapper/library.js +665 -80
- package/dist/modules/apimapper/library.js.map +1 -1
- package/dist/modules/apimapper/license-format.d.ts +22 -0
- package/dist/modules/apimapper/license-format.js +149 -0
- package/dist/modules/apimapper/license-format.js.map +1 -0
- package/dist/modules/apimapper/license.d.ts +16 -2
- package/dist/modules/apimapper/license.js +62 -38
- package/dist/modules/apimapper/license.js.map +1 -1
- package/dist/modules/apimapper/local-sources.d.ts +2 -2
- package/dist/modules/apimapper/local-sources.js +44 -30
- package/dist/modules/apimapper/local-sources.js.map +1 -1
- package/dist/modules/apimapper/misc.d.ts +30 -2
- package/dist/modules/apimapper/misc.js +114 -49
- package/dist/modules/apimapper/misc.js.map +1 -1
- package/dist/modules/apimapper/node-schema.d.ts +52 -0
- package/dist/modules/apimapper/node-schema.js +70 -2
- package/dist/modules/apimapper/node-schema.js.map +1 -1
- package/dist/modules/apimapper/normalizers.d.ts +1 -0
- package/dist/modules/apimapper/normalizers.js +51 -0
- package/dist/modules/apimapper/normalizers.js.map +1 -1
- package/dist/modules/apimapper/onboarding.d.ts +78 -3
- package/dist/modules/apimapper/onboarding.js +428 -26
- package/dist/modules/apimapper/onboarding.js.map +1 -1
- package/dist/modules/apimapper/read-cache.d.ts +31 -2
- package/dist/modules/apimapper/read-cache.js +20 -6
- package/dist/modules/apimapper/read-cache.js.map +1 -1
- package/dist/modules/apimapper/render/_shared.d.ts +24 -0
- package/dist/modules/apimapper/render/_shared.js +84 -0
- package/dist/modules/apimapper/render/_shared.js.map +1 -0
- package/dist/modules/apimapper/render/dag.d.ts +18 -0
- package/dist/modules/apimapper/render/dag.js +70 -0
- package/dist/modules/apimapper/render/dag.js.map +1 -0
- package/dist/modules/apimapper/render/index.d.ts +2 -0
- package/dist/modules/apimapper/render/index.js +112 -0
- package/dist/modules/apimapper/render/index.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/chart-bar.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/chart-bar.js +70 -0
- package/dist/modules/apimapper/render/renderers/chart-bar.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/chart-line.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/chart-line.js +71 -0
- package/dist/modules/apimapper/render/renderers/chart-line.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/diff.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/diff.js +154 -0
- package/dist/modules/apimapper/render/renderers/diff.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/flow-diagram.d.ts +1 -0
- package/dist/modules/apimapper/render/renderers/flow-diagram.js +180 -0
- package/dist/modules/apimapper/render/renderers/flow-diagram.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/json-tree.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/json-tree.js +87 -0
- package/dist/modules/apimapper/render/renderers/json-tree.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/schema-diagram.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/schema-diagram.js +83 -0
- package/dist/modules/apimapper/render/renderers/schema-diagram.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/table.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/table.js +75 -0
- package/dist/modules/apimapper/render/renderers/table.js.map +1 -0
- package/dist/modules/apimapper/render/schemas.d.ts +23 -0
- package/dist/modules/apimapper/render/schemas.js +56 -0
- package/dist/modules/apimapper/render/schemas.js.map +1 -0
- package/dist/modules/apimapper/render/secret-masking.d.ts +5 -0
- package/dist/modules/apimapper/render/secret-masking.js +51 -0
- package/dist/modules/apimapper/render/secret-masking.js.map +1 -0
- package/dist/modules/apimapper/render/sidecar.d.ts +21 -0
- package/dist/modules/apimapper/render/sidecar.js +66 -0
- package/dist/modules/apimapper/render/sidecar.js.map +1 -0
- package/dist/modules/apimapper/render/token-cap.d.ts +21 -0
- package/dist/modules/apimapper/render/token-cap.js +57 -0
- package/dist/modules/apimapper/render/token-cap.js.map +1 -0
- package/dist/modules/apimapper/schema.d.ts +2 -2
- package/dist/modules/apimapper/schema.js +92 -33
- package/dist/modules/apimapper/schema.js.map +1 -1
- package/dist/modules/apimapper/settings-format.d.ts +23 -0
- package/dist/modules/apimapper/settings-format.js +135 -0
- package/dist/modules/apimapper/settings-format.js.map +1 -0
- package/dist/modules/apimapper/settings.d.ts +2 -2
- package/dist/modules/apimapper/settings.js +100 -42
- 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/skill-resources.d.ts +2 -2
- package/dist/modules/apimapper/skill-resources.js.map +1 -1
- package/dist/modules/apimapper/token-baseline.harness.d.ts +91 -0
- package/dist/modules/apimapper/token-baseline.harness.js +291 -0
- package/dist/modules/apimapper/token-baseline.harness.js.map +1 -0
- package/dist/modules/apimapper/tool-result.d.ts +46 -0
- package/dist/modules/apimapper/tool-result.js +63 -0
- package/dist/modules/apimapper/tool-result.js.map +1 -0
- package/dist/modules/apimapper/toolslist-size.d.ts +56 -0
- package/dist/modules/apimapper/toolslist-size.js +192 -0
- package/dist/modules/apimapper/toolslist-size.js.map +1 -0
- package/dist/modules/apimapper/types.d.ts +44 -8
- package/dist/modules/apimapper/types.js +26 -1
- package/dist/modules/apimapper/types.js.map +1 -1
- package/dist/modules/apimapper/use-profile.d.ts +21 -0
- package/dist/modules/apimapper/use-profile.js +56 -2
- package/dist/modules/apimapper/use-profile.js.map +1 -1
- package/dist/modules/apimapper/whitelist-drift.d.ts +85 -0
- package/dist/modules/apimapper/whitelist-drift.js +360 -0
- package/dist/modules/apimapper/whitelist-drift.js.map +1 -0
- package/dist/modules/apimapper/workflows.d.ts +2 -2
- package/dist/modules/apimapper/workflows.js +202 -20
- 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 +186 -0
- package/dist/modules/apimapper/yootheme-binding.js.map +1 -0
- package/dist/platform/index.d.ts +56 -0
- package/dist/platform/index.js +195 -7
- package/dist/platform/index.js.map +1 -1
- 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-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 +60 -0
- package/dist/setup-cli.js +155 -5
- package/dist/setup-cli.js.map +1 -1
- package/dist/sites/loader.d.ts +41 -0
- package/dist/sites/loader.js +119 -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 +1 -1
- package/dist/skill-instructions.js +5 -0
- 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 +22 -22
- package/docs/customgraph-internal-migration.md +4 -4
- package/docs/security.md +2 -21
- package/docs/tools.md +40 -12
- package/manifest.json +77 -70
- package/package.json +68 -60
- package/skills/apimapper/SKILL.md +53 -7
- package/skills/apimapper/reference/conditional-style-multi-items.md +114 -0
- package/skills/apimapper/reference/jmespath-pitfalls.md +108 -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 +99 -0
- package/skills/apimapper/reference/render.md +132 -0
- package/skills/apimapper/reference/troubleshooting.md +21 -1
- package/skills/apimapper/reference/yootheme.md +1 -1
- 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,135 @@
|
|
|
1
|
+
// src/modules/apimapper/settings-format.ts — W3.1 structuredContent helpers
|
|
2
|
+
//
|
|
3
|
+
// rc.13 Welle 3 (2026-05-20) — extracted from settings.ts when the migration
|
|
4
|
+
// to the toolkit's structuredContent builders added the detail builders for
|
|
5
|
+
// settings_get / features_get and the table shape for health_warnings_list.
|
|
6
|
+
// The tool-registration module (settings.ts) keeps the lean surface; the
|
|
7
|
+
// column constants, detail builders and next-step strings live here —
|
|
8
|
+
// matching connections-format.ts / credentials-format.ts.
|
|
9
|
+
//
|
|
10
|
+
// - settings_get / features_get → detailResult (display="detail"): a flat
|
|
11
|
+
// scalar settings/feature dict renders as grouped key-value entries.
|
|
12
|
+
// - health_warnings_list → tableResult (display="data-table").
|
|
13
|
+
// - IA-10 (W3.9): every migrated tool carries actionable next-step guidance
|
|
14
|
+
// in the LLM-readable text (table footer / detail "Next steps" group).
|
|
15
|
+
import { detailResult, } from "@getimo/mcp-toolkit";
|
|
16
|
+
// ── health_warnings_list table shape ──────────────────────────────────
|
|
17
|
+
export const HEALTH_WARNINGS_COLUMNS = [
|
|
18
|
+
{ key: "credentialId", label: "CREDENTIAL_ID", width: 32 },
|
|
19
|
+
{ key: "type", label: "TYPE", width: 28 },
|
|
20
|
+
];
|
|
21
|
+
// IA-10: next-step guidance, kept in the table footer so it is VISIBLE in the
|
|
22
|
+
// LLM-readable text of the warning list.
|
|
23
|
+
export const HEALTH_WARNINGS_NEXT_STEPS = "Next: apimapper_health_warnings_dismiss({ id }) to dismiss a warning · " +
|
|
24
|
+
"apimapper_credential_get({ id }) to inspect the affected credential.";
|
|
25
|
+
/** health_warnings_list row map: warning item → table row. */
|
|
26
|
+
export function mapHealthWarningRow(w) {
|
|
27
|
+
return {
|
|
28
|
+
credentialId: w.credentialId ? String(w.credentialId) : "—",
|
|
29
|
+
type: w.type ? String(w.type) : "—",
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/** Coerce a scalar settings value into a detail entry string. */
|
|
33
|
+
function scalarStr(v) {
|
|
34
|
+
if (v === null || v === undefined)
|
|
35
|
+
return "—";
|
|
36
|
+
if (typeof v === "boolean")
|
|
37
|
+
return v ? "true" : "false";
|
|
38
|
+
return String(v);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Build a structured detail view for settings_get.
|
|
42
|
+
*
|
|
43
|
+
* The settings dict is a flat scalar map (cache_ttl, debug_mode, log_level,
|
|
44
|
+
* …) — each key becomes a detail entry. The active license tier is the
|
|
45
|
+
* badge; the canonical SETTABLE_KEYS list + next-step calls go into an
|
|
46
|
+
* IA-10 "Next steps" group so the LLM reads the affordance in the text.
|
|
47
|
+
*/
|
|
48
|
+
export function buildSettingsDetail(tier, settings, settableKeys) {
|
|
49
|
+
const entries = Object.keys(settings).map((key) => ({
|
|
50
|
+
key,
|
|
51
|
+
label: key,
|
|
52
|
+
value: scalarStr(settings[key]),
|
|
53
|
+
format: typeof settings[key] === "boolean" ? "boolean" : "text",
|
|
54
|
+
}));
|
|
55
|
+
const groups = [];
|
|
56
|
+
groups.push({
|
|
57
|
+
label: "Settings",
|
|
58
|
+
entries: entries.length > 0
|
|
59
|
+
? entries
|
|
60
|
+
: [{ key: "_empty", label: "Settings", value: "no settings returned" }],
|
|
61
|
+
});
|
|
62
|
+
groups.push({
|
|
63
|
+
// IA-10 (W3.9): actionable next steps in a dedicated group.
|
|
64
|
+
label: "Next steps",
|
|
65
|
+
entries: [
|
|
66
|
+
{
|
|
67
|
+
key: "settable_keys",
|
|
68
|
+
label: "Settable keys",
|
|
69
|
+
value: settableKeys.join(", "),
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
key: "update",
|
|
73
|
+
label: "Update",
|
|
74
|
+
value: "apimapper_settings_update({ patch: { … } }) — only the settable keys above are honored",
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
});
|
|
78
|
+
return detailResult({
|
|
79
|
+
title: "API Mapper Settings",
|
|
80
|
+
subtitle: tier ? `License tier: ${tier}` : undefined,
|
|
81
|
+
badge: tier
|
|
82
|
+
? { text: `tier: ${tier}`, variant: "info" }
|
|
83
|
+
: { text: "settings", variant: "secondary" },
|
|
84
|
+
groups,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Build a structured detail view for features_get.
|
|
89
|
+
*
|
|
90
|
+
* The feature dict mixes booleans (jmespath: true) and numeric limits
|
|
91
|
+
* (max_connections: -1) — each key becomes a detail entry. The active tier
|
|
92
|
+
* is the badge; a single IA-10 "Next steps" group points at the license
|
|
93
|
+
* tools for upgrading a gated feature.
|
|
94
|
+
*/
|
|
95
|
+
export function buildFeaturesDetail(tier, features) {
|
|
96
|
+
const keys = Object.keys(features);
|
|
97
|
+
const entries = keys.map((key) => ({
|
|
98
|
+
key,
|
|
99
|
+
label: key,
|
|
100
|
+
value: scalarStr(features[key]),
|
|
101
|
+
format: typeof features[key] === "boolean" ? "boolean" : "text",
|
|
102
|
+
}));
|
|
103
|
+
const groups = [];
|
|
104
|
+
groups.push({
|
|
105
|
+
label: "Features",
|
|
106
|
+
entries: entries.length > 0
|
|
107
|
+
? entries
|
|
108
|
+
: [{ key: "_empty", label: "Features", value: "no features returned" }],
|
|
109
|
+
});
|
|
110
|
+
groups.push({
|
|
111
|
+
label: "Next steps",
|
|
112
|
+
entries: [
|
|
113
|
+
{
|
|
114
|
+
key: "feature_count",
|
|
115
|
+
label: "Feature count",
|
|
116
|
+
value: keys.length,
|
|
117
|
+
format: "text",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
key: "upgrade",
|
|
121
|
+
label: "Upgrade",
|
|
122
|
+
value: "A gated feature unlocks with a higher tier — apimapper_license_status to check the current license, apimapper_license_activate to apply a new key.",
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
});
|
|
126
|
+
return detailResult({
|
|
127
|
+
title: "License-Gated Features",
|
|
128
|
+
subtitle: tier ? `License tier: ${tier}` : undefined,
|
|
129
|
+
badge: tier
|
|
130
|
+
? { text: `tier: ${tier}`, variant: "info" }
|
|
131
|
+
: { text: "features", variant: "secondary" },
|
|
132
|
+
groups,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=settings-format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-format.js","sourceRoot":"","sources":["../../../src/modules/apimapper/settings-format.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function registerSettingsTools(server:
|
|
1
|
+
import type { ToolRegistrar } from "./gateway/capturing-server.js";
|
|
2
|
+
export declare function registerSettingsTools(server: ToolRegistrar): void;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { formatResult,
|
|
3
|
-
import { request
|
|
2
|
+
import { formatResult, tableResult, readOnly, mutating, destructive, } from "@getimo/mcp-toolkit";
|
|
3
|
+
import { request } from "./client.js";
|
|
4
|
+
import { restErrorResult } from "./tool-result.js";
|
|
5
|
+
import { toRows } from "./types.js";
|
|
6
|
+
import { HEALTH_WARNINGS_COLUMNS, HEALTH_WARNINGS_NEXT_STEPS, mapHealthWarningRow, buildSettingsDetail, buildFeaturesDetail, } from "./settings-format.js";
|
|
4
7
|
// SettingsHandler::sanitizeSettingsData (core/src/Admin/Handler/SettingsHandler.php)
|
|
5
8
|
// pins the canonical allow-list. Keep this in sync with that PHP constant.
|
|
6
9
|
const SETTABLE_KEYS = [
|
|
@@ -12,6 +15,53 @@ const SETTABLE_KEYS = [
|
|
|
12
15
|
"delete_data_on_uninstall",
|
|
13
16
|
"error_reporting",
|
|
14
17
|
];
|
|
18
|
+
// F-18 (W1.11): Strict patch schema — typed per-key, .strict() rejects unknown
|
|
19
|
+
// keys at the Zod boundary so callers see a clear error instead of having
|
|
20
|
+
// keys dropped silently by the server. PHP server-side limits api_timeout to
|
|
21
|
+
// 1..120 (SettingsHandler.php) — surfaced here as int >=1 (upper-bound coerce
|
|
22
|
+
// stays server-side so we don't fail closed if PHP ever widens the cap).
|
|
23
|
+
// log_level intentionally `z.string()` (not enum): PHP accepts any string and
|
|
24
|
+
// existing wire fixtures use values like "warning"/"warn" interchangeably.
|
|
25
|
+
const settingsPatchSchema = z
|
|
26
|
+
.object({
|
|
27
|
+
cache_ttl: z
|
|
28
|
+
.number()
|
|
29
|
+
.int()
|
|
30
|
+
.min(0)
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("Default cache lifetime for connection responses, in seconds (e.g. 3600). 0 disables caching."),
|
|
33
|
+
debug_mode: z
|
|
34
|
+
.boolean()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe("Admin-UI debug mode: surfaces verbose diagnostics in the API Mapper admin screens."),
|
|
37
|
+
log_level: z
|
|
38
|
+
.string()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe('Server log verbosity (e.g. "warning", "info", "debug"). Free-form string — PHP accepts any value.'),
|
|
41
|
+
api_timeout: z
|
|
42
|
+
.number()
|
|
43
|
+
.int()
|
|
44
|
+
.min(1)
|
|
45
|
+
.optional()
|
|
46
|
+
.describe("Upstream HTTP request timeout in seconds (e.g. 30). Server clamps to 1..120."),
|
|
47
|
+
server_debug_mode: z
|
|
48
|
+
.boolean()
|
|
49
|
+
.optional()
|
|
50
|
+
.describe("Server-side debug logging: writes detailed request/response traces to the PHP error log."),
|
|
51
|
+
delete_data_on_uninstall: z
|
|
52
|
+
.boolean()
|
|
53
|
+
.optional()
|
|
54
|
+
.describe("When true, removing the plugin also deletes all API Mapper data (connections, flows, credentials)."),
|
|
55
|
+
error_reporting: z
|
|
56
|
+
.boolean()
|
|
57
|
+
.optional()
|
|
58
|
+
.describe("Opt-in anonymized error reporting (Sentry) for the plugin."),
|
|
59
|
+
})
|
|
60
|
+
.strict()
|
|
61
|
+
.describe("Settings patch (strict allow-list). Unknown keys rejected at schema level. " +
|
|
62
|
+
"Known SETTABLE_KEYS: " +
|
|
63
|
+
SETTABLE_KEYS.join(", ") +
|
|
64
|
+
". Provide any subset; only changed keys are sent.");
|
|
15
65
|
export function registerSettingsTools(server) {
|
|
16
66
|
// ── apimapper_settings_get ─────────────────────────────────────────
|
|
17
67
|
// F-A6-09: PHP returns `{success, settings, tier}`. Surface tier + settings
|
|
@@ -23,20 +73,19 @@ export function registerSettingsTools(server) {
|
|
|
23
73
|
"server_debug_mode, delete_data_on_uninstall, error_reporting) plus the active license tier." +
|
|
24
74
|
"\n\nExample:\n apimapper_settings_get({})",
|
|
25
75
|
inputSchema: {},
|
|
26
|
-
annotations: readOnly(),
|
|
76
|
+
annotations: readOnly({ title: "Get Settings", openWorld: true }),
|
|
27
77
|
}, async () => {
|
|
28
78
|
const r = await request("/settings");
|
|
29
79
|
if (!r.success) {
|
|
30
|
-
return
|
|
80
|
+
return restErrorResult(r, {}, { message: "settings get failed" });
|
|
31
81
|
}
|
|
32
82
|
const settings = (r.data?.settings && typeof r.data.settings === "object")
|
|
33
83
|
? r.data.settings
|
|
34
84
|
: {};
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}, false, { maxChars: 4000 });
|
|
85
|
+
// W3.1 — detailResult: grouped key-value detail for the Rich Card. The
|
|
86
|
+
// settings dict is a flat scalar map; IA-10 carries the settable-keys
|
|
87
|
+
// affordance + the settings_update follow-up in a "Next steps" group.
|
|
88
|
+
return buildSettingsDetail(r.data?.tier, settings, SETTABLE_KEYS);
|
|
40
89
|
});
|
|
41
90
|
// ── apimapper_settings_update ──────────────────────────────────────
|
|
42
91
|
// F-A6-10: Real allow-list is SETTABLE_KEYS above; telemetry_enabled +
|
|
@@ -49,22 +98,17 @@ export function registerSettingsTools(server) {
|
|
|
49
98
|
"Use apimapper_settings_get to inspect the current full set." +
|
|
50
99
|
"\n\nExample:\n apimapper_settings_update({ patch: { cache_ttl: 600, debug_mode: true } })",
|
|
51
100
|
inputSchema: {
|
|
52
|
-
patch:
|
|
101
|
+
patch: settingsPatchSchema,
|
|
53
102
|
},
|
|
54
|
-
annotations: mutating(),
|
|
103
|
+
annotations: mutating({ title: "Update Settings", openWorld: true }),
|
|
55
104
|
}, async ({ patch }) => {
|
|
105
|
+
const requestedKeys = Object.keys(patch);
|
|
56
106
|
const r = await request("/settings", {
|
|
57
107
|
method: "POST",
|
|
58
108
|
body: JSON.stringify(patch),
|
|
59
109
|
});
|
|
60
110
|
if (!r.success) {
|
|
61
|
-
return
|
|
62
|
-
error: r.error,
|
|
63
|
-
status: r.status,
|
|
64
|
-
errorCode: r.errorCode,
|
|
65
|
-
context: { keys: Object.keys(patch) },
|
|
66
|
-
hint: hintFor(r.errorCode),
|
|
67
|
-
}, true);
|
|
111
|
+
return restErrorResult(r, { keys: requestedKeys }, { message: "settings update failed" });
|
|
68
112
|
}
|
|
69
113
|
// PHP returns the post-update sanitised settings dict; surface what was
|
|
70
114
|
// actually applied (not what was requested), so the caller can spot
|
|
@@ -72,10 +116,17 @@ export function registerSettingsTools(server) {
|
|
|
72
116
|
const appliedSettings = (r.data?.settings && typeof r.data.settings === "object")
|
|
73
117
|
? r.data.settings
|
|
74
118
|
: undefined;
|
|
119
|
+
// F-18 (W1.11): compute server-side dropped keys. With .strict() unknown
|
|
120
|
+
// keys never reach here, but the server can still drop keys (e.g. a
|
|
121
|
+
// tier-gated value gets sanitised away). dropped_keys only surfaces when
|
|
122
|
+
// non-empty so the success envelope stays clean.
|
|
123
|
+
const appliedKeys = appliedSettings ? Object.keys(appliedSettings) : [];
|
|
124
|
+
const droppedKeys = requestedKeys.filter((k) => !appliedKeys.includes(k));
|
|
75
125
|
return formatResult({
|
|
76
126
|
updated: true,
|
|
77
|
-
requested_keys:
|
|
127
|
+
requested_keys: requestedKeys,
|
|
78
128
|
applied_settings: appliedSettings,
|
|
129
|
+
...(droppedKeys.length > 0 ? { dropped_keys: droppedKeys } : {}),
|
|
79
130
|
}, false, { maxChars: 2000 });
|
|
80
131
|
});
|
|
81
132
|
// ── apimapper_settings_reset_demo ──────────────────────────────────
|
|
@@ -92,7 +143,7 @@ export function registerSettingsTools(server) {
|
|
|
92
143
|
.default(false)
|
|
93
144
|
.describe("Must be true to execute. Ask user for confirmation first."),
|
|
94
145
|
},
|
|
95
|
-
annotations: destructive(),
|
|
146
|
+
annotations: destructive({ title: "Reset Demo Settings", openWorld: true }),
|
|
96
147
|
}, async ({ confirm }) => {
|
|
97
148
|
if (!confirm) {
|
|
98
149
|
return formatResult({
|
|
@@ -104,7 +155,7 @@ export function registerSettingsTools(server) {
|
|
|
104
155
|
}
|
|
105
156
|
const r = await request("/settings/reset-demo", { method: "POST" });
|
|
106
157
|
if (!r.success) {
|
|
107
|
-
return
|
|
158
|
+
return restErrorResult(r, {}, { message: "demo reset failed" });
|
|
108
159
|
}
|
|
109
160
|
return formatResult({ reset: true, result: r.data?.result }, false, { maxChars: 2000 });
|
|
110
161
|
});
|
|
@@ -116,29 +167,39 @@ export function registerSettingsTools(server) {
|
|
|
116
167
|
"(e.g., 'max_connections: 1'); read each key by its expected type." +
|
|
117
168
|
"\n\nExample:\n apimapper_features_get({})",
|
|
118
169
|
inputSchema: {},
|
|
119
|
-
annotations: readOnly(),
|
|
170
|
+
annotations: readOnly({ title: "Get Feature Flags", openWorld: true }),
|
|
120
171
|
}, async () => {
|
|
121
172
|
const r = await request("/features");
|
|
122
173
|
if (!r.success) {
|
|
123
|
-
return
|
|
174
|
+
return restErrorResult(r, {}, { message: "features get failed" });
|
|
124
175
|
}
|
|
125
|
-
const features = r.data?.features
|
|
126
|
-
|
|
127
|
-
|
|
176
|
+
const features = (r.data?.features && typeof r.data.features === "object")
|
|
177
|
+
? r.data.features
|
|
178
|
+
: {};
|
|
179
|
+
// W3.1 — detailResult: the feature dict mixes booleans + numeric limits;
|
|
180
|
+
// each key becomes a scalar detail entry. IA-10 "Next steps" group
|
|
181
|
+
// points at the license tools for unlocking a gated feature.
|
|
182
|
+
return buildFeaturesDetail(r.data?.tier, features);
|
|
128
183
|
});
|
|
129
184
|
// ── apimapper_platform_parity ──────────────────────────────────────
|
|
130
185
|
// F-A6-02: PHP PlatformParityHandler returns `{matrix, summary, gaps}` —
|
|
131
186
|
// `wordpress`/`joomla` are nested inside `matrix`, not top-level.
|
|
132
187
|
server.registerTool("apimapper_platform_parity", {
|
|
133
188
|
title: "Get Platform Parity Status",
|
|
134
|
-
description: "Compare feature parity between WordPress and Joomla
|
|
189
|
+
description: "Compare feature parity between the WordPress and Joomla builds of API " +
|
|
190
|
+
"Mapper and report any gaps. Use before promising a feature works on the " +
|
|
191
|
+
"user's platform, or when a flow behaves differently on WP vs Joomla. " +
|
|
192
|
+
"Returns a matrix (per-feature WP/Joomla support), a summary, and a gaps list. " +
|
|
193
|
+
"Keywords: parity, WordPress vs Joomla, platform differences, feature gaps, cross-platform. " +
|
|
194
|
+
"When NOT to use: for connectivity/auth checks use apimapper_health; for the " +
|
|
195
|
+
"feature-flag matrix of the current license tier use apimapper_features_get." +
|
|
135
196
|
"\n\nExample:\n apimapper_platform_parity({})",
|
|
136
197
|
inputSchema: {},
|
|
137
|
-
annotations: readOnly(),
|
|
198
|
+
annotations: readOnly({ title: "Check Platform Parity", openWorld: true }),
|
|
138
199
|
}, async () => {
|
|
139
200
|
const r = await request("/platform-parity");
|
|
140
201
|
if (!r.success) {
|
|
141
|
-
return
|
|
202
|
+
return restErrorResult(r, {}, { message: "platform parity failed" });
|
|
142
203
|
}
|
|
143
204
|
const gaps = Array.isArray(r.data?.gaps) ? r.data.gaps : [];
|
|
144
205
|
return formatResult({
|
|
@@ -156,24 +217,21 @@ export function registerSettingsTools(server) {
|
|
|
156
217
|
description: "List active admin health-warnings (banners shown in the Admin UI)." +
|
|
157
218
|
"\n\nExample:\n apimapper_health_warnings_list({})",
|
|
158
219
|
inputSchema: {},
|
|
159
|
-
annotations: readOnly(),
|
|
220
|
+
annotations: readOnly({ title: "List Health Warnings", openWorld: true }),
|
|
160
221
|
}, async () => {
|
|
161
222
|
const r = await request("/admin/health-warnings");
|
|
162
223
|
if (!r.success) {
|
|
163
|
-
return
|
|
224
|
+
return restErrorResult(r, {}, { message: "health warnings list failed" });
|
|
164
225
|
}
|
|
165
226
|
const items = Array.isArray(r.data?.items) ? r.data.items : [];
|
|
166
227
|
const visible = Boolean(r.data?.visible);
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
{ key: "credentialId", label: "CREDENTIAL_ID", width: 32 },
|
|
173
|
-
{ key: "type", label: "TYPE", width: 28 },
|
|
174
|
-
],
|
|
228
|
+
// W3.1 — tableResult: ASCII table for the LLM + typed DataTable payload
|
|
229
|
+
// for the Rich Card. IA-10: the footer carries the next-step guidance.
|
|
230
|
+
return tableResult(toRows(items), {
|
|
231
|
+
columns: HEALTH_WARNINGS_COLUMNS,
|
|
232
|
+
map: mapHealthWarningRow,
|
|
175
233
|
header: (n) => `${n} active warnings${visible ? "" : " (banner dismissed)"}`,
|
|
176
|
-
footer:
|
|
234
|
+
footer: HEALTH_WARNINGS_NEXT_STEPS,
|
|
177
235
|
});
|
|
178
236
|
});
|
|
179
237
|
// ── apimapper_health_warnings_dismiss ──────────────────────────────
|
|
@@ -184,14 +242,14 @@ export function registerSettingsTools(server) {
|
|
|
184
242
|
inputSchema: {
|
|
185
243
|
id: z.string().describe("Warning ID. Use apimapper_health_warnings_list to find."),
|
|
186
244
|
},
|
|
187
|
-
annotations: mutating(),
|
|
245
|
+
annotations: mutating({ title: "Dismiss Health Warning", openWorld: true }),
|
|
188
246
|
}, async ({ id }) => {
|
|
189
247
|
const r = await request("/admin/health-warnings/dismiss", {
|
|
190
248
|
method: "POST",
|
|
191
249
|
body: JSON.stringify({ id }),
|
|
192
250
|
});
|
|
193
251
|
if (!r.success) {
|
|
194
|
-
return
|
|
252
|
+
return restErrorResult(r, { id }, { message: "warning dismiss failed" });
|
|
195
253
|
}
|
|
196
254
|
return formatResult({ dismissed: true, id }, false, { maxChars: 1500 });
|
|
197
255
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/modules/apimapper/settings.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/modules/apimapper/settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { SitesRegistry } from "../../sites/loader.js";
|
|
3
|
+
import type { SiteEntryT } from "../../sites/schema.js";
|
|
4
|
+
interface ToolRegistrar {
|
|
5
|
+
registerTool(name: string, config: unknown, handler: unknown): void;
|
|
6
|
+
}
|
|
7
|
+
export interface SitesIdentityProbeResult {
|
|
8
|
+
plugin_version: string;
|
|
9
|
+
plugin_hash: string;
|
|
10
|
+
capabilities: string[];
|
|
11
|
+
site_url: string;
|
|
12
|
+
}
|
|
13
|
+
/** Identity probe for the active site. Injected so tests can stub the network. */
|
|
14
|
+
export type SitesProbeIdentityFn = (entry: SiteEntryT) => Promise<SitesIdentityProbeResult>;
|
|
15
|
+
export interface SitesListProfilesDeps {
|
|
16
|
+
getRegistry: () => SitesRegistry;
|
|
17
|
+
/** The active site_id pointer, or null when none set (default entry active). */
|
|
18
|
+
getActiveSiteId: () => string | null;
|
|
19
|
+
}
|
|
20
|
+
export declare function registerSitesListProfilesTool(server: ToolRegistrar | McpServer, deps: SitesListProfilesDeps): void;
|
|
21
|
+
export interface SitesUseProfileDeps {
|
|
22
|
+
getRegistry: () => SitesRegistry;
|
|
23
|
+
/** Flip the client's active-site pointer (resets resolution → retargets). */
|
|
24
|
+
setActiveSite: (id: string) => void;
|
|
25
|
+
/** Identity probe. Defaults to a real /identity call on the active site. */
|
|
26
|
+
probeIdentity?: SitesProbeIdentityFn;
|
|
27
|
+
}
|
|
28
|
+
export declare function registerSitesUseProfileTool(server: ToolRegistrar | McpServer, deps: SitesUseProfileDeps): void;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// src/modules/apimapper/sites-tools.ts — Phase 3.
|
|
2
|
+
//
|
|
3
|
+
// Sites-file-backed implementations of the profile tools. When a sites-file is
|
|
4
|
+
// active (APIMAPPER_SITES_FILE set + non-empty), index.ts wires THESE registrars
|
|
5
|
+
// under the canonical tool names (apimapper_list_profiles / apimapper_use_profile)
|
|
6
|
+
// instead of the keychain ProfileStore versions in use-profile.ts. The tool
|
|
7
|
+
// names + response shapes stay identical so the agent surface is unchanged —
|
|
8
|
+
// only the backing store differs (sites-file entries vs keychain profiles).
|
|
9
|
+
//
|
|
10
|
+
// `apimapper_use_profile(name)` calls `setActiveSite(name)` on the client, which
|
|
11
|
+
// resets the resolution memo so the NEXT request() retargets the chosen site.
|
|
12
|
+
// `setActiveSite` runs BEFORE the optional identity probe so the probe hits the
|
|
13
|
+
// newly-activated site.
|
|
14
|
+
import { z } from "zod";
|
|
15
|
+
import { formatResult, mutating, readOnly } from "@getimo/mcp-toolkit";
|
|
16
|
+
import { request } from "./client.js";
|
|
17
|
+
export function registerSitesListProfilesTool(server, deps) {
|
|
18
|
+
const registrar = server;
|
|
19
|
+
registrar.registerTool("apimapper_list_profiles", {
|
|
20
|
+
title: "List Configured Profiles",
|
|
21
|
+
description: "List all configured site profiles (name, siteUrl, platform) with an " +
|
|
22
|
+
"is_active flag indicating which one is currently active. " +
|
|
23
|
+
"Backed by your sites-file (APIMAPPER_SITES_FILE). " +
|
|
24
|
+
"Use this to discover available profile names before calling " +
|
|
25
|
+
"apimapper_use_profile to switch the active site. " +
|
|
26
|
+
"Read-only — does not contact any site." +
|
|
27
|
+
"\n\nResponse shape:\n" +
|
|
28
|
+
" { profile_count, active_profile, profiles: [{ name, siteUrl, platform, is_active }] }",
|
|
29
|
+
inputSchema: {},
|
|
30
|
+
annotations: readOnly({ title: "List Configured Profiles", openWorld: false }),
|
|
31
|
+
}, async () => {
|
|
32
|
+
const reg = deps.getRegistry();
|
|
33
|
+
const active = deps.getActiveSiteId();
|
|
34
|
+
// When no explicit pointer is set, the default entry is the active one.
|
|
35
|
+
const activeName = active ?? reg.getDefault().site_id;
|
|
36
|
+
const profiles = reg.list().map((entry) => ({
|
|
37
|
+
name: entry.site_id,
|
|
38
|
+
siteUrl: entry.url,
|
|
39
|
+
platform: entry.platform,
|
|
40
|
+
is_active: entry.site_id === activeName,
|
|
41
|
+
}));
|
|
42
|
+
return formatResult({
|
|
43
|
+
profile_count: profiles.length,
|
|
44
|
+
active_profile: activeName,
|
|
45
|
+
source: "sites-file",
|
|
46
|
+
profiles,
|
|
47
|
+
}, false, { maxChars: 3000 });
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Default probe: switch already happened (setActiveSite ran first), so the
|
|
52
|
+
* legacy `request("identity")` now resolves to the freshly-activated site.
|
|
53
|
+
*/
|
|
54
|
+
async function defaultSitesProbeIdentity(_entry) {
|
|
55
|
+
const r = await request("/identity");
|
|
56
|
+
if (!r.success) {
|
|
57
|
+
throw new Error(r.error ?? "identity probe failed");
|
|
58
|
+
}
|
|
59
|
+
return normaliseIdentity(r.data);
|
|
60
|
+
}
|
|
61
|
+
function normaliseIdentity(data) {
|
|
62
|
+
if (!data || typeof data !== "object") {
|
|
63
|
+
throw new Error("identity response missing object body");
|
|
64
|
+
}
|
|
65
|
+
const o = data;
|
|
66
|
+
const plugin_version = typeof o.plugin_version === "string" ? o.plugin_version : "";
|
|
67
|
+
const plugin_hash = typeof o.plugin_hash === "string" ? o.plugin_hash : "";
|
|
68
|
+
const site_url = (typeof o.site_url === "string" && o.site_url) ||
|
|
69
|
+
(typeof o.siteurl === "string" && o.siteurl) ||
|
|
70
|
+
"";
|
|
71
|
+
const caps = Array.isArray(o.capabilities)
|
|
72
|
+
? o.capabilities.filter((c) => typeof c === "string")
|
|
73
|
+
: [];
|
|
74
|
+
if (!plugin_version || !plugin_hash) {
|
|
75
|
+
throw new Error("identity response missing required fields");
|
|
76
|
+
}
|
|
77
|
+
return { plugin_version, plugin_hash, site_url, capabilities: caps };
|
|
78
|
+
}
|
|
79
|
+
export function registerSitesUseProfileTool(server, deps) {
|
|
80
|
+
const probe = deps.probeIdentity ?? defaultSitesProbeIdentity;
|
|
81
|
+
const registrar = server;
|
|
82
|
+
registrar.registerTool("apimapper_use_profile", {
|
|
83
|
+
title: "Switch Active Profile",
|
|
84
|
+
description: "Activate a configured site (from your sites-file) and probe its identity " +
|
|
85
|
+
"endpoint to confirm the site is reachable and the plugin is installed. " +
|
|
86
|
+
"Switching retargets every subsequent tool call at the chosen site. " +
|
|
87
|
+
"Use `noProbe: true` to skip the network probe for offline activation." +
|
|
88
|
+
"\n\nExample:\n apimapper_use_profile({ name: 'prod', noProbe: false })",
|
|
89
|
+
inputSchema: {
|
|
90
|
+
name: z
|
|
91
|
+
.string()
|
|
92
|
+
.min(1)
|
|
93
|
+
.describe('Site_id to activate (e.g., "dev", "client-x-prod"). Use apimapper_list_profiles to discover.'),
|
|
94
|
+
noProbe: z
|
|
95
|
+
.boolean()
|
|
96
|
+
.default(false)
|
|
97
|
+
.describe("Skip the live /identity probe. Use for offline activation when the site is unreachable."),
|
|
98
|
+
},
|
|
99
|
+
// Mutating: flips the active-site pointer (changes which backend every
|
|
100
|
+
// subsequent request targets). Closed-world — bounded to the local
|
|
101
|
+
// sites-file selection + an internal /identity call.
|
|
102
|
+
annotations: mutating({ title: "Switch Active Profile", openWorld: false }),
|
|
103
|
+
}, async (args) => {
|
|
104
|
+
const { name, noProbe = false } = args;
|
|
105
|
+
const reg = deps.getRegistry();
|
|
106
|
+
const entry = reg.get(name);
|
|
107
|
+
if (!entry) {
|
|
108
|
+
return formatResult({
|
|
109
|
+
error: `Site "${name}" not found in sites-file`,
|
|
110
|
+
context: { name, known: reg.listIds() },
|
|
111
|
+
hint: "Use apimapper_list_profiles to see configured sites.",
|
|
112
|
+
}, true);
|
|
113
|
+
}
|
|
114
|
+
// Switch FIRST so the (default) identity probe targets the new site.
|
|
115
|
+
try {
|
|
116
|
+
deps.setActiveSite(name);
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
120
|
+
return formatResult({
|
|
121
|
+
error: `Failed to activate site "${name}": ${msg}`,
|
|
122
|
+
context: { name },
|
|
123
|
+
hint: "Verify APIMAPPER_SITES_FILE is set and the site_id exists.",
|
|
124
|
+
}, true);
|
|
125
|
+
}
|
|
126
|
+
if (noProbe) {
|
|
127
|
+
return formatResult({
|
|
128
|
+
activated: true,
|
|
129
|
+
profile: { name: entry.site_id, siteUrl: entry.url, platform: entry.platform },
|
|
130
|
+
noProbe: true,
|
|
131
|
+
source: "sites-file",
|
|
132
|
+
warnings: [
|
|
133
|
+
"Identity probe skipped (noProbe=true). Plugin reachability not verified.",
|
|
134
|
+
],
|
|
135
|
+
}, false, { maxChars: 2500 });
|
|
136
|
+
}
|
|
137
|
+
let identity;
|
|
138
|
+
try {
|
|
139
|
+
identity = await probe(entry);
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
143
|
+
return formatResult({
|
|
144
|
+
// The switch already happened; surface that the probe (not the
|
|
145
|
+
// switch) failed so the agent knows the active site DID change.
|
|
146
|
+
error: `Site "${name}" activated, but identity probe failed: ${msg}`,
|
|
147
|
+
context: { name, siteUrl: entry.url, platform: entry.platform },
|
|
148
|
+
hint: "Verify the site is reachable and the plugin is installed/active. " +
|
|
149
|
+
"Re-run with `noProbe: true` to activate without probing.",
|
|
150
|
+
}, true);
|
|
151
|
+
}
|
|
152
|
+
return formatResult({
|
|
153
|
+
activated: true,
|
|
154
|
+
profile: { name: entry.site_id, siteUrl: entry.url, platform: entry.platform },
|
|
155
|
+
source: "sites-file",
|
|
156
|
+
identity: {
|
|
157
|
+
plugin_version: identity.plugin_version,
|
|
158
|
+
plugin_hash: identity.plugin_hash,
|
|
159
|
+
capabilities: identity.capabilities,
|
|
160
|
+
site_url: identity.site_url,
|
|
161
|
+
},
|
|
162
|
+
}, false, { maxChars: 3000 });
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=sites-tools.js.map
|