summaryrefslogtreecommitdiffhomepage
path: root/packages/mcp/src/transport.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/mcp/src/transport.ts')
-rw-r--r--packages/mcp/src/transport.ts146
1 files changed, 73 insertions, 73 deletions
diff --git a/packages/mcp/src/transport.ts b/packages/mcp/src/transport.ts
index b1e3ec5..492879f 100644
--- a/packages/mcp/src/transport.ts
+++ b/packages/mcp/src/transport.ts
@@ -7,95 +7,95 @@ import { FrameDecoder } from "./framing.js";
import { JsonRpcClient, type WriteFn } from "./rpc.js";
export interface SpawnedProcess {
- readonly stdin: { readonly write: (bytes: Uint8Array) => void };
- readonly stdout:
- | AsyncIterable<Uint8Array>
- | { readonly on: (event: string, cb: (data: Uint8Array) => void) => void };
- readonly stderr?:
- | AsyncIterable<Uint8Array>
- | { readonly on: (event: string, cb: (data: Uint8Array) => void) => void }
- | undefined;
- readonly pid: number | undefined;
- readonly kill: () => void;
+ readonly stdin: { readonly write: (bytes: Uint8Array) => void };
+ readonly stdout:
+ | AsyncIterable<Uint8Array>
+ | { readonly on: (event: string, cb: (data: Uint8Array) => void) => void };
+ readonly stderr?:
+ | AsyncIterable<Uint8Array>
+ | { readonly on: (event: string, cb: (data: Uint8Array) => void) => void }
+ | undefined;
+ readonly pid: number | undefined;
+ readonly kill: () => void;
}
export type SpawnProcess = (
- command: readonly string[],
- opts: { readonly cwd: string; readonly env?: Readonly<Record<string, string>> | undefined },
+ command: readonly string[],
+ opts: { readonly cwd: string; readonly env?: Readonly<Record<string, string>> | undefined },
) => SpawnedProcess;
export interface Connection {
- readonly send: (method: string, params?: unknown) => Promise<unknown>;
- readonly notify: (method: string, params?: unknown) => void;
- readonly onNotification: (method: string, handler: (params: unknown) => void) => void;
- readonly close: () => void;
- readonly pid: number | undefined;
+ readonly send: (method: string, params?: unknown) => Promise<unknown>;
+ readonly notify: (method: string, params?: unknown) => void;
+ readonly onNotification: (method: string, handler: (params: unknown) => void) => void;
+ readonly close: () => void;
+ readonly pid: number | undefined;
}
export interface StdioTransportDeps {
- readonly spawn: SpawnProcess;
- readonly command: readonly string[];
- readonly env?: Readonly<Record<string, string>>;
+ readonly spawn: SpawnProcess;
+ readonly command: readonly string[];
+ readonly env?: Readonly<Record<string, string>>;
}
export function createStdioTransport(
- deps: StdioTransportDeps,
- cwd: string,
+ deps: StdioTransportDeps,
+ cwd: string,
): { connection: Connection; promise: Promise<void> } {
- const spawnOpts: { readonly cwd: string; readonly env?: Readonly<Record<string, string>> } = {
- cwd,
- };
- if (deps.env) {
- (spawnOpts as { env?: Readonly<Record<string, string>> }).env = deps.env;
- }
+ const spawnOpts: { readonly cwd: string; readonly env?: Readonly<Record<string, string>> } = {
+ cwd,
+ };
+ if (deps.env) {
+ (spawnOpts as { env?: Readonly<Record<string, string>> }).env = deps.env;
+ }
- const proc = deps.spawn(deps.command, spawnOpts);
- const decoder = new FrameDecoder();
+ const proc = deps.spawn(deps.command, spawnOpts);
+ const decoder = new FrameDecoder();
- const writeFn: WriteFn = (bytes) => proc.stdin.write(bytes);
- const rpc = new JsonRpcClient(writeFn);
+ const writeFn: WriteFn = (bytes) => proc.stdin.write(bytes);
+ const rpc = new JsonRpcClient(writeFn);
- const stdoutSource = proc.stdout;
- const promise = new Promise<void>((resolve, reject) => {
- if (Symbol.asyncIterator in stdoutSource) {
- (async () => {
- try {
- for await (const chunk of stdoutSource as AsyncIterable<Uint8Array>) {
- const messages = decoder.decode(chunk);
- for (const msg of messages) {
- rpc.handleMessage(msg);
- }
- }
- resolve();
- } catch (err: unknown) {
- reject(err);
- }
- })();
- } else {
- const source = stdoutSource as {
- readonly on: (event: string, cb: (data: Uint8Array) => void) => void;
- };
- source.on("data", (data: Uint8Array) => {
- const messages = decoder.decode(data);
- for (const msg of messages) {
- rpc.handleMessage(msg);
- }
- });
- source.on("end", () => resolve());
- source.on("error", (err: unknown) => reject(err));
- }
- });
+ const stdoutSource = proc.stdout;
+ const promise = new Promise<void>((resolve, reject) => {
+ if (Symbol.asyncIterator in stdoutSource) {
+ (async () => {
+ try {
+ for await (const chunk of stdoutSource as AsyncIterable<Uint8Array>) {
+ const messages = decoder.decode(chunk);
+ for (const msg of messages) {
+ rpc.handleMessage(msg);
+ }
+ }
+ resolve();
+ } catch (err: unknown) {
+ reject(err);
+ }
+ })();
+ } else {
+ const source = stdoutSource as {
+ readonly on: (event: string, cb: (data: Uint8Array) => void) => void;
+ };
+ source.on("data", (data: Uint8Array) => {
+ const messages = decoder.decode(data);
+ for (const msg of messages) {
+ rpc.handleMessage(msg);
+ }
+ });
+ source.on("end", () => resolve());
+ source.on("error", (err: unknown) => reject(err));
+ }
+ });
- const connection: Connection = {
- send: (method, params) => rpc.request(method, params),
- notify: (method, params) => rpc.notify(method, params),
- onNotification: (method, handler) => rpc.onNotification(method, handler),
- close: () => {
- rpc.close();
- proc.kill();
- },
- pid: proc.pid,
- };
+ const connection: Connection = {
+ send: (method, params) => rpc.request(method, params),
+ notify: (method, params) => rpc.notify(method, params),
+ onNotification: (method, handler) => rpc.onNotification(method, handler),
+ close: () => {
+ rpc.close();
+ proc.kill();
+ },
+ pid: proc.pid,
+ };
- return { connection, promise };
+ return { connection, promise };
}