@wootsup/mcp 0.1.0-rc.1 → 0.1.0-rc.11
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/README.md +10 -39
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/modules/apimapper/cache.js +63 -33
- package/dist/modules/apimapper/cache.js.map +1 -1
- package/dist/modules/apimapper/client.d.ts +10 -1
- package/dist/modules/apimapper/client.js +51 -11
- package/dist/modules/apimapper/client.js.map +1 -1
- package/dist/modules/apimapper/connections.js +110 -34
- package/dist/modules/apimapper/connections.js.map +1 -1
- package/dist/modules/apimapper/credentials.js +61 -10
- package/dist/modules/apimapper/credentials.js.map +1 -1
- package/dist/modules/apimapper/diagnose.js +7 -2
- package/dist/modules/apimapper/diagnose.js.map +1 -1
- package/dist/modules/apimapper/envelope.d.ts +12 -0
- package/dist/modules/apimapper/envelope.js +28 -0
- package/dist/modules/apimapper/envelope.js.map +1 -0
- package/dist/modules/apimapper/flows.js +82 -42
- package/dist/modules/apimapper/flows.js.map +1 -1
- package/dist/modules/apimapper/graph.js +23 -23
- package/dist/modules/apimapper/graph.js.map +1 -1
- package/dist/modules/apimapper/index.js +13 -1
- package/dist/modules/apimapper/index.js.map +1 -1
- package/dist/modules/apimapper/library.js +154 -17
- package/dist/modules/apimapper/library.js.map +1 -1
- package/dist/modules/apimapper/license.d.ts +23 -0
- package/dist/modules/apimapper/license.js +38 -10
- package/dist/modules/apimapper/license.js.map +1 -1
- package/dist/modules/apimapper/local-sources.js +24 -7
- package/dist/modules/apimapper/local-sources.js.map +1 -1
- package/dist/modules/apimapper/misc.js +55 -37
- package/dist/modules/apimapper/misc.js.map +1 -1
- package/dist/modules/apimapper/onboarding.d.ts +21 -0
- package/dist/modules/apimapper/onboarding.js +81 -6
- package/dist/modules/apimapper/onboarding.js.map +1 -1
- package/dist/modules/apimapper/read-cache.d.ts +44 -0
- package/dist/modules/apimapper/read-cache.js +165 -0
- package/dist/modules/apimapper/read-cache.js.map +1 -0
- package/dist/modules/apimapper/schema.js +68 -30
- package/dist/modules/apimapper/schema.js.map +1 -1
- package/dist/modules/apimapper/settings.js +64 -22
- package/dist/modules/apimapper/settings.js.map +1 -1
- package/dist/modules/apimapper/skill-resources.js +24 -5
- package/dist/modules/apimapper/skill-resources.js.map +1 -1
- package/dist/modules/apimapper/use-profile.js +5 -1
- package/dist/modules/apimapper/use-profile.js.map +1 -1
- package/dist/modules/apimapper/workflows.js +23 -7
- package/dist/modules/apimapper/workflows.js.map +1 -1
- package/dist/setup/write-config.d.ts +12 -2
- package/dist/setup/write-config.js +31 -4
- package/dist/setup/write-config.js.map +1 -1
- package/dist/setup-cli.d.ts +3 -3
- package/dist/setup-cli.js +26 -6
- package/dist/setup-cli.js.map +1 -1
- package/dist/skill-instructions.d.ts +10 -0
- package/dist/skill-instructions.js +29 -4
- package/dist/skill-instructions.js.map +1 -1
- package/manifest.json +1 -1
- package/package.json +4 -3
|
@@ -3,55 +3,61 @@ import { formatResult, autoFormatTable, readOnly, creating } from "@getimo/mcp-t
|
|
|
3
3
|
import { request, hintFor } from "./client.js";
|
|
4
4
|
export function registerMiscTools(server) {
|
|
5
5
|
// ── apimapper_release_list ─────────────────────────────────────────
|
|
6
|
+
// F-A6-03: PHP ReleaseHandler returns `{success, current_version, releases}`.
|
|
7
|
+
// Releases shape: `{version, date, changelog, has_breaking_changes}` (NO
|
|
8
|
+
// `channel` filter is honored server-side; NO `notes_url` field exists).
|
|
6
9
|
server.registerTool("apimapper_release_list", {
|
|
7
10
|
title: "List Available Releases",
|
|
8
|
-
description: "List API Mapper plugin releases available for download." +
|
|
9
|
-
"
|
|
11
|
+
description: "List API Mapper plugin releases available for download. " +
|
|
12
|
+
"Returns version, release date, and breaking-changes flag per row." +
|
|
13
|
+
"\n\nExample:\n apimapper_release_list({ limit: 5 })",
|
|
10
14
|
inputSchema: {
|
|
11
|
-
channel: z
|
|
12
|
-
.enum(["stable", "beta", "all"])
|
|
13
|
-
.default("stable")
|
|
14
|
-
.describe("Release channel filter"),
|
|
15
15
|
limit: z.number().min(1).max(50).default(10).describe("Max items (1-50)"),
|
|
16
16
|
},
|
|
17
17
|
annotations: readOnly(),
|
|
18
|
-
}, async ({
|
|
19
|
-
const
|
|
20
|
-
const r = await request(`/releases?${params.toString()}`);
|
|
18
|
+
}, async ({ limit }) => {
|
|
19
|
+
const r = await request("/releases");
|
|
21
20
|
if (!r.success) {
|
|
22
21
|
return formatResult({
|
|
23
22
|
error: r.error,
|
|
24
23
|
status: r.status,
|
|
25
24
|
errorCode: r.errorCode,
|
|
26
|
-
context: {
|
|
25
|
+
context: { limit },
|
|
27
26
|
hint: hintFor(r.errorCode),
|
|
28
27
|
}, true);
|
|
29
28
|
}
|
|
30
|
-
const
|
|
29
|
+
const allReleases = Array.isArray(r.data?.releases) ? r.data.releases : [];
|
|
30
|
+
const releases = allReleases.slice(0, limit);
|
|
31
|
+
const currentVersion = r.data?.current_version ?? "?";
|
|
31
32
|
return autoFormatTable(releases.map((rel) => ({
|
|
32
|
-
version: rel.version,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
version: rel.version ?? "?",
|
|
34
|
+
date: rel.date ?? "—",
|
|
35
|
+
breaking: rel.has_breaking_changes ? "✓" : "✗",
|
|
36
|
+
is_current: rel.version === currentVersion ? "✓" : "",
|
|
36
37
|
})), {
|
|
37
38
|
columns: [
|
|
38
39
|
{ key: "version", label: "VERSION", width: 12 },
|
|
39
|
-
{ key: "channel", label: "CHANNEL", width: 10 },
|
|
40
40
|
{ key: "date", label: "DATE", width: 22 },
|
|
41
|
-
{ key: "
|
|
41
|
+
{ key: "breaking", label: "BREAKING", width: 8 },
|
|
42
|
+
{ key: "is_current", label: "CURRENT", width: 7 },
|
|
42
43
|
],
|
|
43
|
-
header: (n) => `${n} releases`,
|
|
44
|
-
footer: "Use apimapper_release_download to fetch a
|
|
44
|
+
header: (n) => `${n} releases (current=${currentVersion})`,
|
|
45
|
+
footer: "Use apimapper_release_download to fetch a download URL.",
|
|
45
46
|
});
|
|
46
47
|
});
|
|
47
48
|
// ── apimapper_release_download ─────────────────────────────────────
|
|
49
|
+
// F-A6-04: PHP ReleaseHandler::getDownloadUrl returns `{success, download_url}`.
|
|
50
|
+
// No `expires_at` field — the URL itself embeds the license key (signed).
|
|
48
51
|
server.registerTool("apimapper_release_download", {
|
|
49
52
|
title: "Get Release Download URL",
|
|
50
53
|
description: "Request a signed download URL for a release ZIP. Read-only operation server-side " +
|
|
51
54
|
"(generates a temporary signed URL — no state change)." +
|
|
52
|
-
"\n\nExample:\n apimapper_release_download({ version: '2.0.6' })",
|
|
55
|
+
"\n\nExample:\n apimapper_release_download({ version: '2.0.6', product: 'wordpress' })",
|
|
53
56
|
inputSchema: {
|
|
54
|
-
version: z
|
|
57
|
+
version: z
|
|
58
|
+
.string()
|
|
59
|
+
.regex(/^\d+\.\d+\.\d+$/, "Must be semver MAJOR.MINOR.PATCH")
|
|
60
|
+
.describe('Release version (e.g., "2.0.7")'),
|
|
55
61
|
product: z.enum(["wordpress", "joomla"]).describe("Product variant"),
|
|
56
62
|
},
|
|
57
63
|
annotations: creating(),
|
|
@@ -69,7 +75,11 @@ export function registerMiscTools(server) {
|
|
|
69
75
|
hint: hintFor(r.errorCode),
|
|
70
76
|
}, true);
|
|
71
77
|
}
|
|
72
|
-
|
|
78
|
+
// Defensive read: PHP currently returns flat `{success, download_url}`
|
|
79
|
+
// (post Wave 1B), but older shape wrapped under `data.download_url`.
|
|
80
|
+
// Tolerate either.
|
|
81
|
+
const downloadUrl = r.data?.data?.download_url ?? r.data?.download_url;
|
|
82
|
+
if (!downloadUrl) {
|
|
73
83
|
return formatResult({
|
|
74
84
|
error: "no download URL returned",
|
|
75
85
|
status: r.status,
|
|
@@ -78,16 +88,20 @@ export function registerMiscTools(server) {
|
|
|
78
88
|
}, true);
|
|
79
89
|
}
|
|
80
90
|
return formatResult({
|
|
81
|
-
download_url:
|
|
82
|
-
expires_at: r.data.expires_at,
|
|
91
|
+
download_url: downloadUrl,
|
|
83
92
|
version,
|
|
84
93
|
product,
|
|
85
94
|
}, false, { maxChars: 2000 });
|
|
86
95
|
});
|
|
87
96
|
// ── apimapper_brandfetch ───────────────────────────────────────────
|
|
97
|
+
// F-A6-05: PHP BrandfetchCache::getSVG returns `{svg, hash, domain}` — the
|
|
98
|
+
// field name is `svg` (NOT `logo_svg`/`logo_png`/`logo_hex` which were stale
|
|
99
|
+
// assumptions). Surface size + hash so the caller can decide whether to
|
|
100
|
+
// fetch the full SVG.
|
|
88
101
|
server.registerTool("apimapper_brandfetch", {
|
|
89
102
|
title: "Brandfetch Logo Proxy",
|
|
90
|
-
description: "Fetch a
|
|
103
|
+
description: "Fetch a sanitized SVG logo for a domain via the API Mapper proxy. Returns the SVG body, " +
|
|
104
|
+
"an SRI hash for subresource integrity, and the normalised domain." +
|
|
91
105
|
"\n\nExample:\n apimapper_brandfetch({ domain: 'pexels.com' })",
|
|
92
106
|
inputSchema: {
|
|
93
107
|
domain: z.string().describe('Domain (e.g., "calendly.com", "google.com")'),
|
|
@@ -98,21 +112,27 @@ export function registerMiscTools(server) {
|
|
|
98
112
|
if (!r.success) {
|
|
99
113
|
return formatResult({ error: r.error, status: r.status, errorCode: r.errorCode, context: { domain }, hint: hintFor(r.errorCode) }, true);
|
|
100
114
|
}
|
|
115
|
+
// Defensive read: tolerate both flat (Wave 1B) and wrapped (legacy) shapes.
|
|
116
|
+
const svg = r.data?.data?.svg ?? r.data?.svg;
|
|
117
|
+
const hash = r.data?.data?.hash ?? r.data?.hash;
|
|
118
|
+
const normalisedDomain = r.data?.data?.domain ?? r.data?.domain ?? domain;
|
|
101
119
|
return formatResult({
|
|
102
|
-
domain,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
has_png: Boolean(r.data?.logo_png),
|
|
107
|
-
logo_svg_size: r.data?.logo_svg?.length ?? 0,
|
|
120
|
+
domain: normalisedDomain,
|
|
121
|
+
has_svg: Boolean(svg),
|
|
122
|
+
svg_size: svg ? svg.length : 0,
|
|
123
|
+
hash,
|
|
108
124
|
}, false, { maxChars: 2000 });
|
|
109
125
|
});
|
|
110
126
|
// ── apimapper_feedback_submit ──────────────────────────────────────
|
|
127
|
+
// F-A6-13: PHP FeedbackController accepts `type`, `message`, and forwards
|
|
128
|
+
// optional `subject`/`email`/`attachments` straight into the Discord embed.
|
|
129
|
+
// Response is `{success: true}` only (no `queued`/`ticket_id` fields).
|
|
130
|
+
// `unwrapInnerSuccess: true` catches Discord-webhook failures (200+success:false).
|
|
111
131
|
server.registerTool("apimapper_feedback_submit", {
|
|
112
132
|
title: "Submit Feedback",
|
|
113
133
|
description: "Submit user feedback (bug report, feature request, support question) to the API Mapper team. " +
|
|
114
|
-
"Returns submitted:true ONLY when
|
|
115
|
-
"\n\nExample:\n apimapper_feedback_submit({
|
|
134
|
+
"Returns submitted:true ONLY when the Discord proxy confirms; 200 + success:false → structured error." +
|
|
135
|
+
"\n\nExample:\n apimapper_feedback_submit({ type: 'bug', subject: 'Schema misses nested fields', message: '...' })",
|
|
116
136
|
inputSchema: {
|
|
117
137
|
type: z.enum(["bug", "feature", "support", "other"]).describe("Feedback type"),
|
|
118
138
|
subject: z.string().min(1).describe("Subject (short)"),
|
|
@@ -134,15 +154,13 @@ export function registerMiscTools(server) {
|
|
|
134
154
|
payloadFailed: r.payloadFailed,
|
|
135
155
|
context: { type, subject_len: subject.length },
|
|
136
156
|
hint: r.payloadFailed
|
|
137
|
-
? "Server accepted the request but did not
|
|
157
|
+
? "Server accepted the request but the proxy did not deliver it. Reason in error field."
|
|
138
158
|
: hintFor(r.errorCode),
|
|
139
159
|
}, true);
|
|
140
160
|
}
|
|
141
|
-
// unwrapInnerSuccess already caught success:false, so here
|
|
161
|
+
// unwrapInnerSuccess already caught success:false, so here success is true.
|
|
142
162
|
return formatResult({
|
|
143
163
|
submitted: true,
|
|
144
|
-
queued: r.data?.queued ?? true,
|
|
145
|
-
ticket_id: r.data?.ticket_id,
|
|
146
164
|
}, false, { maxChars: 2000 });
|
|
147
165
|
});
|
|
148
166
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"misc.js","sourceRoot":"","sources":["../../../src/modules/apimapper/misc.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"misc.js","sourceRoot":"","sources":["../../../src/modules/apimapper/misc.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,13 @@ export interface OnboardingSubError {
|
|
|
13
13
|
export interface OnboardingReport {
|
|
14
14
|
site: {
|
|
15
15
|
wp_base: string;
|
|
16
|
+
/**
|
|
17
|
+
* rc.10 B (2026-05-19) — platform inferred from WP_BASE shape so the
|
|
18
|
+
* AI knows which surface it is talking to without a follow-up call.
|
|
19
|
+
*/
|
|
20
|
+
platform: "wordpress" | "joomla" | "unknown";
|
|
21
|
+
plugin_version?: string;
|
|
22
|
+
api_version?: string;
|
|
16
23
|
};
|
|
17
24
|
license: Partial<LicenseStatus> & {
|
|
18
25
|
available: boolean;
|
|
@@ -27,8 +34,22 @@ export interface OnboardingReport {
|
|
|
27
34
|
draft: number;
|
|
28
35
|
items: Array<Pick<Flow, "id" | "name" | "source" | "is_compiled" | "node_count">>;
|
|
29
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* rc.10 B (2026-05-19) — extended library brief so the AI sees the FULL
|
|
39
|
+
* catalog shape from a single onboarding call. Previously the report
|
|
40
|
+
* only included `popular[5]` which the AI mistook for the entire library,
|
|
41
|
+
* triggering 29× discovery-loop calls in the Maria-walkthrough logs.
|
|
42
|
+
*/
|
|
30
43
|
library: {
|
|
44
|
+
total_count: number;
|
|
45
|
+
categories: Array<{
|
|
46
|
+
id: string;
|
|
47
|
+
name: string;
|
|
48
|
+
count: number;
|
|
49
|
+
}>;
|
|
50
|
+
featured: Array<Pick<LibraryItem, "id" | "name" | "category">>;
|
|
31
51
|
popular: Array<Pick<LibraryItem, "id" | "name" | "category">>;
|
|
52
|
+
hint: string;
|
|
32
53
|
};
|
|
33
54
|
suggestions: OnboardingSuggestion[];
|
|
34
55
|
errors: OnboardingSubError[];
|
|
@@ -69,17 +69,40 @@ export function deriveSuggestions(args) {
|
|
|
69
69
|
}
|
|
70
70
|
return out;
|
|
71
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* rc.10 B (2026-05-19) — Infer the host platform from the configured
|
|
74
|
+
* WP_BASE URL. WordPress installs typically end in `/wp-json/...` or
|
|
75
|
+
* contain `/wordpress/`; Joomla installs expose `option=com_…` or
|
|
76
|
+
* `/administrator/`. We only return `unknown` when neither pattern
|
|
77
|
+
* matches — the AI then has explicit signal that something is off.
|
|
78
|
+
*/
|
|
79
|
+
function detectPlatform(baseUrl) {
|
|
80
|
+
const u = baseUrl.toLowerCase();
|
|
81
|
+
if (/\/wp-json|\/wordpress|wp\-content/.test(u) || /\bwordpress\b/.test(u)) {
|
|
82
|
+
return "wordpress";
|
|
83
|
+
}
|
|
84
|
+
if (/option=com_|\/administrator|\bjoomla\b/.test(u)) {
|
|
85
|
+
return "joomla";
|
|
86
|
+
}
|
|
87
|
+
return "unknown";
|
|
88
|
+
}
|
|
72
89
|
/**
|
|
73
90
|
* Run the five sub-calls in parallel + assemble an OnboardingReport.
|
|
74
91
|
* Never throws. Sub-call failures land in `errors[]`.
|
|
75
92
|
*/
|
|
76
93
|
export async function buildOnboardingReport() {
|
|
77
|
-
|
|
78
|
-
|
|
94
|
+
// rc.10 B (2026-05-19) — added /library/categories and /library/featured
|
|
95
|
+
// in parallel so a single onboarding call returns the full catalog brief.
|
|
96
|
+
// ~30 ms extra wall-clock (parallel) saves 5-10s of nachgelagerte
|
|
97
|
+
// discovery calls.
|
|
98
|
+
const [health, license, connections, flows, popular, featured, categories] = await Promise.allSettled([
|
|
99
|
+
safeRequest("apimapper_health", "/health"),
|
|
79
100
|
safeRequest("apimapper_license_status", "/license"),
|
|
80
101
|
safeRequest("apimapper_connection_list", "/connections"),
|
|
81
102
|
safeRequest("apimapper_flow_list", "/flows"),
|
|
82
103
|
safeRequest("apimapper_library_popular", "/library/popular?limit=5"),
|
|
104
|
+
safeRequest("apimapper_library_featured", "/library/featured?limit=5"),
|
|
105
|
+
safeRequest("apimapper_library_categories", "/library/categories"),
|
|
83
106
|
]);
|
|
84
107
|
const errors = [];
|
|
85
108
|
// Helper that pulls .value from a settled promise + records any error.
|
|
@@ -95,14 +118,36 @@ export async function buildOnboardingReport() {
|
|
|
95
118
|
}
|
|
96
119
|
return s.value.data;
|
|
97
120
|
};
|
|
98
|
-
|
|
121
|
+
const healthData = take(health);
|
|
99
122
|
const licenseData = take(license);
|
|
100
123
|
const connData = take(connections);
|
|
101
124
|
const flowData = take(flows);
|
|
102
125
|
const popularData = take(popular);
|
|
126
|
+
const featuredData = take(featured);
|
|
127
|
+
const categoriesData = take(categories);
|
|
103
128
|
const allConns = Array.isArray(connData?.connections) ? connData.connections : [];
|
|
104
129
|
const allFlows = Array.isArray(flowData?.flows) ? flowData.flows : [];
|
|
105
|
-
|
|
130
|
+
// F-A6-15: PHP /library/popular returns `connections`; tolerate legacy `items`.
|
|
131
|
+
const popItems = Array.isArray(popularData?.connections)
|
|
132
|
+
? popularData.connections
|
|
133
|
+
: Array.isArray(popularData?.items)
|
|
134
|
+
? popularData.items
|
|
135
|
+
: [];
|
|
136
|
+
const featuredItems = Array.isArray(featuredData?.connections)
|
|
137
|
+
? featuredData.connections
|
|
138
|
+
: Array.isArray(featuredData?.items)
|
|
139
|
+
? featuredData.items
|
|
140
|
+
: [];
|
|
141
|
+
// rc.10 B — categories shape: {categories: [{id, name, count}, ...]}.
|
|
142
|
+
// When the call fails or shape is unexpected, fall back to an empty list;
|
|
143
|
+
// total_count then falls back to popItems.length so the AI still gets a
|
|
144
|
+
// best-effort number.
|
|
145
|
+
const categoryRows = Array.isArray(categoriesData?.categories)
|
|
146
|
+
? categoriesData.categories.filter((c) => typeof c?.id === "string" && typeof c?.name === "string" && typeof c?.count === "number")
|
|
147
|
+
: [];
|
|
148
|
+
const libraryTotalCount = categoryRows.length > 0
|
|
149
|
+
? categoryRows.reduce((sum, c) => sum + c.count, 0)
|
|
150
|
+
: popItems.length;
|
|
106
151
|
// ── Conditional second-stage call: credentials, only if any conn has an oauth creds.
|
|
107
152
|
const oauthCredIds = allConns
|
|
108
153
|
.filter((c) => (c.auth_type || "").startsWith("oauth2") && c.credential_id)
|
|
@@ -147,8 +192,28 @@ export async function buildOnboardingReport() {
|
|
|
147
192
|
beta_channel: typeof o.beta_channel === "boolean" ? o.beta_channel : undefined,
|
|
148
193
|
};
|
|
149
194
|
})();
|
|
195
|
+
// rc.10 B — version + platform briefs. Plugin/api version come from
|
|
196
|
+
// /health response; platform from WP_BASE shape inference.
|
|
197
|
+
const pluginVersion = typeof healthData?.plugin_version === "string"
|
|
198
|
+
? healthData.plugin_version
|
|
199
|
+
: typeof healthData?.version === "string"
|
|
200
|
+
? healthData.version
|
|
201
|
+
: undefined;
|
|
202
|
+
const apiVersion = typeof healthData?.api_version === "string" ? healthData.api_version : undefined;
|
|
203
|
+
// rc.10 B — free-text hint that lives ADJACENT to the library data
|
|
204
|
+
// so the LLM reads it in the natural flow. `next_tools[]` arrays are
|
|
205
|
+
// ignored by most agents; prose anchored to numbers is not.
|
|
206
|
+
const libraryHint = `Catalog has ${libraryTotalCount} templates across ${categoryRows.length} categories. ` +
|
|
207
|
+
`Skip pagination and category-iteration: a single library_list({}) call returns the ` +
|
|
208
|
+
`complete catalog. Use the categories list above to filter results client-side rather ` +
|
|
209
|
+
`than calling library_list({category}) per slug.`;
|
|
150
210
|
return {
|
|
151
|
-
site: {
|
|
211
|
+
site: {
|
|
212
|
+
wp_base: WP_BASE,
|
|
213
|
+
platform: detectPlatform(WP_BASE),
|
|
214
|
+
...(pluginVersion ? { plugin_version: pluginVersion } : {}),
|
|
215
|
+
...(apiVersion ? { api_version: apiVersion } : {}),
|
|
216
|
+
},
|
|
152
217
|
license: licMap,
|
|
153
218
|
connections: {
|
|
154
219
|
count: allConns.length,
|
|
@@ -173,11 +238,19 @@ export async function buildOnboardingReport() {
|
|
|
173
238
|
})),
|
|
174
239
|
},
|
|
175
240
|
library: {
|
|
241
|
+
total_count: libraryTotalCount,
|
|
242
|
+
categories: categoryRows,
|
|
243
|
+
featured: featuredItems.slice(0, 5).map((f) => ({
|
|
244
|
+
id: f.id,
|
|
245
|
+
name: f.name,
|
|
246
|
+
category: f.category,
|
|
247
|
+
})),
|
|
176
248
|
popular: popItems.slice(0, 5).map((p) => ({
|
|
177
249
|
id: p.id,
|
|
178
250
|
name: p.name,
|
|
179
251
|
category: p.category,
|
|
180
252
|
})),
|
|
253
|
+
hint: libraryHint,
|
|
181
254
|
},
|
|
182
255
|
suggestions,
|
|
183
256
|
errors,
|
|
@@ -195,7 +268,9 @@ export function registerOnboardingTool(server) {
|
|
|
195
268
|
annotations: readOnly(),
|
|
196
269
|
}, async () => {
|
|
197
270
|
const report = await buildOnboardingReport();
|
|
198
|
-
|
|
271
|
+
// rc.10 B (2026-05-19) — bumped maxChars 6000→9000 to accommodate
|
|
272
|
+
// the extended library brief (categories + featured added).
|
|
273
|
+
return formatResult(report, false, { maxChars: 9000 });
|
|
199
274
|
});
|
|
200
275
|
}
|
|
201
276
|
//# sourceMappingURL=onboarding.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onboarding.js","sourceRoot":"","sources":["../../../src/modules/apimapper/onboarding.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,EAAE;AACF,uEAAuE;AACvE,2EAA2E;AAC3E,0EAA0E;AAC1E,qDAAqD;AACrD,EAAE;AACF,0EAA0E;AAC1E,uEAAuE;AACvE,iDAAiD;AACjD,EAAE;AACF,yEAAyE;AACzE,2EAA2E;AAC3E,yEAAyE;AACzE,8CAA8C;AAG9C,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"onboarding.js","sourceRoot":"","sources":["../../../src/modules/apimapper/onboarding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export declare const READ_CACHE_TTL_MS = 60000;
|
|
2
|
+
export declare const READ_CACHE_MAX_ENTRIES = 200;
|
|
3
|
+
/**
|
|
4
|
+
* Is the request eligible for caching? GET only, and the path must
|
|
5
|
+
* match at least one allowlist prefix. We compare against the path-
|
|
6
|
+
* portion (no host) so the key is stable whether the request goes
|
|
7
|
+
* through the WP plugin proxy or directly to the API server.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isCacheableRequest(method: string, url: string): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Retrieve a cached entry. Returns undefined on miss or expired entry —
|
|
12
|
+
* expired entries are also evicted to keep the store small.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getCached<T = unknown>(method: string, url: string): T | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Store an entry. Caps the store at READ_CACHE_MAX_ENTRIES — when full,
|
|
17
|
+
* we drop the OLDEST entry first (by storedAt). This is FIFO rather than
|
|
18
|
+
* LRU; LRU would require an access-time update on every read which is
|
|
19
|
+
* not worth it at 200-entry scale.
|
|
20
|
+
*/
|
|
21
|
+
export declare function setCached<T = unknown>(method: string, url: string, data: T): void;
|
|
22
|
+
/**
|
|
23
|
+
* Invalidate cache entries whose request path overlaps with the mutated
|
|
24
|
+
* resource. Conservative — clears every entry whose key includes the
|
|
25
|
+
* given path-substring. e.g. invalidateByPath('/flows') clears
|
|
26
|
+
* `/flows`, `/flows?status=published`, `/flows/abc123`.
|
|
27
|
+
*
|
|
28
|
+
* Called automatically from client.ts on POST/PUT/PATCH/DELETE.
|
|
29
|
+
*/
|
|
30
|
+
export declare function invalidateByPath(path: string): void;
|
|
31
|
+
/**
|
|
32
|
+
* Clear the entire cache. Used by tests and by the explicit
|
|
33
|
+
* `apimapper_cache_invalidate` MCP tool (which already broadcasts to
|
|
34
|
+
* the server's render cache; calling this here keeps the client view
|
|
35
|
+
* coherent).
|
|
36
|
+
*/
|
|
37
|
+
export declare function clearCache(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Snapshot for tests and diagnostic tooling. Not exposed via MCP tool.
|
|
40
|
+
*/
|
|
41
|
+
export declare function getCacheStats(): {
|
|
42
|
+
entries: number;
|
|
43
|
+
ttlMs: number;
|
|
44
|
+
};
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// src/modules/apimapper/read-cache.ts — Perf-#2 (2026-05-19)
|
|
2
|
+
//
|
|
3
|
+
// In-memory TTL cache for GET responses. A typical Maria-walkthrough chat
|
|
4
|
+
// hits `apimapper_health`, `apimapper_license_status`, `apimapper_features_get`,
|
|
5
|
+
// `apimapper_library_categories`, `apimapper_library_list` etc. repeatedly
|
|
6
|
+
// across turns. Each call is a ~200-2500ms round-trip through:
|
|
7
|
+
//
|
|
8
|
+
// AI → MCP-server fetch → dev.wootsup.com plugin REST → api.wootsup.com
|
|
9
|
+
// → Cloudflare Worker
|
|
10
|
+
//
|
|
11
|
+
// On cache HIT we return in ~0.01ms — orders of magnitude faster than the
|
|
12
|
+
// network path.
|
|
13
|
+
//
|
|
14
|
+
// Scope
|
|
15
|
+
// =====
|
|
16
|
+
//
|
|
17
|
+
// **Cached:** GET requests against read-only domain endpoints (health,
|
|
18
|
+
// features, license, library, connection-list, flow-list,
|
|
19
|
+
// platform-parity, settings-get). The MCP-server protocol
|
|
20
|
+
// already marks these tools with `annotations: readOnly()`;
|
|
21
|
+
// we mirror that contract at the HTTP layer with a 60s TTL.
|
|
22
|
+
//
|
|
23
|
+
// **Not cached:** Non-GET methods; any request with a header explicitly
|
|
24
|
+
// saying `Cache-Control: no-cache` (e.g. when the AI wants
|
|
25
|
+
// to verify a just-mutated state); any 4xx/5xx response
|
|
26
|
+
// (errors are not memoised — the next call retries fresh).
|
|
27
|
+
//
|
|
28
|
+
// **Invalidation:** Mutation methods (POST/PUT/PATCH/DELETE) clear cache
|
|
29
|
+
// entries whose path-prefix matches the mutated resource.
|
|
30
|
+
// e.g. POST /flows/abc invalidates GET /flows*. This is a
|
|
31
|
+
// conservative strategy — over-invalidates rather than
|
|
32
|
+
// risk serving stale state.
|
|
33
|
+
//
|
|
34
|
+
// The cache is process-scoped (per MCP-server instance per AI client). No
|
|
35
|
+
// cross-process or cross-machine sharing — that would need a Redis/D1 tier.
|
|
36
|
+
// At our 60s TTL and per-customer-LLM-conversation scale, in-memory is
|
|
37
|
+
// sufficient and gives us O(1) gets without operational overhead.
|
|
38
|
+
// Tunable knobs. Exported so tests can drive them.
|
|
39
|
+
export const READ_CACHE_TTL_MS = 60_000;
|
|
40
|
+
export const READ_CACHE_MAX_ENTRIES = 200;
|
|
41
|
+
// Tools we explicitly allow to be cached. Conservative allowlist — if a
|
|
42
|
+
// tool isn't in here, requests pass through untouched. We use endpoint
|
|
43
|
+
// path-prefixes (not tool names) because client.ts works in HTTP-path
|
|
44
|
+
// terms, not MCP-tool terms.
|
|
45
|
+
//
|
|
46
|
+
// Keep in sync with `annotations: readOnly()` tools in src/modules/apimapper/.
|
|
47
|
+
const READ_CACHE_PATH_ALLOWLIST = [
|
|
48
|
+
"/health",
|
|
49
|
+
"/features",
|
|
50
|
+
"/license",
|
|
51
|
+
"/library",
|
|
52
|
+
"/connections",
|
|
53
|
+
"/credentials",
|
|
54
|
+
"/flows",
|
|
55
|
+
"/platform-parity",
|
|
56
|
+
"/settings",
|
|
57
|
+
"/inspect-token",
|
|
58
|
+
"/onboarding",
|
|
59
|
+
"/releases",
|
|
60
|
+
"/skill",
|
|
61
|
+
];
|
|
62
|
+
const store = new Map();
|
|
63
|
+
/**
|
|
64
|
+
* Build the cache key. Includes the path + serialised query so e.g.
|
|
65
|
+
* `library?category=cms` and `library?category=media` don't collide.
|
|
66
|
+
* The HTTP method is part of the key only for safety — non-GET will
|
|
67
|
+
* never reach here, but we don't want a future caller to accidentally
|
|
68
|
+
* cache a POST against the same path.
|
|
69
|
+
*/
|
|
70
|
+
function cacheKey(method, url) {
|
|
71
|
+
return `${method.toUpperCase()}::${url}`;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Is the request eligible for caching? GET only, and the path must
|
|
75
|
+
* match at least one allowlist prefix. We compare against the path-
|
|
76
|
+
* portion (no host) so the key is stable whether the request goes
|
|
77
|
+
* through the WP plugin proxy or directly to the API server.
|
|
78
|
+
*/
|
|
79
|
+
export function isCacheableRequest(method, url) {
|
|
80
|
+
if (method.toUpperCase() !== "GET")
|
|
81
|
+
return false;
|
|
82
|
+
try {
|
|
83
|
+
// Tolerate both absolute and relative URLs.
|
|
84
|
+
const path = url.startsWith("http") ? new URL(url).pathname : url.split("?")[0];
|
|
85
|
+
return READ_CACHE_PATH_ALLOWLIST.some((prefix) => path.includes(prefix));
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Retrieve a cached entry. Returns undefined on miss or expired entry —
|
|
93
|
+
* expired entries are also evicted to keep the store small.
|
|
94
|
+
*/
|
|
95
|
+
export function getCached(method, url) {
|
|
96
|
+
const key = cacheKey(method, url);
|
|
97
|
+
const entry = store.get(key);
|
|
98
|
+
if (!entry)
|
|
99
|
+
return undefined;
|
|
100
|
+
if (Date.now() > entry.expiresAt) {
|
|
101
|
+
store.delete(key);
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
return entry.data;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Store an entry. Caps the store at READ_CACHE_MAX_ENTRIES — when full,
|
|
108
|
+
* we drop the OLDEST entry first (by storedAt). This is FIFO rather than
|
|
109
|
+
* LRU; LRU would require an access-time update on every read which is
|
|
110
|
+
* not worth it at 200-entry scale.
|
|
111
|
+
*/
|
|
112
|
+
export function setCached(method, url, data) {
|
|
113
|
+
if (store.size >= READ_CACHE_MAX_ENTRIES) {
|
|
114
|
+
let oldestKey;
|
|
115
|
+
let oldestTime = Infinity;
|
|
116
|
+
for (const [k, v] of store) {
|
|
117
|
+
if (v.storedAt < oldestTime) {
|
|
118
|
+
oldestTime = v.storedAt;
|
|
119
|
+
oldestKey = k;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (oldestKey)
|
|
123
|
+
store.delete(oldestKey);
|
|
124
|
+
}
|
|
125
|
+
const now = Date.now();
|
|
126
|
+
store.set(cacheKey(method, url), {
|
|
127
|
+
data,
|
|
128
|
+
expiresAt: now + READ_CACHE_TTL_MS,
|
|
129
|
+
storedAt: now,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Invalidate cache entries whose request path overlaps with the mutated
|
|
134
|
+
* resource. Conservative — clears every entry whose key includes the
|
|
135
|
+
* given path-substring. e.g. invalidateByPath('/flows') clears
|
|
136
|
+
* `/flows`, `/flows?status=published`, `/flows/abc123`.
|
|
137
|
+
*
|
|
138
|
+
* Called automatically from client.ts on POST/PUT/PATCH/DELETE.
|
|
139
|
+
*/
|
|
140
|
+
export function invalidateByPath(path) {
|
|
141
|
+
const needle = path.split("?")[0]; // strip query, match path only
|
|
142
|
+
for (const key of store.keys()) {
|
|
143
|
+
if (key.includes(needle))
|
|
144
|
+
store.delete(key);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Clear the entire cache. Used by tests and by the explicit
|
|
149
|
+
* `apimapper_cache_invalidate` MCP tool (which already broadcasts to
|
|
150
|
+
* the server's render cache; calling this here keeps the client view
|
|
151
|
+
* coherent).
|
|
152
|
+
*/
|
|
153
|
+
export function clearCache() {
|
|
154
|
+
store.clear();
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Snapshot for tests and diagnostic tooling. Not exposed via MCP tool.
|
|
158
|
+
*/
|
|
159
|
+
export function getCacheStats() {
|
|
160
|
+
return {
|
|
161
|
+
entries: store.size,
|
|
162
|
+
ttlMs: READ_CACHE_TTL_MS,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=read-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-cache.js","sourceRoot":"","sources":["../../../src/modules/apimapper/read-cache.ts"],"names":[],"mappings":"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"}
|