@evantahler/mcpx 0.21.3 → 0.21.5
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/package.json
CHANGED
|
@@ -10,9 +10,20 @@
|
|
|
10
10
|
// that environment node_modules exists and onnxruntime-web is reachable
|
|
11
11
|
// through normal module resolution.
|
|
12
12
|
|
|
13
|
+
// The relative `../../node_modules/...` paths only resolve from the local repo
|
|
14
|
+
// layout (and inside `bun build --compile`). When this file is shipped via npm,
|
|
15
|
+
// deps are hoisted, so consumer `tsc` runs hit TS2307. The `ts-ignore` directive
|
|
16
|
+
// below silences that for consumers; we avoid the stricter `expect-error` form
|
|
17
|
+
// because in the local repo the path resolves fine and there would be no error
|
|
18
|
+
// to expect. At runtime the dynamic import in semantic.ts is wrapped in
|
|
19
|
+
// try/catch and falls back to transformers.js's default WASM loader (issue #85).
|
|
20
|
+
// biome-ignore lint/suspicious/noTsIgnore: must stay as ts-ignore per comment above
|
|
21
|
+
// @ts-ignore - dynamic-only import
|
|
13
22
|
import wasmMjsPath from "../../node_modules/onnxruntime-web/dist/ort-wasm-simd-threaded.asyncify.mjs" with {
|
|
14
23
|
type: "file",
|
|
15
24
|
};
|
|
25
|
+
// biome-ignore lint/suspicious/noTsIgnore: must stay as ts-ignore per comment above
|
|
26
|
+
// @ts-ignore - dynamic-only import
|
|
16
27
|
import wasmBinPath from "../../node_modules/onnxruntime-web/dist/ort-wasm-simd-threaded.asyncify.wasm" with {
|
|
17
28
|
type: "file",
|
|
18
29
|
};
|
package/src/validation/schema.ts
CHANGED
|
@@ -26,7 +26,7 @@ function validateWithSchema(
|
|
|
26
26
|
|
|
27
27
|
if (!validate) {
|
|
28
28
|
try {
|
|
29
|
-
validate = ajv.compile(schema);
|
|
29
|
+
validate = ajv.compile(normalizeSchema(schema));
|
|
30
30
|
validatorCache.set(cacheKey, validate);
|
|
31
31
|
} catch (err) {
|
|
32
32
|
const msg = err instanceof Error ? err.message : "unknown error";
|
|
@@ -60,6 +60,64 @@ export function validateElicitationResponse(
|
|
|
60
60
|
return validateWithSchema(`__elicitation__${JSON.stringify(schema)}`, schema, input);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
type JsonPrimitive = string | number | boolean | null;
|
|
64
|
+
|
|
65
|
+
function isPrimitive(v: unknown): v is JsonPrimitive {
|
|
66
|
+
return v === null || ["string", "number", "boolean"].includes(typeof v);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function primitiveJsonType(v: JsonPrimitive): "string" | "number" | "boolean" | "null" {
|
|
70
|
+
if (v === null) return "null";
|
|
71
|
+
if (typeof v === "boolean") return "boolean";
|
|
72
|
+
if (typeof v === "number") return "number";
|
|
73
|
+
return "string";
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Normalize a JSON Schema before handing it to Ajv. Rewrites the malformed
|
|
78
|
+
* shape `{ type: "array", enum: [<primitives>], items: { type: <matching> } }`
|
|
79
|
+
* — published by some real MCP servers — into `{ type: "array", items: { ..., enum: [...] } }`.
|
|
80
|
+
* Without this fix Ajv compares the whole array value against the primitive enum
|
|
81
|
+
* and rejects every input. Returns a deep clone; the input schema is untouched.
|
|
82
|
+
*/
|
|
83
|
+
function normalizeSchema(schema: Record<string, unknown>): Record<string, unknown> {
|
|
84
|
+
return walk(schema) as Record<string, unknown>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function walk(node: unknown): unknown {
|
|
88
|
+
if (Array.isArray(node)) {
|
|
89
|
+
return node.map(walk);
|
|
90
|
+
}
|
|
91
|
+
if (!node || typeof node !== "object") {
|
|
92
|
+
return node;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const out: Record<string, unknown> = {};
|
|
96
|
+
for (const [key, value] of Object.entries(node as Record<string, unknown>)) {
|
|
97
|
+
out[key] = walk(value);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (out.type === "array" && Array.isArray(out.enum) && out.enum.every(isPrimitive)) {
|
|
101
|
+
const items = out.items;
|
|
102
|
+
const enumValues = out.enum as JsonPrimitive[];
|
|
103
|
+
if (items && typeof items === "object" && !Array.isArray(items)) {
|
|
104
|
+
const itemsObj = items as Record<string, unknown>;
|
|
105
|
+
const enumType = primitiveJsonType(enumValues[0]!);
|
|
106
|
+
const allSameType = enumValues.every((v) => primitiveJsonType(v) === enumType);
|
|
107
|
+
const itemsTypeMatches =
|
|
108
|
+
itemsObj.type === undefined ||
|
|
109
|
+
itemsObj.type === enumType ||
|
|
110
|
+
(Array.isArray(itemsObj.type) && itemsObj.type.includes(enumType));
|
|
111
|
+
if (allSameType && itemsTypeMatches && itemsObj.enum === undefined) {
|
|
112
|
+
out.items = { ...itemsObj, enum: enumValues };
|
|
113
|
+
delete out.enum;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
|
|
63
121
|
function formatAjvError(err: ErrorObject): ValidationError {
|
|
64
122
|
const path = err.instancePath ? err.instancePath.replace(/^\//, "").replace(/\//g, ".") : "(root)";
|
|
65
123
|
|