@runpod/mcp-server 4.10.1 → 4.11.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 +11 -0
- package/dist/{chunk-FQJFKWUV.mjs → chunk-24UOECYY.mjs} +19 -1
- package/dist/chunk-24UOECYY.mjs.map +1 -0
- package/dist/{chunk-AKX5ZMCL.mjs → chunk-4M7QDHK4.mjs} +312 -28
- package/dist/chunk-4M7QDHK4.mjs.map +1 -0
- package/dist/hosted.cjs +326 -26
- package/dist/hosted.cjs.map +1 -1
- package/dist/hosted.mjs +2 -2
- package/dist/http.cjs +326 -26
- package/dist/http.cjs.map +1 -1
- package/dist/http.mjs +2 -2
- package/dist/specgen/profile.cjs +19 -0
- package/dist/specgen/profile.cjs.map +1 -1
- package/dist/specgen/profile.d.cts +6 -3
- package/dist/specgen/profile.d.ts +6 -3
- package/dist/specgen/profile.mjs +3 -1
- package/dist/stdio.cjs +324 -25
- package/dist/stdio.cjs.map +1 -1
- package/dist/stdio.mjs +324 -25
- package/dist/stdio.mjs.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-AKX5ZMCL.mjs.map +0 -1
- package/dist/chunk-FQJFKWUV.mjs.map +0 -1
package/dist/stdio.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
12
12
|
|
|
13
13
|
// src/server.ts
|
|
14
14
|
var SERVER_NAME = "Runpod API Server";
|
|
15
|
-
var SERVER_VERSION = true ? "4.
|
|
15
|
+
var SERVER_VERSION = true ? "4.11.0" : "dev";
|
|
16
16
|
|
|
17
17
|
// src/specgen/server.ts
|
|
18
18
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -244,25 +244,16 @@ async function dispatchGeneratedTool(client, tool, args) {
|
|
|
244
244
|
const value = args[param.name];
|
|
245
245
|
query[param.name] = param.explode === false && Array.isArray(value) ? value.join(",") : value;
|
|
246
246
|
}
|
|
247
|
-
|
|
248
|
-
if (
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
if (tool.hasBody && requestBody !== void 0) {
|
|
262
|
-
const properties = tool.inputSchema.properties ?? {};
|
|
263
|
-
const defs = tool.inputSchema.$defs ?? {};
|
|
264
|
-
requestBody = coerceScalars(requestBody, properties.body, defs);
|
|
265
|
-
}
|
|
247
|
+
const sent = tool.hasBody ? bodyAsSent(tool, args.body) : { body: args.body };
|
|
248
|
+
if (!sent)
|
|
249
|
+
return {
|
|
250
|
+
ok: false,
|
|
251
|
+
status: 400,
|
|
252
|
+
payload: {
|
|
253
|
+
error: "The body argument arrived as a string that is not valid JSON. Send body as an object."
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
const requestBody = sent.body;
|
|
266
257
|
const verbs = client;
|
|
267
258
|
const { data, error, response } = await verbs[tool.method](tool.path, {
|
|
268
259
|
params: { path: pathParams, query },
|
|
@@ -275,6 +266,32 @@ async function dispatchGeneratedTool(client, tool, args) {
|
|
|
275
266
|
payload: data ?? { status: response.status }
|
|
276
267
|
};
|
|
277
268
|
}
|
|
269
|
+
function bodyAsSent(tool, body) {
|
|
270
|
+
let parsed = body;
|
|
271
|
+
if (typeof parsed === "string") {
|
|
272
|
+
try {
|
|
273
|
+
parsed = JSON.parse(parsed);
|
|
274
|
+
} catch {
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (parsed === void 0) return { body: parsed };
|
|
279
|
+
const properties = tool.inputSchema.properties ?? {};
|
|
280
|
+
const defs = tool.inputSchema.$defs ?? {};
|
|
281
|
+
return { body: coerceScalars(parsed, properties.body, defs) };
|
|
282
|
+
}
|
|
283
|
+
function argsAsSent(tool, args) {
|
|
284
|
+
if (!tool.hasBody || args.body === void 0) return args;
|
|
285
|
+
const sent = bodyAsSent(tool, args.body);
|
|
286
|
+
return sent ? { ...args, body: sent.body } : null;
|
|
287
|
+
}
|
|
288
|
+
function omittedEmptyQueryArg(tool) {
|
|
289
|
+
const required = new Set(tool.inputSchema.required ?? []);
|
|
290
|
+
const query = new Set(
|
|
291
|
+
tool.params.filter((p) => p.location === "query").map((p) => p.name)
|
|
292
|
+
);
|
|
293
|
+
return (name, value) => query.has(name) && !required.has(name) && isEmptyValue(value);
|
|
294
|
+
}
|
|
278
295
|
function isEmptyValue(value) {
|
|
279
296
|
return value === null || value === "" || Array.isArray(value) && !value.length;
|
|
280
297
|
}
|
|
@@ -2711,6 +2728,109 @@ var generatedTools = [
|
|
|
2711
2728
|
}
|
|
2712
2729
|
}
|
|
2713
2730
|
},
|
|
2731
|
+
{
|
|
2732
|
+
name: "exec-pod",
|
|
2733
|
+
title: "Run a command in a Pod",
|
|
2734
|
+
operationId: "execPod",
|
|
2735
|
+
description: `Run one command inside a running Pod's container and get stdout, stderr and the exit code back. No SSH key, public IP or exposed port is needed. command is an argv array run without a shell: pass ["sh", "-c", "..."] for pipes, redirects, globs or &&. One call waits at most timeoutSeconds (1-25, default 20). timedOut true means the call stopped waiting, NOT that the command stopped: it keeps running in the container. For anything longer (model downloads, pip installs, builds), start it in the background and log to a file, e.g. ["sh", "-c", "nohup wget -c -O /workspace/m.safetensors URL > /tmp/dl.log 2>&1 &"], then check progress with later calls (ls -la, du -h, tail /tmp/dl.log). stdout and stderr are each capped at 1 MiB (truncated true). Right after a create, the Pod can answer 404 "Pod not found" for about 10 seconds even with the right id, then 409 while its container starts: retry in about 10 seconds, a few times at most. A Pod that is not running answers 409. A host not yet updated for exec answers 503. Reaches only Pods owned by the API key's own account. Commands can change or delete data in the Pod: run write commands only for what the user asked.`,
|
|
2736
|
+
directoryDescription: "Run one command inside a running Pod's container and return stdout, stderr and the exit code. The command is an argv array run without a shell. One call waits at most timeoutSeconds (1-25, default 20); a command still running then keeps running in the container, and the result says timedOut. stdout and stderr are each capped at 1 MiB. A Pod that is not running answers 409, and a host not yet updated for exec answers 503. Reaches only Pods owned by the caller's own account. The command can change or delete data in the Pod.",
|
|
2737
|
+
method: "POST",
|
|
2738
|
+
path: "/v2/pods/{id}/exec",
|
|
2739
|
+
params: [
|
|
2740
|
+
{
|
|
2741
|
+
name: "id",
|
|
2742
|
+
location: "path"
|
|
2743
|
+
}
|
|
2744
|
+
],
|
|
2745
|
+
hasBody: true,
|
|
2746
|
+
annotations: {
|
|
2747
|
+
readOnlyHint: false,
|
|
2748
|
+
destructiveHint: true,
|
|
2749
|
+
idempotentHint: false,
|
|
2750
|
+
openWorldHint: true
|
|
2751
|
+
},
|
|
2752
|
+
inputSchema: {
|
|
2753
|
+
type: "object",
|
|
2754
|
+
properties: {
|
|
2755
|
+
id: {
|
|
2756
|
+
type: "string",
|
|
2757
|
+
description: "Pod identifier"
|
|
2758
|
+
},
|
|
2759
|
+
body: {
|
|
2760
|
+
$ref: "#/$defs/PodExecRequest",
|
|
2761
|
+
type: "object"
|
|
2762
|
+
}
|
|
2763
|
+
},
|
|
2764
|
+
required: ["id", "body"],
|
|
2765
|
+
$defs: {
|
|
2766
|
+
PodExecRequest: {
|
|
2767
|
+
type: "object",
|
|
2768
|
+
additionalProperties: false,
|
|
2769
|
+
required: ["command"],
|
|
2770
|
+
properties: {
|
|
2771
|
+
command: {
|
|
2772
|
+
type: "array",
|
|
2773
|
+
minItems: 1,
|
|
2774
|
+
maxItems: 256,
|
|
2775
|
+
prefixItems: [
|
|
2776
|
+
{
|
|
2777
|
+
type: "string",
|
|
2778
|
+
minLength: 1,
|
|
2779
|
+
maxLength: 4096,
|
|
2780
|
+
pattern: "^[^\\x00]*[^\\t-\\r \x85\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\\x00][^\\x00]*$"
|
|
2781
|
+
}
|
|
2782
|
+
],
|
|
2783
|
+
items: {
|
|
2784
|
+
type: "string",
|
|
2785
|
+
maxLength: 4096,
|
|
2786
|
+
pattern: "^[^\\x00]*$"
|
|
2787
|
+
},
|
|
2788
|
+
description: 'Command to run, as an argv array of 1-256 arguments of at most 4096 characters each. It is run directly, never through a shell; for pipes, redirects or globbing pass `["sh", "-c", "..."]`.',
|
|
2789
|
+
examples: [
|
|
2790
|
+
["nvidia-smi", "--query-gpu=name,memory.used", "--format=csv"]
|
|
2791
|
+
]
|
|
2792
|
+
},
|
|
2793
|
+
timeoutSeconds: {
|
|
2794
|
+
type: "integer",
|
|
2795
|
+
minimum: 1,
|
|
2796
|
+
maximum: 25,
|
|
2797
|
+
default: 20,
|
|
2798
|
+
description: "How long the call waits for the command to finish, in seconds. A command still running at this point returns with `timedOut: true`.",
|
|
2799
|
+
examples: [10]
|
|
2800
|
+
},
|
|
2801
|
+
cwd: {
|
|
2802
|
+
type: "string",
|
|
2803
|
+
pattern: "^/[^\\x00-\\x1f\\x7f]*$",
|
|
2804
|
+
maxLength: 1024,
|
|
2805
|
+
description: "Absolute working directory for the command, at most 1024 characters and without control characters. Defaults to the image's `WORKDIR`.",
|
|
2806
|
+
examples: ["/workspace"]
|
|
2807
|
+
},
|
|
2808
|
+
env: {
|
|
2809
|
+
type: "object",
|
|
2810
|
+
maxProperties: 64,
|
|
2811
|
+
propertyNames: {
|
|
2812
|
+
type: "string",
|
|
2813
|
+
minLength: 1,
|
|
2814
|
+
maxLength: 256,
|
|
2815
|
+
pattern: "^[^=\\x00]+$"
|
|
2816
|
+
},
|
|
2817
|
+
additionalProperties: {
|
|
2818
|
+
type: "string",
|
|
2819
|
+
maxLength: 16384,
|
|
2820
|
+
pattern: "^[^\\x00]*$"
|
|
2821
|
+
},
|
|
2822
|
+
description: "Up to 64 environment variables added to the container's environment for this command only. A name is 1-256 characters and must not contain `=` or a NUL character; a value is at most 16384 characters and must not contain a NUL character.",
|
|
2823
|
+
examples: [
|
|
2824
|
+
{
|
|
2825
|
+
HF_HOME: "/workspace/hf"
|
|
2826
|
+
}
|
|
2827
|
+
]
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
},
|
|
2714
2834
|
{
|
|
2715
2835
|
name: "get-cluster",
|
|
2716
2836
|
title: "Get cluster",
|
|
@@ -6773,6 +6893,122 @@ var generatedTools = [
|
|
|
6773
6893
|
}
|
|
6774
6894
|
];
|
|
6775
6895
|
|
|
6896
|
+
// src/specgen/validate.ts
|
|
6897
|
+
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
6898
|
+
function schemaValidationMode(value = process.env.MCP_SCHEMA_VALIDATION) {
|
|
6899
|
+
const mode = value?.trim().toLowerCase();
|
|
6900
|
+
return mode === "off" || mode === "enforce" ? mode : "shadow";
|
|
6901
|
+
}
|
|
6902
|
+
var ajv = new Ajv2020({
|
|
6903
|
+
strict: false,
|
|
6904
|
+
allErrors: true,
|
|
6905
|
+
validateFormats: false
|
|
6906
|
+
});
|
|
6907
|
+
var compiled = /* @__PURE__ */ new WeakMap();
|
|
6908
|
+
function validatorFor(schema) {
|
|
6909
|
+
let validate = compiled.get(schema);
|
|
6910
|
+
if (!validate) {
|
|
6911
|
+
validate = ajv.compile(structuredClone(schema));
|
|
6912
|
+
compiled.set(schema, validate);
|
|
6913
|
+
}
|
|
6914
|
+
return validate;
|
|
6915
|
+
}
|
|
6916
|
+
var MAX_NULL_PASSES = 8;
|
|
6917
|
+
function isNullTypeError(error, data) {
|
|
6918
|
+
return error.keyword === "type" && error.instancePath !== "" && valueAt(data, error.instancePath) === null;
|
|
6919
|
+
}
|
|
6920
|
+
function pointerSegments(pointer) {
|
|
6921
|
+
return pointer.split("/").slice(1).map((s) => s.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
6922
|
+
}
|
|
6923
|
+
function valueAt(data, pointer) {
|
|
6924
|
+
let node = data;
|
|
6925
|
+
for (const key of pointerSegments(pointer)) {
|
|
6926
|
+
if (node === null || typeof node !== "object") return void 0;
|
|
6927
|
+
node = node[key];
|
|
6928
|
+
}
|
|
6929
|
+
return node;
|
|
6930
|
+
}
|
|
6931
|
+
function removeAt(data, pointer) {
|
|
6932
|
+
const segments = pointerSegments(pointer);
|
|
6933
|
+
const last = segments.pop();
|
|
6934
|
+
const parent = valueAt(data, segments.length ? `/${segments.join("/")}` : "");
|
|
6935
|
+
if (last === void 0 || parent === null || typeof parent !== "object")
|
|
6936
|
+
return false;
|
|
6937
|
+
if (Array.isArray(parent)) return false;
|
|
6938
|
+
delete parent[last];
|
|
6939
|
+
return true;
|
|
6940
|
+
}
|
|
6941
|
+
var WRAPPER_KEYWORDS = /* @__PURE__ */ new Set(["if"]);
|
|
6942
|
+
function toViolation(error) {
|
|
6943
|
+
const base = pointerSegments(error.instancePath);
|
|
6944
|
+
let path = base.join(".");
|
|
6945
|
+
let message = error.message ?? "is invalid";
|
|
6946
|
+
const params = error.params;
|
|
6947
|
+
if (error.keyword === "required" && typeof params.missingProperty === "string") {
|
|
6948
|
+
path = [...base, params.missingProperty].join(".");
|
|
6949
|
+
message = "is required";
|
|
6950
|
+
} else if (error.keyword === "additionalProperties" && typeof params.additionalProperty === "string") {
|
|
6951
|
+
path = [...base, params.additionalProperty].join(".");
|
|
6952
|
+
message = "is not an accepted argument here";
|
|
6953
|
+
} else if (error.keyword === "pattern") {
|
|
6954
|
+
message = "is not in an accepted format";
|
|
6955
|
+
}
|
|
6956
|
+
const allowed = error.keyword === "enum" ? params.allowedValues : error.keyword === "const" ? [params.allowedValue] : void 0;
|
|
6957
|
+
return {
|
|
6958
|
+
path,
|
|
6959
|
+
keyword: error.keyword,
|
|
6960
|
+
message,
|
|
6961
|
+
...allowed ? { allowed } : {},
|
|
6962
|
+
schemaPath: error.schemaPath
|
|
6963
|
+
};
|
|
6964
|
+
}
|
|
6965
|
+
function schemaViolations(schema, args, omitted = () => false) {
|
|
6966
|
+
const validate = validatorFor(schema);
|
|
6967
|
+
const data = structuredClone(
|
|
6968
|
+
Object.fromEntries(
|
|
6969
|
+
Object.entries(args).filter(([name, value]) => !omitted(name, value))
|
|
6970
|
+
)
|
|
6971
|
+
);
|
|
6972
|
+
for (let pass = 0; ; pass++) {
|
|
6973
|
+
if (validate(data)) return [];
|
|
6974
|
+
const errors = validate.errors ?? [];
|
|
6975
|
+
let removed = false;
|
|
6976
|
+
if (pass < MAX_NULL_PASSES) {
|
|
6977
|
+
for (const error of errors.filter((e) => isNullTypeError(e, data)))
|
|
6978
|
+
removed = removeAt(data, error.instancePath) || removed;
|
|
6979
|
+
}
|
|
6980
|
+
if (!removed) {
|
|
6981
|
+
return errors.filter((e) => !WRAPPER_KEYWORDS.has(e.keyword)).map(toViolation);
|
|
6982
|
+
}
|
|
6983
|
+
}
|
|
6984
|
+
}
|
|
6985
|
+
var INVALID_ARGUMENTS_HINT = "Fix the listed fields and call again.";
|
|
6986
|
+
function invalidArgumentsPayload(violations) {
|
|
6987
|
+
return {
|
|
6988
|
+
error: "Invalid arguments",
|
|
6989
|
+
code: "invalid_arguments",
|
|
6990
|
+
fields: violations.map(({ path, message, allowed }) => ({
|
|
6991
|
+
path,
|
|
6992
|
+
problem: message,
|
|
6993
|
+
...allowed ? { allowed } : {}
|
|
6994
|
+
})),
|
|
6995
|
+
hint: INVALID_ARGUMENTS_HINT
|
|
6996
|
+
};
|
|
6997
|
+
}
|
|
6998
|
+
function logSchemaViolations(tool, mode, violations) {
|
|
6999
|
+
console.error(
|
|
7000
|
+
"schema_violation",
|
|
7001
|
+
JSON.stringify({
|
|
7002
|
+
tool,
|
|
7003
|
+
mode,
|
|
7004
|
+
violations: violations.map(({ keyword, schemaPath }) => ({
|
|
7005
|
+
keyword,
|
|
7006
|
+
schemaPath
|
|
7007
|
+
}))
|
|
7008
|
+
})
|
|
7009
|
+
);
|
|
7010
|
+
}
|
|
7011
|
+
|
|
6776
7012
|
// src/specgen/tools/annotations.ts
|
|
6777
7013
|
var readOnly = {
|
|
6778
7014
|
readOnlyHint: true,
|
|
@@ -6986,6 +7222,8 @@ var DIRECTORY_TOOLS = {
|
|
|
6986
7222
|
"deploy-hub-repo": IN,
|
|
6987
7223
|
"detach-cost-center-resource": IN,
|
|
6988
7224
|
"endpoint-health": IN,
|
|
7225
|
+
// env can carry tokens (HF_TOKEN for a model download), so the directory omits it.
|
|
7226
|
+
"exec-pod": { include: true, omitInputs: ["body.env"] },
|
|
6989
7227
|
"get-capacity": IN,
|
|
6990
7228
|
"get-cluster": IN,
|
|
6991
7229
|
"get-cost-center": IN,
|
|
@@ -7105,6 +7343,21 @@ function directoryOmittedInputs(name) {
|
|
|
7105
7343
|
const decision = DIRECTORY_TOOLS[name];
|
|
7106
7344
|
return decision?.include ? decision.omitInputs ?? [] : [];
|
|
7107
7345
|
}
|
|
7346
|
+
function omittedInputsIn(omit, args) {
|
|
7347
|
+
return omit.filter((key) => {
|
|
7348
|
+
const [parent, child] = key.split(".");
|
|
7349
|
+
if (child === void 0) return parent in args;
|
|
7350
|
+
let value = args[parent];
|
|
7351
|
+
if (typeof value === "string") {
|
|
7352
|
+
try {
|
|
7353
|
+
value = JSON.parse(value);
|
|
7354
|
+
} catch {
|
|
7355
|
+
return false;
|
|
7356
|
+
}
|
|
7357
|
+
}
|
|
7358
|
+
return !!value && typeof value === "object" && child in value;
|
|
7359
|
+
});
|
|
7360
|
+
}
|
|
7108
7361
|
|
|
7109
7362
|
// src/specgen/redact.ts
|
|
7110
7363
|
var REDACTED = "[redacted]";
|
|
@@ -10673,13 +10926,40 @@ function withoutCredentialExamples(schema) {
|
|
|
10673
10926
|
};
|
|
10674
10927
|
return strip(schema);
|
|
10675
10928
|
}
|
|
10676
|
-
function
|
|
10677
|
-
if (!omit.length) return schema;
|
|
10929
|
+
function withoutKeys(schema, omit) {
|
|
10678
10930
|
const properties = { ...schema.properties ?? {} };
|
|
10679
10931
|
for (const key of omit) delete properties[key];
|
|
10680
10932
|
const required = Array.isArray(schema.required) ? schema.required.filter((key) => !omit.includes(key)) : schema.required;
|
|
10681
10933
|
return { ...schema, properties, ...required ? { required } : {} };
|
|
10682
10934
|
}
|
|
10935
|
+
function withoutInputs(schema, omit) {
|
|
10936
|
+
if (!omit.length) return schema;
|
|
10937
|
+
let out = withoutKeys(
|
|
10938
|
+
schema,
|
|
10939
|
+
omit.filter((key) => !key.includes("."))
|
|
10940
|
+
);
|
|
10941
|
+
for (const key of omit.filter((k) => k.includes("."))) {
|
|
10942
|
+
const [parent, child] = key.split(".");
|
|
10943
|
+
const properties = out.properties ?? {};
|
|
10944
|
+
const node = properties[parent];
|
|
10945
|
+
if (!node) continue;
|
|
10946
|
+
const ref = typeof node.$ref === "string" ? node.$ref : void 0;
|
|
10947
|
+
const defName = ref?.startsWith("#/$defs/") ? ref.slice(8) : void 0;
|
|
10948
|
+
const defs = out.$defs ?? {};
|
|
10949
|
+
if (defName && defs[defName]) {
|
|
10950
|
+
out = {
|
|
10951
|
+
...out,
|
|
10952
|
+
$defs: { ...defs, [defName]: withoutKeys(defs[defName], [child]) }
|
|
10953
|
+
};
|
|
10954
|
+
} else {
|
|
10955
|
+
out = {
|
|
10956
|
+
...out,
|
|
10957
|
+
properties: { ...properties, [parent]: withoutKeys(node, [child]) }
|
|
10958
|
+
};
|
|
10959
|
+
}
|
|
10960
|
+
}
|
|
10961
|
+
return out;
|
|
10962
|
+
}
|
|
10683
10963
|
function callShape(schema) {
|
|
10684
10964
|
const defs = schema.$defs ?? {};
|
|
10685
10965
|
const resolve = (node) => {
|
|
@@ -11642,6 +11922,7 @@ function createSpecgenServer(ctx, version = "0.1.0", opts = {}) {
|
|
|
11642
11922
|
const caller = callerId(ctx.apiKey);
|
|
11643
11923
|
const profile = opts.profile ?? "default";
|
|
11644
11924
|
const directory = profile === "directory";
|
|
11925
|
+
const schemaMode = schemaValidationMode();
|
|
11645
11926
|
const alp = directory ? void 0 : opts.alp;
|
|
11646
11927
|
const servedGeneratedTools = directory ? generatedTools.filter((tool) => directoryIncludes(tool.name)) : generatedTools;
|
|
11647
11928
|
const servedCuratedTools = [
|
|
@@ -11748,7 +12029,7 @@ function createSpecgenServer(ctx, version = "0.1.0", opts = {}) {
|
|
|
11748
12029
|
(tool) => tool.name === request.params.name
|
|
11749
12030
|
);
|
|
11750
12031
|
const curatedArgs = curated ? withoutNullOptionals(curated.inputSchema, args) : args;
|
|
11751
|
-
const omitted = directory ? directoryOmittedInputs(request.params.name)
|
|
12032
|
+
const omitted = directory ? omittedInputsIn(directoryOmittedInputs(request.params.name), args) : [];
|
|
11752
12033
|
const rejected = omitted.length ? {
|
|
11753
12034
|
ok: false,
|
|
11754
12035
|
status: 400,
|
|
@@ -11758,8 +12039,26 @@ function createSpecgenServer(ctx, version = "0.1.0", opts = {}) {
|
|
|
11758
12039
|
} : curated && !curated.lenientArguments ? validateArguments(
|
|
11759
12040
|
curated.inputSchema,
|
|
11760
12041
|
curatedArgs
|
|
11761
|
-
) : null;
|
|
11762
|
-
|
|
12042
|
+
) : generated ? validateArguments(generated.inputSchema, args) : null;
|
|
12043
|
+
let schemaRejected = null;
|
|
12044
|
+
if (!rejected && schemaMode !== "off") {
|
|
12045
|
+
const sent = generated ? argsAsSent(generated, args) : null;
|
|
12046
|
+
const violations = curated ? curated.lenientArguments ? [] : schemaViolations(curated.inputSchema, curatedArgs) : generated && sent ? schemaViolations(
|
|
12047
|
+
generated.inputSchema,
|
|
12048
|
+
sent,
|
|
12049
|
+
omittedEmptyQueryArg(generated)
|
|
12050
|
+
) : [];
|
|
12051
|
+
if (violations.length) {
|
|
12052
|
+
logSchemaViolations(request.params.name, schemaMode, violations);
|
|
12053
|
+
if (schemaMode === "enforce")
|
|
12054
|
+
schemaRejected = {
|
|
12055
|
+
ok: false,
|
|
12056
|
+
status: 400,
|
|
12057
|
+
payload: invalidArgumentsPayload(violations)
|
|
12058
|
+
};
|
|
12059
|
+
}
|
|
12060
|
+
}
|
|
12061
|
+
const result = rejected ?? schemaRejected ?? await runTool(
|
|
11763
12062
|
() => curated ? curated.handler(ctx, curatedArgs) : dispatchTool(generated, request.params.name, args)
|
|
11764
12063
|
);
|
|
11765
12064
|
logToolCall({
|