stitchkit 0.53.1 → 0.54.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.d.ts +2 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -1
- package/dist/contract/define.d.ts +27 -0
- package/dist/contract/define.d.ts.map +1 -1
- package/dist/contract/index.d.ts +1 -1
- package/dist/contract/index.d.ts.map +1 -1
- package/dist/{index-6j4j5wf9.js → index-7vb44hy8.js} +404 -72
- package/dist/{index-yydqk4fh.js → index-b15rtha1.js} +30 -1
- package/dist/{index-pdv1mjjr.js → index-z7761jk2.js} +15 -38
- package/dist/node.js +2 -2
- package/dist/observability/event.d.ts +2 -16
- package/dist/observability/event.d.ts.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/process-signal-common.d.ts +6 -0
- package/dist/server/process-signal-common.d.ts.map +1 -0
- package/dist/server/process-signals.d.ts.map +1 -1
- package/dist/tools/cli-command.d.ts +29 -0
- package/dist/tools/cli-command.d.ts.map +1 -0
- package/dist/tools/cli.d.ts +11 -6
- package/dist/tools/cli.d.ts.map +1 -1
- package/dist/tools/define-download-tool.d.ts +17 -0
- package/dist/tools/define-download-tool.d.ts.map +1 -0
- package/dist/tools/define-upload-tool.d.ts +14 -0
- package/dist/tools/define-upload-tool.d.ts.map +1 -0
- package/dist/tools/define-view-file-tool.d.ts +10 -0
- package/dist/tools/define-view-file-tool.d.ts.map +1 -0
- package/dist/tools/define-wait-tool.d.ts +22 -0
- package/dist/tools/define-wait-tool.d.ts.map +1 -0
- package/dist/tools/download-core.d.ts +25 -0
- package/dist/tools/download-core.d.ts.map +1 -0
- package/dist/tools/execute.d.ts +3 -1
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/mcp-round.d.ts +0 -1
- package/dist/tools/mcp-round.d.ts.map +1 -1
- package/dist/tools/mcp-stdio-signals.d.ts +33 -0
- package/dist/tools/mcp-stdio-signals.d.ts.map +1 -0
- package/dist/tools/mount-download.d.ts +5 -0
- package/dist/tools/mount-download.d.ts.map +1 -1
- package/dist/tools/mount-upload.d.ts.map +1 -1
- package/dist/tools/mount-wait.d.ts.map +1 -1
- package/dist/tools/native-definition.d.ts +15 -0
- package/dist/tools/native-definition.d.ts.map +1 -0
- package/dist/tools/runtime-tool.d.ts +5 -4
- package/dist/tools/runtime-tool.d.ts.map +1 -1
- package/dist/tools/surface.d.ts.map +1 -1
- package/dist/tools/upload-core.d.ts +3 -0
- package/dist/tools/upload-core.d.ts.map +1 -0
- package/dist/tools/view-file.d.ts +80 -20
- package/dist/tools/view-file.d.ts.map +1 -1
- package/dist/tools/wait-core.d.ts +10 -1
- package/dist/tools/wait-core.d.ts.map +1 -1
- package/dist/tools.d.ts +10 -2
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +570 -379
- package/llms-full.txt +312 -35
- package/package.json +1 -1
package/llms-full.txt
CHANGED
|
@@ -2364,8 +2364,9 @@ must not be used as authorization input.
|
|
|
2364
2364
|
### Modern discovery, routing and cache hints
|
|
2365
2365
|
|
|
2366
2366
|
Stitchkit forwards the negotiated protocol era and validated MCP request data
|
|
2367
|
-
to `RequestEvent.mcp
|
|
2368
|
-
identity. The SDK validates
|
|
2367
|
+
to both `RequestEvent.mcp` and the current managed call's typed `context.mcp`;
|
|
2368
|
+
untrusted routing headers never become application identity. The SDK validates
|
|
2369
|
+
`MCP-Protocol-Version`, JSON-RPC shape and routing
|
|
2369
2370
|
metadata before lifecycle or tool handlers run. Framework-owned tool and
|
|
2370
2371
|
resource registration preserves declaration order across HTTP and stdio. Tool
|
|
2371
2372
|
manifests preserve mount order; `listToolNames` is a sorted diagnostics view.
|
|
@@ -2380,6 +2381,30 @@ finite `surfaces` registry when identities share a provably immutable surface.
|
|
|
2380
2381
|
Stitchkit never advertises list-change or subscription capabilities
|
|
2381
2382
|
without an implementation.
|
|
2382
2383
|
|
|
2384
|
+
### Typed MCP call metadata
|
|
2385
|
+
|
|
2386
|
+
Contract handlers, runtime-tool handlers/factories, lifecycle and tool hooks all
|
|
2387
|
+
see the same optional `McpCallContext` for the current invocation:
|
|
2388
|
+
|
|
2389
|
+
```ts
|
|
2390
|
+
const sourceLabel = context.mcp?.clientInfo?.name ?? context.source
|
|
2391
|
+
|
|
2392
|
+
context.mcp?.era // 'modern' | 'legacy'
|
|
2393
|
+
context.mcp?.method // validated MCP method
|
|
2394
|
+
context.mcp?.toolName // resolved framework tool name
|
|
2395
|
+
context.mcp?.protocolVersion // when supplied by a modern host
|
|
2396
|
+
context.mcp?.clientInfo // { name, version } when validated
|
|
2397
|
+
context.mcp?.outcome // multi-round attempt outcome
|
|
2398
|
+
context.mcp?.round // multi-round attempt number
|
|
2399
|
+
```
|
|
2400
|
+
|
|
2401
|
+
The field is absent on HTTP, Agent, CLI and bring-your-own transports. A legacy
|
|
2402
|
+
MCP call exposes `era: 'legacy'` but does not invent modern client information.
|
|
2403
|
+
`clientInfo` is the host's self-description: use it for labels or analytics,
|
|
2404
|
+
never for authentication, RBAC, tenant selection or rate limiting. Verified
|
|
2405
|
+
identity still comes from `auth`; the `context(auth)` callback remains the
|
|
2406
|
+
application-context factory and receives no protocol metadata.
|
|
2407
|
+
|
|
2383
2408
|
### Multi-round tool input (`input_required`)
|
|
2384
2409
|
|
|
2385
2410
|
An MCP-only operation can require typed user input before its final side effect:
|
|
@@ -2598,7 +2623,7 @@ client (Claude Desktop, Claude Code, Cursor, Codex), on the user's machine, so
|
|
|
2598
2623
|
it can reach the local filesystem.
|
|
2599
2624
|
|
|
2600
2625
|
```ts
|
|
2601
|
-
import { createStdioMcpServer } from 'stitchkit/tools'
|
|
2626
|
+
import { bindStdioProcessSignals, createStdioMcpServer } from 'stitchkit/tools'
|
|
2602
2627
|
|
|
2603
2628
|
const stdio = await createStdioMcpServer({
|
|
2604
2629
|
serverInfo: { name: 'my-app', version: '1.0.0' },
|
|
@@ -2606,8 +2631,16 @@ const stdio = await createStdioMcpServer({
|
|
|
2606
2631
|
services: [usersService],
|
|
2607
2632
|
})
|
|
2608
2633
|
|
|
2609
|
-
|
|
2610
|
-
|
|
2634
|
+
const signals = bindStdioProcessSignals(stdio, {
|
|
2635
|
+
onClose: () => stopWorkers(),
|
|
2636
|
+
onComplete: () => { process.exitCode = 0 },
|
|
2637
|
+
onError: (_phase, error) => {
|
|
2638
|
+
console.error(error) // stderr only — stdout is JSON-RPC
|
|
2639
|
+
process.exitCode = 1
|
|
2640
|
+
},
|
|
2641
|
+
})
|
|
2642
|
+
|
|
2643
|
+
await signals.promise
|
|
2611
2644
|
```
|
|
2612
2645
|
|
|
2613
2646
|
A stdio server is a single process serving one client, so `auth` is a value (or
|
|
@@ -2620,6 +2653,14 @@ through the official stdio adapter. Use `legacy: 'reject'` for a modern-only
|
|
|
2620
2653
|
binary. Each invocation builds a fresh server; the returned handle owns
|
|
2621
2654
|
transport shutdown.
|
|
2622
2655
|
|
|
2656
|
+
Signal binding is explicit: `createStdioMcpServer` installs no global process
|
|
2657
|
+
listeners by itself. The first `SIGINT`/`SIGTERM` starts exactly one official
|
|
2658
|
+
`close()` chain. Stdio has no force primitive, so a later signal restores the
|
|
2659
|
+
OS default disposition instead of reporting a fictional forced result.
|
|
2660
|
+
`signals.close()` removes an idle binding; the framework never calls
|
|
2661
|
+
`process.exit()` or chooses the exit code. See
|
|
2662
|
+
[deployment lifecycle](./testing-and-deployment.md#stdio-process-signals).
|
|
2663
|
+
|
|
2623
2664
|
Both transports build the server through the shared `buildMcpServer` — same
|
|
2624
2665
|
contract/runtime pipeline, same surface selection, context, hooks, raw escape
|
|
2625
2666
|
hatch and instructions.
|
|
@@ -2943,7 +2984,9 @@ const countRecords = knowledgeTools.define({
|
|
|
2943
2984
|
`defineRuntimeTool` when tools do not share a context schema or identity.
|
|
2944
2985
|
|
|
2945
2986
|
`transports` defaults to `['MCP', 'AGENT']`; set an explicit subset when an
|
|
2946
|
-
operation belongs on only one surface.
|
|
2987
|
+
operation belongs on only one surface. Include `'CLI'` explicitly to reuse the
|
|
2988
|
+
definition through `createCli({ runtimeTools })`; adding CLI support never
|
|
2989
|
+
widens existing definitions silently. The configured identity becomes the
|
|
2947
2990
|
hook/lifecycle `OperationIdentity` and the tool `RequestEvent`
|
|
2948
2991
|
(`serviceName`, `action`, `httpMethod`). A runtime operation has no HTTP route,
|
|
2949
2992
|
so no fake `path` is added.
|
|
@@ -2960,12 +3003,88 @@ The MCP registration uses an identity carrier: the SDK advertises the compiled
|
|
|
2960
3003
|
JSON Schema but forwards the raw object into Stitchkit. Input failures therefore
|
|
2961
3004
|
use the same validation, lifecycle and hook path as contract tools.
|
|
2962
3005
|
|
|
3006
|
+
### Managed wait, download, upload and view-file
|
|
3007
|
+
|
|
3008
|
+
The common imperative shapes have typed definition factories. They produce
|
|
3009
|
+
ordinary runtime-tool definitions, so one value can enter `runtimeTools` on MCP
|
|
3010
|
+
and Agent and receives the same lifecycle, hooks, context, cancellation,
|
|
3011
|
+
collision checks and introspection as any `defineRuntimeTool` operation:
|
|
3012
|
+
|
|
3013
|
+
```ts
|
|
3014
|
+
import {
|
|
3015
|
+
defineDownloadTool,
|
|
3016
|
+
defineUploadTool,
|
|
3017
|
+
defineViewFileTool,
|
|
3018
|
+
defineWaitTool,
|
|
3019
|
+
} from 'stitchkit/tools'
|
|
3020
|
+
import { z } from 'zod'
|
|
3021
|
+
|
|
3022
|
+
const waitForJob = defineWaitTool({
|
|
3023
|
+
name: 'wait_for_job',
|
|
3024
|
+
description: 'Wait for a job to finish',
|
|
3025
|
+
identity: { serviceName: 'jobs', action: 'waitForJob', scope: 'user' },
|
|
3026
|
+
input: z.object({ id: z.string() }),
|
|
3027
|
+
state: z.object({ id: z.string(), status: z.enum(['RUNNING', 'DONE']) }),
|
|
3028
|
+
poll: ({ id }, context) => getJob(id, context.signal),
|
|
3029
|
+
done: (state) => state.status === 'DONE',
|
|
3030
|
+
backoff: [2, 3, 5],
|
|
3031
|
+
defaultTimeout: 120,
|
|
3032
|
+
})
|
|
3033
|
+
|
|
3034
|
+
const downloadResult = defineDownloadTool({
|
|
3035
|
+
name: 'download_result',
|
|
3036
|
+
description: 'Download a completed result',
|
|
3037
|
+
identity: { serviceName: 'jobs', action: 'downloadResult', scope: 'user' },
|
|
3038
|
+
input: z.object({ id: z.string(), dir: z.string().optional() }),
|
|
3039
|
+
resolveUrl: ({ id }) => resolveResultUrl(id),
|
|
3040
|
+
defaultDir: './downloads',
|
|
3041
|
+
dirFromInput: ({ dir }) => dir,
|
|
3042
|
+
})
|
|
3043
|
+
|
|
3044
|
+
const uploadInput = defineUploadTool({
|
|
3045
|
+
name: 'upload_input',
|
|
3046
|
+
description: 'Upload a local input file',
|
|
3047
|
+
identity: { serviceName: 'jobs', action: 'uploadInput', scope: 'user' },
|
|
3048
|
+
output: z.object({ url: z.url() }),
|
|
3049
|
+
upload: (path, context) => uploadFile(path, context.signal),
|
|
3050
|
+
})
|
|
3051
|
+
|
|
3052
|
+
const viewResult = defineViewFileTool({
|
|
3053
|
+
name: 'view_result',
|
|
3054
|
+
description: 'Inspect generated media',
|
|
3055
|
+
identity: { serviceName: 'jobs', action: 'viewResult', scope: 'user' },
|
|
3056
|
+
// Local files are disabled when baseDir is omitted. URL fetches retain SSRF
|
|
3057
|
+
// protection; use allowPrivateHosts only for an explicitly trusted network.
|
|
3058
|
+
baseDir: '/srv/job-media',
|
|
3059
|
+
})
|
|
3060
|
+
|
|
3061
|
+
const runtimeTools = [waitForJob, downloadResult, uploadInput, viewResult]
|
|
3062
|
+
```
|
|
3063
|
+
|
|
3064
|
+
Managed factories return neutral validated data. Expected failures go through
|
|
3065
|
+
the standard failed `ToolResult` path rather than masquerading as a successful
|
|
3066
|
+
payload with `isError`. Wait sleep is abort-aware, guarded downloads receive the
|
|
3067
|
+
active signal, and upload implementations receive it on their typed context.
|
|
3068
|
+
Managed view-file accepts one or several paths/URLs, retains successful
|
|
3069
|
+
multimodal content beside structured per-item `errors`, and charges every item
|
|
3070
|
+
to one total 20 MB batch budget. Its MCP and Agent presenters are built in;
|
|
3071
|
+
remote fetch cancellation follows the active call signal.
|
|
3072
|
+
|
|
3073
|
+
The older `mountWait`, `mountDownload`, `mountUpload` and `mountViewFile`
|
|
3074
|
+
functions remain
|
|
3075
|
+
intentional raw MCP adapters with their text-envelope behavior. Use them under
|
|
3076
|
+
`rawTools` only when opting out of managed policy is deliberate; they share the
|
|
3077
|
+
same neutral mechanics but do not gain lifecycle or hooks. The raw view-file
|
|
3078
|
+
adapter preserves its content-only MCP envelope while using the same bounded
|
|
3079
|
+
batch operation.
|
|
3080
|
+
|
|
2963
3081
|
### Explicit raw SDK registration
|
|
2964
3082
|
|
|
2965
3083
|
`rawTools` is deliberately named as an escape hatch. A tool registered there
|
|
2966
3084
|
does **not** receive stitchkit schema policy, lifecycle, per-call context or
|
|
2967
|
-
hooks. The built-in `mountViewFile`
|
|
2968
|
-
|
|
3085
|
+
hooks. The built-in `mountViewFile`, `mountWait`, `mountDownload` and
|
|
3086
|
+
`mountUpload` helpers remain raw for callers that choose that boundary; the
|
|
3087
|
+
media helper fetches with SSRF and path-traversal defenses:
|
|
2969
3088
|
|
|
2970
3089
|
```ts
|
|
2971
3090
|
import { createMcpHandler, mountViewFile } from 'stitchkit/tools'
|
|
@@ -2979,8 +3098,10 @@ const handleMcp = createMcpHandler({
|
|
|
2979
3098
|
```
|
|
2980
3099
|
|
|
2981
3100
|
Use raw registration only when opting out is intentional. For a protected
|
|
2982
|
-
`view_file`,
|
|
2983
|
-
|
|
3101
|
+
`view_file`, use `defineViewFileTool` in `runtimeTools`; it supplies the
|
|
3102
|
+
canonical schemas, shared batch budget, structured partial failures and both
|
|
3103
|
+
multimodal presenters. `resolveMedia` remains the single-item core for custom
|
|
3104
|
+
operations whose contract intentionally differs.
|
|
2984
3105
|
|
|
2985
3106
|
## Introspecting the complete tool surface
|
|
2986
3107
|
|
|
@@ -3061,11 +3182,13 @@ identical. Write the handler once; it serves every surface.
|
|
|
3061
3182
|
|
|
3062
3183
|
# CLI
|
|
3063
3184
|
|
|
3064
|
-
The same contract that
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3185
|
+
The same contract and managed runtime tools that drive HTTP, MCP and agent
|
|
3186
|
+
surfaces can also drive a command-line program. `createCli` composes their
|
|
3187
|
+
commands with explicitly local binary commands in one router and help tree.
|
|
3188
|
+
Managed commands — `myapp generate "a fox" --wait`,
|
|
3189
|
+
`myapp models list --json | jq …` — run through the same validation, auth gate
|
|
3190
|
+
and error model as every other managed surface (HTTP ≡ MCP ≡ agent ≡ CLI,
|
|
3191
|
+
[ADR 0014](../decisions/0014-tool-http-parity.md)).
|
|
3069
3192
|
|
|
3070
3193
|
It exists for what the other three surfaces cannot do: a generation kicked off
|
|
3071
3194
|
with `Bash(run_in_background)` that notifies on exit, a `SKILL.md` that shells
|
|
@@ -3086,8 +3209,10 @@ the CLI never silently turns your existing API tools into shell commands.
|
|
|
3086
3209
|
```
|
|
3087
3210
|
|
|
3088
3211
|
A fresh contract shows **zero** CLI commands until methods opt in — that is the
|
|
3089
|
-
design, not a bug.
|
|
3090
|
-
|
|
3212
|
+
design, not a bug. A pathless runtime definition follows the same rule: it must
|
|
3213
|
+
explicitly include `'CLI'` in `transports`; the undefined default remains
|
|
3214
|
+
`['MCP', 'AGENT']`. The command name is the tool name — `toolName` if set, else
|
|
3215
|
+
a verb-aware name from the method + prefix (`list` → `list_widgets`, `get` →
|
|
3091
3216
|
`get_widget`), not a literal `prefix_key`.
|
|
3092
3217
|
|
|
3093
3218
|
## A minimal CLI
|
|
@@ -3105,7 +3230,7 @@ await createCli({
|
|
|
3105
3230
|
name: 'myapp',
|
|
3106
3231
|
version: '1.0.0',
|
|
3107
3232
|
services: [catalogService, generateService],
|
|
3108
|
-
|
|
3233
|
+
resolveAuth: () => resolveToken(process.env.MYAPP_TOKEN), // lazy, at most once
|
|
3109
3234
|
})
|
|
3110
3235
|
```
|
|
3111
3236
|
|
|
@@ -3117,6 +3242,81 @@ await createCli({
|
|
|
3117
3242
|
`stitchkit/cli` pulls in neither the MCP SDK nor `ai`, so a CLI binary needs no
|
|
3118
3243
|
MCP/agent peer dependencies.
|
|
3119
3244
|
|
|
3245
|
+
## Pathless managed commands
|
|
3246
|
+
|
|
3247
|
+
Use `runtimeTools` when an application operation has no HTTP path but must keep
|
|
3248
|
+
the canonical operation identity, context, lifecycle/RBAC, hooks and
|
|
3249
|
+
introspection. It can share one definition with MCP and Agent while opting into
|
|
3250
|
+
CLI explicitly:
|
|
3251
|
+
|
|
3252
|
+
```ts
|
|
3253
|
+
import { createCli } from 'stitchkit/cli'
|
|
3254
|
+
import { defineUploadTool } from 'stitchkit/tools'
|
|
3255
|
+
import { z } from 'zod'
|
|
3256
|
+
|
|
3257
|
+
const uploadInput = defineUploadTool({
|
|
3258
|
+
name: 'upload_input',
|
|
3259
|
+
description: 'Upload one local input file',
|
|
3260
|
+
identity: { serviceName: 'jobs', action: 'uploadInput', scope: 'user' },
|
|
3261
|
+
output: z.object({ url: z.url() }),
|
|
3262
|
+
transports: ['MCP', 'AGENT', 'CLI'],
|
|
3263
|
+
upload: (path, context) => uploadFile(path, context.signal),
|
|
3264
|
+
})
|
|
3265
|
+
|
|
3266
|
+
await createCli({
|
|
3267
|
+
name: 'myapp',
|
|
3268
|
+
version: '1.0.0',
|
|
3269
|
+
runtimeTools: [uploadInput],
|
|
3270
|
+
})
|
|
3271
|
+
```
|
|
3272
|
+
|
|
3273
|
+
`services` and `runtimeTools` may each be static arrays or factories receiving
|
|
3274
|
+
the resolved identity. A runtime-only CLI is valid; `stitchkit/cli` still pulls
|
|
3275
|
+
in neither MCP nor AI peers. Contract/runtime name collisions and reserved
|
|
3276
|
+
option fields fail through the same checks before managed dispatch.
|
|
3277
|
+
|
|
3278
|
+
## Native binary commands
|
|
3279
|
+
|
|
3280
|
+
Login, self-update, diagnostics, integration setup and shell completion belong
|
|
3281
|
+
to the executable, not to HTTP/MCP/Agent. Define them with `defineCliCommand`:
|
|
3282
|
+
|
|
3283
|
+
```ts
|
|
3284
|
+
import { createCli, defineCliCommand } from 'stitchkit/cli'
|
|
3285
|
+
import { z } from 'zod'
|
|
3286
|
+
|
|
3287
|
+
const login = defineCliCommand({
|
|
3288
|
+
name: 'login',
|
|
3289
|
+
description: 'Store credentials for later managed commands',
|
|
3290
|
+
input: z.object({ token: z.string() }),
|
|
3291
|
+
output: z.object({ configured: z.boolean() }),
|
|
3292
|
+
handler: async ({ input }) => {
|
|
3293
|
+
await saveToken(input.token)
|
|
3294
|
+
return { configured: true }
|
|
3295
|
+
},
|
|
3296
|
+
})
|
|
3297
|
+
|
|
3298
|
+
await createCli({
|
|
3299
|
+
name: 'myapp',
|
|
3300
|
+
version: '1.0.0',
|
|
3301
|
+
commands: [login],
|
|
3302
|
+
resolveAuth: loadStoredIdentity,
|
|
3303
|
+
services: (identity) => createRemoteServices(identity),
|
|
3304
|
+
})
|
|
3305
|
+
```
|
|
3306
|
+
|
|
3307
|
+
Native commands receive only typed `input`, parsed global `options` and the
|
|
3308
|
+
configured stdout/stderr writers. They reuse help, argv/stdin parsing,
|
|
3309
|
+
validation, dry-run, error envelopes and exit mapping, but deliberately have no
|
|
3310
|
+
fake service/action/scope/method identity, lifecycle or tool hooks and never
|
|
3311
|
+
appear in MCP/Agent manifests.
|
|
3312
|
+
|
|
3313
|
+
`--version`, a selected native command and its command help run before
|
|
3314
|
+
`resolveAuth`, services, context or runtime-tool factories. Top-level help is
|
|
3315
|
+
also credential-free when managed surfaces are static. A dynamic factory must
|
|
3316
|
+
resolve identity to discover its command names; its collisions are checked at
|
|
3317
|
+
that resolution boundary. If eager global collision proof matters, keep the
|
|
3318
|
+
surface static.
|
|
3319
|
+
|
|
3120
3320
|
## Calling commands
|
|
3121
3321
|
|
|
3122
3322
|
```
|
|
@@ -3201,7 +3401,7 @@ const authHook = createAuthHook({ /* resolve, resolveFromContext, rules */ })
|
|
|
3201
3401
|
await createCli({
|
|
3202
3402
|
name: 'myapp',
|
|
3203
3403
|
version: '1.0.0',
|
|
3204
|
-
|
|
3404
|
+
resolveAuth: () => resolveIdentityFromToken(process.env.MYAPP_TOKEN),
|
|
3205
3405
|
context: (identity) => ({ user: identity }), // resolveFromContext reads this
|
|
3206
3406
|
lifecycle: { beforeHandle: authHook }, // same policy; HTTP wires it as authorize
|
|
3207
3407
|
services,
|
|
@@ -3233,11 +3433,12 @@ await tools.createCli({
|
|
|
3233
3433
|
})
|
|
3234
3434
|
```
|
|
3235
3435
|
|
|
3236
|
-
##
|
|
3436
|
+
## Remaining boundary
|
|
3237
3437
|
|
|
3238
|
-
File-upload (`multipart`) endpoints
|
|
3239
|
-
|
|
3240
|
-
|
|
3438
|
+
File-upload (`multipart`) contract endpoints remain CLI-invisible, the same as
|
|
3439
|
+
on MCP/Agent: their wire body is not a JSON tool form. Model file-oriented
|
|
3440
|
+
application behavior as a managed pathless command, or binary-only behavior as
|
|
3441
|
+
a native command. Streaming (SSE) output is not yet piped to stdout.
|
|
3241
3442
|
|
|
3242
3443
|
|
|
3243
3444
|
==============================================================================
|
|
@@ -5079,6 +5280,38 @@ domain run-state remain application resources and close explicitly after server
|
|
|
5079
5280
|
drain. Do not call `runtime.stop()` or `socket.io.close()` in parallel with
|
|
5080
5281
|
`shutdown()`.
|
|
5081
5282
|
|
|
5283
|
+
### Stdio process signals
|
|
5284
|
+
|
|
5285
|
+
An MCP stdio handle has `close()`, not managed HTTP `shutdown()` with a force
|
|
5286
|
+
signal and deadline. Bind its process lifecycle with the truthful close-only
|
|
5287
|
+
sibling from `stitchkit/tools`:
|
|
5288
|
+
|
|
5289
|
+
```ts
|
|
5290
|
+
import {
|
|
5291
|
+
bindStdioProcessSignals,
|
|
5292
|
+
createStdioMcpServer,
|
|
5293
|
+
} from 'stitchkit/tools'
|
|
5294
|
+
|
|
5295
|
+
const stdio = await createStdioMcpServer(config)
|
|
5296
|
+
const binding = bindStdioProcessSignals(stdio, {
|
|
5297
|
+
onClose: () => stopWorkers(),
|
|
5298
|
+
onComplete: () => { process.exitCode = 0 },
|
|
5299
|
+
onError: (phase, error) => {
|
|
5300
|
+
console.error(phase, error) // stderr; stdout stays JSON-RPC-only
|
|
5301
|
+
process.exitCode = 1
|
|
5302
|
+
},
|
|
5303
|
+
})
|
|
5304
|
+
|
|
5305
|
+
await binding.promise
|
|
5306
|
+
```
|
|
5307
|
+
|
|
5308
|
+
The first signal starts exactly one close chain. A same-turn duplicate is
|
|
5309
|
+
ignored; a later signal restores the default OS disposition because the
|
|
5310
|
+
official stdio close is not abortable and Stitchkit will not pretend otherwise.
|
|
5311
|
+
`binding.close()` removes idle listeners and resolves the promise with
|
|
5312
|
+
`undefined`. No listener is installed until the binder is called, and the
|
|
5313
|
+
framework never calls `process.exit()`.
|
|
5314
|
+
|
|
5082
5315
|
### Deploy on Node
|
|
5083
5316
|
|
|
5084
5317
|
The contract, `implement`, hooks, auth and the client are runtime-agnostic. Only
|
|
@@ -6443,8 +6676,11 @@ from the root `stitchkit`.
|
|
|
6443
6676
|
| `HttpMethod` | _type_ | `GET \| HEAD \| POST \| PUT \| PATCH \| DELETE` |
|
|
6444
6677
|
| `Transport` | _type_ | `HTTP \| MCP \| AGENT \| CLI` |
|
|
6445
6678
|
| `TransportSource` | _type_ | `http \| mcp \| agent \| cli` — the value of `ctx.source` |
|
|
6446
|
-
| `RuntimeContext` | _type_ | the loose context seen by transport and hooks |
|
|
6447
|
-
| `HandlerContext` | _type_ | the typed context seen by a handler |
|
|
6679
|
+
| `RuntimeContext` | _type_ | the loose context seen by transport and hooks, including optional typed `mcp` metadata |
|
|
6680
|
+
| `HandlerContext` | _type_ | the typed context seen by a handler, including optional typed `mcp` metadata |
|
|
6681
|
+
| `McpCallContext` | _type_ | validated metadata for the active managed MCP call (`era`, method, tool, client and multi-round fields) |
|
|
6682
|
+
| `McpClientInfo` | _type_ | self-reported MCP host name/version; attribution only, never application identity |
|
|
6683
|
+
| `McpRoundOutcome` | _type_ | managed multi-round attempt outcome |
|
|
6448
6684
|
| `EndpointHandlerContext` | _type_ | one endpoint handler's fully inferred params, input, files and runtime context |
|
|
6449
6685
|
| `EndpointFn` | _type_ | the call signature of one client method |
|
|
6450
6686
|
| `TypedClient` | _type_ | the full typed client for a contract |
|
|
@@ -6775,14 +7011,16 @@ payload.
|
|
|
6775
7011
|
| `createMcpHandler` | function | a stateless dual-era Streamable-HTTP MCP handler — [guide](../guide/mcp-and-agents.md#mcp--createmcphandler) |
|
|
6776
7012
|
| `createMcpHttpRoute` | function | framework-owned `RawRoute` adapter for an MCP HTTP handler |
|
|
6777
7013
|
| `createStdioMcpServer` | function | a complete stdio MCP server — [guide](../guide/mcp-and-agents.md#mcp-over-stdio--createstdiomcpserver) |
|
|
7014
|
+
| `bindStdioProcessSignals` | function | explicitly bind OS signals to one close-only stdio handle — [guide](../guide/testing-and-deployment.md#stdio-process-signals) |
|
|
6778
7015
|
| `buildMcpServer` | function | build an `McpServer` from contract/runtime surfaces; no-auth configs omit the second argument |
|
|
6779
7016
|
| `mountMcp` | function | add contract tools to an existing `McpServer` — [guide](../guide/mcp-and-agents.md#mountmcp) |
|
|
6780
7017
|
| `implementRemote` | function | bind a contract to a remote HTTP API — [guide](../guide/mcp-and-agents.md#proxying-a-remote-api--implementremote) |
|
|
6781
7018
|
| `mountAgent` | function | a Vercel AI SDK `ToolSet` from a service — [guide](../guide/mcp-and-agents.md#ai-agents--mountagent) |
|
|
6782
|
-
| `defineRuntimeTool` | function | define one validated pathless operation for MCP, Agent or
|
|
7019
|
+
| `defineRuntimeTool` | function | define one validated pathless operation for explicit MCP, Agent and/or CLI surfaces — [guide](../guide/mcp-and-agents.md#pathless-runtime-tools-and-multimodal-results) |
|
|
6783
7020
|
| `createRuntimeToolFactory` | function | bind shared identity and Zod-validated per-call context for runtime tools — [guide](../guide/mcp-and-agents.md#pathless-runtime-tools-and-multimodal-results) |
|
|
6784
7021
|
| `createToolInvoker` | function | compile an exposure-aware in-process dispatcher over the canonical tool runner — [guide](../guide/mcp-and-agents.md#in-process-calls--createtoolinvoker) |
|
|
6785
7022
|
| `createCli` | function | a command-line program from contracts — [guide](../guide/cli.md) (also on `stitchkit/cli`) |
|
|
7023
|
+
| `defineCliCommand` | function | define one typed CLI-only command with no fake managed-tool identity — [guide](../guide/cli.md#native-binary-commands) (also on `stitchkit/cli`) |
|
|
6786
7024
|
| `createToolkit` | function | context-typed tool mounts — [guide](../guide/cli.md#typed-context) |
|
|
6787
7025
|
| `mountViewFile` | function | a native multimodal "view file" MCP tool |
|
|
6788
7026
|
| `resolveMedia` | function | resolve a media reference for a tool result |
|
|
@@ -6796,6 +7034,10 @@ payload.
|
|
|
6796
7034
|
| `McpLegacyPolicy` | _type_ | `'serve' \| 'reject'` protocol-era compatibility policy |
|
|
6797
7035
|
| `McpStdioHandle` | _type_ | closeable official stdio transport handle |
|
|
6798
7036
|
| `StdioMcpServerConfig` | _type_ | config for `createStdioMcpServer` |
|
|
7037
|
+
| `StdioCloseTarget` | _type_ | minimal close-only target accepted by `bindStdioProcessSignals` |
|
|
7038
|
+
| `StdioProcessSignalsOptions` | _type_ | signal source, close callbacks and phased error reporting |
|
|
7039
|
+
| `StdioProcessSignalsBinding` | _type_ | close-only signal binding with observed `promise` and listener `close()` |
|
|
7040
|
+
| `StdioProcessSignalsErrorPhase` | _type_ | `'prepare' \| 'close' \| 'complete'` reporting phase |
|
|
6799
7041
|
| `McpServerBuildConfig` | _type_ | shared config for `buildMcpServer` |
|
|
6800
7042
|
| `McpServerSharedConfig` | _type_ | transport-neutral options shared by direct and finite surface configs |
|
|
6801
7043
|
| `McpServer` | _type_ | official split-SDK server instance accepted by raw extension points |
|
|
@@ -6833,10 +7075,16 @@ payload.
|
|
|
6833
7075
|
| `CimdCacheEvent` | _type_ | observable CIMD cache hit, miss, revalidation and eviction event |
|
|
6834
7076
|
| `createSecureClientMetadataFetcher` | function | production HTTPS, DNS/IP-pinned CIMD fetcher |
|
|
6835
7077
|
| `RuntimeAgentModelOutput` | _type_ | AI SDK model-facing text/JSON/content output returned by `present.agent` |
|
|
6836
|
-
| `RuntimeToolTransport` | _type_ | runtime exposure: `'MCP' \| 'AGENT'
|
|
7078
|
+
| `RuntimeToolTransport` | _type_ | runtime exposure: `'MCP' \| 'AGENT' \| 'CLI'`; omission still means MCP+Agent only |
|
|
6837
7079
|
| `AgentMountConfig` | _type_ | config for `mountAgent` |
|
|
6838
7080
|
| `AgentContext` | _type_ | the context merged into agent tool handlers |
|
|
6839
7081
|
| `CliConfig` | _type_ | config for `createCli` |
|
|
7082
|
+
| `CliSurfaceSource` | _type_ | static managed surface or identity-dependent surface factory for `createCli` |
|
|
7083
|
+
| `CliCommandDefinition` | _type_ | Zod-first CLI-only command union |
|
|
7084
|
+
| `CliCommandDefinitionBase` | _type_ | native command name, description and input schema |
|
|
7085
|
+
| `CliCommandDefinitionWithOutput` | _type_ | native command with declared output schema and validated handler result |
|
|
7086
|
+
| `CliCommandDefinitionWithoutOutput` | _type_ | void native command with no output schema |
|
|
7087
|
+
| `CliCommandContext` | _type_ | parsed native command input, global options and injected writers |
|
|
6840
7088
|
| `CliWaitConfig` | _type_ | `--wait` polling config |
|
|
6841
7089
|
| `ExitCodeMap` | _type_ | `ToolResult.code` → process exit code |
|
|
6842
7090
|
| `Toolkit` | _type_ | the context-pinned tool surface from `createToolkit` |
|
|
@@ -6853,9 +7101,15 @@ payload.
|
|
|
6853
7101
|
| `ToolInvokerConfig` | _type_ | compile-time exposure, extension and presentation options |
|
|
6854
7102
|
| `ToolInvocationOptions` | _type_ | per-call source, context, lifecycle, hooks and output-strip reporter |
|
|
6855
7103
|
| `ToolInvokerTransport` | _type_ | invoker exposure policy: `MCP \| AGENT \| CLI` |
|
|
6856
|
-
| `ToolCallContext` | _type_ | the context every tool hook receives — `{ source }` plus whatever the mount's `context` added |
|
|
6857
|
-
| `ViewFileOptions` | _type_ |
|
|
7104
|
+
| `ToolCallContext` | _type_ | the context every tool hook receives — `{ source, mcp? }` plus whatever the mount's `context` added |
|
|
7105
|
+
| `ViewFileOptions` | _type_ | shared URL/local-sandbox policy for `defineViewFileTool`, `mountViewFile` and `resolveMedia` |
|
|
7106
|
+
| `ViewFileOutput` | _type_ | neutral managed batch result with multimodal `content` and per-item `errors` |
|
|
7107
|
+
| `ViewFileInputSchema` | constant | fixed one-or-many media path/URL input schema |
|
|
7108
|
+
| `ViewFileOutputSchema` | constant | Zod schema for the neutral managed view-file batch result |
|
|
7109
|
+
| `ViewFileErrorSchema` | constant | Zod schema for one structured per-item view failure |
|
|
6858
7110
|
| `McpAnnotations` | _type_ | MCP annotations on a media result |
|
|
7111
|
+
| `McpAnnotationsSchema` | constant | Zod schema for MCP media annotations |
|
|
7112
|
+
| `McpMediaContentSchema` | constant | Zod schema for text/image/audio media content |
|
|
6859
7113
|
| `CollectToolsConfig` | _type_ | options for `collectTools` |
|
|
6860
7114
|
| `findUntypedProperties` | function | every property in a JSON Schema with no `type`/`enum`/`$ref` — what a model is shown and cannot obey ([guide](../guide/mcp-and-agents.md)) |
|
|
6861
7115
|
| `UntypedProperty` | _type_ | one such property — `{ path, description? }` |
|
|
@@ -6868,13 +7122,28 @@ payload.
|
|
|
6868
7122
|
|
|
6869
7123
|
### Native tools
|
|
6870
7124
|
|
|
6871
|
-
Generic host-supplied
|
|
7125
|
+
Generic host-supplied operations — managed definitions for the canonical
|
|
7126
|
+
runtime-tool runner, plus deliberate raw MCP adapters over the same mechanics.
|
|
6872
7127
|
|
|
6873
7128
|
| Export | Kind | Summary |
|
|
6874
7129
|
|--------|------|---------|
|
|
6875
|
-
| `
|
|
6876
|
-
| `
|
|
6877
|
-
| `
|
|
7130
|
+
| `defineDownloadTool` | function | define a guarded, size-capped managed download for MCP/Agent `runtimeTools` |
|
|
7131
|
+
| `defineUploadTool` | function | define a typed managed local-file upload for MCP/Agent `runtimeTools` |
|
|
7132
|
+
| `defineWaitTool` | function | define a typed, cancellable managed polling operation for MCP/Agent `runtimeTools` |
|
|
7133
|
+
| `defineViewFileTool` | function | define a guarded, batch-capped managed multimodal operation for MCP/Agent `runtimeTools` |
|
|
7134
|
+
| `DefineDownloadToolConfig` | _type_ | Zod input, stable identity, URL resolver, storage policy and presenters for `defineDownloadTool` |
|
|
7135
|
+
| `DefineUploadToolConfig` | _type_ | stable identity, typed output, upload callback and presenters for `defineUploadTool` |
|
|
7136
|
+
| `DefineWaitToolConfig` | _type_ | Zod input/state, identity, poll/done/timeout policy and presenters for `defineWaitTool` |
|
|
7137
|
+
| `DefineViewFileToolConfig` | _type_ | identity, media security policy and optional presenters for `defineViewFileTool` |
|
|
7138
|
+
| `ManagedNativeToolConfig` | _type_ | shared name, description, identity, exposure and annotations for managed native factories |
|
|
7139
|
+
| `NativeToolIdentity` | _type_ | pathless service/action/scope/meta identity; semantic method is factory-owned |
|
|
7140
|
+
| `ManagedWaitRender` | _type_ | optional managed wait terminal text and failure classification |
|
|
7141
|
+
| `DownloadResultSchema` | constant | Zod schema for a saved download's path, byte size and MIME type |
|
|
7142
|
+
| `DownloadResult` | _type_ | validated output of `defineDownloadTool` |
|
|
7143
|
+
| `UploadToolInputSchema` | constant | fixed `{ path: string }` input schema for `defineUploadTool` |
|
|
7144
|
+
| `mountDownload` | function | raw MCP "download a URL to disk" adapter (SSRF-guarded, size-capped) |
|
|
7145
|
+
| `mountUpload` | function | raw MCP "upload a local file" adapter |
|
|
7146
|
+
| `mountWait` | function | raw MCP generic `--wait`-style polling adapter |
|
|
6878
7147
|
| `DownloadToolConfig` | _type_ | config for `mountDownload` |
|
|
6879
7148
|
| `UploadToolConfig` | _type_ | config for `mountUpload` |
|
|
6880
7149
|
| `WaitToolConfig` | _type_ | config for `mountWait` |
|
|
@@ -6979,17 +7248,25 @@ runtime-agnostic pieces of `stitchkit/server` and the error helpers.
|
|
|
6979
7248
|
|
|
6980
7249
|
## `stitchkit/cli`
|
|
6981
7250
|
|
|
6982
|
-
Server-only.
|
|
6983
|
-
Light by design: needs neither the MCP
|
|
7251
|
+
Server-only. Composes contract/runtime managed operations and CLI-only native
|
|
7252
|
+
commands into one command-line program. Light by design: needs neither the MCP
|
|
7253
|
+
SDK nor the `ai` peer.
|
|
6984
7254
|
|
|
6985
7255
|
| Export | Kind | Summary |
|
|
6986
7256
|
|--------|------|---------|
|
|
6987
7257
|
| `createCli` | function | build and run a CLI from contracts — [guide](../guide/cli.md) |
|
|
7258
|
+
| `defineCliCommand` | function | define one Zod-typed CLI-only executable command |
|
|
6988
7259
|
| `parseCliArgs` | function | argv → typed tool args against a schema (advanced) |
|
|
6989
7260
|
| `pollUntilDone` | function | the generic `--wait` poller (advanced) |
|
|
6990
7261
|
| `emitResult` | function | write a `ToolResult` to stdout/stderr + exit code (advanced) |
|
|
6991
7262
|
| `DEFAULT_EXIT_CODES` | const | the default `ToolResult.code` → exit-code map |
|
|
6992
7263
|
| `CliConfig` | _type_ | config for `createCli` |
|
|
7264
|
+
| `CliSurfaceSource` | _type_ | static service/runtime array or identity-dependent factory |
|
|
7265
|
+
| `CliCommandDefinition` | _type_ | native command definition union |
|
|
7266
|
+
| `CliCommandDefinitionBase` | _type_ | native command name, description and input schema |
|
|
7267
|
+
| `CliCommandDefinitionWithOutput` | _type_ | native command with validated declared output |
|
|
7268
|
+
| `CliCommandDefinitionWithoutOutput` | _type_ | native void command without an output contract |
|
|
7269
|
+
| `CliCommandContext` | _type_ | parsed input, global options and stdout/stderr writers |
|
|
6993
7270
|
| `CliRunOptions` | _type_ | parsed global flags (`--json`, `--wait`, …) |
|
|
6994
7271
|
| `ParsedCliArgs` | _type_ | result of `parseCliArgs` |
|
|
6995
7272
|
| `CliWaitConfig` | _type_ | per-command `--wait` polling config |
|
package/package.json
CHANGED