Skip to content

Commit 1916e69

Browse files
refactor(core): add internal Dispatcher and StreamDriver classes
Dispatcher is a stateless handler registry with a dispatch(req, env) async-generator that yields notifications then one terminal response. StreamDriver owns per-connection state (id correlation, timeouts, progress, cancellation) over a persistent transport. Additive: new files, not yet wired. Protocol composes them in R2.
1 parent 39e10ab commit 1916e69

7 files changed

Lines changed: 1432 additions & 0 deletions

File tree

packages/core/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ export * from './auth/errors.js';
22
export * from './errors/sdkErrors.js';
33
export * from './shared/auth.js';
44
export * from './shared/authUtils.js';
5+
export * from './shared/context.js';
6+
export * from './shared/dispatcher.js';
57
export * from './shared/metadataUtils.js';
68
export * from './shared/protocol.js';
79
export * from './shared/responseMessage.js';
810
export * from './shared/stdio.js';
11+
export * from './shared/streamDriver.js';
912
export type { RequestTaskStore, TaskContext, TaskManagerOptions, TaskRequestOptions } from './shared/taskManager.js';
1013
export { extractTaskManagerOptions, NullTaskManager, TaskManager } from './shared/taskManager.js';
1114
export * from './shared/toolNameValidation.js';
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import type { AuthInfo, JSONRPCMessage, Notification, Request, RequestId, Result } from '../types/index.js';
2+
import type { StandardSchemaV1 } from '../util/standardSchema.js';
3+
import type { NotificationOptions, RequestOptions } from './protocol.js';
4+
5+
/**
6+
* Per-request environment a transport adapter passes to {@linkcode Dispatcher.dispatch}.
7+
* Everything is optional; a bare `dispatch()` call works with no transport at all.
8+
*
9+
* @internal
10+
*/
11+
export type RequestEnv = {
12+
/**
13+
* Sends a request back to the peer (server→client elicitation/sampling, or
14+
* client→server nested calls). Supplied by {@linkcode StreamDriver} when running
15+
* over a persistent pipe, or by an HTTP adapter that has a backchannel. When
16+
* undefined, `ctx.mcpReq.send` throws {@linkcode SdkErrorCode.NotConnected}.
17+
*/
18+
send?: (request: Request, options?: RequestOptions) => Promise<Result>;
19+
20+
/** Validated auth token info for HTTP transports. */
21+
authInfo?: AuthInfo;
22+
23+
/** Original HTTP `Request` (Fetch API), if any. */
24+
httpReq?: globalThis.Request;
25+
26+
/** Abort signal for the inbound request. If omitted, a fresh controller is created. */
27+
signal?: AbortSignal;
28+
29+
/** Transport session identifier (legacy `Mcp-Session-Id`). */
30+
sessionId?: string;
31+
32+
/** Extension slot. Adapters and middleware populate keys here; copied onto `BaseContext.ext`. */
33+
ext?: Record<string, unknown>;
34+
};
35+
36+
/**
37+
* The minimal contract a {@linkcode Dispatcher} owner needs to send outbound
38+
* requests/notifications to the connected peer. Implemented by
39+
* {@linkcode StreamDriver} for persistent pipes; request-shaped paths can supply
40+
* their own.
41+
*
42+
* @internal
43+
*/
44+
export interface Outbound {
45+
/** Send a request to the peer and resolve with the parsed result. */
46+
request<T extends StandardSchemaV1>(req: Request, resultSchema: T, options?: RequestOptions): Promise<StandardSchemaV1.InferOutput<T>>;
47+
/** Send a notification to the peer. */
48+
notification(notification: Notification, options?: NotificationOptions): Promise<void>;
49+
/** Close the underlying connection. */
50+
close(): Promise<void>;
51+
/** Clear a registered progress callback by its message id. Optional; pipe-channels expose this. */
52+
removeProgressHandler?(messageId: number): void;
53+
/** Inform the channel which protocol version was negotiated (for header echoing etc.). Optional. */
54+
setProtocolVersion?(version: string): void;
55+
/** Write a raw JSON-RPC message on the same stream as a prior request. Optional; pipe-only. */
56+
sendRaw?(message: JSONRPCMessage, options?: { relatedRequestId?: RequestId }): Promise<void>;
57+
}

0 commit comments

Comments
 (0)