stitchkit 0.43.1 → 0.44.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/README.md +12 -4
- package/dist/cli.js +2 -2
- package/dist/contract/define.d.ts +18 -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-310bfer5.js → index-36f1xkdb.js} +1 -1
- package/dist/{index-esqmem78.js → index-4fyn9f09.js} +2 -1
- package/dist/{index-h2wdcsby.js → index-mvjyq9h9.js} +176 -12
- package/dist/{index-gex6gxhe.js → index-yh0p5ddn.js} +34 -2
- package/dist/index.js +4 -1
- package/dist/internal/secure-fetch.d.ts +21 -1
- package/dist/internal/secure-fetch.d.ts.map +1 -1
- package/dist/node.js +2 -2
- package/dist/observability/audit.d.ts.map +1 -1
- package/dist/observability/event.d.ts +16 -0
- package/dist/observability/event.d.ts.map +1 -1
- package/dist/observability/index.d.ts +1 -1
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +30 -1
- package/dist/observability/trace.d.ts +10 -0
- package/dist/observability/trace.d.ts.map +1 -1
- package/dist/server/implement.d.ts.map +1 -1
- package/dist/server/index.js +3 -3
- package/dist/server/types.d.ts +14 -2
- package/dist/server/types.d.ts.map +1 -1
- package/dist/tools/execute.d.ts +1 -1
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/mcp-app.d.ts +3 -0
- package/dist/tools/mcp-app.d.ts.map +1 -1
- package/dist/tools/mcp-handler.d.ts +34 -23
- package/dist/tools/mcp-handler.d.ts.map +1 -1
- package/dist/tools/mcp-round.d.ts +43 -0
- package/dist/tools/mcp-round.d.ts.map +1 -0
- package/dist/tools/mcp-stdio.d.ts +11 -18
- package/dist/tools/mcp-stdio.d.ts.map +1 -1
- package/dist/tools/mcp-trace.d.ts +4 -0
- package/dist/tools/mcp-trace.d.ts.map +1 -0
- package/dist/tools/mcp.d.ts +24 -3
- package/dist/tools/mcp.d.ts.map +1 -1
- package/dist/tools/mount-download.d.ts +2 -2
- package/dist/tools/mount-download.d.ts.map +1 -1
- package/dist/tools/mount-upload.d.ts +1 -1
- package/dist/tools/mount-upload.d.ts.map +1 -1
- package/dist/tools/mount-wait.d.ts +3 -3
- package/dist/tools/mount-wait.d.ts.map +1 -1
- package/dist/tools/mount.d.ts +1 -1
- package/dist/tools/mount.d.ts.map +1 -1
- package/dist/tools/native-mcp.d.ts +3 -2
- package/dist/tools/native-mcp.d.ts.map +1 -1
- package/dist/tools/oauth-provider.d.ts +77 -7
- package/dist/tools/oauth-provider.d.ts.map +1 -1
- package/dist/tools/runtime-tool.d.ts +27 -20
- package/dist/tools/runtime-tool.d.ts.map +1 -1
- package/dist/tools/toolkit.d.ts +5 -5
- package/dist/tools/toolkit.d.ts.map +1 -1
- package/dist/tools/view-file.d.ts +1 -1
- package/dist/tools/view-file.d.ts.map +1 -1
- package/dist/tools.d.ts +5 -5
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +816 -197
- package/llms-full.txt +412 -78
- package/package.json +5 -4
package/llms-full.txt
CHANGED
|
@@ -27,7 +27,7 @@ bun add stitchkit zod
|
|
|
27
27
|
|
|
28
28
|
`zod` is a required peer — schemas are the source of truth everywhere. Other
|
|
29
29
|
peers are optional and pulled in only when you use the matching feature
|
|
30
|
-
(`@modelcontextprotocol/
|
|
30
|
+
(`@modelcontextprotocol/server` for MCP servers, `ai` for agents, `socket.io*` for
|
|
31
31
|
realtime, `@tanstack/react-query` + `react-query-kit` for React). See
|
|
32
32
|
[deps](#dependencies) below.
|
|
33
33
|
|
|
@@ -141,9 +141,9 @@ map — feature → packages:
|
|
|
141
141
|
| anything (validation) | `zod` |
|
|
142
142
|
| `createServer` (Bun) | — (uses `Bun.serve`) |
|
|
143
143
|
| `serveNode` (Node ≥ 22) | `srvx` (+ `@types/bun` dev) |
|
|
144
|
-
| MCP tools (`stitchkit/tools`) | `@modelcontextprotocol/
|
|
144
|
+
| MCP / agent tools (`stitchkit/tools`) | `@modelcontextprotocol/server` `ai` |
|
|
145
|
+
| MCP host/client tests | `@modelcontextprotocol/client` |
|
|
145
146
|
| MCP Apps UI widgets | `@modelcontextprotocol/ext-apps` |
|
|
146
|
-
| agent tools (`stitchkit/tools`) | `ai` |
|
|
147
147
|
| React data layer (`stitchkit/react`) | `@tanstack/react-query` `react-query-kit` |
|
|
148
148
|
| **Socket.IO server on Bun** | `socket.io` `@socket.io/bun-engine` |
|
|
149
149
|
| **Socket.IO server on Node** | `socket.io` |
|
|
@@ -153,9 +153,22 @@ map — feature → packages:
|
|
|
153
153
|
bun add socket.io @socket.io/bun-engine # e.g. the Socket.IO server on Bun
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
Dynamic optional-peer adapters fail with an actionable error naming the package
|
|
157
|
+
and install command. Static entrypoints such as `stitchkit/tools` fail during
|
|
158
|
+
ESM resolution by naming the exact missing package; the feature-to-peer matrix
|
|
159
|
+
below is the canonical install command.
|
|
160
|
+
|
|
161
|
+
The combined tools entry owns MCP and AI-agent adapters, so install both runtime
|
|
162
|
+
peers before importing `stitchkit/tools`:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
bun add @modelcontextprotocol/server@^2 ai@^7
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Browser, HTTP-client and React entrypoints remain usable without either MCP
|
|
169
|
+
package. MCP hosts and client E2E additionally install
|
|
170
|
+
`@modelcontextprotocol/client@^2`; Apps additionally install
|
|
171
|
+
`@modelcontextprotocol/ext-apps`.
|
|
159
172
|
|
|
160
173
|
## Next
|
|
161
174
|
|
|
@@ -1804,27 +1817,28 @@ the invoker is created.
|
|
|
1804
1817
|
|
|
1805
1818
|
## MCP — `createMcpHandler`
|
|
1806
1819
|
|
|
1807
|
-
`createMcpHandler` builds a complete Streamable-HTTP MCP
|
|
1808
|
-
|
|
1809
|
-
|
|
1820
|
+
`createMcpHandler` builds a complete stateless Streamable-HTTP MCP endpoint on
|
|
1821
|
+
the official TypeScript SDK v2 server package. It owns server creation,
|
|
1822
|
+
protocol-era negotiation and shutdown; application code does not import the SDK
|
|
1823
|
+
to mount a normal endpoint.
|
|
1810
1824
|
|
|
1811
1825
|
```ts
|
|
1812
|
-
import { createMcpHandler } from 'stitchkit/tools'
|
|
1826
|
+
import { createMcpHandler, createMcpHttpRoute } from 'stitchkit/tools'
|
|
1827
|
+
import { createServer } from 'stitchkit/server'
|
|
1813
1828
|
|
|
1814
|
-
const
|
|
1829
|
+
const mcp = createMcpHandler({
|
|
1815
1830
|
serverInfo: { name: 'my-app', version: '1.0.0' },
|
|
1816
1831
|
auth: (req) => resolveApiKey(req), // → an identity, or null for 401
|
|
1817
1832
|
services: [usersService, catalogService],
|
|
1818
1833
|
})
|
|
1819
|
-
```
|
|
1820
1834
|
|
|
1821
|
-
Mount the returned handler on a raw route — typically `/mcp`:
|
|
1822
|
-
|
|
1823
|
-
```ts
|
|
1824
1835
|
createServer({
|
|
1825
1836
|
services,
|
|
1826
|
-
rawRoutes: [{
|
|
1837
|
+
rawRoutes: [createMcpHttpRoute({ path: '/mcp', handler: mcp })],
|
|
1827
1838
|
})
|
|
1839
|
+
|
|
1840
|
+
// During graceful shutdown:
|
|
1841
|
+
await mcp.close()
|
|
1828
1842
|
```
|
|
1829
1843
|
|
|
1830
1844
|
### `McpHandlerConfig`
|
|
@@ -1839,6 +1853,7 @@ createServer({
|
|
|
1839
1853
|
| `selectSurface` | `(auth) => declaredKey` — required with `surfaces` |
|
|
1840
1854
|
| `context` | `(auth) => {…}` — values merged into every tool handler's `ctx` |
|
|
1841
1855
|
| `lifecycle` | `beforeHandle` / `afterHandle` — the tool-side auth gate (see below) |
|
|
1856
|
+
| `multiRound` | Typed MRTR state policy for guarded multi-round tool calls |
|
|
1842
1857
|
| `hooks` | tool-call observability hooks — `afterToolCall` fires on every result |
|
|
1843
1858
|
| `extend` | extra advertised arguments resolved into handler context |
|
|
1844
1859
|
| `schemaValidation` | compatibility policy, typed-property guard and portable-format guard |
|
|
@@ -1851,7 +1866,10 @@ createServer({
|
|
|
1851
1866
|
| `errorHint` | add a project-owned hint to failed tool results |
|
|
1852
1867
|
| `onOutputStrip` | observe output keys removed by contract validation |
|
|
1853
1868
|
| `protectedResource` | RFC 9728 metadata used by HTTP `401` responses |
|
|
1854
|
-
| `
|
|
1869
|
+
| `legacy` | `'serve'` (default) or `'reject'` for pre-2026 clients |
|
|
1870
|
+
| `security` | optional Host/Origin allowlists at the Fetch boundary |
|
|
1871
|
+
| `onTransportRejected` | observe HTTP/protocol rejections without entering lifecycle or tool hooks |
|
|
1872
|
+
| `cache` | explicit operation cache hints; omitted means zero/private |
|
|
1855
1873
|
|
|
1856
1874
|
Direct `services` / `runtimeTools` factories, `context`, `selectSurface` and
|
|
1857
1875
|
`rawTools` receive the resolved identity, so a tenant can be shown only its own
|
|
@@ -1876,20 +1894,106 @@ const handleMcp = createMcpHandler({
|
|
|
1876
1894
|
Every declared entry is schema-validated and prepared once when the handler is
|
|
1877
1895
|
constructed. The selected immutable descriptors are shared; the SDK server,
|
|
1878
1896
|
transport, auth-derived context, lifecycle runner and tool-call context are
|
|
1879
|
-
fresh for every
|
|
1897
|
+
fresh for every request. Unknown keys
|
|
1880
1898
|
fail before the server connects. The registry never retains auth values.
|
|
1881
1899
|
|
|
1882
|
-
### Stateless
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
load balancing cannot strand a client on an in-memory session.
|
|
1900
|
+
### Stateless transport and protocol eras
|
|
1901
|
+
|
|
1902
|
+
Every request gets a fresh SDK server, resolved auth/context and tool-call
|
|
1903
|
+
runner. Static direct and finite registry schemas are still prepared once when
|
|
1904
|
+
the handler is constructed. There is no session map, event store,
|
|
1905
|
+
`Mcp-Session-Id` or resumable cross-request SSE state. Process replacement and
|
|
1906
|
+
load balancing therefore cannot strand a client on an in-memory session.
|
|
1907
|
+
|
|
1908
|
+
The default `legacy: 'serve'` lets the official SDK negotiate either modern
|
|
1909
|
+
`2026-07-28` or the supported legacy stateless opening on this same endpoint.
|
|
1910
|
+
Set `legacy: 'reject'` when every host is modern. Legacy support is protocol
|
|
1911
|
+
translation inside the SDK, not a second Stitchkit transport or compatibility
|
|
1912
|
+
API. Stateful MCP and subscriptions are intentionally outside this layer.
|
|
1913
|
+
|
|
1914
|
+
`createMcpHttpRoute` is the framework-owned raw-route adapter. It registers
|
|
1915
|
+
`ALL` because Streamable HTTP uses multiple HTTP methods, delegates only to
|
|
1916
|
+
`handler.fetch`, and leaves lifecycle ownership with the returned handler.
|
|
1917
|
+
|
|
1918
|
+
By default, a present `Host` header must match the request URL and a present
|
|
1919
|
+
browser `Origin` must be same-origin. Non-browser hosts may omit `Origin`. Behind
|
|
1920
|
+
a trusted reverse proxy, reconstruct the public request URL before calling the
|
|
1921
|
+
handler or configure exact `security.allowedHosts` / `allowedOrigins`; never
|
|
1922
|
+
copy arbitrary forwarded headers into the trusted URL. If a browser calls MCP
|
|
1923
|
+
cross-origin, its HTTP server or gateway must also answer CORS preflight and
|
|
1924
|
+
expose the protocol headers. `onTransportRejected` is the audit boundary for
|
|
1925
|
+
HTTP/security rejections; it is deliberately separate from tool lifecycle and
|
|
1926
|
+
must not be used as authorization input.
|
|
1927
|
+
|
|
1928
|
+
### Modern discovery, routing and cache hints
|
|
1929
|
+
|
|
1930
|
+
Stitchkit forwards the negotiated protocol era and validated MCP request data
|
|
1931
|
+
to `RequestEvent.mcp`; untrusted routing headers never become application
|
|
1932
|
+
identity. The SDK validates `MCP-Protocol-Version`, JSON-RPC shape and routing
|
|
1933
|
+
metadata before lifecycle or tool handlers run. Framework-owned tool and
|
|
1934
|
+
resource registration preserves declaration order across HTTP and stdio. Tool
|
|
1935
|
+
manifests preserve mount order; `listToolNames` is a sorted diagnostics view.
|
|
1936
|
+
Consumer-owned raw SDK registrations are outside this guarantee.
|
|
1937
|
+
|
|
1938
|
+
Caching is opt-in. `cache.operations` maps directly to SDK v2 operation cache
|
|
1939
|
+
hints, while each `McpResourceDef` may declare its own `cacheHint`. Omission
|
|
1940
|
+
means zero/private: neither a prepared surface nor a deterministic response is
|
|
1941
|
+
silently treated as public. Unbounded auth-selected surface factories are
|
|
1942
|
+
always forced to zero/private even when an operation policy is present; use a
|
|
1943
|
+
finite `surfaces` registry when identities share a provably immutable surface.
|
|
1944
|
+
Stitchkit never advertises list-change or subscription capabilities
|
|
1945
|
+
without an implementation.
|
|
1946
|
+
|
|
1947
|
+
### Multi-round tool input (`input_required`)
|
|
1948
|
+
|
|
1949
|
+
An MCP-only operation can require typed user input before its final side effect:
|
|
1950
|
+
|
|
1951
|
+
```ts
|
|
1952
|
+
const DeleteConfirmationSchema = z.object({ confirmed: z.boolean() })
|
|
1953
|
+
|
|
1954
|
+
deleteProject: {
|
|
1955
|
+
method: 'DELETE',
|
|
1956
|
+
path: '/projects/:id',
|
|
1957
|
+
expose: ['MCP'],
|
|
1958
|
+
input: DeleteProjectSchema,
|
|
1959
|
+
output: DeleteProjectResultSchema,
|
|
1960
|
+
mcp: {
|
|
1961
|
+
inputRequired: [
|
|
1962
|
+
{
|
|
1963
|
+
key: 'confirmation',
|
|
1964
|
+
schema: DeleteConfirmationSchema,
|
|
1965
|
+
message: 'Confirm permanent deletion',
|
|
1966
|
+
},
|
|
1967
|
+
{
|
|
1968
|
+
key: 'reason',
|
|
1969
|
+
schema: z.object({ value: z.string().min(3) }),
|
|
1970
|
+
message: 'Record the reason',
|
|
1971
|
+
},
|
|
1972
|
+
],
|
|
1973
|
+
},
|
|
1974
|
+
}
|
|
1975
|
+
```
|
|
1889
1976
|
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1977
|
+
Each continuation accepts exactly the currently requested item. Only after the
|
|
1978
|
+
ordered sequence completes does the handler receive the exact aggregate as
|
|
1979
|
+
`ctx.mcpInput.confirmation` and `ctx.mcpInput.reason`; before then the framework
|
|
1980
|
+
returns `input_required` without calling it. Set
|
|
1981
|
+
`multiRound.serving.maxRounds` to the maximum declaration size you accept
|
|
1982
|
+
(default `10`); empty sequences, duplicate keys and overflow fail first. State
|
|
1983
|
+
is bound to principal, full operation identity, current round, accepted
|
|
1984
|
+
aggregate and canonical original-argument digest and is
|
|
1985
|
+
expiry-checked. Tampered, expired, cross-user or cross-tool state fails before
|
|
1986
|
+
the side effect. Output validation applies only to the final result.
|
|
1987
|
+
|
|
1988
|
+
Every attempt re-runs auth/lifecycle and emits its own tool hooks; audit metadata
|
|
1989
|
+
contains the attempt's `mcp.outcome` and `mcp.round`. Stitchkit does not merge
|
|
1990
|
+
separate HTTP attempts into one logical trace. Parallel
|
|
1991
|
+
rounds have isolated context. HTTP/stdio modern hosts and the supported legacy
|
|
1992
|
+
stdio bridge may use this declaration; Agent, CLI and ordinary HTTP invocation
|
|
1993
|
+
remain single-round and unchanged. Hosts without the capability receive an
|
|
1994
|
+
ordinary unsupported result rather than a falsely advertised round. Signed
|
|
1995
|
+
state is tamper-resistant, not an exactly-once replay store; destructive
|
|
1996
|
+
handlers must still be idempotent where retries matter.
|
|
1893
1997
|
|
|
1894
1998
|
### Guarding tools — `lifecycle`
|
|
1895
1999
|
|
|
@@ -1948,9 +2052,9 @@ cannot become a tool. `schemaValidation.policy` decides what happens:
|
|
|
1948
2052
|
startup assertion or a test.
|
|
1949
2053
|
|
|
1950
2054
|
For a static `services` array, collection, schema conversion and every enabled
|
|
1951
|
-
validation guard run once when the handler is created. Each HTTP request
|
|
1952
|
-
|
|
1953
|
-
|
|
2055
|
+
validation guard run once when the handler is created. Each HTTP request still
|
|
2056
|
+
receives a fresh `McpServer`, runner, context and native registration over that
|
|
2057
|
+
immutable prepared surface. A `services(auth)` factory
|
|
1954
2058
|
is deliberately prepared after resolving each identity because its tool set may
|
|
1955
2059
|
change by tenant.
|
|
1956
2060
|
|
|
@@ -2057,11 +2161,14 @@ it can reach the local filesystem.
|
|
|
2057
2161
|
```ts
|
|
2058
2162
|
import { createStdioMcpServer } from 'stitchkit/tools'
|
|
2059
2163
|
|
|
2060
|
-
await createStdioMcpServer({
|
|
2164
|
+
const stdio = await createStdioMcpServer({
|
|
2061
2165
|
serverInfo: { name: 'my-app', version: '1.0.0' },
|
|
2062
2166
|
auth: resolveIdentity(), // resolved once at startup, not per request
|
|
2063
2167
|
services: [usersService],
|
|
2064
2168
|
})
|
|
2169
|
+
|
|
2170
|
+
// During graceful shutdown:
|
|
2171
|
+
await stdio.close()
|
|
2065
2172
|
```
|
|
2066
2173
|
|
|
2067
2174
|
A stdio server is a single process serving one client, so `auth` is a value (or
|
|
@@ -2069,6 +2176,11 @@ a promise of one) resolved once at startup — typically from an env var — rat
|
|
|
2069
2176
|
than a per-request `(req) => …`. Keep all logging on **stderr**: stdout is the
|
|
2070
2177
|
JSON-RPC channel.
|
|
2071
2178
|
|
|
2179
|
+
The default `legacy: 'serve'` negotiates the modern or supported legacy opening
|
|
2180
|
+
through the official stdio adapter. Use `legacy: 'reject'` for a modern-only
|
|
2181
|
+
binary. Each invocation builds a fresh server; the returned handle owns
|
|
2182
|
+
transport shutdown.
|
|
2183
|
+
|
|
2072
2184
|
Both transports build the server through the shared `buildMcpServer` — same
|
|
2073
2185
|
contract/runtime pipeline, same surface selection, context, hooks, raw escape
|
|
2074
2186
|
hatch and instructions.
|
|
@@ -2077,41 +2189,45 @@ hatch and instructions.
|
|
|
2077
2189
|
|
|
2078
2190
|
A remote MCP server is connectable from Claude (Desktop / web "custom
|
|
2079
2191
|
connector") only through the MCP authorization spec: OAuth 2.1 with PKCE, plus
|
|
2080
|
-
the discovery documents (RFC 9728 / 8414),
|
|
2081
|
-
|
|
2192
|
+
the discovery documents (RFC 9728 / 8414), Client ID Metadata Documents (CIMD)
|
|
2193
|
+
and resource indicators (RFC 8707). A Bearer-only server returns a
|
|
2082
2194
|
bare `401` and the connector never establishes.
|
|
2083
2195
|
|
|
2084
2196
|
stitchkit ships the OAuth **protocol mechanics**; the app supplies only
|
|
2085
2197
|
**identity and storage**. Three pieces wire it together:
|
|
2086
2198
|
|
|
2087
2199
|
```ts
|
|
2088
|
-
import { createMcpHandler, mountOAuthProvider, oauthProtectedResourceRoute } from 'stitchkit/tools'
|
|
2200
|
+
import { createMcpHandler, createMcpHttpRoute, mountOAuthProvider, oauthProtectedResourceRoute } from 'stitchkit/tools'
|
|
2089
2201
|
import { createServer } from 'stitchkit/server'
|
|
2090
2202
|
|
|
2091
2203
|
const resource = 'https://api.example.com/mcp'
|
|
2092
2204
|
const issuer = 'https://api.example.com'
|
|
2093
2205
|
|
|
2094
2206
|
// 1. Resource server — the 401 now points at the metadata.
|
|
2095
|
-
const
|
|
2207
|
+
const mcp = createMcpHandler({
|
|
2096
2208
|
serverInfo: { name: 'my-app', version: '1.0.0' },
|
|
2097
2209
|
auth: resolveOAuthToken, // validate the Bearer JWT (verifyJwt + audience)
|
|
2098
2210
|
services,
|
|
2099
2211
|
protectedResource: { resource, authorizationServers: [issuer] },
|
|
2100
2212
|
})
|
|
2101
2213
|
|
|
2102
|
-
// 2. Authorization server —
|
|
2214
|
+
// 2. Authorization server — CIMD, /authorize (PKCE), /token.
|
|
2103
2215
|
const oauthRoutes = mountOAuthProvider({
|
|
2104
2216
|
issuer,
|
|
2105
2217
|
resource,
|
|
2106
2218
|
signingSecret: env.OAUTH_SECRET,
|
|
2107
|
-
|
|
2108
|
-
|
|
2219
|
+
clientRegistration: {
|
|
2220
|
+
preRegistered: { get: getFirstPartyClient },
|
|
2221
|
+
// CIMD is enabled with secure defaults; DCR remains disabled.
|
|
2222
|
+
},
|
|
2223
|
+
codes, refreshTokens, // your stores (DB or in-memory)
|
|
2224
|
+
authorizeUser, // → { userId, approvedScopes } | Response
|
|
2109
2225
|
})
|
|
2110
2226
|
|
|
2111
2227
|
createServer({
|
|
2112
2228
|
services,
|
|
2113
2229
|
rawRoutes: [
|
|
2114
|
-
{
|
|
2230
|
+
createMcpHttpRoute({ path: '/mcp', handler: mcp }),
|
|
2115
2231
|
oauthProtectedResourceRoute({ resource, authorizationServers: [issuer] }),
|
|
2116
2232
|
...oauthRoutes,
|
|
2117
2233
|
],
|
|
@@ -2122,11 +2238,27 @@ Access tokens are signed HS256 JWTs (`signJwt`) whose `aud` is the resource and
|
|
|
2122
2238
|
whose `iss` is the issuer — validate both in `auth` with
|
|
2123
2239
|
`verifyJwt(token, secret, { audience: resource, issuer })`. `authorizeUser` is
|
|
2124
2240
|
where the app authenticates the user (reuse an existing session) and records
|
|
2125
|
-
consent; return `{ userId }
|
|
2126
|
-
|
|
2241
|
+
consent; return `{ userId, approvedScopes }`, where approved scopes are a subset
|
|
2242
|
+
of the requested/supported values, or a `Response` to redirect the browser to a
|
|
2243
|
+
login page first. The AS and resource server can co-locate or live
|
|
2127
2244
|
on separate origins. See
|
|
2128
2245
|
[ADR 0015](../decisions/0015-oauth-resource-server.md).
|
|
2129
2246
|
|
|
2247
|
+
Client resolution is deterministic: exact pre-registered client, then an HTTPS
|
|
2248
|
+
URL client id resolved as CIMD, then explicitly enabled DCR. CIMD is on by
|
|
2249
|
+
default; DCR is off unless `clientRegistration.dcr` supplies both `register` and
|
|
2250
|
+
`get`. A CIMD-only deployment therefore exposes neither `/register` nor a
|
|
2251
|
+
`registration_endpoint`. The metadata document must declare a `client_id` that
|
|
2252
|
+
exactly equals its URL, explicit redirect URIs and
|
|
2253
|
+
`token_endpoint_auth_method: 'none'`.
|
|
2254
|
+
|
|
2255
|
+
The production fetcher rejects credentials, fragments, non-HTTPS URLs and
|
|
2256
|
+
private/reserved targets. Every redirect is DNS-resolved and IP-pinned again;
|
|
2257
|
+
timeouts, redirect count and body size are bounded. Its bounded cache respects
|
|
2258
|
+
`Cache-Control` (including `no-store`/`no-cache`), `Age`, `Expires`, `ETag` and
|
|
2259
|
+
`Last-Modified`, coalesces concurrent misses and reports sanitized cache events;
|
|
2260
|
+
invalid or unavailable identity receives only a short fail-closed cache entry.
|
|
2261
|
+
|
|
2130
2262
|
### Authorization hardening (MCP 2026-07-28)
|
|
2131
2263
|
|
|
2132
2264
|
- **`iss` on every authorization response (RFC 9207, SEP-2468).** Success *and*
|
|
@@ -2144,9 +2276,9 @@ on separate origins. See
|
|
|
2144
2276
|
behaves exactly as before (loopback allowed); an unknown value is rejected
|
|
2145
2277
|
rather than silently defaulted.
|
|
2146
2278
|
|
|
2147
|
-
> Dynamic Client Registration is
|
|
2148
|
-
>
|
|
2149
|
-
>
|
|
2279
|
+
> Dynamic Client Registration is an explicit interoperability mode, not the
|
|
2280
|
+
> default. Enabling it changes public discovery and adds `/register`; keep it off
|
|
2281
|
+
> unless a client that cannot publish CIMD requires it.
|
|
2150
2282
|
|
|
2151
2283
|
## Proxying a remote API — `implementRemote`
|
|
2152
2284
|
|
|
@@ -2163,11 +2295,14 @@ const http = createHttpClient({
|
|
|
2163
2295
|
headers: () => ({ Authorization: `Bearer ${apiKey}` }),
|
|
2164
2296
|
})
|
|
2165
2297
|
|
|
2166
|
-
await createStdioMcpServer({
|
|
2298
|
+
const stdio = await createStdioMcpServer({
|
|
2167
2299
|
serverInfo: { name: 'my-app', version: '1.0.0' },
|
|
2168
2300
|
auth: null,
|
|
2169
2301
|
services: contracts.map((c) => implementRemote(c, http)),
|
|
2170
2302
|
})
|
|
2303
|
+
|
|
2304
|
+
// During graceful shutdown:
|
|
2305
|
+
await stdio.close()
|
|
2171
2306
|
```
|
|
2172
2307
|
|
|
2173
2308
|
This is how you ship a thin **local** MCP server for an API that already runs in
|
|
@@ -2181,9 +2316,16 @@ no duplicated business logic.
|
|
|
2181
2316
|
|
|
2182
2317
|
## Structured output
|
|
2183
2318
|
|
|
2184
|
-
When a contract endpoint
|
|
2185
|
-
that
|
|
2186
|
-
alongside
|
|
2319
|
+
When a contract endpoint or runtime tool declares `output`, its MCP tool
|
|
2320
|
+
registers that exact schema as `outputSchema` and returns the validated value as
|
|
2321
|
+
`structuredContent` alongside a JSON text block. Every JSON root type is kept
|
|
2322
|
+
unchanged: object, array, string, number, boolean and `null`. Stitchkit does not
|
|
2323
|
+
wrap non-object values in `{ result }`; protocol-era adaptation belongs to the
|
|
2324
|
+
official SDK.
|
|
2325
|
+
|
|
2326
|
+
A tool without an output contract advertises no `outputSchema` and returns no
|
|
2327
|
+
invented structured value. Its successful MCP result has an empty `content`
|
|
2328
|
+
list.
|
|
2187
2329
|
|
|
2188
2330
|
## AI agents — `mountAgent`
|
|
2189
2331
|
|
|
@@ -3759,8 +3901,25 @@ cross-origin `trace: true` client works out of the box. If you set a custom
|
|
|
3759
3901
|
`cors.headers`, extend `DEFAULT_CORS_ALLOW_HEADERS` rather than replacing it, or
|
|
3760
3902
|
the preflight will reject the trace header.
|
|
3761
3903
|
|
|
3904
|
+
MCP tools use the same context. On a modern HTTP or stdio `tools/call`, the
|
|
3905
|
+
official SDK exposes W3C propagation values from request `_meta`; Stitchkit
|
|
3906
|
+
continues a valid `_meta.traceparent` before validation, lifecycle and hooks.
|
|
3907
|
+
If MCP metadata omits `traceparent`, an HTTP call keeps its ambient HTTP trace
|
|
3908
|
+
and a stdio call starts a new root. If the key is present but malformed or
|
|
3909
|
+
all-zero, the call still runs under a fresh local trace instead of trusting the
|
|
3910
|
+
ambient one. This makes explicit MCP propagation authoritative without allowing
|
|
3911
|
+
invalid input to break the tool.
|
|
3912
|
+
|
|
3913
|
+
Bounded `tracestate` and `baggage` are available through
|
|
3914
|
+
`getRequestContext()?.trace` for outbound propagation. Their contents are not
|
|
3915
|
+
copied into the standard `RequestEvent`; never use them for auth, RBAC, tenant
|
|
3916
|
+
selection or rate-limit identity. Every MRTR attempt reads its current request
|
|
3917
|
+
metadata, so callers that want one trace across rounds must propagate it on
|
|
3918
|
+
each request.
|
|
3919
|
+
|
|
3762
3920
|
> **Span ids live in the request context, not on `ctx`.** The handler `ctx`
|
|
3763
|
-
> carries a single `traceId`; the full
|
|
3921
|
+
> carries a single `traceId`; the full
|
|
3922
|
+
> `{ traceId, spanId, parentSpanId, tracestate?, baggage? }` is on
|
|
3764
3923
|
> the observability request context. To stamp `spanId` / `parentSpanId` into an
|
|
3765
3924
|
> audit row read `getRequestContext()?.trace`, not `ctx.spanId`:
|
|
3766
3925
|
>
|
|
@@ -4099,9 +4258,11 @@ an independently built Next.js frontend and Bun/Stitchkit API.
|
|
|
4099
4258
|
|
|
4100
4259
|
### MCP
|
|
4101
4260
|
|
|
4102
|
-
If the app exposes MCP tools, `createMcpHandler`
|
|
4103
|
-
(
|
|
4104
|
-
|
|
4261
|
+
If the app exposes MCP tools, mount `createMcpHandler` with
|
|
4262
|
+
`createMcpHttpRoute({ path: '/mcp', handler })` and close the handler during
|
|
4263
|
+
graceful shutdown. Production needs the `@modelcontextprotocol/server` v2 peer;
|
|
4264
|
+
apps without MCP do not. Only an MCP host or integration-test package needs
|
|
4265
|
+
`@modelcontextprotocol/client`.
|
|
4105
4266
|
|
|
4106
4267
|
|
|
4107
4268
|
==============================================================================
|
|
@@ -4370,6 +4531,174 @@ current one *up to* your target, and apply each snippet.
|
|
|
4370
4531
|
|
|
4371
4532
|
## Unreleased breaking migrations
|
|
4372
4533
|
|
|
4534
|
+
### MCP TypeScript SDK v2 and protocol `2026-07-28`
|
|
4535
|
+
|
|
4536
|
+
This is a hard cut: there is one Stitchkit API and no v1 aliases. Applications
|
|
4537
|
+
that expose MCP install the split server package; applications that implement an
|
|
4538
|
+
MCP host or run client E2E install the split client package.
|
|
4539
|
+
|
|
4540
|
+
```bash
|
|
4541
|
+
bun remove @modelcontextprotocol/sdk
|
|
4542
|
+
bun add @modelcontextprotocol/server@^2 ai@^7
|
|
4543
|
+
# MCP hosts and client-side E2E only:
|
|
4544
|
+
bun add -d @modelcontextprotocol/client@^2
|
|
4545
|
+
```
|
|
4546
|
+
|
|
4547
|
+
Direct SDK imports move to the split packages too:
|
|
4548
|
+
|
|
4549
|
+
```ts
|
|
4550
|
+
// before
|
|
4551
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
4552
|
+
|
|
4553
|
+
// after
|
|
4554
|
+
import { McpServer } from '@modelcontextprotocol/server'
|
|
4555
|
+
```
|
|
4556
|
+
|
|
4557
|
+
MCP Apps additionally install `@modelcontextprotocol/ext-apps`. That adapter may
|
|
4558
|
+
carry its own isolated v1-era transitive/peer relationship while the ecosystem
|
|
4559
|
+
finishes its cutover; it does not permit application code to import the removed
|
|
4560
|
+
monolithic SDK. Application-owned MCP server and client code uses the v2 split
|
|
4561
|
+
packages exclusively.
|
|
4562
|
+
|
|
4563
|
+
```ts
|
|
4564
|
+
// before
|
|
4565
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
|
|
4566
|
+
import { createMcpHandler } from 'stitchkit/tools'
|
|
4567
|
+
|
|
4568
|
+
const handleMcp = createMcpHandler({
|
|
4569
|
+
serverInfo,
|
|
4570
|
+
auth,
|
|
4571
|
+
services,
|
|
4572
|
+
sessionMode: 'stateless',
|
|
4573
|
+
})
|
|
4574
|
+
rawRoutes: [{ method: 'ALL', path: '/mcp', handler: handleMcp }]
|
|
4575
|
+
|
|
4576
|
+
// after
|
|
4577
|
+
import { Client } from '@modelcontextprotocol/client'
|
|
4578
|
+
import { createMcpHandler, createMcpHttpRoute } from 'stitchkit/tools'
|
|
4579
|
+
|
|
4580
|
+
const mcp = createMcpHandler({
|
|
4581
|
+
serverInfo,
|
|
4582
|
+
auth,
|
|
4583
|
+
services,
|
|
4584
|
+
legacy: 'serve',
|
|
4585
|
+
})
|
|
4586
|
+
rawRoutes: [createMcpHttpRoute({ path: '/mcp', handler: mcp })]
|
|
4587
|
+
// graceful shutdown: await mcp.close()
|
|
4588
|
+
```
|
|
4589
|
+
|
|
4590
|
+
Keep the owned handle and close it from the same shutdown path as the HTTP
|
|
4591
|
+
server. A minimal runtime smoke should list tools before shutdown and prove the
|
|
4592
|
+
closed handler no longer serves requests:
|
|
4593
|
+
|
|
4594
|
+
```ts
|
|
4595
|
+
const mcp = createMcpHandler(config)
|
|
4596
|
+
const route = createMcpHttpRoute({ path: '/mcp', handler: mcp })
|
|
4597
|
+
|
|
4598
|
+
const beforeClose = await route.handler(listToolsRequest)
|
|
4599
|
+
if (!beforeClose.ok) throw new Error('MCP list-tools smoke failed')
|
|
4600
|
+
|
|
4601
|
+
await mcp.close()
|
|
4602
|
+
```
|
|
4603
|
+
|
|
4604
|
+
Remove `@modelcontextprotocol/sdk`, `sessionMode`, `McpSessionMode`, session
|
|
4605
|
+
stores and all `Mcp-Session-Id` handling. HTTP is always request-isolated and
|
|
4606
|
+
stateless. `legacy: 'serve'` (default) lets the official SDK negotiate supported
|
|
4607
|
+
pre-2026 stateless clients on the same endpoint; `legacy: 'reject'` makes it
|
|
4608
|
+
modern-only. This is not a stateful compatibility transport.
|
|
4609
|
+
|
|
4610
|
+
The stdio helper now returns an owned lifecycle handle:
|
|
4611
|
+
|
|
4612
|
+
```ts
|
|
4613
|
+
// before
|
|
4614
|
+
await createStdioMcpServer(config)
|
|
4615
|
+
|
|
4616
|
+
// after
|
|
4617
|
+
const stdio = await createStdioMcpServer({ ...config, legacy: 'serve' })
|
|
4618
|
+
await stdio.close()
|
|
4619
|
+
```
|
|
4620
|
+
|
|
4621
|
+
OAuth client registration is now one explicit policy object. CIMD is secure and
|
|
4622
|
+
enabled by default; DCR is disabled unless supplied:
|
|
4623
|
+
|
|
4624
|
+
```ts
|
|
4625
|
+
// before
|
|
4626
|
+
mountOAuthProvider({ ...oauth, clients, codes, refreshTokens })
|
|
4627
|
+
|
|
4628
|
+
// after
|
|
4629
|
+
mountOAuthProvider({
|
|
4630
|
+
...oauth,
|
|
4631
|
+
clientRegistration: {
|
|
4632
|
+
preRegistered: { get: clients.get },
|
|
4633
|
+
// optional: dcr: { register: clients.register, get: clients.get }
|
|
4634
|
+
},
|
|
4635
|
+
codes,
|
|
4636
|
+
refreshTokens,
|
|
4637
|
+
})
|
|
4638
|
+
```
|
|
4639
|
+
|
|
4640
|
+
A URL client id must be HTTPS and serve a document whose `client_id` exactly
|
|
4641
|
+
matches that URL, with explicit `redirect_uris` and
|
|
4642
|
+
`token_endpoint_auth_method: 'none'`. Do not keep a consumer-side metadata
|
|
4643
|
+
fetcher or DCR fallback; Stitchkit owns SSRF-safe resolution and caching.
|
|
4644
|
+
|
|
4645
|
+
Multi-round input is opt-in on the operation and does not change Agent, CLI or
|
|
4646
|
+
ordinary HTTP handlers:
|
|
4647
|
+
|
|
4648
|
+
```ts
|
|
4649
|
+
const ConfirmationSchema = z.object({ confirmed: z.boolean() })
|
|
4650
|
+
|
|
4651
|
+
mcp: {
|
|
4652
|
+
inputRequired: [{
|
|
4653
|
+
key: 'confirmation',
|
|
4654
|
+
message: 'Confirm this action',
|
|
4655
|
+
schema: ConfirmationSchema,
|
|
4656
|
+
}],
|
|
4657
|
+
}
|
|
4658
|
+
```
|
|
4659
|
+
|
|
4660
|
+
Configure `multiRound.state` on the MCP server with a key of at least 32 bytes
|
|
4661
|
+
and a stable authenticated `principal`. Read accepted typed content from
|
|
4662
|
+
`ctx.mcpInput.confirmation`. Multiple declarations run in array order, the
|
|
4663
|
+
aggregate remains exactly typed by key, keys must be unique, and declarations
|
|
4664
|
+
must fit `multiRound.serving.maxRounds` (default `10`). Do not execute a
|
|
4665
|
+
destructive side effect before the complete aggregate is accepted. A modern
|
|
4666
|
+
request missing the declared elicitation capability receives JSON-RPC error
|
|
4667
|
+
code `-32021`. The official per-request legacy HTTP bridge cannot issue
|
|
4668
|
+
server-to-client elicitation, so it returns a deterministic failed tool result;
|
|
4669
|
+
multi-round input is never silently treated as complete.
|
|
4670
|
+
|
|
4671
|
+
#### Compatibility matrix
|
|
4672
|
+
|
|
4673
|
+
| Host / transport | Tools and Apps | Multi-round input | Continuity |
|
|
4674
|
+
|---|---|---|---|
|
|
4675
|
+
| `2026-07-28` HTTP | yes | yes | request-isolated |
|
|
4676
|
+
| supported legacy stateless HTTP | yes | unsupported result | request-isolated |
|
|
4677
|
+
| `2026-07-28` stdio | yes | yes | one process connection |
|
|
4678
|
+
| supported legacy stdio | yes | official SDK bridge | one process connection |
|
|
4679
|
+
| Agent / CLI / ordinary HTTP | unchanged | not exposed | unchanged |
|
|
4680
|
+
|
|
4681
|
+
Subscriptions, cross-request progress and resumable stateful SSE are not
|
|
4682
|
+
implemented or advertised.
|
|
4683
|
+
|
|
4684
|
+
#### Consumer checklist
|
|
4685
|
+
|
|
4686
|
+
1. Replace the monolithic SDK with `@modelcontextprotocol/server@^2` and, only
|
|
4687
|
+
for hosts/tests, `@modelcontextprotocol/client@^2`.
|
|
4688
|
+
2. Replace raw MCP route wiring with `createMcpHttpRoute`; retain and close the
|
|
4689
|
+
returned handler/stdio handle during shutdown.
|
|
4690
|
+
3. Delete all session mode, event-store and session-id code.
|
|
4691
|
+
4. Move OAuth client policy under `clientRegistration`; publish CIMD or enable
|
|
4692
|
+
DCR explicitly.
|
|
4693
|
+
5. Snapshot `listToolNames`, run one contract tool, one runtime tool, any raw
|
|
4694
|
+
multimodal tool and every MCP App resource you use.
|
|
4695
|
+
6. Exercise modern HTTP and stdio with protocol `2026-07-28`; exercise legacy
|
|
4696
|
+
only if `legacy: 'serve'` is part of your support policy.
|
|
4697
|
+
7. Run the consumer's typecheck and runtime gates. A browser/HTTP-only consumer
|
|
4698
|
+
must continue to work without either MCP package.
|
|
4699
|
+
|
|
4700
|
+
## Historical breaking migrations through 0.43.1
|
|
4701
|
+
|
|
4373
4702
|
HTTP observability now completes inside the framework handler instead of a
|
|
4374
4703
|
nested fetch wrapper. Configure request and tool sinks explicitly:
|
|
4375
4704
|
|
|
@@ -4717,23 +5046,6 @@ If a tool hook annotated `endpoint` as `MethodDef`, remove that annotation or
|
|
|
4717
5046
|
use `OperationIdentity`: native operations have service/action/scope/method but
|
|
4718
5047
|
no HTTP path.
|
|
4719
5048
|
|
|
4720
|
-
### MCP HTTP sessions
|
|
4721
|
-
|
|
4722
|
-
Finally, replace the MCP HTTP session boolean. Omission changed meaning:
|
|
4723
|
-
|
|
4724
|
-
```ts
|
|
4725
|
-
// before → after
|
|
4726
|
-
stateless: true // → sessionMode: 'stateless'
|
|
4727
|
-
stateless: false // → sessionMode: 'stateful'
|
|
4728
|
-
|
|
4729
|
-
// before: omission was stateful
|
|
4730
|
-
// after: omission is stateless
|
|
4731
|
-
```
|
|
4732
|
-
|
|
4733
|
-
If the client relies on `Mcp-Session-Id`, server push, progress across requests
|
|
4734
|
-
or resumable SSE, set `sessionMode: 'stateful'` explicitly. Synchronous tool
|
|
4735
|
-
servers should omit it and use the new restart-safe default.
|
|
4736
|
-
|
|
4737
5049
|
### Node-facing server types
|
|
4738
5050
|
|
|
4739
5051
|
`stitchkit/server` remains Bun-concrete: an explicitly annotated `RawRoute`
|
|
@@ -4882,7 +5194,7 @@ can emit / propagate a `traceparent` (see `HttpClientConfig.trace`).
|
|
|
4882
5194
|
| `formatTraceparent` | function | render a `traceparent` header value |
|
|
4883
5195
|
| `parseTraceparent` | function | parse a `traceparent` header |
|
|
4884
5196
|
| `childSpan` | function | a child span of a parent trace |
|
|
4885
|
-
| `TraceContext` | _type_ | `{ traceId, spanId, parentSpanId? }` |
|
|
5197
|
+
| `TraceContext` | _type_ | `{ traceId, spanId, parentSpanId?, tracestate?, baggage? }` |
|
|
4886
5198
|
|
|
4887
5199
|
---
|
|
4888
5200
|
|
|
@@ -4929,6 +5241,8 @@ from the root `stitchkit`.
|
|
|
4929
5241
|
| `FileDescriptor` | _type_ | a React Native / Expo file — `{ uri, name, type }` |
|
|
4930
5242
|
| `EndpointToolAnnotations` | _type_ | MCP behavioural hints on an endpoint (`readOnlyHint` / `destructiveHint` / `title`) |
|
|
4931
5243
|
| `EndpointUiMeta` | _type_ | MCP Apps widget metadata on an endpoint |
|
|
5244
|
+
| `EndpointMcpInputRequired` | _type_ | typed MCP multi-round input request (`key`, message and Zod object schema) |
|
|
5245
|
+
| `EndpointMcpPolicy` | _type_ | MCP-only endpoint policy containing `inputRequired` |
|
|
4932
5246
|
|
|
4933
5247
|
### Errors
|
|
4934
5248
|
|
|
@@ -5146,11 +5460,12 @@ audit event. See the [Observability guide](../guide/observability.md).
|
|
|
5146
5460
|
| Export | Kind | Summary |
|
|
5147
5461
|
|--------|------|---------|
|
|
5148
5462
|
| `resolveTraceContext` | function | the trace for a request — `traceparent` continued or fresh |
|
|
5463
|
+
| `resolvePropagationContext` | function | continue bounded MCP/W3C propagation metadata with optional ambient fallback |
|
|
5149
5464
|
| `parseTraceparent` | function | parse a `traceparent` header |
|
|
5150
5465
|
| `formatTraceparent` | function | render a `traceparent` header value |
|
|
5151
5466
|
| `createTraceContext` | function | a fresh root trace |
|
|
5152
5467
|
| `childSpan` | function | a child span of a parent trace |
|
|
5153
|
-
| `TraceContext` | _type_ | `{ traceId, spanId, parentSpanId? }` |
|
|
5468
|
+
| `TraceContext` | _type_ | `{ traceId, spanId, parentSpanId?, tracestate?, baggage? }` |
|
|
5154
5469
|
|
|
5155
5470
|
### Sanitisation
|
|
5156
5471
|
|
|
@@ -5168,12 +5483,19 @@ audit event. See the [Observability guide](../guide/observability.md).
|
|
|
5168
5483
|
|
|
5169
5484
|
## `stitchkit/tools`
|
|
5170
5485
|
|
|
5171
|
-
Server-only. Turns contracts into MCP and AI-agent tools.
|
|
5172
|
-
`@modelcontextprotocol/
|
|
5486
|
+
Server-only. Turns contracts into MCP and AI-agent tools. MCP server surfaces
|
|
5487
|
+
need the `@modelcontextprotocol/server` v2 peer; MCP hosts/tests use the separate
|
|
5488
|
+
`@modelcontextprotocol/client` package. Agent surfaces need the `ai` peer.
|
|
5489
|
+
|
|
5490
|
+
Framework-owned MCP tools advertise the exact declared output schema and return
|
|
5491
|
+
the validated value unchanged as `structuredContent`, including arrays, scalars
|
|
5492
|
+
and `null`. Tools without an output contract advertise and return no structured
|
|
5493
|
+
payload.
|
|
5173
5494
|
|
|
5174
5495
|
| Export | Kind | Summary |
|
|
5175
5496
|
|--------|------|---------|
|
|
5176
|
-
| `createMcpHandler` | function | a
|
|
5497
|
+
| `createMcpHandler` | function | a stateless dual-era Streamable-HTTP MCP handler — [guide](../guide/mcp-and-agents.md#mcp--createmcphandler) |
|
|
5498
|
+
| `createMcpHttpRoute` | function | framework-owned `RawRoute` adapter for an MCP HTTP handler |
|
|
5177
5499
|
| `createStdioMcpServer` | function | a complete stdio MCP server — [guide](../guide/mcp-and-agents.md#mcp-over-stdio--createstdiomcpserver) |
|
|
5178
5500
|
| `buildMcpServer` | function | build an `McpServer` from contract/runtime surfaces — the transport-neutral core |
|
|
5179
5501
|
| `mountMcp` | function | add contract tools to an existing `McpServer` — [guide](../guide/mcp-and-agents.md#mountmcp) |
|
|
@@ -5188,9 +5510,12 @@ Server-only. Turns contracts into MCP and AI-agent tools. Needs the
|
|
|
5188
5510
|
| `resolveMedia` | function | resolve a media reference for a tool result |
|
|
5189
5511
|
| `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)) |
|
|
5190
5512
|
| `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) |
|
|
5191
|
-
| `McpHandlerConfig` | _type_ |
|
|
5192
|
-
| `McpHttpConfig` | _type_ | HTTP auth, protected-resource and
|
|
5193
|
-
| `
|
|
5513
|
+
| `McpHandlerConfig` | _type_ | server surface plus stateless HTTP transport config |
|
|
5514
|
+
| `McpHttpConfig` | _type_ | HTTP auth, protected-resource, legacy-era and security options |
|
|
5515
|
+
| `McpHttpHandler` | _type_ | framework-owned `{ fetch(request), close() }` lifecycle |
|
|
5516
|
+
| `McpHttpSecurityConfig` | _type_ | Fetch-boundary Host and Origin allowlists |
|
|
5517
|
+
| `McpLegacyPolicy` | _type_ | `'serve' \| 'reject'` protocol-era compatibility policy |
|
|
5518
|
+
| `McpStdioHandle` | _type_ | closeable official stdio transport handle |
|
|
5194
5519
|
| `StdioMcpServerConfig` | _type_ | config for `createStdioMcpServer` |
|
|
5195
5520
|
| `McpServerBuildConfig` | _type_ | shared config for `buildMcpServer` |
|
|
5196
5521
|
| `McpServerSharedConfig` | _type_ | transport-neutral options shared by direct and finite surface configs |
|
|
@@ -5218,6 +5543,15 @@ Server-only. Turns contracts into MCP and AI-agent tools. Needs the
|
|
|
5218
5543
|
| `RuntimeToolOutput` | _type_ | output inferred from a runtime tool's optional Zod schema |
|
|
5219
5544
|
| `RuntimeToolPresenters` | _type_ | optional MCP and AI SDK `toModelOutput` presentation callbacks |
|
|
5220
5545
|
| `RuntimeMcpPresentation` | _type_ | MCP content/metadata result without framework-owned `structuredContent` or `isError` |
|
|
5546
|
+
| `RuntimeMcpInput` | _type_ | typed accepted multi-round input for an opted-in runtime tool |
|
|
5547
|
+
| `OAuthClientRegistrationConfig` | _type_ | deterministic pre-registered → CIMD → explicit-DCR client resolution |
|
|
5548
|
+
| `CimdClientMetadata` | _type_ | validated Client ID Metadata Document |
|
|
5549
|
+
| `CimdClientMetadataFetcher` | _type_ | injectable secure network boundary for metadata loading |
|
|
5550
|
+
| `CimdFetchResponse` | _type_ | bounded metadata fetch result passed across the injectable network boundary |
|
|
5551
|
+
| `CimdFetchPolicy` | _type_ | CIMD timeout, redirect and size limits |
|
|
5552
|
+
| `CimdCachePolicy` | _type_ | bounded HTTP-aware positive/negative cache policy |
|
|
5553
|
+
| `CimdCacheEvent` | _type_ | observable CIMD cache hit, miss, revalidation and eviction event |
|
|
5554
|
+
| `createSecureClientMetadataFetcher` | function | production HTTPS, DNS/IP-pinned CIMD fetcher |
|
|
5221
5555
|
| `RuntimeAgentModelOutput` | _type_ | AI SDK model-facing text/JSON/content output returned by `present.agent` |
|
|
5222
5556
|
| `RuntimeToolTransport` | _type_ | runtime exposure: `'MCP' \| 'AGENT'` |
|
|
5223
5557
|
| `AgentMountConfig` | _type_ | config for `mountAgent` |
|