stitchkit 0.23.0 → 0.25.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/dist/cli.js +1 -1
- package/dist/{index-x8m8e7dc.js → index-h9d1fm0p.js} +114 -65
- package/dist/tools/coerce.d.ts +2 -1
- package/dist/tools/coerce.d.ts.map +1 -1
- package/dist/tools/flatten.d.ts +16 -6
- package/dist/tools/flatten.d.ts.map +1 -1
- package/dist/tools/mount.d.ts.map +1 -1
- package/dist/tools/oauth-provider.d.ts +10 -0
- package/dist/tools/oauth-provider.d.ts.map +1 -1
- package/dist/tools/schema.d.ts +43 -1
- package/dist/tools/schema.d.ts.map +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +22 -11
- package/llms-full.txt +45 -10
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -76,13 +76,66 @@ function coerceJsonArgs(args, schema) {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
// src/tools/flatten.ts
|
|
79
|
+
import { z as z3 } from "zod";
|
|
80
|
+
|
|
81
|
+
// src/tools/schema.ts
|
|
79
82
|
import { z as z2 } from "zod";
|
|
83
|
+
function objectShapeKeys(schema) {
|
|
84
|
+
return schema instanceof z2.ZodObject ? Object.keys(schema.shape) : [];
|
|
85
|
+
}
|
|
86
|
+
function keyPolicyOf(schema) {
|
|
87
|
+
return schema.def.catchall;
|
|
88
|
+
}
|
|
89
|
+
function rebuildObject(source, shape) {
|
|
90
|
+
return withKeyPolicy(z2.object(shape), keyPolicyOf(source));
|
|
91
|
+
}
|
|
92
|
+
function withKeyPolicy(object, policy) {
|
|
93
|
+
if (policy === undefined)
|
|
94
|
+
return object;
|
|
95
|
+
return object.catchall(representable(policy));
|
|
96
|
+
}
|
|
97
|
+
function representable(policy) {
|
|
98
|
+
if (policy instanceof z2.ZodNever || policy instanceof z2.ZodUnknown)
|
|
99
|
+
return policy;
|
|
100
|
+
if (!(policy instanceof z2.ZodType))
|
|
101
|
+
return z2.unknown();
|
|
102
|
+
try {
|
|
103
|
+
toJsonSchema(policy, "input");
|
|
104
|
+
return policy;
|
|
105
|
+
} catch {
|
|
106
|
+
return z2.unknown();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function mergeSchemas(paramsSchema, inputSchema) {
|
|
110
|
+
if (paramsSchema && !(paramsSchema instanceof z2.ZodObject)) {
|
|
111
|
+
throw new Error("Tool params schema must be a z.object()");
|
|
112
|
+
}
|
|
113
|
+
const paramsObject = paramsSchema instanceof z2.ZodObject ? paramsSchema : undefined;
|
|
114
|
+
if (!inputSchema) {
|
|
115
|
+
return paramsObject ?? z2.object({});
|
|
116
|
+
}
|
|
117
|
+
if (inputSchema instanceof z2.ZodObject) {
|
|
118
|
+
if (paramsObject) {
|
|
119
|
+
const conflicts = Object.keys(paramsObject.shape).filter((key) => (key in inputSchema.shape));
|
|
120
|
+
if (conflicts.length > 0) {
|
|
121
|
+
throw new Error(`Schema merge conflict: ${conflicts.join(", ")} appear in both params and input`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return rebuildObject(inputSchema, {
|
|
125
|
+
...paramsObject?.shape ?? {},
|
|
126
|
+
...inputSchema.shape
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return paramsObject ? z2.intersection(paramsObject, inputSchema) : inputSchema;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// src/tools/flatten.ts
|
|
80
133
|
function flattenDiscriminatedUnion(union) {
|
|
81
134
|
const discriminator = union.def.discriminator;
|
|
82
135
|
const allDiscValues = [];
|
|
83
136
|
const perKey = new Map;
|
|
84
137
|
for (const opt of union.def.options) {
|
|
85
|
-
if (!(opt instanceof
|
|
138
|
+
if (!(opt instanceof z3.ZodObject)) {
|
|
86
139
|
throw new Error(`flattenDiscriminatedUnion: variant for discriminator '${discriminator}' is not a ZodObject`);
|
|
87
140
|
}
|
|
88
141
|
const discValues = stringLiteralOrEnumValues(opt.shape[discriminator]);
|
|
@@ -95,7 +148,7 @@ function flattenDiscriminatedUnion(union) {
|
|
|
95
148
|
if (key === discriminator)
|
|
96
149
|
continue;
|
|
97
150
|
const entry = perKey.get(key) ?? { schemas: [], variants: [] };
|
|
98
|
-
entry.schemas.push(
|
|
151
|
+
entry.schemas.push(unwrapField(field));
|
|
99
152
|
entry.variants.push(label);
|
|
100
153
|
perKey.set(key, entry);
|
|
101
154
|
}
|
|
@@ -106,23 +159,44 @@ function flattenDiscriminatedUnion(union) {
|
|
|
106
159
|
throw new Error("flattenDiscriminatedUnion: union has no options");
|
|
107
160
|
}
|
|
108
161
|
const shape = {
|
|
109
|
-
[discriminator]:
|
|
162
|
+
[discriminator]: z3.enum([firstLiteral, ...restLiterals])
|
|
110
163
|
};
|
|
111
164
|
for (const [key, entry] of perKey) {
|
|
112
165
|
const advertised = mergeCollidingFields(entry.schemas);
|
|
113
166
|
const hint = `Required if ${discriminator} = ${[...new Set(entry.variants)].join(" | ")}`;
|
|
114
|
-
shape[key] =
|
|
167
|
+
shape[key] = z3.optional(advertised).describe(hint);
|
|
168
|
+
}
|
|
169
|
+
return withKeyPolicy(z3.object(shape), mergeVariantKeyPolicies(union.def.options));
|
|
170
|
+
}
|
|
171
|
+
function mergeVariantKeyPolicies(options) {
|
|
172
|
+
let strict = 0;
|
|
173
|
+
let counted = 0;
|
|
174
|
+
for (const option of options) {
|
|
175
|
+
const policy = option instanceof z3.ZodObject ? keyPolicyOf(option) : undefined;
|
|
176
|
+
if (policy !== undefined && !(policy instanceof z3.ZodNever))
|
|
177
|
+
return z3.unknown();
|
|
178
|
+
counted++;
|
|
179
|
+
if (policy instanceof z3.ZodNever)
|
|
180
|
+
strict++;
|
|
181
|
+
}
|
|
182
|
+
if (counted === 0 || strict === 0)
|
|
183
|
+
return;
|
|
184
|
+
return strict === counted ? z3.never() : z3.unknown();
|
|
185
|
+
}
|
|
186
|
+
function unwrapField(field) {
|
|
187
|
+
if (field instanceof z3.ZodOptional || field instanceof z3.ZodDefault) {
|
|
188
|
+
return unwrapField(field.unwrap());
|
|
115
189
|
}
|
|
116
|
-
return
|
|
190
|
+
return field;
|
|
117
191
|
}
|
|
118
192
|
function preserveDescription(from, to) {
|
|
119
193
|
return from.description === undefined ? to : to.describe(from.description);
|
|
120
194
|
}
|
|
121
195
|
function stringLiteralOrEnumValues(field) {
|
|
122
196
|
let raw = null;
|
|
123
|
-
if (field instanceof
|
|
197
|
+
if (field instanceof z3.ZodLiteral)
|
|
124
198
|
raw = field.def.values;
|
|
125
|
-
else if (field instanceof
|
|
199
|
+
else if (field instanceof z3.ZodEnum)
|
|
126
200
|
raw = field.options;
|
|
127
201
|
if (raw === null)
|
|
128
202
|
return null;
|
|
@@ -134,7 +208,7 @@ function isFlattenableDU(union) {
|
|
|
134
208
|
if (union.def.options.length === 0)
|
|
135
209
|
return false;
|
|
136
210
|
for (const opt of union.def.options) {
|
|
137
|
-
if (!(opt instanceof
|
|
211
|
+
if (!(opt instanceof z3.ZodObject))
|
|
138
212
|
return false;
|
|
139
213
|
if (stringLiteralOrEnumValues(opt.shape[disc]) === null)
|
|
140
214
|
return false;
|
|
@@ -156,31 +230,31 @@ function stripAnnotations(node) {
|
|
|
156
230
|
}
|
|
157
231
|
}
|
|
158
232
|
function hasChecks(schema) {
|
|
159
|
-
if (!(schema instanceof
|
|
233
|
+
if (!(schema instanceof z3.ZodType))
|
|
160
234
|
return false;
|
|
161
235
|
const def = schema.def;
|
|
162
236
|
if (isRecord(def) && Array.isArray(def.checks) && def.checks.length > 0)
|
|
163
237
|
return true;
|
|
164
|
-
if (schema instanceof
|
|
238
|
+
if (schema instanceof z3.ZodOptional || schema instanceof z3.ZodNullable || schema instanceof z3.ZodDefault) {
|
|
165
239
|
return hasChecks(schema.unwrap());
|
|
166
240
|
}
|
|
167
|
-
if (schema instanceof
|
|
241
|
+
if (schema instanceof z3.ZodPipe)
|
|
168
242
|
return hasChecks(schema.def.in) || hasChecks(schema.def.out);
|
|
169
|
-
if (schema instanceof
|
|
243
|
+
if (schema instanceof z3.ZodObject)
|
|
170
244
|
return Object.values(schema.shape).some(hasChecks);
|
|
171
|
-
if (schema instanceof
|
|
245
|
+
if (schema instanceof z3.ZodArray)
|
|
172
246
|
return hasChecks(schema.element);
|
|
173
|
-
if (schema instanceof
|
|
247
|
+
if (schema instanceof z3.ZodUnion)
|
|
174
248
|
return schema.def.options.some(hasChecks);
|
|
175
|
-
if (schema instanceof
|
|
249
|
+
if (schema instanceof z3.ZodRecord)
|
|
176
250
|
return hasChecks(schema.valueType);
|
|
177
|
-
if (schema instanceof
|
|
251
|
+
if (schema instanceof z3.ZodIntersection) {
|
|
178
252
|
return hasChecks(schema.def.left) || hasChecks(schema.def.right);
|
|
179
253
|
}
|
|
180
254
|
return false;
|
|
181
255
|
}
|
|
182
256
|
function normalizedJson(schema) {
|
|
183
|
-
if (!(schema instanceof
|
|
257
|
+
if (!(schema instanceof z3.ZodType))
|
|
184
258
|
return "{}";
|
|
185
259
|
const json = toJsonSchema(schema, "input", "any");
|
|
186
260
|
stripAnnotations(json);
|
|
@@ -197,8 +271,8 @@ function mergeCollidingFields(schemas) {
|
|
|
197
271
|
const only = values[0];
|
|
198
272
|
if (values.length <= 1) {
|
|
199
273
|
if (only === undefined)
|
|
200
|
-
return
|
|
201
|
-
return schemas.length > 1 && hasChecks(only) ?
|
|
274
|
+
return z3.unknown();
|
|
275
|
+
return schemas.length > 1 && hasChecks(only) ? z3.unknown() : only;
|
|
202
276
|
}
|
|
203
277
|
const merged = [];
|
|
204
278
|
let allEnum = true;
|
|
@@ -214,47 +288,47 @@ function mergeCollidingFields(schemas) {
|
|
|
214
288
|
const uniq = [...new Set(merged)];
|
|
215
289
|
const [first, ...rest] = uniq;
|
|
216
290
|
if (first !== undefined)
|
|
217
|
-
return
|
|
291
|
+
return z3.enum([first, ...rest]);
|
|
218
292
|
}
|
|
219
|
-
return
|
|
293
|
+
return z3.unknown();
|
|
220
294
|
}
|
|
221
295
|
function flattenUnionsDeep(schema) {
|
|
222
|
-
if (!(schema instanceof
|
|
223
|
-
return
|
|
224
|
-
if (schema instanceof
|
|
296
|
+
if (!(schema instanceof z3.ZodType))
|
|
297
|
+
return z3.unknown();
|
|
298
|
+
if (schema instanceof z3.ZodDiscriminatedUnion) {
|
|
225
299
|
if (!isFlattenableDU(schema))
|
|
226
300
|
return schema;
|
|
227
301
|
return preserveDescription(schema, flattenUnionsDeep(flattenDiscriminatedUnion(schema)));
|
|
228
302
|
}
|
|
229
|
-
if (schema instanceof
|
|
303
|
+
if (schema instanceof z3.ZodObject) {
|
|
230
304
|
const shape = {};
|
|
231
305
|
for (const [key, field] of Object.entries(schema.shape)) {
|
|
232
306
|
shape[key] = flattenUnionsDeep(field);
|
|
233
307
|
}
|
|
234
|
-
return preserveDescription(schema,
|
|
308
|
+
return preserveDescription(schema, rebuildObject(schema, shape));
|
|
235
309
|
}
|
|
236
|
-
if (schema instanceof
|
|
237
|
-
return preserveDescription(schema,
|
|
310
|
+
if (schema instanceof z3.ZodArray) {
|
|
311
|
+
return preserveDescription(schema, z3.array(flattenUnionsDeep(schema.element)));
|
|
238
312
|
}
|
|
239
|
-
if (schema instanceof
|
|
313
|
+
if (schema instanceof z3.ZodUnion) {
|
|
240
314
|
const opts = schema.def.options.map((option) => flattenUnionsDeep(option));
|
|
241
315
|
const [a, b, ...rest] = opts;
|
|
242
|
-
return a && b ? preserveDescription(schema,
|
|
316
|
+
return a && b ? preserveDescription(schema, z3.union([a, b, ...rest])) : schema;
|
|
243
317
|
}
|
|
244
|
-
if (schema instanceof
|
|
245
|
-
return preserveDescription(schema,
|
|
318
|
+
if (schema instanceof z3.ZodRecord) {
|
|
319
|
+
return preserveDescription(schema, z3.record(schema.keyType, flattenUnionsDeep(schema.valueType)));
|
|
246
320
|
}
|
|
247
|
-
if (schema instanceof
|
|
248
|
-
return preserveDescription(schema,
|
|
321
|
+
if (schema instanceof z3.ZodOptional) {
|
|
322
|
+
return preserveDescription(schema, z3.optional(flattenUnionsDeep(schema.unwrap())));
|
|
249
323
|
}
|
|
250
|
-
if (schema instanceof
|
|
251
|
-
return preserveDescription(schema,
|
|
324
|
+
if (schema instanceof z3.ZodNullable) {
|
|
325
|
+
return preserveDescription(schema, z3.nullable(flattenUnionsDeep(schema.unwrap())));
|
|
252
326
|
}
|
|
253
|
-
if (schema instanceof
|
|
327
|
+
if (schema instanceof z3.ZodDefault) {
|
|
254
328
|
return preserveDescription(schema, flattenUnionsDeep(schema.unwrap()).default(schema.def.defaultValue));
|
|
255
329
|
}
|
|
256
|
-
if (schema instanceof
|
|
257
|
-
return preserveDescription(schema,
|
|
330
|
+
if (schema instanceof z3.ZodIntersection) {
|
|
331
|
+
return preserveDescription(schema, z3.intersection(flattenUnionsDeep(schema.def.left), flattenUnionsDeep(schema.def.right)));
|
|
258
332
|
}
|
|
259
333
|
return schema;
|
|
260
334
|
}
|
|
@@ -262,31 +336,6 @@ function flattenUnionsDeep(schema) {
|
|
|
262
336
|
// src/tools/mount.ts
|
|
263
337
|
import { z as z4 } from "zod";
|
|
264
338
|
|
|
265
|
-
// src/tools/schema.ts
|
|
266
|
-
import { z as z3 } from "zod";
|
|
267
|
-
function objectShapeKeys(schema) {
|
|
268
|
-
return schema instanceof z3.ZodObject ? Object.keys(schema.shape) : [];
|
|
269
|
-
}
|
|
270
|
-
function mergeSchemas(paramsSchema, inputSchema) {
|
|
271
|
-
if (paramsSchema && !(paramsSchema instanceof z3.ZodObject)) {
|
|
272
|
-
throw new Error("Tool params schema must be a z.object()");
|
|
273
|
-
}
|
|
274
|
-
const paramsObject = paramsSchema instanceof z3.ZodObject ? paramsSchema : undefined;
|
|
275
|
-
if (!inputSchema) {
|
|
276
|
-
return paramsObject ?? z3.object({});
|
|
277
|
-
}
|
|
278
|
-
if (inputSchema instanceof z3.ZodObject) {
|
|
279
|
-
if (paramsObject) {
|
|
280
|
-
const conflicts = Object.keys(paramsObject.shape).filter((key) => (key in inputSchema.shape));
|
|
281
|
-
if (conflicts.length > 0) {
|
|
282
|
-
throw new Error(`Schema merge conflict: ${conflicts.join(", ")} appear in both params and input`);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
return z3.object({ ...paramsObject?.shape ?? {}, ...inputSchema.shape });
|
|
286
|
-
}
|
|
287
|
-
return paramsObject ? z3.intersection(paramsObject, inputSchema) : inputSchema;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
339
|
// src/tools/execute.ts
|
|
291
340
|
function toolResultFromError(err) {
|
|
292
341
|
const appErr = normalizeError(err);
|
|
@@ -421,7 +470,7 @@ function applyExtend(base, extra) {
|
|
|
421
470
|
if (conflicts.length > 0) {
|
|
422
471
|
throw new Error(`Tool extend conflict: ${conflicts.join(", ")} already declared by the contract`);
|
|
423
472
|
}
|
|
424
|
-
return
|
|
473
|
+
return rebuildObject(base, { ...extra, ...base.shape });
|
|
425
474
|
}
|
|
426
475
|
return z4.intersection(z4.object(extra), base);
|
|
427
476
|
}
|
package/dist/tools/coerce.d.ts
CHANGED
|
@@ -6,7 +6,8 @@ import { z } from 'zod';
|
|
|
6
6
|
* Operates recursively against the schema (object fields, array items, and the
|
|
7
7
|
* matching variant of a discriminated union) so a stringified value at any depth
|
|
8
8
|
* is repaired, not just a top-level field. The transform touches the **arguments**
|
|
9
|
-
* only —
|
|
9
|
+
* only — it never rebuilds a schema, so it cannot alter what an object does with
|
|
10
|
+
* an undeclared key (→ ADR 0034).
|
|
10
11
|
*/
|
|
11
12
|
export declare function coerceJsonArgs(args: Record<string, unknown>, schema: z.ZodType | undefined): Record<string, unknown>;
|
|
12
13
|
//# sourceMappingURL=coerce.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coerce.d.ts","sourceRoot":"","sources":["../../src/tools/coerce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAoFxB
|
|
1
|
+
{"version":3,"file":"coerce.d.ts","sourceRoot":"","sources":["../../src/tools/coerce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAoFxB;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,SAAS,GAC5B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGzB"}
|
package/dist/tools/flatten.d.ts
CHANGED
|
@@ -18,10 +18,18 @@ import { z } from 'zod';
|
|
|
18
18
|
* 0033) **and** a superset of the original union, so a model can always produce a
|
|
19
19
|
* value that passes both the transport SDK and validation.
|
|
20
20
|
*
|
|
21
|
-
* **
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
21
|
+
* **Key policy is merged, not dropped.** The flat object stands in for every
|
|
22
|
+
* variant, so it takes the policy that cannot remove what any variant would have
|
|
23
|
+
* kept: every variant `.strict()` → strict (sound, because the flat shape is the
|
|
24
|
+
* union of all variant keys); any variant with a catchall → loose; otherwise
|
|
25
|
+
* plain. A *typed* catchall is never copied onto the flat object — it would
|
|
26
|
+
* reject a sibling variant's differently-typed extra key.
|
|
27
|
+
*
|
|
28
|
+
* **Still lossy:** per-variant strictness (a key legal in variant A and illegal
|
|
29
|
+
* in B) is unrepresentable in one flat object, as are object-level refinements.
|
|
30
|
+
* Those stay enforced only by the original union in `executeToolMethod`. What is
|
|
31
|
+
* *not* lossy any more is deletion — the advertised schema can no longer drop a
|
|
32
|
+
* key the contract would have seen. → ADR 0034.
|
|
25
33
|
*/
|
|
26
34
|
export declare function flattenDiscriminatedUnion(union: z.ZodDiscriminatedUnion): z.ZodObject<z.ZodRawShape>;
|
|
27
35
|
/**
|
|
@@ -30,8 +38,10 @@ export declare function flattenDiscriminatedUnion(union: z.ZodDiscriminatedUnion
|
|
|
30
38
|
* and `optional` / `nullable` / `default` / intersection wrappers — so the
|
|
31
39
|
* advertised JSON Schema carries no `oneOf` / `anyOf` at any depth. A union that
|
|
32
40
|
* cannot be flattened (non-string discriminator, non-object variant) is left
|
|
33
|
-
* untouched rather than crashing the mount (→ ADR 0033).
|
|
34
|
-
*
|
|
41
|
+
* untouched rather than crashing the mount (→ ADR 0033).
|
|
42
|
+
*
|
|
43
|
+
* Every object is rebuilt **with its key policy** (`rebuildObject`) — the walk
|
|
44
|
+
* changes union shape, never what an object does with an undeclared key. → ADR 0034.
|
|
35
45
|
*/
|
|
36
46
|
export declare function flattenUnionsDeep(schema: z.core.$ZodType): z.ZodType;
|
|
37
47
|
//# sourceMappingURL=flatten.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flatten.d.ts","sourceRoot":"","sources":["../../src/tools/flatten.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"flatten.d.ts","sourceRoot":"","sources":["../../src/tools/flatten.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,CAAC,CAAC,qBAAqB,GAC7B,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAiD5B;AAsKD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,OAAO,CAqDpE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/tools/mount.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,WAAW,CAAC;AAKnB;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU,CACzB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAElE,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IAClC,qEAAqE;IACrE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC3F,uEAAuE;IACvE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC;CAC9D;AAED,2DAA2D;AAC3D,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,MAAM,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,sFAAsF;IACtF,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC;IAClB,mDAAmD;IACnD,YAAY,EAAE,OAAO,CAAC;CACvB;
|
|
1
|
+
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/tools/mount.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,WAAW,CAAC;AAKnB;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU,CACzB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAElE,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IAClC,qEAAqE;IACrE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC3F,uEAAuE;IACvE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC;CAC9D;AAED,2DAA2D;AAC3D,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,MAAM,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,sFAAsF;IACtF,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC;IAClB,mDAAmD;IACnD,YAAY,EAAE,OAAO,CAAC;CACvB;AAyBD,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,uFAAuF;IACvF,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,SAAS,EACpB,MAAM,GAAE,kBAAuB,GAC9B,aAAa,EAAE,CAmCjB;AAED,kDAAkD;AAClD,MAAM,WAAW,gBAAgB;IAC/B,iDAAiD;IACjD,MAAM,EAAE,eAAe,CAAC;IACxB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,qCAAqC;IACrC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,yEAAyE;IACzE,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,gEAAgE;IAChE,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,gBAAgB,GACvB,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,UAAU,CAAC,CA4BhF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC,EAC1C,QAAQ,CAAC,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,WAAW,GACtB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAazB"}
|
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
import type { RawRoute } from '../server/types';
|
|
2
|
+
/**
|
|
3
|
+
* OpenID Connect DCR `application_type` (SEP-837). A `native` client (desktop /
|
|
4
|
+
* CLI) may register an `http` loopback redirect; a `web` client may not — the
|
|
5
|
+
* mismatch is the usual cause of a `redirect_uri` rejection for CLI clients.
|
|
6
|
+
*/
|
|
7
|
+
export type ApplicationType = 'native' | 'web';
|
|
2
8
|
/** A client as registered via DCR. Public clients (PKCE) carry no secret. */
|
|
3
9
|
export interface RegisteredClient {
|
|
4
10
|
clientId: string;
|
|
5
11
|
redirectUris: string[];
|
|
6
12
|
clientName?: string;
|
|
13
|
+
/** The `application_type` the client declared, when it declared one. */
|
|
14
|
+
applicationType?: ApplicationType;
|
|
7
15
|
}
|
|
8
16
|
/** Metadata posted to `/register` (RFC 7591) before a client id is assigned. */
|
|
9
17
|
export interface ClientMetadata {
|
|
10
18
|
redirectUris: string[];
|
|
11
19
|
clientName?: string;
|
|
12
20
|
tokenEndpointAuthMethod?: string;
|
|
21
|
+
/** `native` (desktop / CLI, loopback allowed) or `web` (https only). */
|
|
22
|
+
applicationType?: ApplicationType;
|
|
13
23
|
}
|
|
14
24
|
/** State persisted between `/authorize` and `/token`, keyed by the auth code. */
|
|
15
25
|
export interface AuthCodeData {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-provider.d.ts","sourceRoot":"","sources":["../../src/tools/oauth-provider.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"oauth-provider.d.ts","sourceRoot":"","sources":["../../src/tools/oauth-provider.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/schema.d.ts
CHANGED
|
@@ -1,6 +1,39 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
/** Keys of a Zod object schema's shape — `[]` for a non-object or absent schema. */
|
|
3
3
|
export declare function objectShapeKeys(schema?: z.ZodType): string[];
|
|
4
|
+
/**
|
|
5
|
+
* An object schema's own key policy — what it does with a key its shape does not
|
|
6
|
+
* declare. Zod stores it in `def.catchall`: `ZodNever` for `.strict()` (reject),
|
|
7
|
+
* `ZodUnknown` for `.loose()` / `.passthrough()` (keep), a concrete type for
|
|
8
|
+
* `.catchall(T)` (keep and validate), `undefined` for a plain object (strip).
|
|
9
|
+
*/
|
|
10
|
+
export type KeyPolicy = z.core.$ZodType | undefined;
|
|
11
|
+
/** The key policy of an object schema. */
|
|
12
|
+
export declare function keyPolicyOf(schema: z.ZodObject): KeyPolicy;
|
|
13
|
+
/**
|
|
14
|
+
* Rebuild an object schema with a new shape, **carrying the source object's key
|
|
15
|
+
* policy over**.
|
|
16
|
+
*
|
|
17
|
+
* Load-bearing, not cosmetic: the advertised tool schema is not
|
|
18
|
+
* advertised-only. Both transport SDKs parse the caller's arguments *with it* and
|
|
19
|
+
* hand the handler the parsed result (MCP `validateToolInput` →
|
|
20
|
+
* `parseResult.data`; the AI SDK's `doParseToolCall` → `parseResult.value`), so
|
|
21
|
+
* an object rebuilt as a bare `z.object()` silently **deletes** every key the
|
|
22
|
+
* contract schema would have rejected (`.strict()`) or kept (`.loose()` /
|
|
23
|
+
* `.catchall()`) — the caller gets a success and never learns its argument was
|
|
24
|
+
* wrong. → ADR 0034.
|
|
25
|
+
*
|
|
26
|
+
* A plain source (`undefined` policy) needs no special case: the rebuilt object
|
|
27
|
+
* strips exactly as the contract object would have.
|
|
28
|
+
*
|
|
29
|
+
* A policy JSON Schema cannot represent (`.catchall(z.date())`) degrades to
|
|
30
|
+
* `z.unknown()`: copying it verbatim would fail the mount's JSON Schema probe and
|
|
31
|
+
* take every tool down with it, while dropping it would silently delete data.
|
|
32
|
+
* Loose keeps the invariant — nothing the contract would have kept is removed.
|
|
33
|
+
*/
|
|
34
|
+
export declare function rebuildObject(source: z.ZodObject, shape: Record<string, z.core.$ZodType>): z.ZodObject;
|
|
35
|
+
/** Apply a key policy to a freshly built object, degrading what JSON Schema cannot carry. */
|
|
36
|
+
export declare function withKeyPolicy(object: z.ZodObject<z.ZodRawShape>, policy: KeyPolicy): z.ZodObject;
|
|
4
37
|
/**
|
|
5
38
|
* Merge an endpoint's `params` and `input` schemas into the single schema a
|
|
6
39
|
* tool advertises.
|
|
@@ -10,12 +43,21 @@ export declare function objectShapeKeys(schema?: z.ZodType): string[];
|
|
|
10
43
|
* - A non-object `input` (a union, a discriminated union, a refined / piped
|
|
11
44
|
* schema) is kept intact and intersected with `params` when present — the
|
|
12
45
|
* transport SDK converts it natively (a discriminated union becomes a clean
|
|
13
|
-
* `oneOf`).
|
|
46
|
+
* `oneOf`). ⚠️ Zod drops both sides' key policy when it intersects objects, so
|
|
47
|
+
* this branch still strips (MCP rejects a non-object merged schema at mount;
|
|
48
|
+
* the agent surface does not). → ADR 0034, "Not covered".
|
|
14
49
|
*
|
|
15
50
|
* The merged schema is exactly the two source schemas side by side: nothing is
|
|
16
51
|
* coerced, flattened or transformed, so the schema a tool advertises is the
|
|
17
52
|
* schema its arguments are validated against (`executeToolMethod` parses each
|
|
18
53
|
* source schema over its own slice of the args).
|
|
54
|
+
*
|
|
55
|
+
* The merged object takes the **input** schema's key policy, never the params
|
|
56
|
+
* one. `executeToolMethod` slices the flat args by the params shape's keys and
|
|
57
|
+
* routes *everything else* into the input slice, so a params catchall can never
|
|
58
|
+
* fire (its slice is built from its own shape) while an undeclared top-level key
|
|
59
|
+
* is judged by the input schema. A params-only tool returns the params object
|
|
60
|
+
* untouched, policy included.
|
|
19
61
|
*/
|
|
20
62
|
export declare function mergeSchemas(paramsSchema?: z.ZodType<unknown>, inputSchema?: z.ZodType<unknown>): z.ZodType;
|
|
21
63
|
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/tools/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/tools/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,GAAG,MAAM,EAAE,CAE5D;AAED;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;AAEpD,0CAA0C;AAC1C,wBAAgB,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,SAAS,GAAG,SAAS,CAE1D;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,CAAC,CAAC,SAAS,EACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GACrC,CAAC,CAAC,SAAS,CAEb;AAED,6FAA6F;AAC7F,wBAAgB,aAAa,CAC3B,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,EAClC,MAAM,EAAE,SAAS,GAChB,CAAC,CAAC,SAAS,CAGb;AAcD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,YAAY,CAC1B,YAAY,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EACjC,WAAW,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAC/B,CAAC,CAAC,OAAO,CA8BX"}
|
package/dist/tools.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export { type DownloadToolConfig, mountDownload } from './tools/mount-download';
|
|
|
17
17
|
export { mountUpload, type UploadToolConfig } from './tools/mount-upload';
|
|
18
18
|
export { mountWait, type WaitToolConfig } from './tools/mount-wait';
|
|
19
19
|
export { oauthProtectedResourceRoute, PROTECTED_RESOURCE_PATH, type ProtectedResourceConfig, protectedResourceMetadataUrl, wwwAuthenticateHeader, } from './tools/oauth-metadata';
|
|
20
|
-
export { type AuthCodeData, type AuthRequest, type ClientMetadata, mountOAuthProvider, type OAuthProviderConfig, type RefreshData, type RegisteredClient, } from './tools/oauth-provider';
|
|
20
|
+
export { type ApplicationType, type AuthCodeData, type AuthRequest, type ClientMetadata, mountOAuthProvider, type OAuthProviderConfig, type RefreshData, type RegisteredClient, } from './tools/oauth-provider';
|
|
21
21
|
export { type ImplementRemoteOptions, implementRemote } from './tools/remote';
|
|
22
22
|
export { createToolLogger, type ToolCallRecord, type ToolLoggerConfig, } from './tools/tool-logger';
|
|
23
23
|
export { createToolkit, type Toolkit } from './tools/toolkit';
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7F,OAAO,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EACL,cAAc,EACd,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,2BAA2B,EAC3B,kBAAkB,EAClB,KAAK,SAAS,EACd,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,KAAK,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,KAAK,kBAAkB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,KAAK,uBAAuB,EAC5B,4BAA4B,EAC5B,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,KAAK,sBAAsB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EACL,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EACL,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,KAAK,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7F,OAAO,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EACL,cAAc,EACd,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,2BAA2B,EAC3B,kBAAkB,EAClB,KAAK,SAAS,EACd,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,KAAK,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,KAAK,kBAAkB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,KAAK,uBAAuB,EAC5B,4BAA4B,EAC5B,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,KAAK,sBAAsB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EACL,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EACL,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,KAAK,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/tools.js
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
pollUntil,
|
|
19
19
|
readCapped,
|
|
20
20
|
toolResultFromError
|
|
21
|
-
} from "./index-
|
|
21
|
+
} from "./index-h9d1fm0p.js";
|
|
22
22
|
import {
|
|
23
23
|
toJsonSchema
|
|
24
24
|
} from "./index-0ed3bx43.js";
|
|
@@ -615,13 +615,15 @@ function json(body, status = 200, extraHeaders) {
|
|
|
615
615
|
function oauthError(error, description, status = 400) {
|
|
616
616
|
return json({ error, error_description: description }, status);
|
|
617
617
|
}
|
|
618
|
-
function
|
|
618
|
+
function isRegistrableRedirectUri(value, applicationType) {
|
|
619
619
|
try {
|
|
620
620
|
const url = new URL(value);
|
|
621
621
|
if (url.protocol === "https:")
|
|
622
622
|
return true;
|
|
623
623
|
if (url.protocol !== "http:")
|
|
624
624
|
return false;
|
|
625
|
+
if (applicationType === "web")
|
|
626
|
+
return false;
|
|
625
627
|
const host = url.hostname.replace(/^\[|\]$/g, "");
|
|
626
628
|
return host === "127.0.0.1" || host === "::1" || host === "localhost";
|
|
627
629
|
} catch {
|
|
@@ -655,6 +657,7 @@ function mountOAuthProvider(config) {
|
|
|
655
657
|
const registerPath = `${base}/register`;
|
|
656
658
|
const authorizePath = `${base}/authorize`;
|
|
657
659
|
const tokenPath = `${base}/token`;
|
|
660
|
+
const redirectToClient = (uri, params) => redirectWith(uri, { ...params, iss: config.issuer });
|
|
658
661
|
const metadataRoute = {
|
|
659
662
|
method: "ALL",
|
|
660
663
|
path: AS_METADATA_PATH,
|
|
@@ -670,6 +673,7 @@ function mountOAuthProvider(config) {
|
|
|
670
673
|
grant_types_supported: config.refreshTokens ? ["authorization_code", "refresh_token"] : ["authorization_code"],
|
|
671
674
|
code_challenge_methods_supported: ["S256"],
|
|
672
675
|
token_endpoint_auth_methods_supported: ["none"],
|
|
676
|
+
authorization_response_iss_parameter_supported: true,
|
|
673
677
|
...config.scopesSupported && { scopes_supported: config.scopesSupported }
|
|
674
678
|
});
|
|
675
679
|
}
|
|
@@ -686,14 +690,20 @@ function mountOAuthProvider(config) {
|
|
|
686
690
|
if (!isRecord(meta)) {
|
|
687
691
|
return oauthError("invalid_client_metadata", "Body must be a JSON object");
|
|
688
692
|
}
|
|
693
|
+
const rawAppType = meta.application_type;
|
|
694
|
+
if (rawAppType !== undefined && rawAppType !== "native" && rawAppType !== "web") {
|
|
695
|
+
return oauthError("invalid_client_metadata", "application_type must be 'native' or 'web'");
|
|
696
|
+
}
|
|
697
|
+
const applicationType = rawAppType;
|
|
689
698
|
const redirectUris = meta.redirect_uris;
|
|
690
|
-
if (!Array.isArray(redirectUris) || redirectUris.length === 0 || !redirectUris.every((u) => typeof u === "string" &&
|
|
691
|
-
return oauthError("invalid_redirect_uri", "redirect_uris must be a non-empty array of absolute https URLs (http is allowed only on a loopback host)");
|
|
699
|
+
if (!Array.isArray(redirectUris) || redirectUris.length === 0 || !redirectUris.every((u) => typeof u === "string" && isRegistrableRedirectUri(u, applicationType))) {
|
|
700
|
+
return oauthError("invalid_redirect_uri", applicationType === "web" ? "redirect_uris must be a non-empty array of absolute https URLs (a web client cannot register an http loopback URI)" : "redirect_uris must be a non-empty array of absolute https URLs (http is allowed only on a loopback host)");
|
|
692
701
|
}
|
|
693
702
|
const client = await config.clients.register({
|
|
694
703
|
redirectUris,
|
|
695
704
|
clientName: typeof meta.client_name === "string" ? meta.client_name : undefined,
|
|
696
|
-
tokenEndpointAuthMethod: typeof meta.token_endpoint_auth_method === "string" ? meta.token_endpoint_auth_method : undefined
|
|
705
|
+
tokenEndpointAuthMethod: typeof meta.token_endpoint_auth_method === "string" ? meta.token_endpoint_auth_method : undefined,
|
|
706
|
+
...applicationType && { applicationType }
|
|
697
707
|
});
|
|
698
708
|
return json({
|
|
699
709
|
client_id: client.clientId,
|
|
@@ -701,7 +711,8 @@ function mountOAuthProvider(config) {
|
|
|
701
711
|
token_endpoint_auth_method: "none",
|
|
702
712
|
grant_types: config.refreshTokens ? ["authorization_code", "refresh_token"] : ["authorization_code"],
|
|
703
713
|
response_types: ["code"],
|
|
704
|
-
...client.clientName && { client_name: client.clientName }
|
|
714
|
+
...client.clientName && { client_name: client.clientName },
|
|
715
|
+
...client.applicationType && { application_type: client.applicationType }
|
|
705
716
|
}, 201);
|
|
706
717
|
}
|
|
707
718
|
};
|
|
@@ -731,27 +742,27 @@ function mountOAuthProvider(config) {
|
|
|
731
742
|
return oauthError("invalid_request", "redirect_uri does not match a registered URI");
|
|
732
743
|
}
|
|
733
744
|
if (responseType !== "code") {
|
|
734
|
-
return
|
|
745
|
+
return redirectToClient(redirectUri, {
|
|
735
746
|
error: "unsupported_response_type",
|
|
736
747
|
...state && { state }
|
|
737
748
|
});
|
|
738
749
|
}
|
|
739
750
|
if (!codeChallenge || codeChallengeMethod !== "S256") {
|
|
740
|
-
return
|
|
751
|
+
return redirectToClient(redirectUri, {
|
|
741
752
|
error: "invalid_request",
|
|
742
753
|
error_description: "PKCE S256 code_challenge is required",
|
|
743
754
|
...state && { state }
|
|
744
755
|
});
|
|
745
756
|
}
|
|
746
757
|
if (!resource) {
|
|
747
|
-
return
|
|
758
|
+
return redirectToClient(redirectUri, {
|
|
748
759
|
error: "invalid_target",
|
|
749
760
|
error_description: "resource parameter is required",
|
|
750
761
|
...state && { state }
|
|
751
762
|
});
|
|
752
763
|
}
|
|
753
764
|
if (resource !== config.resource) {
|
|
754
|
-
return
|
|
765
|
+
return redirectToClient(redirectUri, {
|
|
755
766
|
error: "invalid_target",
|
|
756
767
|
error_description: "resource is not served by this authorization server",
|
|
757
768
|
...state && { state }
|
|
@@ -772,7 +783,7 @@ function mountOAuthProvider(config) {
|
|
|
772
783
|
userId: result.userId,
|
|
773
784
|
expiresAt: Date.now() + AUTH_CODE_TTL_MS
|
|
774
785
|
});
|
|
775
|
-
return
|
|
786
|
+
return redirectToClient(redirectUri, { code, ...state && { state } });
|
|
776
787
|
}
|
|
777
788
|
};
|
|
778
789
|
const issueAccessToken = (userId, audience, clientId, scope) => signJwt({ scope, client_id: clientId }, config.signingSecret, {
|
package/llms-full.txt
CHANGED
|
@@ -1303,11 +1303,23 @@ each variant's fields become optional with a `Required if <disc> = …` hint.
|
|
|
1303
1303
|
It is **deep**: unions are flattened at every depth — top level, object fields,
|
|
1304
1304
|
array items, and through `optional` / `nullable` / `default` / intersection
|
|
1305
1305
|
wrappers — so no `oneOf` survives anywhere (e.g. a `content.parts[]` that is an
|
|
1306
|
-
array of a discriminated union).
|
|
1307
|
-
schemas stay the validation schemas in `executeToolMethod`, so requests are still
|
|
1308
|
-
validated against the real union. Schemas a transform cannot safely rebuild
|
|
1306
|
+
array of a discriminated union). Schemas a transform cannot safely rebuild
|
|
1309
1307
|
(refined / piped / lazy / plain non-discriminated unions) are left as-is.
|
|
1310
1308
|
|
|
1309
|
+
The flattened form is **lossy but never destructive**. Lossy: per-variant
|
|
1310
|
+
strictness and object-level refinements are not advertised — the original schemas
|
|
1311
|
+
enforce them in `executeToolMethod`. Not destructive: every object keeps its own
|
|
1312
|
+
**key policy** (`.strict()` stays strict, `.loose()` / `.catchall()` still keep
|
|
1313
|
+
extra keys), because the advertised schema is not advertised-only — the MCP and
|
|
1314
|
+
AI SDKs parse the caller's arguments *with it* and hand the handler the parsed
|
|
1315
|
+
result. An object advertised without its policy would silently delete keys the
|
|
1316
|
+
contract would have rejected. → [ADR 0034](../decisions/0034-advertised-schema-key-policy.md).
|
|
1317
|
+
|
|
1318
|
+
A consequence worth knowing when you read logs: a `.strict()` violation is caught
|
|
1319
|
+
by the SDK **before** the tool callback runs, so it comes back as an MCP
|
|
1320
|
+
`InvalidParams` protocol error rather than a stitchkit `VALIDATION_ERROR`
|
|
1321
|
+
envelope, and `beforeToolCall` / `afterToolCall` do not fire for it.
|
|
1322
|
+
|
|
1311
1323
|
## `mountMcp`
|
|
1312
1324
|
|
|
1313
1325
|
If you already run an `McpServer` from the SDK, `mountMcp` adds contract tools
|
|
@@ -1393,14 +1405,36 @@ createServer({
|
|
|
1393
1405
|
})
|
|
1394
1406
|
```
|
|
1395
1407
|
|
|
1396
|
-
Access tokens are signed HS256 JWTs (`signJwt`) whose `aud` is the resource
|
|
1397
|
-
validate
|
|
1398
|
-
`
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
server can co-locate or live
|
|
1408
|
+
Access tokens are signed HS256 JWTs (`signJwt`) whose `aud` is the resource and
|
|
1409
|
+
whose `iss` is the issuer — validate both in `auth` with
|
|
1410
|
+
`verifyJwt(token, secret, { audience: resource, issuer })`. `authorizeUser` is
|
|
1411
|
+
where the app authenticates the user (reuse an existing session) and records
|
|
1412
|
+
consent; return `{ userId }` to issue a code, or a `Response` to redirect the
|
|
1413
|
+
browser to a login page first. The AS and resource server can co-locate or live
|
|
1414
|
+
on separate origins. See
|
|
1402
1415
|
[ADR 0015](../decisions/0015-oauth-resource-server.md).
|
|
1403
1416
|
|
|
1417
|
+
### Authorization hardening (MCP 2026-07-28)
|
|
1418
|
+
|
|
1419
|
+
- **`iss` on every authorization response (RFC 9207, SEP-2468).** Success *and*
|
|
1420
|
+
error redirects carry `iss`, and the AS metadata advertises
|
|
1421
|
+
`authorization_response_iss_parameter_supported: true`. A client that talks to
|
|
1422
|
+
several authorization servers validates `iss` before redeeming the code, which
|
|
1423
|
+
closes the **mix-up attack** — an attacker's server cannot pass its response
|
|
1424
|
+
off as this issuer's. Additive on the wire: a client that ignores `iss` is
|
|
1425
|
+
unaffected.
|
|
1426
|
+
- **`application_type` on registration (SEP-837).** A client may declare
|
|
1427
|
+
`"native"` (desktop / CLI) or `"web"` in its DCR body. A **native** client may
|
|
1428
|
+
register an `http` loopback redirect (`http://127.0.0.1:…`, RFC 8252 §7.3); a
|
|
1429
|
+
**web** client is held to `https` only — that mismatch is the usual cause of
|
|
1430
|
+
the `redirect_uri` rejection CLI clients hit. Omit the field and registration
|
|
1431
|
+
behaves exactly as before (loopback allowed); an unknown value is rejected
|
|
1432
|
+
rather than silently defaulted.
|
|
1433
|
+
|
|
1434
|
+
> Dynamic Client Registration is **deprecated** in the 2026-07-28 spec in favour
|
|
1435
|
+
> of Client ID Metadata Documents (CIMD), with a ≥12-month window. DCR keeps
|
|
1436
|
+
> working and stays supported here; CIMD support is tracked separately.
|
|
1437
|
+
|
|
1404
1438
|
## Proxying a remote API — `implementRemote`
|
|
1405
1439
|
|
|
1406
1440
|
`implement` binds a contract to local handlers. `implementRemote` binds it to a
|
|
@@ -3470,6 +3504,7 @@ A native remote-connector auth surface for MCP — [guide](../guide/mcp-and-agen
|
|
|
3470
3504
|
| `PROTECTED_RESOURCE_PATH` | const | the well-known metadata path |
|
|
3471
3505
|
| `OAuthProviderConfig` | _type_ | config for `mountOAuthProvider` |
|
|
3472
3506
|
| `ProtectedResourceConfig` | _type_ | config for `oauthProtectedResourceRoute` |
|
|
3507
|
+
| `ApplicationType` | _type_ | DCR `application_type` — `'native'` (loopback allowed) \| `'web'` (https only) |
|
|
3473
3508
|
| `AuthCodeData` | _type_ | a stored authorization-code record |
|
|
3474
3509
|
| `AuthRequest` | _type_ | a parsed authorization request |
|
|
3475
3510
|
| `ClientMetadata` | _type_ | dynamic-client-registration metadata |
|
|
@@ -3506,7 +3541,7 @@ Advanced building blocks — the shared machinery the mounts are built on.
|
|
|
3506
3541
|
| `TransportCounts` | _type_ | per-transport counts (`{ HTTP, MCP, AGENT, CLI }`) |
|
|
3507
3542
|
| `coerceJsonArgs` | function | coerce JSON-stringified array/object tool arguments |
|
|
3508
3543
|
| `flattenDiscriminatedUnion` | function | flatten one discriminated union into a single object schema |
|
|
3509
|
-
| `flattenUnionsDeep` | function | flatten discriminated unions at every depth
|
|
3544
|
+
| `flattenUnionsDeep` | function | flatten discriminated unions at every depth — union shape only; each object keeps its own key policy (`.strict()` / `.loose()` / `.catchall()`) |
|
|
3510
3545
|
| `MountableTool` | _type_ | one contract method resolved for mounting |
|
|
3511
3546
|
| `ToolManifestEntry` | _type_ | one `buildToolManifest` row |
|
|
3512
3547
|
|
package/package.json
CHANGED