@orkestrel/mcp 0.0.26 → 0.0.27
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/src/browser/index.d.ts +13 -4
- package/dist/src/browser/index.js +68 -15
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/core/index.cjs +754 -68
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +657 -44
- package/dist/src/core/index.d.ts +657 -44
- package/dist/src/core/index.js +734 -69
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +212 -33
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +123 -22
- package/dist/src/server/index.d.ts +123 -22
- package/dist/src/server/index.js +213 -36
- package/dist/src/server/index.js.map +1 -1
- package/package.json +8 -7
package/dist/src/core/index.d.ts
CHANGED
|
@@ -189,6 +189,60 @@ export declare function buildCancelledNotification(id: JSONRPCId, reason?: strin
|
|
|
189
189
|
*/
|
|
190
190
|
export declare function buildDiscoverResult(options: MCPServerOptions): MCPDiscoverResult;
|
|
191
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Builds the `x-mcp-header` projections one tool's `inputSchema` declares.
|
|
194
|
+
*
|
|
195
|
+
* @remarks
|
|
196
|
+
* The single decision both sides of the protocol make about an annotated tool: an HTTP
|
|
197
|
+
* CLIENT excludes a definition this refuses from the `tools/list` result it delivers, and a
|
|
198
|
+
* SERVER recognizes exactly the `Mcp-Param-*` names this returns for its own definitions.
|
|
199
|
+
*
|
|
200
|
+
* `undefined` means the definition is invalid, and every rule the protocol states produces
|
|
201
|
+
* it: a value that is not an RFC 9110 token, a non-primitive or untyped annotated leaf, a
|
|
202
|
+
* name repeated case-insensitively within the schema, an annotation the `properties` chain
|
|
203
|
+
* does not reach, and a schema that is not a record at all. An empty list is the valid answer
|
|
204
|
+
* for a schema carrying no annotation.
|
|
205
|
+
*
|
|
206
|
+
* Total — never throws, and a cyclic or stack-hostile schema is refused rather than followed.
|
|
207
|
+
*
|
|
208
|
+
* @param schema - The tool's advertised `inputSchema`
|
|
209
|
+
* @returns The declared projections, or `undefined` when the definition is invalid
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```ts
|
|
213
|
+
* buildHeaderParameters({
|
|
214
|
+
* type: 'object',
|
|
215
|
+
* properties: { region: { type: 'string', 'x-mcp-header': 'Region' } },
|
|
216
|
+
* }) // → [{ name: 'Region', path: ['region'], primitive: 'string' }]
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
219
|
+
export declare function buildHeaderParameters(schema: unknown): readonly MCPHeaderParameter[] | undefined;
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Builds the `Mcp-Param-*` request headers one `tools/call` carries.
|
|
223
|
+
*
|
|
224
|
+
* @remarks
|
|
225
|
+
* The projection SEP-2243 requires of an HTTP client, and the same derivation a server runs
|
|
226
|
+
* to know what the request should have carried. Each parameter's value is read at its exact
|
|
227
|
+
* property path in the call's own `arguments`; an absent or `null` value omits its header
|
|
228
|
+
* entirely, which is the protocol's distinction between "not supplied" and "supplied empty".
|
|
229
|
+
* The rendered text then travels through {@link encodeSentinel}, so a value carrying
|
|
230
|
+
* non-ASCII, control, or edge whitespace characters reaches the peer intact.
|
|
231
|
+
*
|
|
232
|
+
* @param parameters - The projections the tool's `inputSchema` declares
|
|
233
|
+
* @param values - The call's `arguments` record
|
|
234
|
+
* @returns The header field names and values, empty when nothing projects
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```ts
|
|
238
|
+
* buildHeaderProjection(
|
|
239
|
+
* [{ name: 'Region', path: ['region'], primitive: 'string' }],
|
|
240
|
+
* { region: 'us-west1' },
|
|
241
|
+
* ) // → { 'Mcp-Param-Region': 'us-west1' }
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
export declare function buildHeaderProjection(parameters: readonly MCPHeaderParameter[], values: unknown): Readonly<Record<string, string>>;
|
|
245
|
+
|
|
192
246
|
/**
|
|
193
247
|
* Builds the MCP `initialize` result — the negotiated protocol version, the
|
|
194
248
|
* advertised capabilities, and the server identity.
|
|
@@ -358,6 +412,65 @@ export declare function buildToolCall(request: JSONRPCRequest, caller?: unknown,
|
|
|
358
412
|
*/
|
|
359
413
|
export declare function buildToolDescriptors(manager: ToolManagerInterface): readonly MCPToolDescriptor[];
|
|
360
414
|
|
|
415
|
+
/**
|
|
416
|
+
* Computes the capabilities one round of input requests needs and the client did not declare.
|
|
417
|
+
*
|
|
418
|
+
* @remarks
|
|
419
|
+
* The protocol's rule is about SENDING: a server never issues a request kind the client's
|
|
420
|
+
* declared capabilities exclude. So this reads the round rather than the method, and it
|
|
421
|
+
* answers with the refusal's own payload — the `requiredCapabilities` record a
|
|
422
|
+
* `MissingRequiredClientCapability` error carries, keyed by each missing capability, in the
|
|
423
|
+
* `ClientCapabilities` shape the schema defines rather than as a list of names.
|
|
424
|
+
*
|
|
425
|
+
* Each kind maps to one declaration: `sampling/createMessage` to `sampling`, `roots/list` to
|
|
426
|
+
* `roots`, a form elicitation to what {@link isFormElicitationSupported} accepts, and a
|
|
427
|
+
* URL-mode elicitation to a record-valued `elicitation.url`. A request this package cannot
|
|
428
|
+
* recognize needs nothing, because {@link import('./validators.js').isMCPInputRequestMap}
|
|
429
|
+
* has already refused the round it would have travelled in. Total over hostile input.
|
|
430
|
+
*
|
|
431
|
+
* The `elicitation` value names the ARM the round needs, so a client can act on the refusal
|
|
432
|
+
* by declaring exactly what the payload asks for. A missing URL arm answers `{ url: {} }`, a
|
|
433
|
+
* missing form arm answers the empty record this package reads as form-only, and a round
|
|
434
|
+
* needing both answers `{ form: {}, url: {} }`. An empty record for a URL round would name
|
|
435
|
+
* the declaration a URL-capable client already sent, and refuse the identical round again.
|
|
436
|
+
*
|
|
437
|
+
* @param requests - The round the server is about to issue
|
|
438
|
+
* @param capabilities - The client capability record the request declared
|
|
439
|
+
* @returns The missing capabilities, or `undefined` when the client declared every one
|
|
440
|
+
*
|
|
441
|
+
* @example
|
|
442
|
+
* ```ts
|
|
443
|
+
* computeMissingCapabilities({ answer: { method: 'roots/list' } }, {}) // { roots: {} }
|
|
444
|
+
* computeMissingCapabilities({ answer: { method: 'roots/list' } }, { roots: {} }) // undefined
|
|
445
|
+
* ```
|
|
446
|
+
*/
|
|
447
|
+
export declare function computeMissingCapabilities(requests: MCPInputRequestMap, capabilities: unknown): MCPClientCapabilities | undefined;
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Counts every {@link MCP_HEADER_ANNOTATION} key one JSON value carries, at any position.
|
|
451
|
+
*
|
|
452
|
+
* @remarks
|
|
453
|
+
* The companion of {@link extractHeaderAnnotations}, which reads only the annotations a
|
|
454
|
+
* `properties` chain reaches. Comparing the two answers is how
|
|
455
|
+
* {@link buildHeaderParameters} decides reachability without a second walk that would have
|
|
456
|
+
* to re-state which JSON Schema keywords are traversable: an annotation the reachable walk
|
|
457
|
+
* did not read is one sitting under `items`, a composition or conditional keyword, a `$ref`
|
|
458
|
+
* target, or any other position, and the protocol makes the whole tool definition invalid for
|
|
459
|
+
* it.
|
|
460
|
+
*
|
|
461
|
+
* Iterative and ancestor-tracked, so a deeply nested or self-referential value terminates
|
|
462
|
+
* rather than exhausting the stack. Total — never throws, whatever the input.
|
|
463
|
+
*
|
|
464
|
+
* @param value - The value to scan, normally a tool's `inputSchema`
|
|
465
|
+
* @returns How many annotation keys the value carries
|
|
466
|
+
*
|
|
467
|
+
* @example
|
|
468
|
+
* ```ts
|
|
469
|
+
* countHeaderAnnotations({ properties: { region: { 'x-mcp-header': 'Region' } } }) // 1
|
|
470
|
+
* ```
|
|
471
|
+
*/
|
|
472
|
+
export declare function countHeaderAnnotations(value: unknown): number;
|
|
473
|
+
|
|
361
474
|
/**
|
|
362
475
|
* Adapts an {@link MCPTransportInterface} (the environment-agnostic duplex message
|
|
363
476
|
* channel) into a {@link MCPClientTransportInterface} — the additive bridge that lets
|
|
@@ -525,6 +638,55 @@ export declare function createMCPServer(options: MCPServerOptions): MCPServerInt
|
|
|
525
638
|
*/
|
|
526
639
|
export declare function decodeBoundedMessage(message: string, limits: MCPJSONLimitOptions): JSONRPCMessage | undefined;
|
|
527
640
|
|
|
641
|
+
/**
|
|
642
|
+
* Reads the value one standard MCP request header carries, decoding the Base64 sentinel.
|
|
643
|
+
*
|
|
644
|
+
* @remarks
|
|
645
|
+
* The sentinel format is `=?base64?{Base64OfUTF8}?=`, spelled once as
|
|
646
|
+
* {@link MCP_SENTINEL_PREFIX} and {@link MCP_SENTINEL_SUFFIX} and read from there by both
|
|
647
|
+
* directions of the codec.
|
|
648
|
+
* The markers alone decide whether a value is a sentinel: a value carrying the prefix and the
|
|
649
|
+
* suffix is one, and its payload is then held to `decodeBase64` from `@orkestrel/codec` — the
|
|
650
|
+
* canonical RFC 4648 § 4 grammar, which admits exactly one spelling per byte sequence — and to
|
|
651
|
+
* well-formed UTF-8. A payload leaving a non-zero bit in the sextet its padding discards is a
|
|
652
|
+
* second spelling of a byte, so it is refused: `=?base64?QR==?=` reaches for the byte
|
|
653
|
+
* `=?base64?QQ==?=` spells canonically, and only the canonical spelling decodes. A malformed
|
|
654
|
+
* payload answers `undefined` rather than falling back to the literal, because the protocol
|
|
655
|
+
* requires a server to REJECT invalid characters, and a fallback would admit the very value
|
|
656
|
+
* the rule exists to refuse. A value missing either marker is a literal and comes back
|
|
657
|
+
* unchanged.
|
|
658
|
+
*
|
|
659
|
+
* `decodeUTF8` from `@orkestrel/codec` reads the bytes back as text: strict RFC 3629, where an
|
|
660
|
+
* overlong, an encoded surrogate, a code point past U+10FFFF, and a truncated sequence each
|
|
661
|
+
* answer `undefined` rather than a replacement character, and total, so the refusal arrives as
|
|
662
|
+
* that value instead of as a throw. It also keeps a leading U+FEFF as a character of the
|
|
663
|
+
* value, where the platform decoder consumes it as a byte order mark — which is what lets a
|
|
664
|
+
* value leading with U+FEFF survive {@link encodeSentinel} and come back whole.
|
|
665
|
+
*
|
|
666
|
+
* {@link import('./validators.js').isStandardBase64} is a wider and separate rule: it names
|
|
667
|
+
* JSON Schema `byte` membership for the blob, image, and audio content a peer sends, where
|
|
668
|
+
* this package receives liberally. It does not govern this payload.
|
|
669
|
+
*
|
|
670
|
+
* Optional whitespace is excluded first, per RFC 9110 § 5.5: a recipient parses a field value
|
|
671
|
+
* with its surrounding spaces and horizontal tabs removed, so a peer that padded a plain value
|
|
672
|
+
* still matches the body. A value whose own leading or trailing whitespace is significant
|
|
673
|
+
* cannot survive that, which is what {@link encodeSentinel} encodes it for.
|
|
674
|
+
*
|
|
675
|
+
* Total — never throws, whatever the input.
|
|
676
|
+
*
|
|
677
|
+
* @param value - The raw header field value the peer sent
|
|
678
|
+
* @returns The carried value, or `undefined` when the sentinel's payload is invalid
|
|
679
|
+
*
|
|
680
|
+
* @example
|
|
681
|
+
* ```ts
|
|
682
|
+
* decodeSentinel('=?base64?Y2Fmw6k=?=') // 'café'
|
|
683
|
+
* decodeSentinel(' search ') // 'search' — optional whitespace excluded
|
|
684
|
+
* decodeSentinel('=?base64?SGVsbG8?=') // undefined — invalid padding
|
|
685
|
+
* decodeSentinel('=?base64?QR==?=') // undefined — a non-canonical spelling
|
|
686
|
+
* ```
|
|
687
|
+
*/
|
|
688
|
+
export declare function decodeSentinel(value: string): string | undefined;
|
|
689
|
+
|
|
528
690
|
/**
|
|
529
691
|
* Default modern result freshness lifetime in milliseconds.
|
|
530
692
|
*
|
|
@@ -547,10 +709,11 @@ export declare const DEFAULT_MCP_CLIENT_VERSION = "1.0.0";
|
|
|
547
709
|
* One MiB admits ordinary JSON-RPC requests and substantial tool arguments; 16 KiB admits
|
|
548
710
|
* extension-rich modern metadata and signed multi-round state; four MiB admits substantial
|
|
549
711
|
* JSON tool output without allowing an unconfigured service to serialize arbitrary process
|
|
550
|
-
* memory; 64
|
|
551
|
-
*
|
|
552
|
-
*
|
|
553
|
-
* defaults observed by later
|
|
712
|
+
* memory; 64 keys admits `_meta`'s reserved keys plus many extensions, and bounds a produced
|
|
713
|
+
* result's breadth by the same leaf; 128 concurrent streams admits a busy service while
|
|
714
|
+
* bounding retained producers; depth 32 admits ordinary JSON documents while rejecting
|
|
715
|
+
* stack-hostile nesting. Frozen so callers cannot alter the defaults observed by later
|
|
716
|
+
* servers.
|
|
554
717
|
*/
|
|
555
718
|
export declare const DEFAULT_MCP_LIMITS: Readonly<{
|
|
556
719
|
message: 1048576;
|
|
@@ -596,6 +759,44 @@ export declare function digestJSON(value: unknown, limits: MCPJSONLimitOptions):
|
|
|
596
759
|
*/
|
|
597
760
|
export declare const EMPTY_MCP_ARGUMENTS: Readonly<Record<string, unknown>>;
|
|
598
761
|
|
|
762
|
+
/**
|
|
763
|
+
* Builds the wire form one standard MCP request header value must travel as.
|
|
764
|
+
*
|
|
765
|
+
* @remarks
|
|
766
|
+
* The exact inverse of {@link decodeSentinel}, and its membership rule is stated as that
|
|
767
|
+
* inverse rather than as a second list that could drift: a value travels LITERALLY when it is
|
|
768
|
+
* plain printable ASCII — every code point in `U+0020`–`U+007E`, the RFC 9110 field-value
|
|
769
|
+
* range this package admits — and {@link decodeSentinel} gives it back unchanged. Every other
|
|
770
|
+
* value travels wrapped in {@link MCP_SENTINEL_PREFIX} and {@link MCP_SENTINEL_SUFFIX}, the
|
|
771
|
+
* same markers the decode recognizes a sentinel by. `encodeBase64` from `@orkestrel/codec`
|
|
772
|
+
* spells the payload, so the wire form carries the canonical spelling {@link decodeSentinel}
|
|
773
|
+
* accepts.
|
|
774
|
+
*
|
|
775
|
+
* That one rule covers each row of the protocol's encoding table. A non-ASCII value and a
|
|
776
|
+
* value carrying a control character fail the ASCII test. A value with leading or trailing
|
|
777
|
+
* whitespace comes back trimmed, so it fails the round trip. A value already wearing the
|
|
778
|
+
* sentinel markers decodes to something else, or to nothing, so it fails the round trip too
|
|
779
|
+
* and is encoded rather than read back as a sentinel it never was.
|
|
780
|
+
*
|
|
781
|
+
* The bytes come from the platform `TextEncoder`, not from codec's `encodeUTF8`, and that is a
|
|
782
|
+
* ruling rather than an oversight. `TextEncoder` is total: it spells ill-formed text — a lone
|
|
783
|
+
* surrogate, which has no UTF-8 spelling — with the replacement character, so this function
|
|
784
|
+
* answers a `string` for every input. `encodeUTF8` refuses that text with `undefined`, which
|
|
785
|
+
* would widen this return to `string | undefined` and oblige every header projection to handle
|
|
786
|
+
* a value it cannot send. The decode side carries no such tension, so it reads back through
|
|
787
|
+
* codec's strict `decodeUTF8`.
|
|
788
|
+
*
|
|
789
|
+
* @param value - The value the header must carry
|
|
790
|
+
* @returns The literal value, or its Base64 sentinel form
|
|
791
|
+
*
|
|
792
|
+
* @example
|
|
793
|
+
* ```ts
|
|
794
|
+
* encodeSentinel('search') // 'search'
|
|
795
|
+
* encodeSentinel('café') // '=?base64?Y2Fmw6k=?='
|
|
796
|
+
* ```
|
|
797
|
+
*/
|
|
798
|
+
export declare function encodeSentinel(value: string): string;
|
|
799
|
+
|
|
599
800
|
/**
|
|
600
801
|
* Concatenates an MCP tool-call result's text content blocks into one string.
|
|
601
802
|
*
|
|
@@ -616,6 +817,56 @@ export declare const EMPTY_MCP_ARGUMENTS: Readonly<Record<string, unknown>>;
|
|
|
616
817
|
*/
|
|
617
818
|
export declare function extractContentText(result: unknown): string;
|
|
618
819
|
|
|
820
|
+
/**
|
|
821
|
+
* Reads every `x-mcp-header` annotation reachable from a schema node through `properties`.
|
|
822
|
+
*
|
|
823
|
+
* @remarks
|
|
824
|
+
* Reachability is the protocol's own rule: an annotation counts only where a chain of
|
|
825
|
+
* `properties` keys leads to it from the `inputSchema` root, so `path` is both the schema
|
|
826
|
+
* position and the position the call's `arguments` carry the value at. A property named
|
|
827
|
+
* `items` is reachable like any other, because the chain is read by key POSITION rather than
|
|
828
|
+
* by key name.
|
|
829
|
+
*
|
|
830
|
+
* `undefined` means the definition is invalid rather than empty: a reachable annotation whose
|
|
831
|
+
* value is not an {@link import('./validators.js').isFieldToken} token, one sitting on the
|
|
832
|
+
* schema ROOT (which is no property), one on a leaf whose declared type is not an
|
|
833
|
+
* {@link import('./validators.js').isMCPHeaderPrimitive} primitive, or a chain deeper than
|
|
834
|
+
* `DEFAULT_MCP_LIMITS.depth` — which is also what makes a self-referential schema terminate.
|
|
835
|
+
* A node that is not a record carries nothing and answers an empty list, because a leaf the
|
|
836
|
+
* walk cannot read is not a violation.
|
|
837
|
+
*
|
|
838
|
+
* @param schema - The schema node to read
|
|
839
|
+
* @param path - The `properties` keys already traversed; the root is called with `[]`
|
|
840
|
+
* @returns The annotations reachable from this node, or `undefined` when one is invalid
|
|
841
|
+
*
|
|
842
|
+
* @example
|
|
843
|
+
* ```ts
|
|
844
|
+
* extractHeaderAnnotations({ properties: { region: { type: 'string', 'x-mcp-header': 'Region' } } }, [])
|
|
845
|
+
* // → [{ name: 'Region', path: ['region'], primitive: 'string' }]
|
|
846
|
+
* ```
|
|
847
|
+
*/
|
|
848
|
+
export declare function extractHeaderAnnotations(schema: unknown, path: readonly string[]): readonly MCPHeaderParameter[] | undefined;
|
|
849
|
+
|
|
850
|
+
/**
|
|
851
|
+
* Reads one named tool's advertised `inputSchema` out of a `tools/list` answer.
|
|
852
|
+
*
|
|
853
|
+
* @remarks
|
|
854
|
+
* The answer is read as foreign data end to end — a dispatched response, an error envelope,
|
|
855
|
+
* and a result whose `tools` member is absent or is not an array all read as "no schema"
|
|
856
|
+
* rather than as a fault. That is what lets the HTTP POST handler ask its own dispatcher
|
|
857
|
+
* which `Mcp-Param-*` names a `tools/call` may carry without narrowing anything first.
|
|
858
|
+
*
|
|
859
|
+
* @param response - The `tools/list` answer, normally a {@link JSONRPCResponse}
|
|
860
|
+
* @param name - The tool whose schema to read
|
|
861
|
+
* @returns The advertised `inputSchema`, or `undefined` when the answer carries none
|
|
862
|
+
*
|
|
863
|
+
* @example
|
|
864
|
+
* ```ts
|
|
865
|
+
* extractToolSchema(answer, 'search')?.['properties']
|
|
866
|
+
* ```
|
|
867
|
+
*/
|
|
868
|
+
export declare function extractToolSchema(response: unknown, name: string): Readonly<Record<string, unknown>> | undefined;
|
|
869
|
+
|
|
619
870
|
/**
|
|
620
871
|
* Infers the wire era for an MCP protocol revision.
|
|
621
872
|
*
|
|
@@ -758,6 +1009,27 @@ export declare function isBoundedString(value: unknown, bytes: number): value is
|
|
|
758
1009
|
*/
|
|
759
1010
|
export declare function isElicitContent(value: unknown, schema: unknown): value is Readonly<Record<string, MCPElicitValue>>;
|
|
760
1011
|
|
|
1012
|
+
/**
|
|
1013
|
+
* Determines whether a value is one RFC 9110 field token.
|
|
1014
|
+
*
|
|
1015
|
+
* @remarks
|
|
1016
|
+
* A token is one or more `tchar`: the ASCII letters, the digits, and
|
|
1017
|
+
* ``!#$%&'*+-.^_`|~``. That set already excludes the empty string, whitespace, a colon, a
|
|
1018
|
+
* control character, and every non-ASCII code point, so it is the whole constraint an
|
|
1019
|
+
* `x-mcp-header` annotation's value must satisfy — the value is appended verbatim to
|
|
1020
|
+
* {@link MCP_PARAM_PREFIX} and must survive as an HTTP field name.
|
|
1021
|
+
*
|
|
1022
|
+
* @param value - The unknown value to inspect
|
|
1023
|
+
* @returns Whether the value is a non-empty RFC 9110 token
|
|
1024
|
+
*
|
|
1025
|
+
* @example
|
|
1026
|
+
* ```ts
|
|
1027
|
+
* isFieldToken('Region') // true
|
|
1028
|
+
* isFieldToken('My Region') // false
|
|
1029
|
+
* ```
|
|
1030
|
+
*/
|
|
1031
|
+
export declare function isFieldToken(value: unknown): value is string;
|
|
1032
|
+
|
|
761
1033
|
/**
|
|
762
1034
|
* Determines whether a client capability record declares form-mode elicitation.
|
|
763
1035
|
*
|
|
@@ -1144,6 +1416,25 @@ export declare function isMCPElicitURL(value: unknown): value is MCPElicitURL;
|
|
|
1144
1416
|
*/
|
|
1145
1417
|
export declare function isMCPError(value: unknown): value is MCPError;
|
|
1146
1418
|
|
|
1419
|
+
/**
|
|
1420
|
+
* Determines whether a value is a JSON Schema type an `x-mcp-header` annotation may sit on.
|
|
1421
|
+
*
|
|
1422
|
+
* @remarks
|
|
1423
|
+
* `number` is refused deliberately: a JSON number has no interoperable decimal text form, so
|
|
1424
|
+
* a header carrying one could not be compared with the body byte for byte. `integer` renders
|
|
1425
|
+
* exactly, and the server compares it numerically.
|
|
1426
|
+
*
|
|
1427
|
+
* @param value - The unknown value to inspect
|
|
1428
|
+
* @returns Whether the value is one of `'string'`, `'integer'`, or `'boolean'`
|
|
1429
|
+
*
|
|
1430
|
+
* @example
|
|
1431
|
+
* ```ts
|
|
1432
|
+
* isMCPHeaderPrimitive('integer') // true
|
|
1433
|
+
* isMCPHeaderPrimitive('number') // false
|
|
1434
|
+
* ```
|
|
1435
|
+
*/
|
|
1436
|
+
export declare function isMCPHeaderPrimitive(value: unknown): value is MCPHeaderPrimitive;
|
|
1437
|
+
|
|
1147
1438
|
/**
|
|
1148
1439
|
* Determines whether a value is one exact dated-schema MCP icon.
|
|
1149
1440
|
*
|
|
@@ -1159,7 +1450,7 @@ export declare function isMCPIdentity(value: unknown): value is MCPIdentity;
|
|
|
1159
1450
|
* Determines whether a value is one legal embedded multi-round-trip request.
|
|
1160
1451
|
*
|
|
1161
1452
|
* @param value - The unknown value to inspect
|
|
1162
|
-
* @returns `true` for elicitation,
|
|
1453
|
+
* @returns `true` for an embedded elicitation, sampling, or roots request
|
|
1163
1454
|
*
|
|
1164
1455
|
* @example
|
|
1165
1456
|
* ```ts
|
|
@@ -1169,7 +1460,7 @@ export declare function isMCPIdentity(value: unknown): value is MCPIdentity;
|
|
|
1169
1460
|
export declare function isMCPInputRequest(value: unknown): value is MCPInputRequest;
|
|
1170
1461
|
|
|
1171
1462
|
/**
|
|
1172
|
-
* Determines whether a value is a
|
|
1463
|
+
* Determines whether a value is a consumer-keyed map of embedded input requests.
|
|
1173
1464
|
*
|
|
1174
1465
|
* @param value - The unknown value to inspect
|
|
1175
1466
|
* @returns `true` when every own value is a legal {@link MCPInputRequest}
|
|
@@ -1181,6 +1472,30 @@ export declare function isMCPInputRequest(value: unknown): value is MCPInputRequ
|
|
|
1181
1472
|
*/
|
|
1182
1473
|
export declare function isMCPInputRequestMap(value: unknown): value is MCPInputRequestMap;
|
|
1183
1474
|
|
|
1475
|
+
/**
|
|
1476
|
+
* Determines whether a response answers the exact embedded request that was issued.
|
|
1477
|
+
*
|
|
1478
|
+
* @remarks
|
|
1479
|
+
* A response carries no `method` of its own, so the ISSUED request selects which arm applies
|
|
1480
|
+
* — the same way {@link isElicitContent} takes the issued schema rather than trusting the
|
|
1481
|
+
* content to describe itself. A form elicitation is checked twice: once for the response
|
|
1482
|
+
* shape and once, on `accept`, for the content against the schema that round issued. A
|
|
1483
|
+
* URL-mode elicitation issues no schema, so only the shape is checked. A request this
|
|
1484
|
+
* package cannot recognize admits NOTHING, because an unrecognized question has no correct
|
|
1485
|
+
* answer. Total over hostile responses and hostile requests alike.
|
|
1486
|
+
*
|
|
1487
|
+
* @param value - The client's answer to check
|
|
1488
|
+
* @param request - The exact {@link MCPInputRequest} that was issued under the same key
|
|
1489
|
+
* @returns `true` when the answer is legal for that request
|
|
1490
|
+
*
|
|
1491
|
+
* @example
|
|
1492
|
+
* ```ts
|
|
1493
|
+
* isMCPInputResponse({ roots: [] }, { method: 'roots/list' }) // true
|
|
1494
|
+
* isMCPInputResponse({ roots: [] }, { method: 'sampling/createMessage', params: {} }) // false
|
|
1495
|
+
* ```
|
|
1496
|
+
*/
|
|
1497
|
+
export declare function isMCPInputResponse(value: unknown, request: unknown): value is MCPInputResponse;
|
|
1498
|
+
|
|
1184
1499
|
/**
|
|
1185
1500
|
* Determines whether a value is an MCP input-required result.
|
|
1186
1501
|
*
|
|
@@ -1391,6 +1706,95 @@ export declare function isMCPResult(value: unknown): value is MCPResult;
|
|
|
1391
1706
|
/** Determines whether a value is exact result metadata with a valid reserved server identity. */
|
|
1392
1707
|
export declare function isMCPResultMetaObject(value: unknown): value is MCPResultMetaObject;
|
|
1393
1708
|
|
|
1709
|
+
/**
|
|
1710
|
+
* Determines whether a value is one filesystem root a client exposes.
|
|
1711
|
+
*
|
|
1712
|
+
* @remarks
|
|
1713
|
+
* The dated schema declares `uri` with `format: uri`, so this applies the same RFC 3986
|
|
1714
|
+
* check {@link isAbsoluteURI} gives every other `format: uri` field the package validates,
|
|
1715
|
+
* including a URL-mode elicitation's `url`. Total over hostile input.
|
|
1716
|
+
*
|
|
1717
|
+
* @param value - The unknown value to inspect
|
|
1718
|
+
* @returns `true` when `value` carries an absolute `uri` and an optional string `name`
|
|
1719
|
+
*
|
|
1720
|
+
* @example
|
|
1721
|
+
* ```ts
|
|
1722
|
+
* isMCPRoot({ uri: 'file:///workspace', name: 'workspace' }) // true
|
|
1723
|
+
* isMCPRoot({ uri: 'workspace' }) // false — the schema declares `format: uri`
|
|
1724
|
+
* ```
|
|
1725
|
+
*/
|
|
1726
|
+
export declare function isMCPRoot(value: unknown): value is MCPRoot;
|
|
1727
|
+
|
|
1728
|
+
/**
|
|
1729
|
+
* Determines whether a value is one client answer to an embedded `roots/list` request.
|
|
1730
|
+
*
|
|
1731
|
+
* @remarks
|
|
1732
|
+
* The dated schema requires the `roots` array, and each root is checked by
|
|
1733
|
+
* {@link isMCPRoot}. Total over hostile input.
|
|
1734
|
+
*
|
|
1735
|
+
* @param value - The unknown value to inspect
|
|
1736
|
+
* @returns `true` when `value` carries an array of valid roots
|
|
1737
|
+
*
|
|
1738
|
+
* @example
|
|
1739
|
+
* ```ts
|
|
1740
|
+
* isMCPRootResult({ roots: [{ uri: 'file:///workspace' }] }) // true
|
|
1741
|
+
* isMCPRootResult({ roots: {} }) // false — the schema requires an array
|
|
1742
|
+
* ```
|
|
1743
|
+
*/
|
|
1744
|
+
export declare function isMCPRootResult(value: unknown): value is MCPRootResult;
|
|
1745
|
+
|
|
1746
|
+
/**
|
|
1747
|
+
* Determines whether a value is one block a sampling completion may carry.
|
|
1748
|
+
*
|
|
1749
|
+
* @remarks
|
|
1750
|
+
* The schema's `SamplingMessageContentBlock`: the text, image, and audio blocks
|
|
1751
|
+
* {@link isMCPContent} also admits, plus `tool_use` and `tool_result`. The resource arms of
|
|
1752
|
+
* {@link isMCPContent} are refused, because the schema leaves them out of a sampling
|
|
1753
|
+
* completion. A `tool_result` carries ordinary {@link isMCPContent} blocks and an open
|
|
1754
|
+
* `structuredContent`, which the schema constrains to no shape at all. Total over hostile
|
|
1755
|
+
* input.
|
|
1756
|
+
*
|
|
1757
|
+
* @param value - The unknown value to inspect
|
|
1758
|
+
* @returns `true` when `value` is one legal sampling content block
|
|
1759
|
+
*
|
|
1760
|
+
* @example
|
|
1761
|
+
* ```ts
|
|
1762
|
+
* isMCPSampleContent({ type: 'text', text: 'Paris' }) // true
|
|
1763
|
+
* isMCPSampleContent({ type: 'tool_use', id: 'c1', name: 'lookup', input: {} }) // true
|
|
1764
|
+
* isMCPSampleContent({ type: 'resource_link', name: 'doc', uri: 'file:///doc' }) // false
|
|
1765
|
+
* ```
|
|
1766
|
+
*/
|
|
1767
|
+
export declare function isMCPSampleContent(value: unknown): value is MCPSampleContent;
|
|
1768
|
+
|
|
1769
|
+
/**
|
|
1770
|
+
* Determines whether a value is one client answer to an embedded sampling request.
|
|
1771
|
+
*
|
|
1772
|
+
* @remarks
|
|
1773
|
+
* The schema's `CreateMessageResult` types `content` as an `anyOf` over one
|
|
1774
|
+
* {@link isMCPSampleContent} block or an ARRAY of them, so both are admitted here: a
|
|
1775
|
+
* tool-using model answers with `tool_use` and `tool_result` blocks, and a model answering in
|
|
1776
|
+
* several parts answers with the array. `stopReason` stays an open string because the schema
|
|
1777
|
+
* names four values and permits any other a provider reports. Total over hostile input.
|
|
1778
|
+
*
|
|
1779
|
+
* @param value - The unknown value to inspect
|
|
1780
|
+
* @returns `true` when `value` has the sampling-completion shape
|
|
1781
|
+
*
|
|
1782
|
+
* @example
|
|
1783
|
+
* ```ts
|
|
1784
|
+
* isMCPSampleResult({
|
|
1785
|
+
* role: 'assistant',
|
|
1786
|
+
* content: { type: 'text', text: 'Paris' },
|
|
1787
|
+
* model: 'test-model',
|
|
1788
|
+
* }) // true
|
|
1789
|
+
* isMCPSampleResult({
|
|
1790
|
+
* role: 'assistant',
|
|
1791
|
+
* content: [{ type: 'text', text: 'Paris' }],
|
|
1792
|
+
* model: 'test-model',
|
|
1793
|
+
* }) // true
|
|
1794
|
+
* ```
|
|
1795
|
+
*/
|
|
1796
|
+
export declare function isMCPSampleResult(value: unknown): value is MCPSampleResult;
|
|
1797
|
+
|
|
1394
1798
|
/** Determines whether a value is one exact open dated server-capability declaration. */
|
|
1395
1799
|
export declare function isMCPServerCapabilities(value: unknown): value is MCPServerCapabilities;
|
|
1396
1800
|
|
|
@@ -1903,9 +2307,36 @@ export declare const MCP_FALLBACK_VERSION: MCPLegacyVersion;
|
|
|
1903
2307
|
*/
|
|
1904
2308
|
export declare const MCP_HANDSHAKE_VERSION: MCPLegacyVersion;
|
|
1905
2309
|
|
|
2310
|
+
/**
|
|
2311
|
+
* The tool-schema annotation key naming the header one parameter projects into.
|
|
2312
|
+
*
|
|
2313
|
+
* @remarks
|
|
2314
|
+
* It is valid ONLY on a primitive property schema statically reachable from the `inputSchema`
|
|
2315
|
+
* root through `properties` keys alone. An occurrence anywhere else — under `items`, a
|
|
2316
|
+
* composition or conditional keyword, or a `$ref` target — makes the whole tool definition
|
|
2317
|
+
* invalid, which is what {@link import('@orkestrel/mcp').buildHeaderParameters} decides.
|
|
2318
|
+
*/
|
|
2319
|
+
export declare const MCP_HEADER_ANNOTATION = "x-mcp-header";
|
|
2320
|
+
|
|
1906
2321
|
/** MCP reserved error: required HTTP metadata does not match the request body. */
|
|
1907
2322
|
export declare const MCP_HEADER_MISMATCH = -32020;
|
|
1908
2323
|
|
|
2324
|
+
/**
|
|
2325
|
+
* The `tools/list` pages one modern `tools/call` walks to reach its own annotations.
|
|
2326
|
+
*
|
|
2327
|
+
* @remarks
|
|
2328
|
+
* The HTTP POST handler reads a called tool's {@link MCP_HEADER_ANNOTATION} annotations by
|
|
2329
|
+
* dispatching `tools/list` fresh on every `tools/call`, following `nextCursor` until the
|
|
2330
|
+
* named tool is found or the answer carries no cursor. The walk is bounded because its cost
|
|
2331
|
+
* is paid per call: at a page size of 100 this bound reaches 800 definitions, and a consumer
|
|
2332
|
+
* whose replacement `tools/list` pages more finely than that pays the extra dispatches on
|
|
2333
|
+
* every call it serves. The built-in listing answers the whole registry on one page and
|
|
2334
|
+
* never reaches the second. A definition further in than the walk reaches reads as no
|
|
2335
|
+
* definition, so its {@link MCP_PARAM_PREFIX} headers are forwarded untouched — the same
|
|
2336
|
+
* answer a name no served definition annotates receives.
|
|
2337
|
+
*/
|
|
2338
|
+
export declare const MCP_LOOKUP_PAGES = 8;
|
|
2339
|
+
|
|
1909
2340
|
/** Reserved modern `_meta` key carrying the client's open capability record. */
|
|
1910
2341
|
export declare const MCP_META_CAPABILITIES = "io.modelcontextprotocol/clientCapabilities";
|
|
1911
2342
|
|
|
@@ -1939,6 +2370,31 @@ export declare const MCP_MISSING_CAPABILITY = -32021;
|
|
|
1939
2370
|
/** The modern revision offered by an unpinned client during discovery. */
|
|
1940
2371
|
export declare const MCP_MODERN_VERSION: MCPModernVersion;
|
|
1941
2372
|
|
|
2373
|
+
/**
|
|
2374
|
+
* The request-header prefix an `x-mcp-header` annotation projects a tool argument onto.
|
|
2375
|
+
*
|
|
2376
|
+
* @remarks
|
|
2377
|
+
* The full field name is this prefix followed by the annotation's own value verbatim, so
|
|
2378
|
+
* `x-mcp-header: 'Region'` becomes `Mcp-Param-Region`. HTTP field names are case-insensitive,
|
|
2379
|
+
* which is why {@link MCP_HEADER_ANNOTATION} values are unique case-insensitively within one
|
|
2380
|
+
* `inputSchema`.
|
|
2381
|
+
*/
|
|
2382
|
+
export declare const MCP_PARAM_PREFIX = "Mcp-Param-";
|
|
2383
|
+
|
|
2384
|
+
/**
|
|
2385
|
+
* The opening marker of the Base64 sentinel a standard MCP header value travels in.
|
|
2386
|
+
*
|
|
2387
|
+
* @remarks
|
|
2388
|
+
* The markers are LOWERCASE and exact, and this constant with {@link MCP_SENTINEL_SUFFIX} is
|
|
2389
|
+
* their ONE spelling in this package: {@link import('@orkestrel/mcp').encodeSentinel} builds a
|
|
2390
|
+
* sentinel from them and {@link import('@orkestrel/mcp').decodeSentinel} recognizes one by
|
|
2391
|
+
* them, so the two directions cannot drift apart.
|
|
2392
|
+
*/
|
|
2393
|
+
export declare const MCP_SENTINEL_PREFIX = "=?base64?";
|
|
2394
|
+
|
|
2395
|
+
/** The closing marker of the Base64 sentinel a standard MCP header value travels in. */
|
|
2396
|
+
export declare const MCP_SENTINEL_SUFFIX = "?=";
|
|
2397
|
+
|
|
1942
2398
|
/** MCP reserved error: a request names an unsupported protocol revision. */
|
|
1943
2399
|
export declare const MCP_UNSUPPORTED_VERSION = -32022;
|
|
1944
2400
|
|
|
@@ -1980,10 +2436,11 @@ export declare interface MCPBlobResource {
|
|
|
1980
2436
|
* - `progress` receives each `notifications/progress` frame the peer publishes for this
|
|
1981
2437
|
* request. Supplying it is what stamps the request's progress token, so a peer only
|
|
1982
2438
|
* reports where a caller is listening.
|
|
1983
|
-
* - `input` carries one input-required retry.
|
|
1984
|
-
*
|
|
1985
|
-
* `
|
|
1986
|
-
* `
|
|
2439
|
+
* - `input` carries one input-required retry. `responses` is required; `state` is optional
|
|
2440
|
+
* because a peer may issue a round with no `requestState` to return, and the client sends
|
|
2441
|
+
* the `requestState` parameter exactly when a state is supplied. The retry must repeat the
|
|
2442
|
+
* original `name` and byte-identical `arguments`; the client maps the leaves to the
|
|
2443
|
+
* top-level `requestState` and `inputResponses` parameters.
|
|
1987
2444
|
*
|
|
1988
2445
|
* No option survives the call: the continuation data is placed only on that request, and when
|
|
1989
2446
|
* the request settles — answered, refused, timed out, aborted, or drained by a `disconnect` —
|
|
@@ -1994,9 +2451,9 @@ export declare interface MCPCallOptions {
|
|
|
1994
2451
|
readonly signal?: AbortSignal;
|
|
1995
2452
|
/** Receives this request's progress frames; supplying it stamps the progress token. */
|
|
1996
2453
|
readonly progress?: MCPProgressHandler;
|
|
1997
|
-
/** Carries the protected state
|
|
2454
|
+
/** Carries the responses, and any protected state, for one input-required retry. */
|
|
1998
2455
|
readonly input?: {
|
|
1999
|
-
readonly state
|
|
2456
|
+
readonly state?: string;
|
|
2000
2457
|
readonly responses: Readonly<Record<string, unknown>>;
|
|
2001
2458
|
};
|
|
2002
2459
|
}
|
|
@@ -2660,12 +3117,6 @@ export declare interface MCPDispatchOptions {
|
|
|
2660
3117
|
readonly caller?: unknown;
|
|
2661
3118
|
}
|
|
2662
3119
|
|
|
2663
|
-
/** One consumer-requested form elicitation, before MCP assigns its map key and signs state. */
|
|
2664
|
-
export declare interface MCPElicitation {
|
|
2665
|
-
readonly request: MCPElicitForm;
|
|
2666
|
-
readonly state?: JSONValue;
|
|
2667
|
-
}
|
|
2668
|
-
|
|
2669
3120
|
/** One titled value in a form elicitation's single- or multi-select schema. */
|
|
2670
3121
|
export declare interface MCPElicitChoice {
|
|
2671
3122
|
readonly const: string;
|
|
@@ -2837,6 +3288,34 @@ export declare interface MCPExecutionContext {
|
|
|
2837
3288
|
/** Executes one canonical tool call or return a fully formed complete MCP result. */
|
|
2838
3289
|
export declare type MCPExecutionHandler = (context: MCPExecutionContext) => ToolResult | MCPCallResult | Promise<ToolResult | MCPCallResult>;
|
|
2839
3290
|
|
|
3291
|
+
/**
|
|
3292
|
+
* One `x-mcp-header` projection a tool's `inputSchema` declares.
|
|
3293
|
+
*
|
|
3294
|
+
* @remarks
|
|
3295
|
+
* - `name` — the annotation's own value, appended verbatim to {@link MCP_PARAM_PREFIX} to
|
|
3296
|
+
* form the request field name.
|
|
3297
|
+
* - `path` — the `properties` keys leading from the `inputSchema` root to the annotated
|
|
3298
|
+
* leaf, which is also the path the call's `arguments` carry the value at.
|
|
3299
|
+
* - `primitive` — the leaf's declared type, which fixes the value's text rendering and, for
|
|
3300
|
+
* `integer`, makes the server's comparison numeric rather than textual.
|
|
3301
|
+
*/
|
|
3302
|
+
export declare interface MCPHeaderParameter {
|
|
3303
|
+
readonly name: string;
|
|
3304
|
+
readonly path: readonly string[];
|
|
3305
|
+
readonly primitive: MCPHeaderPrimitive;
|
|
3306
|
+
}
|
|
3307
|
+
|
|
3308
|
+
/**
|
|
3309
|
+
* The JSON Schema types an `x-mcp-header` annotation may sit on.
|
|
3310
|
+
*
|
|
3311
|
+
* @remarks
|
|
3312
|
+
* The protocol admits primitives alone, and it splits the JSON Schema number tower: `integer`
|
|
3313
|
+
* carries a decimal rendering an HTTP field can hold exactly, while `number` has no
|
|
3314
|
+
* interoperable text form and is refused. `object`, `array`, and `null` are refused for the
|
|
3315
|
+
* same reason — a header field carries text, not structure.
|
|
3316
|
+
*/
|
|
3317
|
+
export declare type MCPHeaderPrimitive = 'boolean' | 'integer' | 'string';
|
|
3318
|
+
|
|
2840
3319
|
/** One sized, themed icon associated with an MCP resource link. */
|
|
2841
3320
|
export declare type MCPIcon = MCPMetaObject & {
|
|
2842
3321
|
readonly src: string;
|
|
@@ -2869,18 +3348,19 @@ export declare interface MCPInputContext {
|
|
|
2869
3348
|
readonly request: JSONRPCRequest;
|
|
2870
3349
|
readonly name: string;
|
|
2871
3350
|
readonly arguments: Readonly<Record<string, unknown>>;
|
|
2872
|
-
|
|
3351
|
+
/** Every verified answer to the previous round, under the keys that round assigned. */
|
|
3352
|
+
readonly responses?: MCPInputResponseMap;
|
|
2873
3353
|
readonly state?: JSONValue;
|
|
2874
3354
|
}
|
|
2875
3355
|
|
|
2876
3356
|
/**
|
|
2877
|
-
* Decides whether the current `tools/call` needs
|
|
3357
|
+
* Decides whether the current `tools/call` still needs input from the client.
|
|
2878
3358
|
*
|
|
2879
|
-
* @param context - The original call plus
|
|
3359
|
+
* @param context - The original call plus every verified answer and state on a retry
|
|
2880
3360
|
* @param options - The resolved per-request method options
|
|
2881
|
-
* @returns
|
|
3361
|
+
* @returns The next round to send, or `undefined` to continue into the tool registry
|
|
2882
3362
|
*/
|
|
2883
|
-
export declare type MCPInputHandler = (context: MCPInputContext, options: MCPMethodOptions) =>
|
|
3363
|
+
export declare type MCPInputHandler = (context: MCPInputContext, options: MCPMethodOptions) => MCPInputRound | undefined | Promise<MCPInputRound | undefined>;
|
|
2884
3364
|
|
|
2885
3365
|
/** Consumer policy for the server's multi-round-trip input mechanism. */
|
|
2886
3366
|
export declare interface MCPInputOptions {
|
|
@@ -2890,17 +3370,19 @@ export declare interface MCPInputOptions {
|
|
|
2890
3370
|
readonly ttl: number;
|
|
2891
3371
|
/** Resolves the authenticated principal for the call in hand. */
|
|
2892
3372
|
readonly principal: MCPPrincipalHandler;
|
|
2893
|
-
/**
|
|
2894
|
-
readonly
|
|
3373
|
+
/** Composes the next round of input requests, including on verified retries. */
|
|
3374
|
+
readonly selector: MCPInputHandler;
|
|
2895
3375
|
}
|
|
2896
3376
|
|
|
2897
3377
|
/**
|
|
2898
3378
|
* One embedded multi-round-trip request.
|
|
2899
3379
|
*
|
|
2900
3380
|
* @remarks
|
|
2901
|
-
*
|
|
2902
|
-
*
|
|
2903
|
-
*
|
|
3381
|
+
* A consumer composes any of the three arms into an {@link MCPInputRound}, and this server
|
|
3382
|
+
* issues whichever arms that round carries. The elicitation arm is fully typed because this
|
|
3383
|
+
* package issues its schema and enforces the answer against it. The sampling and roots arms
|
|
3384
|
+
* keep OPEN parameter records: the dated schema leaves their request bodies to the caller, and
|
|
3385
|
+
* narrowing them here would refuse parameters the protocol permits.
|
|
2904
3386
|
*/
|
|
2905
3387
|
export declare type MCPInputRequest = MCPElicitRequest | {
|
|
2906
3388
|
readonly method: 'sampling/createMessage';
|
|
@@ -2910,9 +3392,24 @@ export declare type MCPInputRequest = MCPElicitRequest | {
|
|
|
2910
3392
|
readonly params?: Readonly<Record<string, unknown>>;
|
|
2911
3393
|
};
|
|
2912
3394
|
|
|
2913
|
-
/** A
|
|
3395
|
+
/** A consumer-keyed map of embedded requests the client must fulfil. */
|
|
2914
3396
|
export declare type MCPInputRequestMap = Readonly<Record<string, MCPInputRequest>>;
|
|
2915
3397
|
|
|
3398
|
+
/**
|
|
3399
|
+
* One client answer to one embedded input request.
|
|
3400
|
+
*
|
|
3401
|
+
* @remarks
|
|
3402
|
+
* The arms are discriminated by their own required members — `action` for an elicitation,
|
|
3403
|
+
* `roots` for a roots listing, and `model` beside `role` for a sampling completion — because
|
|
3404
|
+
* the protocol gives a response no `method` of its own. The server knows which arm applies
|
|
3405
|
+
* from the request it ISSUED under that key, so {@link MCPInputHandler} receives every answer
|
|
3406
|
+
* already checked against the question it answers.
|
|
3407
|
+
*/
|
|
3408
|
+
export declare type MCPInputResponse = MCPElicitResult | MCPSampleResult | MCPRootResult;
|
|
3409
|
+
|
|
3410
|
+
/** A consumer-keyed map of the client's answers to one issued round. */
|
|
3411
|
+
export declare type MCPInputResponseMap = Readonly<Record<string, MCPInputResponse>>;
|
|
3412
|
+
|
|
2916
3413
|
/**
|
|
2917
3414
|
* An incomplete modern result carrying input requests, protected request state, or both.
|
|
2918
3415
|
*
|
|
@@ -2932,16 +3429,30 @@ export declare type MCPInputResult = {
|
|
|
2932
3429
|
readonly _meta?: MCPResultMetaObject;
|
|
2933
3430
|
};
|
|
2934
3431
|
|
|
3432
|
+
/**
|
|
3433
|
+
* One consumer-composed round of embedded requests, before MCP seals its continuation state.
|
|
3434
|
+
*
|
|
3435
|
+
* @remarks
|
|
3436
|
+
* The consumer owns the keys and the request kinds, because the keys are how it correlates
|
|
3437
|
+
* each answer and the kinds are what its own policy needs. MCP owns everything protective
|
|
3438
|
+
* around the round: the capability gate, the seal, the expiry, and the per-answer check on
|
|
3439
|
+
* the retry.
|
|
3440
|
+
*/
|
|
3441
|
+
export declare interface MCPInputRound {
|
|
3442
|
+
readonly requests: MCPInputRequestMap;
|
|
3443
|
+
readonly state?: JSONValue;
|
|
3444
|
+
}
|
|
3445
|
+
|
|
2935
3446
|
/**
|
|
2936
3447
|
* The integrity-protected payload carried inside an opaque `requestState` token.
|
|
2937
3448
|
*
|
|
2938
3449
|
* @remarks
|
|
2939
3450
|
* `id` is the FIRST round's request id and stays bound across every later round, so a
|
|
2940
3451
|
* multi-round exchange remains one correlated call rather than a chain whose origin is lost
|
|
2941
|
-
* after the second hop. `
|
|
2942
|
-
*
|
|
2943
|
-
*
|
|
2944
|
-
* `
|
|
3452
|
+
* after the second hop. `requests` is the EXACT round that was issued: it carries the keys the
|
|
3453
|
+
* retry must answer and, for a form elicitation, the schema {@link isElicitContent} enforces
|
|
3454
|
+
* an accepted answer against — a round that is bound but never enforced buys nothing.
|
|
3455
|
+
* `requests` and `expiry` are re-minted every round; `principal`, `id`, `version`, `method`,
|
|
2945
3456
|
* `name`, and `digest` are the bindings that must not move.
|
|
2946
3457
|
*/
|
|
2947
3458
|
export declare interface MCPInputState {
|
|
@@ -2950,11 +3461,10 @@ export declare interface MCPInputState {
|
|
|
2950
3461
|
readonly id: JSONRPCId;
|
|
2951
3462
|
readonly version: string;
|
|
2952
3463
|
readonly method: string;
|
|
2953
|
-
|
|
3464
|
+
/** The exact round issued under this state, enforced answer by answer on the retry. */
|
|
3465
|
+
readonly requests: MCPInputRequestMap;
|
|
2954
3466
|
readonly name: string;
|
|
2955
3467
|
readonly digest: string;
|
|
2956
|
-
/** The exact schema issued with this round, enforced on the accepted response. */
|
|
2957
|
-
readonly schema: MCPElicitSchema;
|
|
2958
3468
|
readonly state?: JSONValue;
|
|
2959
3469
|
}
|
|
2960
3470
|
|
|
@@ -3097,7 +3607,10 @@ export declare interface MCPLimitOptions {
|
|
|
3097
3607
|
readonly message?: number;
|
|
3098
3608
|
/** Maximum serialized UTF-8 bytes accepted in one `_meta` value. */
|
|
3099
3609
|
readonly metadata?: number;
|
|
3100
|
-
/**
|
|
3610
|
+
/**
|
|
3611
|
+
* Maximum total enumerable keys accepted in one bounded value: one `_meta` value under
|
|
3612
|
+
* `metadata`, and one produced tool-call result under `content`.
|
|
3613
|
+
*/
|
|
3101
3614
|
readonly keys?: number;
|
|
3102
3615
|
/** Maximum UTF-8 bytes accepted in one protected `requestState`. */
|
|
3103
3616
|
readonly state?: number;
|
|
@@ -3247,7 +3760,7 @@ export declare interface MCPMethodManagerInterface {
|
|
|
3247
3760
|
* The mirror of {@link MCPDispatchOptions} on the far side of dispatch: a CALLER may
|
|
3248
3761
|
* have no signal to offer, but a dispatched method always has one to observe, so
|
|
3249
3762
|
* `signal` is REQUIRED here. Dispatch resolves it once, at the single ingress, and
|
|
3250
|
-
* supplies the same value to every handler,
|
|
3763
|
+
* supplies the same value to every handler, input, principal, and subscription
|
|
3251
3764
|
* producer the request reaches — none of them may reinvent a cancellation source or
|
|
3252
3765
|
* treat absence as a case.
|
|
3253
3766
|
*
|
|
@@ -3700,6 +4213,49 @@ export declare type MCPResultMetaObject = MCPMetaObject & {
|
|
|
3700
4213
|
/** The intended recipient of annotated MCP content. */
|
|
3701
4214
|
export declare type MCPRole = 'user' | 'assistant';
|
|
3702
4215
|
|
|
4216
|
+
/** One filesystem root a client exposes to a server. */
|
|
4217
|
+
export declare interface MCPRoot {
|
|
4218
|
+
readonly uri: string;
|
|
4219
|
+
readonly name?: string;
|
|
4220
|
+
readonly _meta?: MCPMetaObject;
|
|
4221
|
+
}
|
|
4222
|
+
|
|
4223
|
+
/** The client's answer to one embedded `roots/list` request. */
|
|
4224
|
+
export declare interface MCPRootResult {
|
|
4225
|
+
readonly roots: readonly MCPRoot[];
|
|
4226
|
+
readonly _meta?: MCPMetaObject;
|
|
4227
|
+
}
|
|
4228
|
+
|
|
4229
|
+
/**
|
|
4230
|
+
* One block a sampling completion may carry.
|
|
4231
|
+
*
|
|
4232
|
+
* @remarks
|
|
4233
|
+
* The dated schema's `SamplingMessageContentBlock`: the text, image, and audio blocks
|
|
4234
|
+
* {@link MCPContent} also admits, plus the two tool blocks a tool-using model produces. The
|
|
4235
|
+
* resource arms of {@link MCPContent} are deliberately absent — the schema leaves them out of
|
|
4236
|
+
* a sampling completion.
|
|
4237
|
+
*/
|
|
4238
|
+
export declare type MCPSampleContent = MCPTextContent | MCPImageContent | MCPAudioContent | MCPToolUseContent | MCPToolResultContent;
|
|
4239
|
+
|
|
4240
|
+
/**
|
|
4241
|
+
* The client's answer to one embedded `sampling/createMessage` request.
|
|
4242
|
+
*
|
|
4243
|
+
* @remarks
|
|
4244
|
+
* `content` is the dated schema's own `anyOf`: one {@link MCPSampleContent} block, or an array
|
|
4245
|
+
* of them. A tool-using model answers with `tool_use` and `tool_result` blocks, and a model
|
|
4246
|
+
* answering in several parts answers with the array, so narrowing this to a single text, image,
|
|
4247
|
+
* or audio block would refuse completions the schema permits. `stopReason` is an open string
|
|
4248
|
+
* because the schema names `endTurn`, `stopSequence`, `maxTokens`, and `toolUse` while
|
|
4249
|
+
* permitting any other value a provider reports.
|
|
4250
|
+
*/
|
|
4251
|
+
export declare interface MCPSampleResult {
|
|
4252
|
+
readonly role: 'user' | 'assistant';
|
|
4253
|
+
readonly content: MCPSampleContent | readonly MCPSampleContent[];
|
|
4254
|
+
readonly model: string;
|
|
4255
|
+
readonly stopReason?: string;
|
|
4256
|
+
readonly _meta?: MCPMetaObject;
|
|
4257
|
+
}
|
|
4258
|
+
|
|
3703
4259
|
/**
|
|
3704
4260
|
* A transport-agnostic Model Context Protocol server — dispatches JSON-RPC 2.0
|
|
3705
4261
|
* requests over a live {@link ToolManagerInterface}, with NO transport coupling.
|
|
@@ -3791,6 +4347,15 @@ export declare type MCPServerEventMap = {
|
|
|
3791
4347
|
* inbound traffic. Only SCALARS are reported: nothing read out of the request graph
|
|
3792
4348
|
* escapes here, so a listener can never observe a value the ownership seam has not yet
|
|
3793
4349
|
* bounded.
|
|
4350
|
+
*
|
|
4351
|
+
* Not every reported invocation arrived from a peer. A modern `tools/call` reaching the
|
|
4352
|
+
* HTTP POST handler (`createMCPPostHandler`) reports the SYNTHETIC `tools/list` that
|
|
4353
|
+
* handler dispatches to read the called tool's `x-mcp-header` annotations, ahead of the
|
|
4354
|
+
* call itself. Each carries the RESERVED id `0`, and one fires per page the handler
|
|
4355
|
+
* walks, up to {@link MCP_LOOKUP_PAGES}. So an observer accounting for inbound traffic
|
|
4356
|
+
* subtracts a `('tools/list', 0, 'modern')` that precedes a `tools/call`, and one
|
|
4357
|
+
* tracing the server's own work keeps it. The id is reserved by convention rather than
|
|
4358
|
+
* enforced: a peer sending its own `tools/list` under id `0` is not told apart here.
|
|
3794
4359
|
*/
|
|
3795
4360
|
readonly request: readonly [method: string, id: JSONRPCId | undefined, era: MCPEra];
|
|
3796
4361
|
/**
|
|
@@ -3972,6 +4537,11 @@ export declare interface MCPServerOptions {
|
|
|
3972
4537
|
* completion even after the request that asked for it has ended, and abandons the result.
|
|
3973
4538
|
* An {@link MCPExecutionHandler} receives `signal` on its {@link MCPExecutionContext} and
|
|
3974
4539
|
* can stop the work itself.
|
|
4540
|
+
*
|
|
4541
|
+
* A handler returning a complete {@link MCPCallResult} is taken at its word: the server
|
|
4542
|
+
* bounds it and re-proves its shape, then sends what the handler composed. Nothing stamps
|
|
4543
|
+
* the `_meta` server identity `buildModernResult` puts on a normalized result, so a handler
|
|
4544
|
+
* whose peer reads that key composes it through `buildModernResult` itself.
|
|
3975
4545
|
*/
|
|
3976
4546
|
readonly execution?: MCPExecutionHandler;
|
|
3977
4547
|
/** Optional human guidance exposed by `server/discover`. */
|
|
@@ -4656,7 +5226,7 @@ export declare interface MCPTaskManagerInterface {
|
|
|
4656
5226
|
* VERBATIM — it holds none of the task's keys, so the ignoring is this method's to do.
|
|
4657
5227
|
*
|
|
4658
5228
|
* This is the SECOND multi-round-trip mechanism in the package, and it is the weaker one.
|
|
4659
|
-
* The
|
|
5229
|
+
* The built-in input path binds each round with a sealed `requestState`, an argument digest,
|
|
4660
5230
|
* an absolute expiry, and the resolved principal; this path has none of them, because MCP
|
|
4661
5231
|
* neither issued the question nor owns the channel it is answered on. Anything equivalent
|
|
4662
5232
|
* has to live here: bind each published key to the principal that may answer it, expire
|
|
@@ -4958,6 +5528,25 @@ export declare interface MCPToolDescriptor {
|
|
|
4958
5528
|
readonly inputSchema: Readonly<Record<string, unknown>>;
|
|
4959
5529
|
}
|
|
4960
5530
|
|
|
5531
|
+
/** One tool's outcome returned to the model, carried inside a sampling completion. */
|
|
5532
|
+
export declare interface MCPToolResultContent {
|
|
5533
|
+
readonly type: 'tool_result';
|
|
5534
|
+
readonly toolUseId: string;
|
|
5535
|
+
readonly content: readonly MCPContent[];
|
|
5536
|
+
readonly isError?: boolean;
|
|
5537
|
+
readonly structuredContent?: JSONValue;
|
|
5538
|
+
readonly _meta?: MCPMetaObject;
|
|
5539
|
+
}
|
|
5540
|
+
|
|
5541
|
+
/** A model's request to call one tool, carried inside a sampling completion. */
|
|
5542
|
+
export declare interface MCPToolUseContent {
|
|
5543
|
+
readonly type: 'tool_use';
|
|
5544
|
+
readonly id: string;
|
|
5545
|
+
readonly name: string;
|
|
5546
|
+
readonly input: Readonly<Record<string, unknown>>;
|
|
5547
|
+
readonly _meta?: MCPMetaObject;
|
|
5548
|
+
}
|
|
5549
|
+
|
|
4961
5550
|
/**
|
|
4962
5551
|
* A duplex message channel an environment face provides to the pure engine — the
|
|
4963
5552
|
* one port `bindServer` and `bindClient` (`./helpers.js`) pipe an
|
|
@@ -5104,17 +5693,18 @@ export declare function parseJSONRPCMessage(value: unknown, limits?: MCPJSONLimi
|
|
|
5104
5693
|
* This parser does not open the opaque continuation carrier; the configured
|
|
5105
5694
|
* continuation port performs that boundary first. The protected
|
|
5106
5695
|
* payload binds the authenticated principal, absolute expiry, ORIGINAL request id, version,
|
|
5107
|
-
* method,
|
|
5108
|
-
*
|
|
5109
|
-
*
|
|
5110
|
-
*
|
|
5696
|
+
* method, the exact round that was issued, tool name, argument digest, and optional
|
|
5697
|
+
* application state. Every member is required except application state: a payload missing its
|
|
5698
|
+
* round cannot have the client's answers enforced, so it is refused rather than admitted
|
|
5699
|
+
* unenforced. An EMPTY round is refused for the same reason — a retry against it would answer
|
|
5700
|
+
* no question at all. Total over malformed or hostile input.
|
|
5111
5701
|
*
|
|
5112
5702
|
* @param value - The opened canonical continuation value to parse
|
|
5113
5703
|
* @returns The protected input state, or `undefined` when malformed
|
|
5114
5704
|
*
|
|
5115
5705
|
* @example
|
|
5116
5706
|
* ```ts
|
|
5117
|
-
* parseMCPInputState('{"principal":"user-1","expiry":2000,"id":1,"version":"2026-07-28","method":"tools/call","
|
|
5707
|
+
* parseMCPInputState('{"principal":"user-1","expiry":2000,"id":1,"version":"2026-07-28","method":"tools/call","requests":{"k":{"method":"roots/list"}},"name":"reply","digest":"abc"}')
|
|
5118
5708
|
* ```
|
|
5119
5709
|
*/
|
|
5120
5710
|
export declare function parseMCPInputState(value: unknown): MCPInputState | undefined;
|
|
@@ -5161,6 +5751,29 @@ export declare function parseRequestContext(value: unknown, limits?: MCPJSONLimi
|
|
|
5161
5751
|
*/
|
|
5162
5752
|
export declare function readCancelledId(message: JSONRPCMessage): JSONRPCId | undefined;
|
|
5163
5753
|
|
|
5754
|
+
/**
|
|
5755
|
+
* Renders one projected argument as the text its `Mcp-Param-*` header carries.
|
|
5756
|
+
*
|
|
5757
|
+
* @remarks
|
|
5758
|
+
* The protocol's conversion table, and the ONE place it is stated: a string travels as
|
|
5759
|
+
* itself, an integer in decimal, and a boolean as lowercase `true` or `false`. The value's
|
|
5760
|
+
* runtime shape must match the leaf's declared type, so a schema that declares `integer` and
|
|
5761
|
+
* an argument that supplies a string, a fraction, or a magnitude outside the IEEE 754 safe
|
|
5762
|
+
* range carries NOTHING — a header that cannot round-trip the body value is worse than an
|
|
5763
|
+
* absent one, and the tool's own argument validation owns the disagreement.
|
|
5764
|
+
*
|
|
5765
|
+
* @param value - The argument value read at the parameter's path
|
|
5766
|
+
* @param primitive - The leaf's declared type
|
|
5767
|
+
* @returns The header text, or `undefined` when the value cannot travel as that type
|
|
5768
|
+
*
|
|
5769
|
+
* @example
|
|
5770
|
+
* ```ts
|
|
5771
|
+
* renderHeaderValue(42, 'integer') // '42'
|
|
5772
|
+
* renderHeaderValue(false, 'boolean') // 'false'
|
|
5773
|
+
* ```
|
|
5774
|
+
*/
|
|
5775
|
+
export declare function renderHeaderValue(value: unknown, primitive: MCPHeaderPrimitive): string | undefined;
|
|
5776
|
+
|
|
5164
5777
|
/**
|
|
5165
5778
|
* Pumps a controlled serialized exchange onto a transport — every notification in order, then
|
|
5166
5779
|
* the terminating response — and END the exchange however the pump leaves.
|