stitchkit 0.41.0 → 0.42.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 +2 -2
- package/dist/contract/errors-factory.d.ts +88 -15
- package/dist/contract/errors-factory.d.ts.map +1 -1
- package/dist/contract/errors.d.ts +4 -4
- package/dist/contract/errors.d.ts.map +1 -1
- package/dist/contract/index.d.ts +1 -1
- package/dist/contract/index.d.ts.map +1 -1
- package/dist/contract/index.js +2 -2
- package/dist/{index-xax049k6.js → index-11x5dts2.js} +44 -13
- package/dist/{index-4e1c0hsw.js → index-181aebw8.js} +1 -1
- package/dist/{index-dnkefke9.js → index-310bfer5.js} +1 -1
- package/dist/{index-sc67e454.js → index-gex6gxhe.js} +7 -4
- package/dist/{index-ncqqn1bc.js → index-p9vkwns1.js} +2 -2
- package/dist/{index-809wc1tt.js → index-s4qsmgwe.js} +4 -1
- package/dist/index.js +2 -2
- package/dist/internal/typed.d.ts +8 -0
- package/dist/internal/typed.d.ts.map +1 -1
- package/dist/node.js +2 -2
- package/dist/observability/index.js +1 -1
- package/dist/react.js +1 -1
- package/dist/server/error-hook.d.ts +8 -4
- package/dist/server/error-hook.d.ts.map +1 -1
- package/dist/server/index.js +7 -6
- package/dist/tools/agent.d.ts +1 -1
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/list-names.d.ts +8 -6
- package/dist/tools/list-names.d.ts.map +1 -1
- package/dist/tools/manifest.d.ts +13 -5
- package/dist/tools/manifest.d.ts.map +1 -1
- package/dist/tools/mcp-handler.d.ts +5 -4
- package/dist/tools/mcp-handler.d.ts.map +1 -1
- package/dist/tools/mcp-stdio.d.ts +3 -2
- package/dist/tools/mcp-stdio.d.ts.map +1 -1
- package/dist/tools/mcp.d.ts +49 -9
- package/dist/tools/mcp.d.ts.map +1 -1
- package/dist/tools/native-mcp.d.ts +4 -18
- package/dist/tools/native-mcp.d.ts.map +1 -1
- package/dist/tools/runtime-tool.d.ts +1 -1
- package/dist/tools/runtime-tool.d.ts.map +1 -1
- package/dist/tools/surface.d.ts +37 -0
- package/dist/tools/surface.d.ts.map +1 -0
- package/dist/tools/toolkit.d.ts +4 -4
- package/dist/tools/toolkit.d.ts.map +1 -1
- package/dist/tools/transports.d.ts +11 -9
- package/dist/tools/transports.d.ts.map +1 -1
- package/dist/tools/view-file.d.ts +3 -3
- package/dist/tools.d.ts +5 -5
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +292 -155
- package/llms-full.txt +264 -47
- package/package.json +1 -1
package/llms-full.txt
CHANGED
|
@@ -1703,16 +1703,16 @@ call —
|
|
|
1703
1703
|
### Pinning tool names — `listToolNames`
|
|
1704
1704
|
|
|
1705
1705
|
Derived tool names are part of your public surface — an MCP client config or an
|
|
1706
|
-
agent prompt refers to them by string. `listToolNames(services)`
|
|
1707
|
-
|
|
1708
|
-
`(service, method)` identity and transports, sorted — a stable shape
|
|
1709
|
-
snapshot:
|
|
1706
|
+
agent prompt refers to them by string. `listToolNames({ services, runtimeTools })`
|
|
1707
|
+
resolves the complete mixed surface (the exact resolver the mounts use), with
|
|
1708
|
+
its origin, `(service, method)` identity and transports, sorted — a stable shape
|
|
1709
|
+
to snapshot:
|
|
1710
1710
|
|
|
1711
1711
|
```ts
|
|
1712
1712
|
import { listToolNames } from 'stitchkit/tools'
|
|
1713
1713
|
|
|
1714
1714
|
test('tool names have not drifted', () => {
|
|
1715
|
-
expect(listToolNames(services)).toMatchSnapshot()
|
|
1715
|
+
expect(listToolNames({ services, runtimeTools })).toMatchSnapshot()
|
|
1716
1716
|
})
|
|
1717
1717
|
```
|
|
1718
1718
|
|
|
@@ -1806,13 +1806,16 @@ createServer({
|
|
|
1806
1806
|
| `serverInfo` | MCP server identity — `{ name, version }` |
|
|
1807
1807
|
| `auth` | `(req) => identity \| null` — `null` rejects with 401 |
|
|
1808
1808
|
| `services` | the services to expose — an array, or `(auth) => ServiceDef[]` |
|
|
1809
|
+
| `runtimeTools` | managed pathless operations — an array, or `(auth) => RuntimeToolDefinition[]` |
|
|
1810
|
+
| `surfaces` | finite `{ key: { services, runtimeTools } }` registry prepared eagerly |
|
|
1811
|
+
| `selectSurface` | `(auth) => declaredKey` — required with `surfaces` |
|
|
1809
1812
|
| `context` | `(auth) => {…}` — values merged into every tool handler's `ctx` |
|
|
1810
1813
|
| `lifecycle` | `beforeHandle` / `afterHandle` — the tool-side auth gate (see below) |
|
|
1811
1814
|
| `hooks` | tool-call observability hooks — `afterToolCall` fires on every result |
|
|
1812
1815
|
| `extend` | extra advertised arguments resolved into handler context |
|
|
1813
1816
|
| `schemaValidation` | compatibility policy, typed-property guard and portable-format guard |
|
|
1814
1817
|
| `logger` | a `StitchLogger` for the `'warn'` policy |
|
|
1815
|
-
| `
|
|
1818
|
+
| `rawTools` | `(server, auth) => …` — explicit SDK registration without framework guarantees |
|
|
1816
1819
|
| `resources` | MCP Apps `ui://` resources mounted on every server |
|
|
1817
1820
|
| `instructions` | a short host-facing usage hint, surfaced to MCP tool-search |
|
|
1818
1821
|
| `coerceJsonArgs` | coerce JSON-stringified object/array arguments (default `true`) |
|
|
@@ -1822,14 +1825,37 @@ createServer({
|
|
|
1822
1825
|
| `protectedResource` | RFC 9728 metadata used by HTTP `401` responses |
|
|
1823
1826
|
| `sessionMode` | `'stateless'` (default) or explicit `'stateful'` session/SSE continuity |
|
|
1824
1827
|
|
|
1825
|
-
`services
|
|
1826
|
-
tenant can be shown only its own
|
|
1828
|
+
Direct `services` / `runtimeTools` factories, `context`, `selectSurface` and
|
|
1829
|
+
`rawTools` receive the resolved identity, so a tenant can be shown only its own
|
|
1830
|
+
tools and every handler can read `ctx.tenantId`.
|
|
1831
|
+
|
|
1832
|
+
Use direct factories only when the definitions are genuinely arbitrary per
|
|
1833
|
+
identity. For a bounded role/plan set, declare a finite registry instead:
|
|
1834
|
+
|
|
1835
|
+
```ts
|
|
1836
|
+
const handleMcp = createMcpHandler({
|
|
1837
|
+
serverInfo,
|
|
1838
|
+
auth,
|
|
1839
|
+
surfaces: {
|
|
1840
|
+
admin: { services: allServices, runtimeTools: [renderPreview] },
|
|
1841
|
+
member: { services: memberServices, runtimeTools: [renderPreview] },
|
|
1842
|
+
},
|
|
1843
|
+
selectSurface: (identity) => identity.isAdmin ? 'admin' : 'member',
|
|
1844
|
+
context: (identity) => ({ identity }),
|
|
1845
|
+
})
|
|
1846
|
+
```
|
|
1847
|
+
|
|
1848
|
+
Every declared entry is schema-validated and prepared once when the handler is
|
|
1849
|
+
constructed. The selected immutable descriptors are shared; the SDK server,
|
|
1850
|
+
transport, auth-derived context, lifecycle runner and tool-call context are
|
|
1851
|
+
fresh for every stateless request (or every stateful session). Unknown keys
|
|
1852
|
+
fail before the server connects. The registry never retains auth values.
|
|
1827
1853
|
|
|
1828
1854
|
### Stateless by default; stateful only when required
|
|
1829
1855
|
|
|
1830
1856
|
The default `sessionMode: 'stateless'` creates a fresh SDK server, transport,
|
|
1831
|
-
resolved auth/context and runner for each HTTP request. Static
|
|
1832
|
-
are still prepared once when the handler is constructed. There is no session
|
|
1857
|
+
resolved auth/context and runner for each HTTP request. Static direct and finite
|
|
1858
|
+
registry schemas are still prepared once when the handler is constructed. There is no session
|
|
1833
1859
|
map, event store, sweep timer or `Mcp-Session-Id`, so process replacement and
|
|
1834
1860
|
load balancing cannot strand a client on an in-memory session.
|
|
1835
1861
|
|
|
@@ -2006,8 +2032,8 @@ than a per-request `(req) => …`. Keep all logging on **stderr**: stdout is the
|
|
|
2006
2032
|
JSON-RPC channel.
|
|
2007
2033
|
|
|
2008
2034
|
Both transports build the server through the shared `buildMcpServer` — same
|
|
2009
|
-
contract pipeline, same
|
|
2010
|
-
|
|
2035
|
+
contract/runtime pipeline, same surface selection, context, hooks, raw escape
|
|
2036
|
+
hatch and instructions.
|
|
2011
2037
|
|
|
2012
2038
|
## OAuth 2.1 — a native remote connector
|
|
2013
2039
|
|
|
@@ -2249,9 +2275,9 @@ const handleMcp = createMcpHandler({
|
|
|
2249
2275
|
serverInfo: { name: 'my-app', version: '1.0.0' },
|
|
2250
2276
|
auth,
|
|
2251
2277
|
services: [service],
|
|
2278
|
+
runtimeTools: [renderPreview],
|
|
2252
2279
|
lifecycle: { beforeHandle: authHook },
|
|
2253
2280
|
hooks: audit.toolCall,
|
|
2254
|
-
nativeTools: ({ registerTool }) => registerTool(renderPreview),
|
|
2255
2281
|
})
|
|
2256
2282
|
|
|
2257
2283
|
const agentTools = mountAgent([service], {
|
|
@@ -2281,7 +2307,7 @@ use the same validation, lifecycle and hook path as contract tools.
|
|
|
2281
2307
|
|
|
2282
2308
|
### Explicit raw SDK registration
|
|
2283
2309
|
|
|
2284
|
-
`
|
|
2310
|
+
`rawTools` is deliberately named as an escape hatch. A tool registered there
|
|
2285
2311
|
does **not** receive stitchkit schema policy, lifecycle, per-call context or
|
|
2286
2312
|
hooks. The built-in `mountViewFile` helper remains raw for callers that choose
|
|
2287
2313
|
that boundary; it fetches media with SSRF and path-traversal defenses:
|
|
@@ -2293,14 +2319,51 @@ const handleMcp = createMcpHandler({
|
|
|
2293
2319
|
serverInfo: { name: 'my-app', version: '1.0.0' },
|
|
2294
2320
|
auth,
|
|
2295
2321
|
services: [service],
|
|
2296
|
-
|
|
2297
|
-
mountViewFile(rawServer, { baseDir: '/srv/uploads' }),
|
|
2322
|
+
rawTools: (server) => mountViewFile(server, { baseDir: '/srv/uploads' }),
|
|
2298
2323
|
})
|
|
2299
2324
|
```
|
|
2300
2325
|
|
|
2301
2326
|
Use raw registration only when opting out is intentional. For a protected
|
|
2302
|
-
`view_file`, define it
|
|
2303
|
-
`resolveMedia` core from its handler.
|
|
2327
|
+
`view_file`, define it with `defineRuntimeTool`, include it in `runtimeTools`,
|
|
2328
|
+
and call the exported `resolveMedia` core from its handler.
|
|
2329
|
+
|
|
2330
|
+
## Introspecting the complete tool surface
|
|
2331
|
+
|
|
2332
|
+
Deferred tool search, name snapshots and boot diagnostics accept the same
|
|
2333
|
+
object-shaped surface as the mounts. Contract operations are followed by
|
|
2334
|
+
runtime definitions, matching mount order; exposure filters and collisions are
|
|
2335
|
+
resolved by Stitchkit rather than by consumer code:
|
|
2336
|
+
|
|
2337
|
+
```ts
|
|
2338
|
+
import {
|
|
2339
|
+
buildToolManifest,
|
|
2340
|
+
listToolNames,
|
|
2341
|
+
summarizeTransports,
|
|
2342
|
+
} from 'stitchkit/tools'
|
|
2343
|
+
|
|
2344
|
+
const surface = { services, runtimeTools: [renderPreview] }
|
|
2345
|
+
|
|
2346
|
+
const manifest = buildToolManifest({
|
|
2347
|
+
...surface,
|
|
2348
|
+
transport: 'AGENT',
|
|
2349
|
+
flattenUnionInput: true,
|
|
2350
|
+
})
|
|
2351
|
+
|
|
2352
|
+
const names = listToolNames(surface)
|
|
2353
|
+
const summary = summarizeTransports(surface)
|
|
2354
|
+
```
|
|
2355
|
+
|
|
2356
|
+
`buildToolManifest` returns the exact immutable presentation schema shown to
|
|
2357
|
+
the selected MCP or Agent transport. It does not execute validation effects and
|
|
2358
|
+
fails first on duplicate contract/runtime names. There is no runtime-only
|
|
2359
|
+
manifest helper or public mount adapter: the framework owns merging and schema
|
|
2360
|
+
projection.
|
|
2361
|
+
|
|
2362
|
+
`listToolNames` remains diagnostic and reports `kind: 'contract' | 'runtime'`
|
|
2363
|
+
for every identity. `summarizeTransports` returns `contractServices`,
|
|
2364
|
+
`runtimeTools`, aggregate `totals`, and a `sources` breakdown. Runtime tools
|
|
2365
|
+
contribute only to MCP/Agent according to their `transports`; they never inflate
|
|
2366
|
+
HTTP or CLI counts.
|
|
2304
2367
|
|
|
2305
2368
|
## Logging tool calls — `createToolLogger`
|
|
2306
2369
|
|
|
@@ -2320,9 +2383,9 @@ Pass `log` to redirect the line, or `onRecord` to feed a metrics sink the
|
|
|
2320
2383
|
structured `ToolCallRecord`. That record carries `traceId` whenever an
|
|
2321
2384
|
observability context is active, so a tool call made inside an HTTP request
|
|
2322
2385
|
joins that request's log line on one key — see
|
|
2323
|
-
[Observability](./observability.md). For a boot-time picture of what is exposed
|
|
2324
|
-
`summarizeTransports(services)` returns
|
|
2325
|
-
|
|
2386
|
+
[Observability](./observability.md). For a boot-time picture of what is exposed
|
|
2387
|
+
where, `summarizeTransports({ services, runtimeTools })` returns the mixed
|
|
2388
|
+
per-transport counts for you to log.
|
|
2326
2389
|
|
|
2327
2390
|
## One handler, three callers
|
|
2328
2391
|
|
|
@@ -3253,27 +3316,46 @@ onError: (ctx, err) => {
|
|
|
3253
3316
|
|
|
3254
3317
|
## Domain errors — `defineErrors`
|
|
3255
3318
|
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
`
|
|
3259
|
-
object):
|
|
3319
|
+
Declare each domain code, HTTP status and optional structured-details schema in
|
|
3320
|
+
one immutable registry. The generated functions construct typed branded
|
|
3321
|
+
`AppError` instances; ordinary `throw` remains explicit at the call site:
|
|
3260
3322
|
|
|
3261
3323
|
```ts
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3324
|
+
import { z } from 'zod'
|
|
3325
|
+
|
|
3326
|
+
export const { errors, codes, definitions, isCode } = defineErrors({
|
|
3327
|
+
SESSION_NOT_FOUND: { status: 404 },
|
|
3328
|
+
QUOTA_EXCEEDED: {
|
|
3329
|
+
status: 429,
|
|
3330
|
+
details: z.object({ retryAfterSeconds: z.number().int().positive() }),
|
|
3331
|
+
},
|
|
3332
|
+
})
|
|
3333
|
+
|
|
3334
|
+
throw errors.SESSION_NOT_FOUND({ message: 'No such session' })
|
|
3335
|
+
throw errors.QUOTA_EXCEEDED({
|
|
3336
|
+
message: 'Try later',
|
|
3337
|
+
details: { retryAfterSeconds: 30 },
|
|
3338
|
+
hint: 'Wait for the current window to expire',
|
|
3265
3339
|
})
|
|
3266
3340
|
|
|
3267
|
-
//
|
|
3268
|
-
|
|
3341
|
+
// Construction without throwing is useful for composition or inspection.
|
|
3342
|
+
const error = errors.QUOTA_EXCEEDED({ details: { retryAfterSeconds: 30 } })
|
|
3343
|
+
definitions.QUOTA_EXCEEDED.status // 429 — same source, no copied status map
|
|
3269
3344
|
|
|
3270
3345
|
// client — match the code, never a magic string
|
|
3271
3346
|
if (err instanceof ApiError && err.code === codes.SESSION_NOT_FOUND) { … }
|
|
3272
3347
|
```
|
|
3273
3348
|
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3349
|
+
With no `details` schema, the options object forbids `details`. A required
|
|
3350
|
+
`z.object` makes `details` required; `z.object(...).optional()` makes it
|
|
3351
|
+
optional. Supplied details are parsed when the error is constructed, before any
|
|
3352
|
+
transport sees them. `code` remains literal and the parsed details type is
|
|
3353
|
+
retained on the returned `AppError`.
|
|
3354
|
+
|
|
3355
|
+
HTTP renders the complete code/status/message/details/hint. Tool transports keep
|
|
3356
|
+
their established model-facing projection (code/details/hint, without HTTP
|
|
3357
|
+
status), while `invokeOrThrow` recovers the exact normalized `AppError`. The
|
|
3358
|
+
codes and schemas remain application-owned; Stitchkit stays domain-free.
|
|
3277
3359
|
|
|
3278
3360
|
## `createErrorHook`
|
|
3279
3361
|
|
|
@@ -3305,6 +3387,27 @@ createServer({ services, hooks: { onError } })
|
|
|
3305
3387
|
Codes you threw yourself (not stitchkit's) pass through `codeMap` unchanged; the
|
|
3306
3388
|
`satisfies Record<StitchErrorCode, …>` keeps the map exhaustive across upgrades.
|
|
3307
3389
|
|
|
3390
|
+
Both `onError` and `render` may be asynchronous and receive the matched endpoint
|
|
3391
|
+
as their final argument. The observer is awaited before rendering, so it can
|
|
3392
|
+
resolve identity or enrich the request context even for failures raised before
|
|
3393
|
+
`beforeHandle`:
|
|
3394
|
+
|
|
3395
|
+
```ts
|
|
3396
|
+
const onError = createErrorHook({
|
|
3397
|
+
onError: async (_error, _info, ctx, endpoint) => {
|
|
3398
|
+
await attributeFailedRequest(ctx, endpoint)
|
|
3399
|
+
},
|
|
3400
|
+
render: (info, ctx) => ({
|
|
3401
|
+
error: { code: info.code },
|
|
3402
|
+
actorId: ctx.actorId,
|
|
3403
|
+
}),
|
|
3404
|
+
})
|
|
3405
|
+
```
|
|
3406
|
+
|
|
3407
|
+
`endpoint` is `undefined` when the failure happened before route resolution.
|
|
3408
|
+
Synchronous callbacks and renderers that declare fewer parameters continue to
|
|
3409
|
+
work normally.
|
|
3410
|
+
|
|
3308
3411
|
Invalid input (a `ZodError`) is classified as `VALIDATION_ERROR` 400 before it
|
|
3309
3412
|
reaches `render` — a client fault is an honest 400, not a 500 — and the
|
|
3310
3413
|
offending fields arrive as structured `info.details.issues`, so your `render`
|
|
@@ -3477,6 +3580,12 @@ context carries nothing yet, so your value always wins.
|
|
|
3477
3580
|
`event.serviceName` / `event.action` are present on every event, including a
|
|
3478
3581
|
pre-handler 400. Nothing to wire.
|
|
3479
3582
|
|
|
3583
|
+
When failure attribution itself is asynchronous, use `createErrorHook`'s
|
|
3584
|
+
`onError(error, info, ctx, endpoint)` observer. The framework awaits it before
|
|
3585
|
+
calling `render`, so identity or audit enrichment is visible to both the final
|
|
3586
|
+
error envelope and the request event. `endpoint` is the matched `MethodDef`, or
|
|
3587
|
+
`undefined` when routing failed before a method was selected.
|
|
3588
|
+
|
|
3480
3589
|
**Domain dimensions** — attach your own tenant / project / entity id with
|
|
3481
3590
|
`setRequestDimensions`. It is an opaque `Record<string, string>` the core gives no
|
|
3482
3591
|
meaning to (→ ADR 0021). Resolve it cheaply from `ctx.params` / headers in
|
|
@@ -4119,6 +4228,97 @@ current one *up to* your target, and apply each snippet.
|
|
|
4119
4228
|
|
|
4120
4229
|
## Unreleased breaking migrations
|
|
4121
4230
|
|
|
4231
|
+
Tool introspection now accepts one object-shaped contract/runtime surface. Stop
|
|
4232
|
+
calling the internal contract collector or merging a locally converted runtime
|
|
4233
|
+
manifest:
|
|
4234
|
+
|
|
4235
|
+
```ts
|
|
4236
|
+
// before
|
|
4237
|
+
buildToolManifest(services.flatMap((service) => collectTools(service, 'AGENT')))
|
|
4238
|
+
listToolNames(services)
|
|
4239
|
+
summarizeTransports(services)
|
|
4240
|
+
|
|
4241
|
+
// after
|
|
4242
|
+
const surface = { services, runtimeTools }
|
|
4243
|
+
buildToolManifest({ ...surface, transport: 'AGENT' })
|
|
4244
|
+
listToolNames(surface)
|
|
4245
|
+
summarizeTransports(surface)
|
|
4246
|
+
```
|
|
4247
|
+
|
|
4248
|
+
`ToolNameEntry` adds `kind: 'contract' | 'runtime'`. `TransportSummary` is now
|
|
4249
|
+
`{ contractServices, runtimeTools, totals, sources }`; replace `services` and
|
|
4250
|
+
`perService` reads with the explicit counts and mixed-source breakdown. There
|
|
4251
|
+
is no positional overload and no `buildRuntimeToolManifest`: Stitchkit owns the
|
|
4252
|
+
combined order, transport filtering, canonical presentation schema and
|
|
4253
|
+
cross-origin collision checks.
|
|
4254
|
+
|
|
4255
|
+
`defineErrors` now uses one Zod-first definition object and returns constructors
|
|
4256
|
+
instead of positional throwers. Add explicit `throw`, move message/details/hint
|
|
4257
|
+
into one options object, and declare a details schema when that code carries
|
|
4258
|
+
structured context:
|
|
4259
|
+
|
|
4260
|
+
```ts
|
|
4261
|
+
// before
|
|
4262
|
+
const { errors } = defineErrors({ QUOTA_EXCEEDED: 429 })
|
|
4263
|
+
errors.QUOTA_EXCEEDED('Try later', { retryAfterSeconds: 30 }, 'Wait')
|
|
4264
|
+
|
|
4265
|
+
// after
|
|
4266
|
+
const { errors, definitions } = defineErrors({
|
|
4267
|
+
QUOTA_EXCEEDED: {
|
|
4268
|
+
status: 429,
|
|
4269
|
+
details: z.object({ retryAfterSeconds: z.number().positive() }),
|
|
4270
|
+
},
|
|
4271
|
+
})
|
|
4272
|
+
throw errors.QUOTA_EXCEEDED({
|
|
4273
|
+
message: 'Try later',
|
|
4274
|
+
details: { retryAfterSeconds: 30 },
|
|
4275
|
+
hint: 'Wait',
|
|
4276
|
+
})
|
|
4277
|
+
```
|
|
4278
|
+
|
|
4279
|
+
There is no positional overload. A code without `details` forbids them; use an
|
|
4280
|
+
optional object schema when the details object itself is optional. Read status
|
|
4281
|
+
and schemas from the frozen `definitions` registry instead of maintaining a
|
|
4282
|
+
parallel map.
|
|
4283
|
+
|
|
4284
|
+
Managed MCP runtime tools are now declared as immutable data. Move protected
|
|
4285
|
+
registrar calls to `runtimeTools`; rename deliberate raw SDK registration to
|
|
4286
|
+
`rawTools`. There is no registrar alias:
|
|
4287
|
+
|
|
4288
|
+
```ts
|
|
4289
|
+
// before — protected
|
|
4290
|
+
createMcpHandler({
|
|
4291
|
+
services,
|
|
4292
|
+
nativeTools: ({ registerTool }) => registerTool(preview),
|
|
4293
|
+
})
|
|
4294
|
+
|
|
4295
|
+
// after — protected and prepared with the rest of the surface
|
|
4296
|
+
createMcpHandler({ services, runtimeTools: [preview] })
|
|
4297
|
+
|
|
4298
|
+
// before — deliberate raw SDK opt-out
|
|
4299
|
+
nativeTools: ({ rawServer }, auth) => mountRaw(rawServer, auth)
|
|
4300
|
+
|
|
4301
|
+
// after — still a deliberate raw SDK opt-out
|
|
4302
|
+
rawTools: (server, auth) => mountRaw(server, auth)
|
|
4303
|
+
```
|
|
4304
|
+
|
|
4305
|
+
When identity selects from a bounded set, replace a repeatedly prepared
|
|
4306
|
+
`services(auth)` factory with a finite registry:
|
|
4307
|
+
|
|
4308
|
+
```ts
|
|
4309
|
+
createMcpHandler({
|
|
4310
|
+
surfaces: {
|
|
4311
|
+
admin: { services: allServices, runtimeTools: [preview] },
|
|
4312
|
+
member: { services: memberServices, runtimeTools: [preview] },
|
|
4313
|
+
},
|
|
4314
|
+
selectSurface: (auth) => auth.isAdmin ? 'admin' : 'member',
|
|
4315
|
+
})
|
|
4316
|
+
```
|
|
4317
|
+
|
|
4318
|
+
Keep direct `services(auth)` / `runtimeTools(auth)` only for genuinely
|
|
4319
|
+
unbounded definitions; Stitchkit intentionally does not cache arbitrary auth
|
|
4320
|
+
values.
|
|
4321
|
+
|
|
4122
4322
|
Contract success bodies are now determined by the presence of `output`, not by
|
|
4123
4323
|
the handler's runtime value. A nullable output returns JSON `null` with status
|
|
4124
4324
|
`200`; `undefined` with a declared output and non-null data without an output
|
|
@@ -4222,7 +4422,7 @@ const preview = defineRuntimeTool({
|
|
|
4222
4422
|
}),
|
|
4223
4423
|
},
|
|
4224
4424
|
})
|
|
4225
|
-
|
|
4425
|
+
runtimeTools: [preview]
|
|
4226
4426
|
```
|
|
4227
4427
|
|
|
4228
4428
|
The removed `NativeMcp*` types have no aliases. Use `RuntimeToolDefinition`,
|
|
@@ -4421,7 +4621,7 @@ name derivation, diff them mechanically:
|
|
|
4421
4621
|
|
|
4422
4622
|
```ts
|
|
4423
4623
|
import { listToolNames } from 'stitchkit/tools'
|
|
4424
|
-
console.log(JSON.stringify(listToolNames(services), null, 2))
|
|
4624
|
+
console.log(JSON.stringify(listToolNames({ services, runtimeTools }), null, 2))
|
|
4425
4625
|
```
|
|
4426
4626
|
|
|
4427
4627
|
`listToolNames` never throws on an illegal name — that is deliberate, so it can
|
|
@@ -4570,9 +4770,17 @@ from the root `stitchkit`.
|
|
|
4570
4770
|
| `conflict` | function | throw `409 CONFLICT` |
|
|
4571
4771
|
| `rateLimited` | function | throw `429 RATE_LIMITED` |
|
|
4572
4772
|
| `appError` | function | throw an `AppError` for any code |
|
|
4573
|
-
| `defineErrors` | function | declare domain error
|
|
4574
|
-
| `DefinedErrors` | _type_ | the `{ errors, codes, isCode }` handle `defineErrors` returns |
|
|
4575
|
-
| `
|
|
4773
|
+
| `defineErrors` | function | declare immutable domain error definitions → typed `AppError` constructors, codes and schemas — [guide](../guide/auth-and-errors.md#domain-errors--defineerrors) |
|
|
4774
|
+
| `DefinedErrors` | _type_ | the `{ errors, codes, definitions, isCode }` handle `defineErrors` returns |
|
|
4775
|
+
| `DefinedAppError` | _type_ | literal-code error instance with schema-refined details |
|
|
4776
|
+
| `ErrorDefinition` | _type_ | `{ status, details? }` definition for one domain code |
|
|
4777
|
+
| `ErrorDefinitions` | _type_ | string-keyed domain error definition registry |
|
|
4778
|
+
| `ErrorDetailsSchema` | _type_ | required or optional Zod object accepted for structured details |
|
|
4779
|
+
| `ErrorDetailsOutput` | _type_ | parsed details inferred from one definition |
|
|
4780
|
+
| `ErrorFactoryArguments` | _type_ | options tuple with forbidden/required/optional details inferred per code |
|
|
4781
|
+
| `ErrorFactory` | _type_ | one typed `AppError` constructor |
|
|
4782
|
+
| `ErrorFactories` | _type_ | mapped constructor registry derived from all definitions |
|
|
4783
|
+
| `FrozenErrorDefinitions` | _type_ | read-only definition registry returned to consumers |
|
|
4576
4784
|
| `STITCH_ERROR_STATUS` | const | `code → HTTP status` map for stitchkit's own error codes — [guide](../guide/auth-and-errors.md#stitch-codes-vs-your-codes) |
|
|
4577
4785
|
| `StitchErrorCode` | _type_ | a code stitchkit itself emits (`keyof STITCH_ERROR_STATUS`) |
|
|
4578
4786
|
| `isStitchErrorCode` | function | type guard — is a code one of stitchkit's own? |
|
|
@@ -4640,8 +4848,8 @@ Also re-exports the error helpers from `stitchkit/contract`.
|
|
|
4640
4848
|
| Export | Kind | Summary |
|
|
4641
4849
|
|--------|------|---------|
|
|
4642
4850
|
| `createAuthHook` | function | a scope-enforcing `beforeHandle` hook — [guide](../guide/auth-and-errors.md#createauthhook) |
|
|
4643
|
-
| `createErrorHook` | function | an `onError` hook from a code map + envelope renderer — [guide](../guide/auth-and-errors.md#createerrorhook) |
|
|
4644
|
-
| `ErrorHookConfig` | _type_ | config for `createErrorHook` |
|
|
4851
|
+
| `createErrorHook` | function | an async-capable, endpoint-aware `onError` hook from a code map + envelope renderer — [guide](../guide/auth-and-errors.md#createerrorhook) |
|
|
4852
|
+
| `ErrorHookConfig` | _type_ | async observer/renderer config for `createErrorHook` |
|
|
4645
4853
|
| `ResolvedError` | _type_ | the normalised error handed to `createErrorHook`'s `render` |
|
|
4646
4854
|
| `createBearerResolver` | function | a bearer-token identity resolver |
|
|
4647
4855
|
| `signJwt` | function | sign an HS256 JWT |
|
|
@@ -4790,7 +4998,7 @@ Server-only. Turns contracts into MCP and AI-agent tools. Needs the
|
|
|
4790
4998
|
|--------|------|---------|
|
|
4791
4999
|
| `createMcpHandler` | function | a complete Streamable-HTTP MCP server — [guide](../guide/mcp-and-agents.md#mcp--createmcphandler) |
|
|
4792
5000
|
| `createStdioMcpServer` | function | a complete stdio MCP server — [guide](../guide/mcp-and-agents.md#mcp-over-stdio--createstdiomcpserver) |
|
|
4793
|
-
| `buildMcpServer` | function | build an `McpServer` from
|
|
5001
|
+
| `buildMcpServer` | function | build an `McpServer` from contract/runtime surfaces — the transport-neutral core |
|
|
4794
5002
|
| `mountMcp` | function | add contract tools to an existing `McpServer` — [guide](../guide/mcp-and-agents.md#mountmcp) |
|
|
4795
5003
|
| `implementRemote` | function | bind a contract to a remote HTTP API — [guide](../guide/mcp-and-agents.md#proxying-a-remote-api--implementremote) |
|
|
4796
5004
|
| `mountAgent` | function | a Vercel AI SDK `ToolSet` from a service — [guide](../guide/mcp-and-agents.md#ai-agents--mountagent) |
|
|
@@ -4801,16 +5009,22 @@ Server-only. Turns contracts into MCP and AI-agent tools. Needs the
|
|
|
4801
5009
|
| `mountViewFile` | function | a native multimodal "view file" MCP tool |
|
|
4802
5010
|
| `resolveMedia` | function | resolve a media reference for a tool result |
|
|
4803
5011
|
| `validateMcpSchemas` | function | object-shaped assertion over the exact advertised schema surface — compatibility, typed properties and portable formats ([guide](../guide/mcp-and-agents.md#mcp-schema-validation-profile)) |
|
|
4804
|
-
| `listToolNames` | function | every
|
|
5012
|
+
| `listToolNames` | function | every contract/runtime tool name with origin, identity and transports — for stable snapshots — [guide](../guide/mcp-and-agents.md#pinning-tool-names--listtoolnames) |
|
|
4805
5013
|
| `McpHandlerConfig` | _type_ | config for `createMcpHandler` |
|
|
5014
|
+
| `McpHttpConfig` | _type_ | HTTP auth, protected-resource and session options composed into `McpHandlerConfig` |
|
|
4806
5015
|
| `McpSessionMode` | _type_ | `'stateless' \| 'stateful'`; HTTP defaults to request-isolated stateless mode |
|
|
4807
5016
|
| `StdioMcpServerConfig` | _type_ | config for `createStdioMcpServer` |
|
|
4808
5017
|
| `McpServerBuildConfig` | _type_ | shared config for `buildMcpServer` |
|
|
5018
|
+
| `McpServerSharedConfig` | _type_ | transport-neutral options shared by direct and finite surface configs |
|
|
5019
|
+
| `DirectMcpSurfaceConfig` | _type_ | static or identity-dynamic `services` / `runtimeTools` source |
|
|
5020
|
+
| `FiniteMcpSurfaceConfig` | _type_ | bounded `surfaces` registry plus typed selector |
|
|
5021
|
+
| `McpSurfaceDefinition` | _type_ | one immutable `{ services, runtimeTools }` MCP surface |
|
|
5022
|
+
| `McpSurfaceRegistry` | _type_ | finite keyed surface registry for eager preparation |
|
|
5023
|
+
| `StdioAuthConfig` | _type_ | startup identity composed into `StdioMcpServerConfig` |
|
|
4809
5024
|
| `ImplementRemoteOptions` | _type_ | options for `implementRemote` |
|
|
4810
5025
|
| `McpMountConfig` | _type_ | config for `mountMcp` |
|
|
4811
5026
|
| `McpSchemaValidationConfig` | _type_ | shared `{ policy, requireTypedProperties, allowUntyped, requirePortableFormats, allowFormats }` profile |
|
|
4812
5027
|
| `ValidateMcpSchemasConfig` | _type_ | standalone validation profile plus `services`, `extend`, flattening and logger |
|
|
4813
|
-
| `NativeMcpRegistrar` | _type_ | protected `registerTool` plus explicit unprotected `rawServer` access |
|
|
4814
5028
|
| `RuntimeToolDefinition` | _type_ | transport-neutral pathless operation with identity, schemas, handler and optional presenters |
|
|
4815
5029
|
| `RuntimeToolDefinitionBase` | _type_ | common name, identity, input, exposure and MCP metadata fields |
|
|
4816
5030
|
| `RuntimeToolDefinitionWithOutput` | _type_ | runtime definition whose handler and presenters share a validated output type |
|
|
@@ -4850,7 +5064,7 @@ Server-only. Turns contracts into MCP and AI-agent tools. Needs the
|
|
|
4850
5064
|
| `findNonPortableFormats` | function | deep finder for formats outside the portable MCP/AJV baseline |
|
|
4851
5065
|
| `NonPortableFormat` | _type_ | one `{ path, format }` portability finding |
|
|
4852
5066
|
| `PORTABLE_JSON_SCHEMA_FORMATS` | constant | portable-format baseline used by MCP validation |
|
|
4853
|
-
| `ToolNameEntry` | _type_ | one `listToolNames` row — `{ name, service, method, transports }` |
|
|
5067
|
+
| `ToolNameEntry` | _type_ | one `listToolNames` row — `{ kind, name, service, method, transports }` |
|
|
4854
5068
|
| `IncompatibleSchemaPolicy` | _type_ | `'throw' \| 'skip' \| 'warn'` |
|
|
4855
5069
|
| `McpMediaContent` | _type_ | a multimodal MCP content item |
|
|
4856
5070
|
|
|
@@ -4909,12 +5123,15 @@ Advanced building blocks — the shared machinery the mounts are built on.
|
|
|
4909
5123
|
|--------|------|---------|
|
|
4910
5124
|
| `collectTools` | function | resolve a service's methods to mountable tools (the shared resolver) |
|
|
4911
5125
|
| `createToolLogger` | function | a ready `afterToolCall` that logs every tool call — [guide](../guide/mcp-and-agents.md#logging-tool-calls--createtoollogger) |
|
|
4912
|
-
| `summarizeTransports` | function |
|
|
4913
|
-
| `buildToolManifest` | function |
|
|
5126
|
+
| `summarizeTransports` | function | mixed contract/runtime operation counts and per-source breakdown for a boot-time summary |
|
|
5127
|
+
| `buildToolManifest` | function | transport-aware searchable `{ name, description, inputSchema }` rows from a mixed surface |
|
|
4914
5128
|
| `ToolLoggerConfig` | _type_ | config for `createToolLogger` |
|
|
4915
5129
|
| `ToolCallRecord` | _type_ | the structured record `createToolLogger` passes to `onRecord` |
|
|
4916
|
-
| `TransportSummary` | _type_ |
|
|
5130
|
+
| `TransportSummary` | _type_ | `{ contractServices, runtimeTools, totals, sources }` from `summarizeTransports` |
|
|
4917
5131
|
| `TransportCounts` | _type_ | per-transport counts (`{ HTTP, MCP, AGENT, CLI }`) |
|
|
5132
|
+
| `ToolSurfaceDefinition` | _type_ | shared object-shaped `{ services?, runtimeTools? }` introspection surface |
|
|
5133
|
+
| `ToolSurfaceTransport` | _type_ | tool collector transport: `'MCP' \| 'AGENT' \| 'CLI'` |
|
|
5134
|
+
| `ToolManifestConfig` | _type_ | mixed surface plus required model-facing `transport` and presentation options |
|
|
4918
5135
|
| `coerceJsonArgs` | function | coerce JSON-stringified array/object tool arguments |
|
|
4919
5136
|
| `flattenToolJsonSchema` | function | project structurally identifiable discriminated unions in a JSON Schema document into conservative object joins; never executes validation |
|
|
4920
5137
|
| `ToolPresentationSchema` | _type_ | immutable model-facing JSON Schema document shared by tool transports |
|
package/package.json
CHANGED