added all mcp

This commit is contained in:
liph22
2025-12-19 23:59:54 +01:00
parent edfffd76e1
commit 14bc398915
6240 changed files with 2421602 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=cli.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,129 @@
import EventSource from "eventsource";
import WebSocket from "ws";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
global.EventSource = EventSource;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
global.WebSocket = WebSocket;
import express from "express";
import { Client } from "./client/index.js";
import { SSEClientTransport } from "./client/sse.js";
import { StdioClientTransport } from "./client/stdio.js";
import { WebSocketClientTransport } from "./client/websocket.js";
import { Server } from "./server/index.js";
import { SSEServerTransport } from "./server/sse.js";
import { StdioServerTransport } from "./server/stdio.js";
import { ListResourcesResultSchema } from "./types.js";
async function runClient(url_or_command, args) {
const client = new Client({
name: "mcp-typescript test client",
version: "0.1.0",
}, {
capabilities: {
sampling: {},
},
});
let clientTransport;
let url = undefined;
try {
url = new URL(url_or_command);
}
catch (_a) {
// Ignore
}
if ((url === null || url === void 0 ? void 0 : url.protocol) === "http:" || (url === null || url === void 0 ? void 0 : url.protocol) === "https:") {
clientTransport = new SSEClientTransport(new URL(url_or_command));
}
else if ((url === null || url === void 0 ? void 0 : url.protocol) === "ws:" || (url === null || url === void 0 ? void 0 : url.protocol) === "wss:") {
clientTransport = new WebSocketClientTransport(new URL(url_or_command));
}
else {
clientTransport = new StdioClientTransport({
command: url_or_command,
args,
});
}
console.log("Connected to server.");
await client.connect(clientTransport);
console.log("Initialized.");
await client.request({ method: "resources/list" }, ListResourcesResultSchema);
await client.close();
console.log("Closed.");
}
async function runServer(port) {
if (port !== null) {
const app = express();
let servers = [];
app.get("/sse", async (req, res) => {
console.log("Got new SSE connection");
const transport = new SSEServerTransport("/message", res);
const server = new Server({
name: "mcp-typescript test server",
version: "0.1.0",
}, {
capabilities: {},
});
servers.push(server);
server.onclose = () => {
console.log("SSE connection closed");
servers = servers.filter((s) => s !== server);
};
await server.connect(transport);
});
app.post("/message", async (req, res) => {
console.log("Received message");
const sessionId = req.query.sessionId;
const transport = servers
.map((s) => s.transport)
.find((t) => t.sessionId === sessionId);
if (!transport) {
res.status(404).send("Session not found");
return;
}
await transport.handlePostMessage(req, res);
});
app.listen(port, () => {
console.log(`Server running on http://localhost:${port}/sse`);
});
}
else {
const server = new Server({
name: "mcp-typescript test server",
version: "0.1.0",
}, {
capabilities: {
prompts: {},
resources: {},
tools: {},
logging: {},
},
});
const transport = new StdioServerTransport();
await server.connect(transport);
console.log("Server running on stdio");
}
}
const args = process.argv.slice(2);
const command = args[0];
switch (command) {
case "client":
if (args.length < 2) {
console.error("Usage: client <server_url_or_command> [args...]");
process.exit(1);
}
runClient(args[1], args.slice(2)).catch((error) => {
console.error(error);
process.exit(1);
});
break;
case "server": {
const port = args[1] ? parseInt(args[1]) : null;
runServer(port).catch((error) => {
console.error(error);
process.exit(1);
});
break;
}
default:
console.error("Unrecognized command:", command);
}
//# sourceMappingURL=cli.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,773 @@
import { Protocol, ProtocolOptions, RequestOptions } from "../shared/protocol.js";
import { Transport } from "../shared/transport.js";
import { CallToolRequest, CallToolResultSchema, ClientCapabilities, ClientNotification, ClientRequest, ClientResult, CompatibilityCallToolResultSchema, CompleteRequest, GetPromptRequest, Implementation, ListPromptsRequest, ListResourcesRequest, ListResourceTemplatesRequest, ListToolsRequest, LoggingLevel, Notification, ReadResourceRequest, Request, Result, ServerCapabilities, SubscribeRequest, UnsubscribeRequest } from "../types.js";
export type ClientOptions = ProtocolOptions & {
/**
* Capabilities to advertise as being supported by this client.
*/
capabilities: ClientCapabilities;
};
/**
* An MCP client on top of a pluggable transport.
*
* The client will automatically begin the initialization flow with the server when connect() is called.
*
* To use with custom types, extend the base Request/Notification/Result types and pass them as type parameters:
*
* ```typescript
* // Custom schemas
* const CustomRequestSchema = RequestSchema.extend({...})
* const CustomNotificationSchema = NotificationSchema.extend({...})
* const CustomResultSchema = ResultSchema.extend({...})
*
* // Type aliases
* type CustomRequest = z.infer<typeof CustomRequestSchema>
* type CustomNotification = z.infer<typeof CustomNotificationSchema>
* type CustomResult = z.infer<typeof CustomResultSchema>
*
* // Create typed client
* const client = new Client<CustomRequest, CustomNotification, CustomResult>({
* name: "CustomClient",
* version: "1.0.0"
* })
* ```
*/
export declare class Client<RequestT extends Request = Request, NotificationT extends Notification = Notification, ResultT extends Result = Result> extends Protocol<ClientRequest | RequestT, ClientNotification | NotificationT, ClientResult | ResultT> {
private _clientInfo;
private _serverCapabilities?;
private _serverVersion?;
private _capabilities;
/**
* Initializes this client with the given name and version information.
*/
constructor(_clientInfo: Implementation, options: ClientOptions);
protected assertCapability(capability: keyof ServerCapabilities, method: string): void;
connect(transport: Transport): Promise<void>;
/**
* After initialization has completed, this will be populated with the server's reported capabilities.
*/
getServerCapabilities(): ServerCapabilities | undefined;
/**
* After initialization has completed, this will be populated with information about the server's name and version.
*/
getServerVersion(): Implementation | undefined;
protected assertCapabilityForMethod(method: RequestT["method"]): void;
protected assertNotificationCapability(method: NotificationT["method"]): void;
protected assertRequestHandlerCapability(method: string): void;
ping(): Promise<{
_meta?: import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough"> | undefined;
}>;
complete(params: CompleteRequest["params"], options?: RequestOptions): Promise<import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
_meta: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, {
completion: import("zod").ZodObject<{
values: import("zod").ZodArray<import("zod").ZodString, "many">;
total: import("zod").ZodOptional<import("zod").ZodNumber>;
hasMore: import("zod").ZodOptional<import("zod").ZodBoolean>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
values: import("zod").ZodArray<import("zod").ZodString, "many">;
total: import("zod").ZodOptional<import("zod").ZodNumber>;
hasMore: import("zod").ZodOptional<import("zod").ZodBoolean>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
values: import("zod").ZodArray<import("zod").ZodString, "many">;
total: import("zod").ZodOptional<import("zod").ZodNumber>;
hasMore: import("zod").ZodOptional<import("zod").ZodBoolean>;
}, import("zod").ZodTypeAny, "passthrough">>;
}>, import("zod").ZodTypeAny, "passthrough">>;
setLoggingLevel(level: LoggingLevel): Promise<{
_meta?: import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough"> | undefined;
}>;
getPrompt(params: GetPromptRequest["params"], options?: RequestOptions): Promise<import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
_meta: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, {
description: import("zod").ZodOptional<import("zod").ZodString>;
messages: import("zod").ZodArray<import("zod").ZodObject<{
role: import("zod").ZodEnum<["user", "assistant"]>;
content: import("zod").ZodUnion<[import("zod").ZodObject<{
type: import("zod").ZodLiteral<"text">;
text: import("zod").ZodString;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"text">;
text: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"text">;
text: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<{
type: import("zod").ZodLiteral<"image">;
data: import("zod").ZodString;
mimeType: import("zod").ZodString;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"image">;
data: import("zod").ZodString;
mimeType: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"image">;
data: import("zod").ZodString;
mimeType: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<{
type: import("zod").ZodLiteral<"resource">;
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>]>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"resource">;
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>]>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"resource">;
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>]>;
}, import("zod").ZodTypeAny, "passthrough">>]>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
role: import("zod").ZodEnum<["user", "assistant"]>;
content: import("zod").ZodUnion<[import("zod").ZodObject<{
type: import("zod").ZodLiteral<"text">;
text: import("zod").ZodString;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"text">;
text: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"text">;
text: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<{
type: import("zod").ZodLiteral<"image">;
data: import("zod").ZodString;
mimeType: import("zod").ZodString;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"image">;
data: import("zod").ZodString;
mimeType: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"image">;
data: import("zod").ZodString;
mimeType: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<{
type: import("zod").ZodLiteral<"resource">;
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>]>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"resource">;
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>]>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"resource">;
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>]>;
}, import("zod").ZodTypeAny, "passthrough">>]>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
role: import("zod").ZodEnum<["user", "assistant"]>;
content: import("zod").ZodUnion<[import("zod").ZodObject<{
type: import("zod").ZodLiteral<"text">;
text: import("zod").ZodString;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"text">;
text: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"text">;
text: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<{
type: import("zod").ZodLiteral<"image">;
data: import("zod").ZodString;
mimeType: import("zod").ZodString;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"image">;
data: import("zod").ZodString;
mimeType: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"image">;
data: import("zod").ZodString;
mimeType: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<{
type: import("zod").ZodLiteral<"resource">;
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>]>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"resource">;
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>]>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"resource">;
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>]>;
}, import("zod").ZodTypeAny, "passthrough">>]>;
}, import("zod").ZodTypeAny, "passthrough">>, "many">;
}>, import("zod").ZodTypeAny, "passthrough">>;
listPrompts(params?: ListPromptsRequest["params"], options?: RequestOptions): Promise<import("zod").objectOutputType<import("zod").objectUtil.extendShape<import("zod").objectUtil.extendShape<{
_meta: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, {
nextCursor: import("zod").ZodOptional<import("zod").ZodString>;
}>, {
prompts: import("zod").ZodArray<import("zod").ZodObject<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
arguments: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodObject<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
required: import("zod").ZodOptional<import("zod").ZodBoolean>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
required: import("zod").ZodOptional<import("zod").ZodBoolean>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
required: import("zod").ZodOptional<import("zod").ZodBoolean>;
}, import("zod").ZodTypeAny, "passthrough">>, "many">>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
arguments: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodObject<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
required: import("zod").ZodOptional<import("zod").ZodBoolean>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
required: import("zod").ZodOptional<import("zod").ZodBoolean>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
required: import("zod").ZodOptional<import("zod").ZodBoolean>;
}, import("zod").ZodTypeAny, "passthrough">>, "many">>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
arguments: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodObject<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
required: import("zod").ZodOptional<import("zod").ZodBoolean>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
required: import("zod").ZodOptional<import("zod").ZodBoolean>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
required: import("zod").ZodOptional<import("zod").ZodBoolean>;
}, import("zod").ZodTypeAny, "passthrough">>, "many">>;
}, import("zod").ZodTypeAny, "passthrough">>, "many">;
}>, import("zod").ZodTypeAny, "passthrough">>;
listResources(params?: ListResourcesRequest["params"], options?: RequestOptions): Promise<import("zod").objectOutputType<import("zod").objectUtil.extendShape<import("zod").objectUtil.extendShape<{
_meta: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, {
nextCursor: import("zod").ZodOptional<import("zod").ZodString>;
}>, {
resources: import("zod").ZodArray<import("zod").ZodObject<{
uri: import("zod").ZodString;
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
uri: import("zod").ZodString;
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
uri: import("zod").ZodString;
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod").ZodTypeAny, "passthrough">>, "many">;
}>, import("zod").ZodTypeAny, "passthrough">>;
listResourceTemplates(params?: ListResourceTemplatesRequest["params"], options?: RequestOptions): Promise<import("zod").objectOutputType<import("zod").objectUtil.extendShape<import("zod").objectUtil.extendShape<{
_meta: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, {
nextCursor: import("zod").ZodOptional<import("zod").ZodString>;
}>, {
resourceTemplates: import("zod").ZodArray<import("zod").ZodObject<{
uriTemplate: import("zod").ZodString;
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
uriTemplate: import("zod").ZodString;
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
uriTemplate: import("zod").ZodString;
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod").ZodTypeAny, "passthrough">>, "many">;
}>, import("zod").ZodTypeAny, "passthrough">>;
readResource(params: ReadResourceRequest["params"], options?: RequestOptions): Promise<import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
_meta: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, {
contents: import("zod").ZodArray<import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>]>, "many">;
}>, import("zod").ZodTypeAny, "passthrough">>;
subscribeResource(params: SubscribeRequest["params"]): Promise<{
_meta?: import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough"> | undefined;
}>;
unsubscribeResource(params: UnsubscribeRequest["params"]): Promise<{
_meta?: import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough"> | undefined;
}>;
callTool(params: CallToolRequest["params"], resultSchema?: typeof CallToolResultSchema | typeof CompatibilityCallToolResultSchema, options?: RequestOptions): Promise<import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
_meta: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, {
content: import("zod").ZodArray<import("zod").ZodUnion<[import("zod").ZodObject<{
type: import("zod").ZodLiteral<"text">;
text: import("zod").ZodString;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"text">;
text: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"text">;
text: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<{
type: import("zod").ZodLiteral<"image">;
data: import("zod").ZodString;
mimeType: import("zod").ZodString;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"image">;
data: import("zod").ZodString;
mimeType: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"image">;
data: import("zod").ZodString;
mimeType: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<{
type: import("zod").ZodLiteral<"resource">;
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>]>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"resource">;
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>]>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"resource">;
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
text: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
uri: import("zod").ZodString;
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
}, {
blob: import("zod").ZodString;
}>, import("zod").ZodTypeAny, "passthrough">>]>;
}, import("zod").ZodTypeAny, "passthrough">>]>, "many">;
isError: import("zod").ZodOptional<import("zod").ZodDefault<import("zod").ZodBoolean>>;
}>, import("zod").ZodTypeAny, "passthrough"> | import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
_meta: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, {
toolResult: import("zod").ZodUnknown;
}>, import("zod").ZodTypeAny, "passthrough">>;
listTools(params?: ListToolsRequest["params"], options?: RequestOptions): Promise<import("zod").objectOutputType<import("zod").objectUtil.extendShape<import("zod").objectUtil.extendShape<{
_meta: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, {
nextCursor: import("zod").ZodOptional<import("zod").ZodString>;
}>, {
tools: import("zod").ZodArray<import("zod").ZodObject<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
inputSchema: import("zod").ZodObject<{
type: import("zod").ZodLiteral<"object">;
properties: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"object">;
properties: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"object">;
properties: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, import("zod").ZodTypeAny, "passthrough">>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
inputSchema: import("zod").ZodObject<{
type: import("zod").ZodLiteral<"object">;
properties: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"object">;
properties: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"object">;
properties: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, import("zod").ZodTypeAny, "passthrough">>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
inputSchema: import("zod").ZodObject<{
type: import("zod").ZodLiteral<"object">;
properties: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"object">;
properties: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"object">;
properties: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, import("zod").ZodTypeAny, "passthrough">>;
}, import("zod").ZodTypeAny, "passthrough">>, "many">;
}>, import("zod").ZodTypeAny, "passthrough">>;
sendRootsListChanged(): Promise<void>;
}
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,206 @@
import { Protocol, } from "../shared/protocol.js";
import { CallToolResultSchema, CompleteResultSchema, EmptyResultSchema, GetPromptResultSchema, InitializeResultSchema, LATEST_PROTOCOL_VERSION, ListPromptsResultSchema, ListResourcesResultSchema, ListResourceTemplatesResultSchema, ListToolsResultSchema, ReadResourceResultSchema, SUPPORTED_PROTOCOL_VERSIONS, } from "../types.js";
/**
* An MCP client on top of a pluggable transport.
*
* The client will automatically begin the initialization flow with the server when connect() is called.
*
* To use with custom types, extend the base Request/Notification/Result types and pass them as type parameters:
*
* ```typescript
* // Custom schemas
* const CustomRequestSchema = RequestSchema.extend({...})
* const CustomNotificationSchema = NotificationSchema.extend({...})
* const CustomResultSchema = ResultSchema.extend({...})
*
* // Type aliases
* type CustomRequest = z.infer<typeof CustomRequestSchema>
* type CustomNotification = z.infer<typeof CustomNotificationSchema>
* type CustomResult = z.infer<typeof CustomResultSchema>
*
* // Create typed client
* const client = new Client<CustomRequest, CustomNotification, CustomResult>({
* name: "CustomClient",
* version: "1.0.0"
* })
* ```
*/
export class Client extends Protocol {
/**
* Initializes this client with the given name and version information.
*/
constructor(_clientInfo, options) {
super(options);
this._clientInfo = _clientInfo;
this._capabilities = options.capabilities;
}
assertCapability(capability, method) {
var _a;
if (!((_a = this._serverCapabilities) === null || _a === void 0 ? void 0 : _a[capability])) {
throw new Error(`Server does not support ${capability} (required for ${method})`);
}
}
async connect(transport) {
await super.connect(transport);
try {
const result = await this.request({
method: "initialize",
params: {
protocolVersion: LATEST_PROTOCOL_VERSION,
capabilities: this._capabilities,
clientInfo: this._clientInfo,
},
}, InitializeResultSchema);
if (result === undefined) {
throw new Error(`Server sent invalid initialize result: ${result}`);
}
if (!SUPPORTED_PROTOCOL_VERSIONS.includes(result.protocolVersion)) {
throw new Error(`Server's protocol version is not supported: ${result.protocolVersion}`);
}
this._serverCapabilities = result.capabilities;
this._serverVersion = result.serverInfo;
await this.notification({
method: "notifications/initialized",
});
}
catch (error) {
// Disconnect if initialization fails.
void this.close();
throw error;
}
}
/**
* After initialization has completed, this will be populated with the server's reported capabilities.
*/
getServerCapabilities() {
return this._serverCapabilities;
}
/**
* After initialization has completed, this will be populated with information about the server's name and version.
*/
getServerVersion() {
return this._serverVersion;
}
assertCapabilityForMethod(method) {
var _a, _b, _c, _d, _e;
switch (method) {
case "logging/setLevel":
if (!((_a = this._serverCapabilities) === null || _a === void 0 ? void 0 : _a.logging)) {
throw new Error(`Server does not support logging (required for ${method})`);
}
break;
case "prompts/get":
case "prompts/list":
if (!((_b = this._serverCapabilities) === null || _b === void 0 ? void 0 : _b.prompts)) {
throw new Error(`Server does not support prompts (required for ${method})`);
}
break;
case "resources/list":
case "resources/templates/list":
case "resources/read":
case "resources/subscribe":
case "resources/unsubscribe":
if (!((_c = this._serverCapabilities) === null || _c === void 0 ? void 0 : _c.resources)) {
throw new Error(`Server does not support resources (required for ${method})`);
}
if (method === "resources/subscribe" &&
!this._serverCapabilities.resources.subscribe) {
throw new Error(`Server does not support resource subscriptions (required for ${method})`);
}
break;
case "tools/call":
case "tools/list":
if (!((_d = this._serverCapabilities) === null || _d === void 0 ? void 0 : _d.tools)) {
throw new Error(`Server does not support tools (required for ${method})`);
}
break;
case "completion/complete":
if (!((_e = this._serverCapabilities) === null || _e === void 0 ? void 0 : _e.prompts)) {
throw new Error(`Server does not support prompts (required for ${method})`);
}
break;
case "initialize":
// No specific capability required for initialize
break;
case "ping":
// No specific capability required for ping
break;
}
}
assertNotificationCapability(method) {
var _a;
switch (method) {
case "notifications/roots/list_changed":
if (!((_a = this._capabilities.roots) === null || _a === void 0 ? void 0 : _a.listChanged)) {
throw new Error(`Client does not support roots list changed notifications (required for ${method})`);
}
break;
case "notifications/initialized":
// No specific capability required for initialized
break;
case "notifications/cancelled":
// Cancellation notifications are always allowed
break;
case "notifications/progress":
// Progress notifications are always allowed
break;
}
}
assertRequestHandlerCapability(method) {
switch (method) {
case "sampling/createMessage":
if (!this._capabilities.sampling) {
throw new Error(`Client does not support sampling capability (required for ${method})`);
}
break;
case "roots/list":
if (!this._capabilities.roots) {
throw new Error(`Client does not support roots capability (required for ${method})`);
}
break;
case "ping":
// No specific capability required for ping
break;
}
}
async ping() {
return this.request({ method: "ping" }, EmptyResultSchema);
}
async complete(params, options) {
return this.request({ method: "completion/complete", params }, CompleteResultSchema, options);
}
async setLoggingLevel(level) {
return this.request({ method: "logging/setLevel", params: { level } }, EmptyResultSchema);
}
async getPrompt(params, options) {
return this.request({ method: "prompts/get", params }, GetPromptResultSchema, options);
}
async listPrompts(params, options) {
return this.request({ method: "prompts/list", params }, ListPromptsResultSchema, options);
}
async listResources(params, options) {
return this.request({ method: "resources/list", params }, ListResourcesResultSchema, options);
}
async listResourceTemplates(params, options) {
return this.request({ method: "resources/templates/list", params }, ListResourceTemplatesResultSchema, options);
}
async readResource(params, options) {
return this.request({ method: "resources/read", params }, ReadResourceResultSchema, options);
}
async subscribeResource(params) {
return this.request({ method: "resources/subscribe", params }, EmptyResultSchema);
}
async unsubscribeResource(params) {
return this.request({ method: "resources/unsubscribe", params }, EmptyResultSchema);
}
async callTool(params, resultSchema = CallToolResultSchema, options) {
return this.request({ method: "tools/call", params }, resultSchema, options);
}
async listTools(params, options) {
return this.request({ method: "tools/list", params }, ListToolsResultSchema, options);
}
async sendRootsListChanged() {
return this.notification({ method: "notifications/roots/list_changed" });
}
}
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=index.test.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../src/client/index.test.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,357 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-constant-binary-expression */
/* eslint-disable @typescript-eslint/no-unused-expressions */
import { Client } from "./index.js";
import { z } from "zod";
import { RequestSchema, NotificationSchema, ResultSchema, LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, InitializeRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, CreateMessageRequestSchema, ListRootsRequestSchema, } from "../types.js";
import { Server } from "../server/index.js";
import { InMemoryTransport } from "../inMemory.js";
test("should initialize with matching protocol version", async () => {
const clientTransport = {
start: jest.fn().mockResolvedValue(undefined),
close: jest.fn().mockResolvedValue(undefined),
send: jest.fn().mockImplementation((message) => {
var _a;
if (message.method === "initialize") {
(_a = clientTransport.onmessage) === null || _a === void 0 ? void 0 : _a.call(clientTransport, {
jsonrpc: "2.0",
id: message.id,
result: {
protocolVersion: LATEST_PROTOCOL_VERSION,
capabilities: {},
serverInfo: {
name: "test",
version: "1.0",
},
},
});
}
return Promise.resolve();
}),
};
const client = new Client({
name: "test client",
version: "1.0",
}, {
capabilities: {
sampling: {},
},
});
await client.connect(clientTransport);
// Should have sent initialize with latest version
expect(clientTransport.send).toHaveBeenCalledWith(expect.objectContaining({
method: "initialize",
params: expect.objectContaining({
protocolVersion: LATEST_PROTOCOL_VERSION,
}),
}));
});
test("should initialize with supported older protocol version", async () => {
const OLD_VERSION = SUPPORTED_PROTOCOL_VERSIONS[1];
const clientTransport = {
start: jest.fn().mockResolvedValue(undefined),
close: jest.fn().mockResolvedValue(undefined),
send: jest.fn().mockImplementation((message) => {
var _a;
if (message.method === "initialize") {
(_a = clientTransport.onmessage) === null || _a === void 0 ? void 0 : _a.call(clientTransport, {
jsonrpc: "2.0",
id: message.id,
result: {
protocolVersion: OLD_VERSION,
capabilities: {},
serverInfo: {
name: "test",
version: "1.0",
},
},
});
}
return Promise.resolve();
}),
};
const client = new Client({
name: "test client",
version: "1.0",
}, {
capabilities: {
sampling: {},
},
});
await client.connect(clientTransport);
// Connection should succeed with the older version
expect(client.getServerVersion()).toEqual({
name: "test",
version: "1.0",
});
});
test("should reject unsupported protocol version", async () => {
const clientTransport = {
start: jest.fn().mockResolvedValue(undefined),
close: jest.fn().mockResolvedValue(undefined),
send: jest.fn().mockImplementation((message) => {
var _a;
if (message.method === "initialize") {
(_a = clientTransport.onmessage) === null || _a === void 0 ? void 0 : _a.call(clientTransport, {
jsonrpc: "2.0",
id: message.id,
result: {
protocolVersion: "invalid-version",
capabilities: {},
serverInfo: {
name: "test",
version: "1.0",
},
},
});
}
return Promise.resolve();
}),
};
const client = new Client({
name: "test client",
version: "1.0",
}, {
capabilities: {
sampling: {},
},
});
await expect(client.connect(clientTransport)).rejects.toThrow("Server's protocol version is not supported: invalid-version");
expect(clientTransport.close).toHaveBeenCalled();
});
test("should respect server capabilities", async () => {
const server = new Server({
name: "test server",
version: "1.0",
}, {
capabilities: {
resources: {},
tools: {},
},
});
server.setRequestHandler(InitializeRequestSchema, (_request) => ({
protocolVersion: LATEST_PROTOCOL_VERSION,
capabilities: {
resources: {},
tools: {},
},
serverInfo: {
name: "test",
version: "1.0",
},
}));
server.setRequestHandler(ListResourcesRequestSchema, () => ({
resources: [],
}));
server.setRequestHandler(ListToolsRequestSchema, () => ({
tools: [],
}));
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
const client = new Client({
name: "test client",
version: "1.0",
}, {
capabilities: {
sampling: {},
},
enforceStrictCapabilities: true,
});
await Promise.all([
client.connect(clientTransport),
server.connect(serverTransport),
]);
// Server supports resources and tools, but not prompts
expect(client.getServerCapabilities()).toEqual({
resources: {},
tools: {},
});
// These should work
await expect(client.listResources()).resolves.not.toThrow();
await expect(client.listTools()).resolves.not.toThrow();
// This should throw because prompts are not supported
await expect(client.listPrompts()).rejects.toThrow("Server does not support prompts");
});
test("should respect client notification capabilities", async () => {
const server = new Server({
name: "test server",
version: "1.0",
}, {
capabilities: {},
});
const client = new Client({
name: "test client",
version: "1.0",
}, {
capabilities: {
roots: {
listChanged: true,
},
},
});
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
await Promise.all([
client.connect(clientTransport),
server.connect(serverTransport),
]);
// This should work because the client has the roots.listChanged capability
await expect(client.sendRootsListChanged()).resolves.not.toThrow();
// Create a new client without the roots.listChanged capability
const clientWithoutCapability = new Client({
name: "test client without capability",
version: "1.0",
}, {
capabilities: {},
enforceStrictCapabilities: true,
});
await clientWithoutCapability.connect(clientTransport);
// This should throw because the client doesn't have the roots.listChanged capability
await expect(clientWithoutCapability.sendRootsListChanged()).rejects.toThrow(/^Client does not support/);
});
test("should respect server notification capabilities", async () => {
const server = new Server({
name: "test server",
version: "1.0",
}, {
capabilities: {
logging: {},
resources: {
listChanged: true,
},
},
});
const client = new Client({
name: "test client",
version: "1.0",
}, {
capabilities: {},
});
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
await Promise.all([
client.connect(clientTransport),
server.connect(serverTransport),
]);
// These should work because the server has the corresponding capabilities
await expect(server.sendLoggingMessage({ level: "info", data: "Test" })).resolves.not.toThrow();
await expect(server.sendResourceListChanged()).resolves.not.toThrow();
// This should throw because the server doesn't have the tools capability
await expect(server.sendToolListChanged()).rejects.toThrow("Server does not support notifying of tool list changes");
});
test("should only allow setRequestHandler for declared capabilities", () => {
const client = new Client({
name: "test client",
version: "1.0",
}, {
capabilities: {
sampling: {},
},
});
// This should work because sampling is a declared capability
expect(() => {
client.setRequestHandler(CreateMessageRequestSchema, () => ({
model: "test-model",
role: "assistant",
content: {
type: "text",
text: "Test response",
},
}));
}).not.toThrow();
// This should throw because roots listing is not a declared capability
expect(() => {
client.setRequestHandler(ListRootsRequestSchema, () => ({}));
}).toThrow("Client does not support roots capability");
});
/*
Test that custom request/notification/result schemas can be used with the Client class.
*/
test("should typecheck", () => {
const GetWeatherRequestSchema = RequestSchema.extend({
method: z.literal("weather/get"),
params: z.object({
city: z.string(),
}),
});
const GetForecastRequestSchema = RequestSchema.extend({
method: z.literal("weather/forecast"),
params: z.object({
city: z.string(),
days: z.number(),
}),
});
const WeatherForecastNotificationSchema = NotificationSchema.extend({
method: z.literal("weather/alert"),
params: z.object({
severity: z.enum(["warning", "watch"]),
message: z.string(),
}),
});
const WeatherRequestSchema = GetWeatherRequestSchema.or(GetForecastRequestSchema);
const WeatherNotificationSchema = WeatherForecastNotificationSchema;
const WeatherResultSchema = ResultSchema.extend({
temperature: z.number(),
conditions: z.string(),
});
// Create a typed Client for weather data
const weatherClient = new Client({
name: "WeatherClient",
version: "1.0.0",
}, {
capabilities: {
sampling: {},
},
});
// Typecheck that only valid weather requests/notifications/results are allowed
false &&
weatherClient.request({
method: "weather/get",
params: {
city: "Seattle",
},
}, WeatherResultSchema);
false &&
weatherClient.notification({
method: "weather/alert",
params: {
severity: "warning",
message: "Storm approaching",
},
});
});
test("should handle client cancelling a request", async () => {
const server = new Server({
name: "test server",
version: "1.0",
}, {
capabilities: {
resources: {},
},
});
// Set up server to delay responding to listResources
server.setRequestHandler(ListResourcesRequestSchema, async (request, extra) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
return {
resources: [],
};
});
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
const client = new Client({
name: "test client",
version: "1.0",
}, {
capabilities: {},
});
await Promise.all([
client.connect(clientTransport),
server.connect(serverTransport),
]);
// Set up abort controller
const controller = new AbortController();
// Issue request but cancel it immediately
const listResourcesPromise = client.listResources(undefined, {
signal: controller.signal,
});
controller.abort("Cancelled by test");
// Request should be rejected
await expect(listResourcesPromise).rejects.toBe("Cancelled by test");
});
//# sourceMappingURL=index.test.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,22 @@
import { Transport } from "../shared/transport.js";
import { JSONRPCMessage } from "../types.js";
/**
* Client transport for SSE: this will connect to a server using Server-Sent Events for receiving
* messages and make separate POST requests for sending messages.
*
* This uses the EventSource API in browsers. You can install the `eventsource` package for Node.js.
*/
export declare class SSEClientTransport implements Transport {
private _eventSource?;
private _endpoint?;
private _abortController?;
private _url;
onclose?: () => void;
onerror?: (error: Error) => void;
onmessage?: (message: JSONRPCMessage) => void;
constructor(url: URL);
start(): Promise<void>;
close(): Promise<void>;
send(message: JSONRPCMessage): Promise<void>;
}
//# sourceMappingURL=sse.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/client/sse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAwB,MAAM,aAAa,CAAC;AAEnE;;;;;GAKG;AACH,qBAAa,kBAAmB,YAAW,SAAS;IAClD,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,SAAS,CAAC,CAAM;IACxB,OAAO,CAAC,gBAAgB,CAAC,CAAkB;IAC3C,OAAO,CAAC,IAAI,CAAM;IAElB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;gBAElC,GAAG,EAAE,GAAG;IAIpB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAyDhB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CA0BnD"}

View File

@@ -0,0 +1,91 @@
import { JSONRPCMessageSchema } from "../types.js";
/**
* Client transport for SSE: this will connect to a server using Server-Sent Events for receiving
* messages and make separate POST requests for sending messages.
*
* This uses the EventSource API in browsers. You can install the `eventsource` package for Node.js.
*/
export class SSEClientTransport {
constructor(url) {
this._url = url;
}
start() {
if (this._eventSource) {
throw new Error("SSEClientTransport already started! If using Client class, note that connect() calls start() automatically.");
}
return new Promise((resolve, reject) => {
this._eventSource = new EventSource(this._url.href);
this._abortController = new AbortController();
this._eventSource.onerror = (event) => {
var _a;
const error = new Error(`SSE error: ${JSON.stringify(event)}`);
reject(error);
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
};
this._eventSource.onopen = () => {
// The connection is open, but we need to wait for the endpoint to be received.
};
this._eventSource.addEventListener("endpoint", (event) => {
var _a;
const messageEvent = event;
try {
this._endpoint = new URL(messageEvent.data, this._url);
if (this._endpoint.origin !== this._url.origin) {
throw new Error(`Endpoint origin does not match connection origin: ${this._endpoint.origin}`);
}
}
catch (error) {
reject(error);
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
void this.close();
return;
}
resolve();
});
this._eventSource.onmessage = (event) => {
var _a, _b;
const messageEvent = event;
let message;
try {
message = JSONRPCMessageSchema.parse(JSON.parse(messageEvent.data));
}
catch (error) {
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
return;
}
(_b = this.onmessage) === null || _b === void 0 ? void 0 : _b.call(this, message);
};
});
}
async close() {
var _a, _b, _c;
(_a = this._abortController) === null || _a === void 0 ? void 0 : _a.abort();
(_b = this._eventSource) === null || _b === void 0 ? void 0 : _b.close();
(_c = this.onclose) === null || _c === void 0 ? void 0 : _c.call(this);
}
async send(message) {
var _a, _b;
if (!this._endpoint) {
throw new Error("Not connected");
}
try {
const response = await fetch(this._endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(message),
signal: (_a = this._abortController) === null || _a === void 0 ? void 0 : _a.signal,
});
if (!response.ok) {
const text = await response.text().catch(() => null);
throw new Error(`Error POSTing to endpoint (HTTP ${response.status}): ${text}`);
}
}
catch (error) {
(_b = this.onerror) === null || _b === void 0 ? void 0 : _b.call(this, error);
throw error;
}
}
}
//# sourceMappingURL=sse.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/client/sse.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,56 @@
import { JSONRPCMessage } from "../types.js";
import { Transport } from "../shared/transport.js";
import { Stream } from "node:stream";
export type StdioServerParameters = {
/**
* The executable to run to start the server.
*/
command: string;
/**
* Command line arguments to pass to the executable.
*/
args?: string[];
/**
* The environment to use when spawning the process.
*
* If not specified, the result of getDefaultEnvironment() will be used.
*/
env?: Record<string, string>;
/**
* How to handle stderr of the child process. This matches the semantics of Node's `child_process.spawn`.
*
* The default is "inherit", meaning messages to stderr will be printed to the parent process's stderr.
*/
stderr?: "inherit" | "ignore" | Stream;
};
/**
* Environment variables to inherit by default, if an environment is not explicitly given.
*/
export declare const DEFAULT_INHERITED_ENV_VARS: string[];
/**
* Returns a default environment object including only environment variables deemed safe to inherit.
*/
export declare function getDefaultEnvironment(): Record<string, string>;
/**
* Client transport for stdio: this will connect to a server by spawning a process and communicating with it over stdin/stdout.
*
* This transport is only available in Node.js environments.
*/
export declare class StdioClientTransport implements Transport {
private _process?;
private _abortController;
private _readBuffer;
private _serverParams;
onclose?: () => void;
onerror?: (error: Error) => void;
onmessage?: (message: JSONRPCMessage) => void;
constructor(server: StdioServerParameters);
/**
* Starts the server process and prepares to communicate with it.
*/
start(): Promise<void>;
private processReadBuffer;
close(): Promise<void>;
send(message: JSONRPCMessage): Promise<void>;
}
//# sourceMappingURL=stdio.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/client/stdio.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE7B;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;CACxC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B,UAgBmB,CAAC;AAE3D;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkB9D;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,YAAW,SAAS;IACpD,OAAO,CAAC,QAAQ,CAAC,CAAe;IAChC,OAAO,CAAC,gBAAgB,CAA0C;IAClE,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,aAAa,CAAwB;IAE7C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;gBAElC,MAAM,EAAE,qBAAqB;IAIzC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsD5B,OAAO,CAAC,iBAAiB;IAenB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAc7C"}

View File

@@ -0,0 +1,135 @@
import { spawn } from "node:child_process";
import process from "node:process";
import { ReadBuffer, serializeMessage } from "../shared/stdio.js";
/**
* Environment variables to inherit by default, if an environment is not explicitly given.
*/
export const DEFAULT_INHERITED_ENV_VARS = process.platform === "win32"
? [
"APPDATA",
"HOMEDRIVE",
"HOMEPATH",
"LOCALAPPDATA",
"PATH",
"PROCESSOR_ARCHITECTURE",
"SYSTEMDRIVE",
"SYSTEMROOT",
"TEMP",
"USERNAME",
"USERPROFILE",
]
: /* list inspired by the default env inheritance of sudo */
["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER"];
/**
* Returns a default environment object including only environment variables deemed safe to inherit.
*/
export function getDefaultEnvironment() {
const env = {};
for (const key of DEFAULT_INHERITED_ENV_VARS) {
const value = process.env[key];
if (value === undefined) {
continue;
}
if (value.startsWith("()")) {
// Skip functions, which are a security risk.
continue;
}
env[key] = value;
}
return env;
}
/**
* Client transport for stdio: this will connect to a server by spawning a process and communicating with it over stdin/stdout.
*
* This transport is only available in Node.js environments.
*/
export class StdioClientTransport {
constructor(server) {
this._abortController = new AbortController();
this._readBuffer = new ReadBuffer();
this._serverParams = server;
}
/**
* Starts the server process and prepares to communicate with it.
*/
async start() {
if (this._process) {
throw new Error("StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.");
}
return new Promise((resolve, reject) => {
var _a, _b, _c, _d, _e, _f;
this._process = spawn(this._serverParams.command, (_a = this._serverParams.args) !== null && _a !== void 0 ? _a : [], {
env: (_b = this._serverParams.env) !== null && _b !== void 0 ? _b : getDefaultEnvironment(),
stdio: ["pipe", "pipe", (_c = this._serverParams.stderr) !== null && _c !== void 0 ? _c : "inherit"],
shell: false,
signal: this._abortController.signal,
});
this._process.on("error", (error) => {
var _a, _b;
if (error.name === "AbortError") {
// Expected when close() is called.
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
return;
}
reject(error);
(_b = this.onerror) === null || _b === void 0 ? void 0 : _b.call(this, error);
});
this._process.on("spawn", () => {
resolve();
});
this._process.on("close", (_code) => {
var _a;
this._process = undefined;
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
});
(_d = this._process.stdin) === null || _d === void 0 ? void 0 : _d.on("error", (error) => {
var _a;
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
});
(_e = this._process.stdout) === null || _e === void 0 ? void 0 : _e.on("data", (chunk) => {
this._readBuffer.append(chunk);
this.processReadBuffer();
});
(_f = this._process.stdout) === null || _f === void 0 ? void 0 : _f.on("error", (error) => {
var _a;
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
});
});
}
processReadBuffer() {
var _a, _b;
while (true) {
try {
const message = this._readBuffer.readMessage();
if (message === null) {
break;
}
(_a = this.onmessage) === null || _a === void 0 ? void 0 : _a.call(this, message);
}
catch (error) {
(_b = this.onerror) === null || _b === void 0 ? void 0 : _b.call(this, error);
}
}
}
async close() {
this._abortController.abort();
this._process = undefined;
this._readBuffer.clear();
}
send(message) {
return new Promise((resolve) => {
var _a;
if (!((_a = this._process) === null || _a === void 0 ? void 0 : _a.stdin)) {
throw new Error("Not connected");
}
const json = serializeMessage(message);
if (this._process.stdin.write(json)) {
resolve();
}
else {
this._process.stdin.once("drain", resolve);
}
});
}
}
//# sourceMappingURL=stdio.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/client/stdio.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=stdio.test.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stdio.test.d.ts","sourceRoot":"","sources":["../../src/client/stdio.test.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,51 @@
import { StdioClientTransport } from "./stdio.js";
const serverParameters = {
command: "/usr/bin/tee",
};
test("should start then close cleanly", async () => {
const client = new StdioClientTransport(serverParameters);
client.onerror = (error) => {
throw error;
};
let didClose = false;
client.onclose = () => {
didClose = true;
};
await client.start();
expect(didClose).toBeFalsy();
await client.close();
expect(didClose).toBeTruthy();
});
test("should read messages", async () => {
const client = new StdioClientTransport(serverParameters);
client.onerror = (error) => {
throw error;
};
const messages = [
{
jsonrpc: "2.0",
id: 1,
method: "ping",
},
{
jsonrpc: "2.0",
method: "notifications/initialized",
},
];
const readMessages = [];
const finished = new Promise((resolve) => {
client.onmessage = (message) => {
readMessages.push(message);
if (JSON.stringify(message) === JSON.stringify(messages[1])) {
resolve();
}
};
});
await client.start();
await client.send(messages[0]);
await client.send(messages[1]);
await finished;
expect(readMessages).toEqual(messages);
await client.close();
});
//# sourceMappingURL=stdio.test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stdio.test.js","sourceRoot":"","sources":["../../src/client/stdio.test.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAyB,MAAM,YAAY,CAAC;AAEzE,MAAM,gBAAgB,GAA0B;IAC9C,OAAO,EAAE,cAAc;CACxB,CAAC;AAEF,IAAI,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;IACjD,MAAM,MAAM,GAAG,IAAI,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;IAC1D,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE;QACzB,MAAM,KAAK,CAAC;IACd,CAAC,CAAC;IAEF,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;QACpB,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC,CAAC;IAEF,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACrB,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,EAAE,CAAC;IAC7B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACrB,MAAM,CAAC,QAAQ,CAAC,CAAC,UAAU,EAAE,CAAC;AAChC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;IACtC,MAAM,MAAM,GAAG,IAAI,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;IAC1D,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE;QACzB,MAAM,KAAK,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAqB;QACjC;YACE,OAAO,EAAE,KAAK;YACd,EAAE,EAAE,CAAC;YACL,MAAM,EAAE,MAAM;SACf;QACD;YACE,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,2BAA2B;SACpC;KACF,CAAC;IAEF,MAAM,YAAY,GAAqB,EAAE,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAC7C,MAAM,CAAC,SAAS,GAAG,CAAC,OAAO,EAAE,EAAE;YAC7B,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAE3B,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5D,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACrB,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,QAAQ,CAAC;IACf,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEvC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC,CAAC,CAAC"}

View File

@@ -0,0 +1,17 @@
import { Transport } from "../shared/transport.js";
import { JSONRPCMessage } from "../types.js";
/**
* Client transport for WebSocket: this will connect to a server over the WebSocket protocol.
*/
export declare class WebSocketClientTransport implements Transport {
private _socket?;
private _url;
onclose?: () => void;
onerror?: (error: Error) => void;
onmessage?: (message: JSONRPCMessage) => void;
constructor(url: URL);
start(): Promise<void>;
close(): Promise<void>;
send(message: JSONRPCMessage): Promise<void>;
}
//# sourceMappingURL=websocket.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/client/websocket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAwB,MAAM,aAAa,CAAC;AAInE;;GAEG;AACH,qBAAa,wBAAyB,YAAW,SAAS;IACxD,OAAO,CAAC,OAAO,CAAC,CAAY;IAC5B,OAAO,CAAC,IAAI,CAAM;IAElB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;gBAElC,GAAG,EAAE,GAAG;IAIpB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAyChB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAW7C"}

View File

@@ -0,0 +1,61 @@
import { JSONRPCMessageSchema } from "../types.js";
const SUBPROTOCOL = "mcp";
/**
* Client transport for WebSocket: this will connect to a server over the WebSocket protocol.
*/
export class WebSocketClientTransport {
constructor(url) {
this._url = url;
}
start() {
if (this._socket) {
throw new Error("WebSocketClientTransport already started! If using Client class, note that connect() calls start() automatically.");
}
return new Promise((resolve, reject) => {
this._socket = new WebSocket(this._url, SUBPROTOCOL);
this._socket.onerror = (event) => {
var _a;
const error = "error" in event
? event.error
: new Error(`WebSocket error: ${JSON.stringify(event)}`);
reject(error);
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
};
this._socket.onopen = () => {
resolve();
};
this._socket.onclose = () => {
var _a;
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
};
this._socket.onmessage = (event) => {
var _a, _b;
let message;
try {
message = JSONRPCMessageSchema.parse(JSON.parse(event.data));
}
catch (error) {
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
return;
}
(_b = this.onmessage) === null || _b === void 0 ? void 0 : _b.call(this, message);
};
});
}
async close() {
var _a;
(_a = this._socket) === null || _a === void 0 ? void 0 : _a.close();
}
send(message) {
return new Promise((resolve, reject) => {
var _a;
if (!this._socket) {
reject(new Error("Not connected"));
return;
}
(_a = this._socket) === null || _a === void 0 ? void 0 : _a.send(JSON.stringify(message));
resolve();
});
}
}
//# sourceMappingURL=websocket.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../src/client/websocket.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnE,MAAM,WAAW,GAAG,KAAK,CAAC;AAE1B;;GAEG;AACH,MAAM,OAAO,wBAAwB;IAQnC,YAAY,GAAQ;QAClB,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;IAClB,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,mHAAmH,CACpH,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,OAAO,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAErD,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE;;gBAC/B,MAAM,KAAK,GACT,OAAO,IAAI,KAAK;oBACd,CAAC,CAAE,KAAK,CAAC,KAAe;oBACxB,CAAC,CAAC,IAAI,KAAK,CAAC,oBAAoB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAC7D,MAAM,CAAC,KAAK,CAAC,CAAC;gBACd,MAAA,IAAI,CAAC,OAAO,qDAAG,KAAK,CAAC,CAAC;YACxB,CAAC,CAAC;YAEF,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE;gBACzB,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC;YAEF,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,GAAG,EAAE;;gBAC1B,MAAA,IAAI,CAAC,OAAO,oDAAI,CAAC;YACnB,CAAC,CAAC;YAEF,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,KAAmB,EAAE,EAAE;;gBAC/C,IAAI,OAAuB,CAAC;gBAC5B,IAAI,CAAC;oBACH,OAAO,GAAG,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC/D,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAA,IAAI,CAAC,OAAO,qDAAG,KAAc,CAAC,CAAC;oBAC/B,OAAO;gBACT,CAAC;gBAED,MAAA,IAAI,CAAC,SAAS,qDAAG,OAAO,CAAC,CAAC;YAC5B,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK;;QACT,MAAA,IAAI,CAAC,OAAO,0CAAE,KAAK,EAAE,CAAC;IACxB,CAAC;IAED,IAAI,CAAC,OAAuB;QAC1B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;;YACrC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClB,MAAM,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;gBACnC,OAAO;YACT,CAAC;YAED,MAAA,IAAI,CAAC,OAAO,0CAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;YAC5C,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}

View File

@@ -0,0 +1,20 @@
import { Transport } from "./shared/transport.js";
import { JSONRPCMessage } from "./types.js";
/**
* In-memory transport for creating clients and servers that talk to each other within the same process.
*/
export declare class InMemoryTransport implements Transport {
private _otherTransport?;
private _messageQueue;
onclose?: () => void;
onerror?: (error: Error) => void;
onmessage?: (message: JSONRPCMessage) => void;
/**
* Creates a pair of linked in-memory transports that can communicate with each other. One should be passed to a Client and one to a Server.
*/
static createLinkedPair(): [InMemoryTransport, InMemoryTransport];
start(): Promise<void>;
close(): Promise<void>;
send(message: JSONRPCMessage): Promise<void>;
}
//# sourceMappingURL=inMemory.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"inMemory.d.ts","sourceRoot":"","sources":["../src/inMemory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C;;GAEG;AACH,qBAAa,iBAAkB,YAAW,SAAS;IACjD,OAAO,CAAC,eAAe,CAAC,CAAoB;IAC5C,OAAO,CAAC,aAAa,CAAwB;IAE7C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IAE9C;;OAEG;IACH,MAAM,CAAC,gBAAgB,IAAI,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAQ3D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAUtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtB,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAWnD"}

View File

@@ -0,0 +1,47 @@
/**
* In-memory transport for creating clients and servers that talk to each other within the same process.
*/
export class InMemoryTransport {
constructor() {
this._messageQueue = [];
}
/**
* Creates a pair of linked in-memory transports that can communicate with each other. One should be passed to a Client and one to a Server.
*/
static createLinkedPair() {
const clientTransport = new InMemoryTransport();
const serverTransport = new InMemoryTransport();
clientTransport._otherTransport = serverTransport;
serverTransport._otherTransport = clientTransport;
return [clientTransport, serverTransport];
}
async start() {
var _a;
// Process any messages that were queued before start was called
while (this._messageQueue.length > 0) {
const message = this._messageQueue.shift();
if (message) {
(_a = this.onmessage) === null || _a === void 0 ? void 0 : _a.call(this, message);
}
}
}
async close() {
var _a;
const other = this._otherTransport;
this._otherTransport = undefined;
await (other === null || other === void 0 ? void 0 : other.close());
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
}
async send(message) {
if (!this._otherTransport) {
throw new Error("Not connected");
}
if (this._otherTransport.onmessage) {
this._otherTransport.onmessage(message);
}
else {
this._otherTransport._messageQueue.push(message);
}
}
}
//# sourceMappingURL=inMemory.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"inMemory.js","sourceRoot":"","sources":["../src/inMemory.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,OAAO,iBAAiB;IAA9B;QAEU,kBAAa,GAAqB,EAAE,CAAC;IA6C/C,CAAC;IAvCC;;OAEG;IACH,MAAM,CAAC,gBAAgB;QACrB,MAAM,eAAe,GAAG,IAAI,iBAAiB,EAAE,CAAC;QAChD,MAAM,eAAe,GAAG,IAAI,iBAAiB,EAAE,CAAC;QAChD,eAAe,CAAC,eAAe,GAAG,eAAe,CAAC;QAClD,eAAe,CAAC,eAAe,GAAG,eAAe,CAAC;QAClD,OAAO,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,KAAK;;QACT,gEAAgE;QAChE,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrC,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;YAC3C,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAA,IAAI,CAAC,SAAS,qDAAG,OAAO,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;;QACT,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC;QACnC,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QACjC,MAAM,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,KAAK,EAAE,CAAA,CAAC;QACrB,MAAA,IAAI,CAAC,OAAO,oDAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAuB;QAChC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QACnC,CAAC;QAED,IAAI,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,CAAC;YACnC,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;CACF"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=inMemory.test.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"inMemory.test.d.ts","sourceRoot":"","sources":["../src/inMemory.test.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,74 @@
import { InMemoryTransport } from "./inMemory.js";
describe("InMemoryTransport", () => {
let clientTransport;
let serverTransport;
beforeEach(() => {
[clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
});
test("should create linked pair", () => {
expect(clientTransport).toBeDefined();
expect(serverTransport).toBeDefined();
});
test("should start without error", async () => {
await expect(clientTransport.start()).resolves.not.toThrow();
await expect(serverTransport.start()).resolves.not.toThrow();
});
test("should send message from client to server", async () => {
const message = {
jsonrpc: "2.0",
method: "test",
id: 1,
};
let receivedMessage;
serverTransport.onmessage = (msg) => {
receivedMessage = msg;
};
await clientTransport.send(message);
expect(receivedMessage).toEqual(message);
});
test("should send message from server to client", async () => {
const message = {
jsonrpc: "2.0",
method: "test",
id: 1,
};
let receivedMessage;
clientTransport.onmessage = (msg) => {
receivedMessage = msg;
};
await serverTransport.send(message);
expect(receivedMessage).toEqual(message);
});
test("should handle close", async () => {
let clientClosed = false;
let serverClosed = false;
clientTransport.onclose = () => {
clientClosed = true;
};
serverTransport.onclose = () => {
serverClosed = true;
};
await clientTransport.close();
expect(clientClosed).toBe(true);
expect(serverClosed).toBe(true);
});
test("should throw error when sending after close", async () => {
await clientTransport.close();
await expect(clientTransport.send({ jsonrpc: "2.0", method: "test", id: 1 })).rejects.toThrow("Not connected");
});
test("should queue messages sent before start", async () => {
const message = {
jsonrpc: "2.0",
method: "test",
id: 1,
};
let receivedMessage;
serverTransport.onmessage = (msg) => {
receivedMessage = msg;
};
await clientTransport.send(message);
await serverTransport.start();
expect(receivedMessage).toEqual(message);
});
});
//# sourceMappingURL=inMemory.test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"inMemory.test.js","sourceRoot":"","sources":["../src/inMemory.test.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,112 @@
import { Protocol, ProtocolOptions, RequestOptions } from "../shared/protocol.js";
import { ClientCapabilities, CreateMessageRequest, Implementation, ListRootsRequest, LoggingMessageNotification, Notification, Request, ResourceUpdatedNotification, Result, ServerCapabilities, ServerNotification, ServerRequest, ServerResult } from "../types.js";
export type ServerOptions = ProtocolOptions & {
/**
* Capabilities to advertise as being supported by this server.
*/
capabilities: ServerCapabilities;
};
/**
* An MCP server on top of a pluggable transport.
*
* This server will automatically respond to the initialization flow as initiated from the client.
*
* To use with custom types, extend the base Request/Notification/Result types and pass them as type parameters:
*
* ```typescript
* // Custom schemas
* const CustomRequestSchema = RequestSchema.extend({...})
* const CustomNotificationSchema = NotificationSchema.extend({...})
* const CustomResultSchema = ResultSchema.extend({...})
*
* // Type aliases
* type CustomRequest = z.infer<typeof CustomRequestSchema>
* type CustomNotification = z.infer<typeof CustomNotificationSchema>
* type CustomResult = z.infer<typeof CustomResultSchema>
*
* // Create typed server
* const server = new Server<CustomRequest, CustomNotification, CustomResult>({
* name: "CustomServer",
* version: "1.0.0"
* })
* ```
*/
export declare class Server<RequestT extends Request = Request, NotificationT extends Notification = Notification, ResultT extends Result = Result> extends Protocol<ServerRequest | RequestT, ServerNotification | NotificationT, ServerResult | ResultT> {
private _serverInfo;
private _clientCapabilities?;
private _clientVersion?;
private _capabilities;
/**
* Callback for when initialization has fully completed (i.e., the client has sent an `initialized` notification).
*/
oninitialized?: () => void;
/**
* Initializes this server with the given name and version information.
*/
constructor(_serverInfo: Implementation, options: ServerOptions);
protected assertCapabilityForMethod(method: RequestT["method"]): void;
protected assertNotificationCapability(method: (ServerNotification | NotificationT)["method"]): void;
protected assertRequestHandlerCapability(method: string): void;
private _oninitialize;
/**
* After initialization has completed, this will be populated with the client's reported capabilities.
*/
getClientCapabilities(): ClientCapabilities | undefined;
/**
* After initialization has completed, this will be populated with information about the client's name and version.
*/
getClientVersion(): Implementation | undefined;
private getCapabilities;
ping(): Promise<{
_meta?: import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough"> | undefined;
}>;
createMessage(params: CreateMessageRequest["params"], options?: RequestOptions): Promise<import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
_meta: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, {
model: import("zod").ZodString;
stopReason: import("zod").ZodOptional<import("zod").ZodUnion<[import("zod").ZodEnum<["endTurn", "stopSequence", "maxTokens"]>, import("zod").ZodString]>>;
role: import("zod").ZodEnum<["user", "assistant"]>;
content: import("zod").ZodDiscriminatedUnion<"type", [import("zod").ZodObject<{
type: import("zod").ZodLiteral<"text">;
text: import("zod").ZodString;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"text">;
text: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"text">;
text: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<{
type: import("zod").ZodLiteral<"image">;
data: import("zod").ZodString;
mimeType: import("zod").ZodString;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
type: import("zod").ZodLiteral<"image">;
data: import("zod").ZodString;
mimeType: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
type: import("zod").ZodLiteral<"image">;
data: import("zod").ZodString;
mimeType: import("zod").ZodString;
}, import("zod").ZodTypeAny, "passthrough">>]>;
}>, import("zod").ZodTypeAny, "passthrough">>;
listRoots(params?: ListRootsRequest["params"], options?: RequestOptions): Promise<import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
_meta: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
}, {
roots: import("zod").ZodArray<import("zod").ZodObject<{
uri: import("zod").ZodString;
name: import("zod").ZodOptional<import("zod").ZodString>;
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
uri: import("zod").ZodString;
name: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
uri: import("zod").ZodString;
name: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod").ZodTypeAny, "passthrough">>, "many">;
}>, import("zod").ZodTypeAny, "passthrough">>;
sendLoggingMessage(params: LoggingMessageNotification["params"]): Promise<void>;
sendResourceUpdated(params: ResourceUpdatedNotification["params"]): Promise<void>;
sendResourceListChanged(): Promise<void>;
sendToolListChanged(): Promise<void>;
sendPromptListChanged(): Promise<void>;
}
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,eAAe,EACf,cAAc,EACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EAGpB,cAAc,EAMd,gBAAgB,EAEhB,0BAA0B,EAC1B,YAAY,EACZ,OAAO,EACP,2BAA2B,EAC3B,MAAM,EACN,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,YAAY,EAEb,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG;IAC5C;;OAEG;IACH,YAAY,EAAE,kBAAkB,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,MAAM,CACjB,QAAQ,SAAS,OAAO,GAAG,OAAO,EAClC,aAAa,SAAS,YAAY,GAAG,YAAY,EACjD,OAAO,SAAS,MAAM,GAAG,MAAM,CAC/B,SAAQ,QAAQ,CAChB,aAAa,GAAG,QAAQ,EACxB,kBAAkB,GAAG,aAAa,EAClC,YAAY,GAAG,OAAO,CACvB;IAcG,OAAO,CAAC,WAAW;IAbrB,OAAO,CAAC,mBAAmB,CAAC,CAAqB;IACjD,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,aAAa,CAAqB;IAE1C;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAE3B;;OAEG;gBAEO,WAAW,EAAE,cAAc,EACnC,OAAO,EAAE,aAAa;IAaxB,SAAS,CAAC,yBAAyB,CAAC,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,IAAI;IAwBrE,SAAS,CAAC,4BAA4B,CACpC,MAAM,EAAE,CAAC,kBAAkB,GAAG,aAAa,CAAC,CAAC,QAAQ,CAAC,GACrD,IAAI;IA6CP,SAAS,CAAC,8BAA8B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;YAqDhD,aAAa;IAiB3B;;OAEG;IACH,qBAAqB,IAAI,kBAAkB,GAAG,SAAS;IAIvD;;OAEG;IACH,gBAAgB,IAAI,cAAc,GAAG,SAAS;IAI9C,OAAO,CAAC,eAAe;IAIjB,IAAI;;;IAIJ,aAAa,CACjB,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,EACtC,OAAO,CAAC,EAAE,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IASpB,SAAS,CACb,MAAM,CAAC,EAAE,gBAAgB,CAAC,QAAQ,CAAC,EACnC,OAAO,CAAC,EAAE,cAAc;;;;;;;;;;;;;;IASpB,kBAAkB,CAAC,MAAM,EAAE,0BAA0B,CAAC,QAAQ,CAAC;IAI/D,mBAAmB,CAAC,MAAM,EAAE,2BAA2B,CAAC,QAAQ,CAAC;IAOjE,uBAAuB;IAMvB,mBAAmB;IAInB,qBAAqB;CAG5B"}

View File

@@ -0,0 +1,182 @@
import { Protocol, } from "../shared/protocol.js";
import { CreateMessageResultSchema, EmptyResultSchema, InitializedNotificationSchema, InitializeRequestSchema, LATEST_PROTOCOL_VERSION, ListRootsResultSchema, SUPPORTED_PROTOCOL_VERSIONS, } from "../types.js";
/**
* An MCP server on top of a pluggable transport.
*
* This server will automatically respond to the initialization flow as initiated from the client.
*
* To use with custom types, extend the base Request/Notification/Result types and pass them as type parameters:
*
* ```typescript
* // Custom schemas
* const CustomRequestSchema = RequestSchema.extend({...})
* const CustomNotificationSchema = NotificationSchema.extend({...})
* const CustomResultSchema = ResultSchema.extend({...})
*
* // Type aliases
* type CustomRequest = z.infer<typeof CustomRequestSchema>
* type CustomNotification = z.infer<typeof CustomNotificationSchema>
* type CustomResult = z.infer<typeof CustomResultSchema>
*
* // Create typed server
* const server = new Server<CustomRequest, CustomNotification, CustomResult>({
* name: "CustomServer",
* version: "1.0.0"
* })
* ```
*/
export class Server extends Protocol {
/**
* Initializes this server with the given name and version information.
*/
constructor(_serverInfo, options) {
super(options);
this._serverInfo = _serverInfo;
this._capabilities = options.capabilities;
this.setRequestHandler(InitializeRequestSchema, (request) => this._oninitialize(request));
this.setNotificationHandler(InitializedNotificationSchema, () => { var _a; return (_a = this.oninitialized) === null || _a === void 0 ? void 0 : _a.call(this); });
}
assertCapabilityForMethod(method) {
var _a, _b;
switch (method) {
case "sampling/createMessage":
if (!((_a = this._clientCapabilities) === null || _a === void 0 ? void 0 : _a.sampling)) {
throw new Error(`Client does not support sampling (required for ${method})`);
}
break;
case "roots/list":
if (!((_b = this._clientCapabilities) === null || _b === void 0 ? void 0 : _b.roots)) {
throw new Error(`Client does not support listing roots (required for ${method})`);
}
break;
case "ping":
// No specific capability required for ping
break;
}
}
assertNotificationCapability(method) {
switch (method) {
case "notifications/message":
if (!this._capabilities.logging) {
throw new Error(`Server does not support logging (required for ${method})`);
}
break;
case "notifications/resources/updated":
case "notifications/resources/list_changed":
if (!this._capabilities.resources) {
throw new Error(`Server does not support notifying about resources (required for ${method})`);
}
break;
case "notifications/tools/list_changed":
if (!this._capabilities.tools) {
throw new Error(`Server does not support notifying of tool list changes (required for ${method})`);
}
break;
case "notifications/prompts/list_changed":
if (!this._capabilities.prompts) {
throw new Error(`Server does not support notifying of prompt list changes (required for ${method})`);
}
break;
case "notifications/cancelled":
// Cancellation notifications are always allowed
break;
case "notifications/progress":
// Progress notifications are always allowed
break;
}
}
assertRequestHandlerCapability(method) {
switch (method) {
case "sampling/createMessage":
if (!this._capabilities.sampling) {
throw new Error(`Server does not support sampling (required for ${method})`);
}
break;
case "logging/setLevel":
if (!this._capabilities.logging) {
throw new Error(`Server does not support logging (required for ${method})`);
}
break;
case "prompts/get":
case "prompts/list":
if (!this._capabilities.prompts) {
throw new Error(`Server does not support prompts (required for ${method})`);
}
break;
case "resources/list":
case "resources/templates/list":
case "resources/read":
if (!this._capabilities.resources) {
throw new Error(`Server does not support resources (required for ${method})`);
}
break;
case "tools/call":
case "tools/list":
if (!this._capabilities.tools) {
throw new Error(`Server does not support tools (required for ${method})`);
}
break;
case "ping":
case "initialize":
// No specific capability required for these methods
break;
}
}
async _oninitialize(request) {
const requestedVersion = request.params.protocolVersion;
this._clientCapabilities = request.params.capabilities;
this._clientVersion = request.params.clientInfo;
return {
protocolVersion: SUPPORTED_PROTOCOL_VERSIONS.includes(requestedVersion)
? requestedVersion
: LATEST_PROTOCOL_VERSION,
capabilities: this.getCapabilities(),
serverInfo: this._serverInfo,
};
}
/**
* After initialization has completed, this will be populated with the client's reported capabilities.
*/
getClientCapabilities() {
return this._clientCapabilities;
}
/**
* After initialization has completed, this will be populated with information about the client's name and version.
*/
getClientVersion() {
return this._clientVersion;
}
getCapabilities() {
return this._capabilities;
}
async ping() {
return this.request({ method: "ping" }, EmptyResultSchema);
}
async createMessage(params, options) {
return this.request({ method: "sampling/createMessage", params }, CreateMessageResultSchema, options);
}
async listRoots(params, options) {
return this.request({ method: "roots/list", params }, ListRootsResultSchema, options);
}
async sendLoggingMessage(params) {
return this.notification({ method: "notifications/message", params });
}
async sendResourceUpdated(params) {
return this.notification({
method: "notifications/resources/updated",
params,
});
}
async sendResourceListChanged() {
return this.notification({
method: "notifications/resources/list_changed",
});
}
async sendToolListChanged() {
return this.notification({ method: "notifications/tools/list_changed" });
}
async sendPromptListChanged() {
return this.notification({ method: "notifications/prompts/list_changed" });
}
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=index.test.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../src/server/index.test.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,360 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-constant-binary-expression */
/* eslint-disable @typescript-eslint/no-unused-expressions */
import { Server } from "./index.js";
import { z } from "zod";
import { RequestSchema, NotificationSchema, ResultSchema, LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, CreateMessageRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, SetLevelRequestSchema, } from "../types.js";
import { InMemoryTransport } from "../inMemory.js";
import { Client } from "../client/index.js";
test("should accept latest protocol version", async () => {
var _a;
let sendPromiseResolve;
const sendPromise = new Promise((resolve) => {
sendPromiseResolve = resolve;
});
const serverTransport = {
start: jest.fn().mockResolvedValue(undefined),
close: jest.fn().mockResolvedValue(undefined),
send: jest.fn().mockImplementation((message) => {
if (message.id === 1 && message.result) {
expect(message.result).toEqual({
protocolVersion: LATEST_PROTOCOL_VERSION,
capabilities: expect.any(Object),
serverInfo: {
name: "test server",
version: "1.0",
},
});
sendPromiseResolve(undefined);
}
return Promise.resolve();
}),
};
const server = new Server({
name: "test server",
version: "1.0",
}, {
capabilities: {
prompts: {},
resources: {},
tools: {},
logging: {},
},
});
await server.connect(serverTransport);
// Simulate initialize request with latest version
(_a = serverTransport.onmessage) === null || _a === void 0 ? void 0 : _a.call(serverTransport, {
jsonrpc: "2.0",
id: 1,
method: "initialize",
params: {
protocolVersion: LATEST_PROTOCOL_VERSION,
capabilities: {},
clientInfo: {
name: "test client",
version: "1.0",
},
},
});
await expect(sendPromise).resolves.toBeUndefined();
});
test("should accept supported older protocol version", async () => {
var _a;
const OLD_VERSION = SUPPORTED_PROTOCOL_VERSIONS[1];
let sendPromiseResolve;
const sendPromise = new Promise((resolve) => {
sendPromiseResolve = resolve;
});
const serverTransport = {
start: jest.fn().mockResolvedValue(undefined),
close: jest.fn().mockResolvedValue(undefined),
send: jest.fn().mockImplementation((message) => {
if (message.id === 1 && message.result) {
expect(message.result).toEqual({
protocolVersion: OLD_VERSION,
capabilities: expect.any(Object),
serverInfo: {
name: "test server",
version: "1.0",
},
});
sendPromiseResolve(undefined);
}
return Promise.resolve();
}),
};
const server = new Server({
name: "test server",
version: "1.0",
}, {
capabilities: {
prompts: {},
resources: {},
tools: {},
logging: {},
},
});
await server.connect(serverTransport);
// Simulate initialize request with older version
(_a = serverTransport.onmessage) === null || _a === void 0 ? void 0 : _a.call(serverTransport, {
jsonrpc: "2.0",
id: 1,
method: "initialize",
params: {
protocolVersion: OLD_VERSION,
capabilities: {},
clientInfo: {
name: "test client",
version: "1.0",
},
},
});
await expect(sendPromise).resolves.toBeUndefined();
});
test("should handle unsupported protocol version", async () => {
var _a;
let sendPromiseResolve;
const sendPromise = new Promise((resolve) => {
sendPromiseResolve = resolve;
});
const serverTransport = {
start: jest.fn().mockResolvedValue(undefined),
close: jest.fn().mockResolvedValue(undefined),
send: jest.fn().mockImplementation((message) => {
if (message.id === 1 && message.result) {
expect(message.result).toEqual({
protocolVersion: LATEST_PROTOCOL_VERSION,
capabilities: expect.any(Object),
serverInfo: {
name: "test server",
version: "1.0",
},
});
sendPromiseResolve(undefined);
}
return Promise.resolve();
}),
};
const server = new Server({
name: "test server",
version: "1.0",
}, {
capabilities: {
prompts: {},
resources: {},
tools: {},
logging: {},
},
});
await server.connect(serverTransport);
// Simulate initialize request with unsupported version
(_a = serverTransport.onmessage) === null || _a === void 0 ? void 0 : _a.call(serverTransport, {
jsonrpc: "2.0",
id: 1,
method: "initialize",
params: {
protocolVersion: "invalid-version",
capabilities: {},
clientInfo: {
name: "test client",
version: "1.0",
},
},
});
await expect(sendPromise).resolves.toBeUndefined();
});
test("should respect client capabilities", async () => {
const server = new Server({
name: "test server",
version: "1.0",
}, {
capabilities: {
prompts: {},
resources: {},
tools: {},
logging: {},
},
enforceStrictCapabilities: true,
});
const client = new Client({
name: "test client",
version: "1.0",
}, {
capabilities: {
sampling: {},
},
});
// Implement request handler for sampling/createMessage
client.setRequestHandler(CreateMessageRequestSchema, async (request) => {
// Mock implementation of createMessage
return {
model: "test-model",
role: "assistant",
content: {
type: "text",
text: "This is a test response",
},
};
});
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
await Promise.all([
client.connect(clientTransport),
server.connect(serverTransport),
]);
expect(server.getClientCapabilities()).toEqual({ sampling: {} });
// This should work because sampling is supported by the client
await expect(server.createMessage({
messages: [],
maxTokens: 10,
})).resolves.not.toThrow();
// This should still throw because roots are not supported by the client
await expect(server.listRoots()).rejects.toThrow(/^Client does not support/);
});
test("should respect server notification capabilities", async () => {
const server = new Server({
name: "test server",
version: "1.0",
}, {
capabilities: {
logging: {},
},
enforceStrictCapabilities: true,
});
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
await server.connect(serverTransport);
// This should work because logging is supported by the server
await expect(server.sendLoggingMessage({
level: "info",
data: "Test log message",
})).resolves.not.toThrow();
// This should throw because resource notificaitons are not supported by the server
await expect(server.sendResourceUpdated({ uri: "test://resource" })).rejects.toThrow(/^Server does not support/);
});
test("should only allow setRequestHandler for declared capabilities", () => {
const server = new Server({
name: "test server",
version: "1.0",
}, {
capabilities: {
prompts: {},
resources: {},
},
});
// These should work because the capabilities are declared
expect(() => {
server.setRequestHandler(ListPromptsRequestSchema, () => ({ prompts: [] }));
}).not.toThrow();
expect(() => {
server.setRequestHandler(ListResourcesRequestSchema, () => ({
resources: [],
}));
}).not.toThrow();
// These should throw because the capabilities are not declared
expect(() => {
server.setRequestHandler(ListToolsRequestSchema, () => ({ tools: [] }));
}).toThrow(/^Server does not support tools/);
expect(() => {
server.setRequestHandler(SetLevelRequestSchema, () => ({}));
}).toThrow(/^Server does not support logging/);
});
/*
Test that custom request/notification/result schemas can be used with the Server class.
*/
test("should typecheck", () => {
const GetWeatherRequestSchema = RequestSchema.extend({
method: z.literal("weather/get"),
params: z.object({
city: z.string(),
}),
});
const GetForecastRequestSchema = RequestSchema.extend({
method: z.literal("weather/forecast"),
params: z.object({
city: z.string(),
days: z.number(),
}),
});
const WeatherForecastNotificationSchema = NotificationSchema.extend({
method: z.literal("weather/alert"),
params: z.object({
severity: z.enum(["warning", "watch"]),
message: z.string(),
}),
});
const WeatherRequestSchema = GetWeatherRequestSchema.or(GetForecastRequestSchema);
const WeatherNotificationSchema = WeatherForecastNotificationSchema;
const WeatherResultSchema = ResultSchema.extend({
temperature: z.number(),
conditions: z.string(),
});
// Create a typed Server for weather data
const weatherServer = new Server({
name: "WeatherServer",
version: "1.0.0",
}, {
capabilities: {
prompts: {},
resources: {},
tools: {},
logging: {},
},
});
// Typecheck that only valid weather requests/notifications/results are allowed
weatherServer.setRequestHandler(GetWeatherRequestSchema, (request) => {
return {
temperature: 72,
conditions: "sunny",
};
});
weatherServer.setNotificationHandler(WeatherForecastNotificationSchema, (notification) => {
console.log(`Weather alert: ${notification.params.message}`);
});
});
test("should handle server cancelling a request", async () => {
const server = new Server({
name: "test server",
version: "1.0",
}, {
capabilities: {
sampling: {},
},
});
const client = new Client({
name: "test client",
version: "1.0",
}, {
capabilities: {
sampling: {},
},
});
// Set up client to delay responding to createMessage
client.setRequestHandler(CreateMessageRequestSchema, async (_request, extra) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
return {
model: "test",
role: "assistant",
content: {
type: "text",
text: "Test response",
},
};
});
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
await Promise.all([
client.connect(clientTransport),
server.connect(serverTransport),
]);
// Set up abort controller
const controller = new AbortController();
// Issue request but cancel it immediately
const createMessagePromise = server.createMessage({
messages: [],
maxTokens: 10,
}, {
signal: controller.signal,
});
controller.abort("Cancelled by test");
// Request should be rejected
await expect(createMessagePromise).rejects.toBe("Cancelled by test");
});
//# sourceMappingURL=index.test.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,46 @@
import { IncomingMessage, ServerResponse } from "node:http";
import { Transport } from "../shared/transport.js";
import { JSONRPCMessage } from "../types.js";
/**
* Server transport for SSE: this will send messages over an SSE connection and receive messages from HTTP POST requests.
*
* This transport is only available in Node.js environments.
*/
export declare class SSEServerTransport implements Transport {
private _endpoint;
private res;
private _sseResponse?;
private _sessionId;
onclose?: () => void;
onerror?: (error: Error) => void;
onmessage?: (message: JSONRPCMessage) => void;
/**
* Creates a new SSE server transport, which will direct the client to POST messages to the relative or absolute URL identified by `_endpoint`.
*/
constructor(_endpoint: string, res: ServerResponse);
/**
* Handles the initial SSE connection request.
*
* This should be called when a GET request is made to establish the SSE stream.
*/
start(): Promise<void>;
/**
* Handles incoming POST messages.
*
* This should be called when a POST request is made to send a message to the server.
*/
handlePostMessage(req: IncomingMessage, res: ServerResponse): Promise<void>;
/**
* Handle a client message, regardless of how it arrived. This can be used to inform the server of messages that arrive via a means different than HTTP POST.
*/
handleMessage(message: unknown): Promise<void>;
close(): Promise<void>;
send(message: JSONRPCMessage): Promise<void>;
/**
* Returns the session ID for this transport.
*
* This can be used to route incoming POST requests.
*/
get sessionId(): string;
}
//# sourceMappingURL=sse.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/server/sse.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAwB,MAAM,aAAa,CAAC;AAMnE;;;;GAIG;AACH,qBAAa,kBAAmB,YAAW,SAAS;IAYhD,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,GAAG;IAZb,OAAO,CAAC,YAAY,CAAC,CAAiB;IACtC,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IAE9C;;OAEG;gBAEO,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,cAAc;IAK7B;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB5B;;;;OAIG;IACG,iBAAiB,CACrB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,IAAI,CAAC;IAkChB;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAY9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAUlD;;;;OAIG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;CACF"}

View File

@@ -0,0 +1,116 @@
import { randomUUID } from "node:crypto";
import { JSONRPCMessageSchema } from "../types.js";
import getRawBody from "raw-body";
import contentType from "content-type";
const MAXIMUM_MESSAGE_SIZE = "4mb";
/**
* Server transport for SSE: this will send messages over an SSE connection and receive messages from HTTP POST requests.
*
* This transport is only available in Node.js environments.
*/
export class SSEServerTransport {
/**
* Creates a new SSE server transport, which will direct the client to POST messages to the relative or absolute URL identified by `_endpoint`.
*/
constructor(_endpoint, res) {
this._endpoint = _endpoint;
this.res = res;
this._sessionId = randomUUID();
}
/**
* Handles the initial SSE connection request.
*
* This should be called when a GET request is made to establish the SSE stream.
*/
async start() {
if (this._sseResponse) {
throw new Error("SSEServerTransport already started! If using Server class, note that connect() calls start() automatically.");
}
this.res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
});
// Send the endpoint event
this.res.write(`event: endpoint\ndata: ${encodeURI(this._endpoint)}?sessionId=${this._sessionId}\n\n`);
this._sseResponse = this.res;
this.res.on("close", () => {
var _a;
this._sseResponse = undefined;
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
});
}
/**
* Handles incoming POST messages.
*
* This should be called when a POST request is made to send a message to the server.
*/
async handlePostMessage(req, res) {
var _a, _b, _c;
if (!this._sseResponse) {
const message = "SSE connection not established";
res.writeHead(500).end(message);
throw new Error(message);
}
let body;
try {
const ct = contentType.parse((_a = req.headers["content-type"]) !== null && _a !== void 0 ? _a : "");
if (ct.type !== "application/json") {
throw new Error(`Unsupported content-type: ${ct}`);
}
body = await getRawBody(req, {
limit: MAXIMUM_MESSAGE_SIZE,
encoding: (_b = ct.parameters.charset) !== null && _b !== void 0 ? _b : "utf-8",
});
}
catch (error) {
res.writeHead(400).end(String(error));
(_c = this.onerror) === null || _c === void 0 ? void 0 : _c.call(this, error);
return;
}
try {
await this.handleMessage(JSON.parse(body));
}
catch (_d) {
res.writeHead(400).end(`Invalid message: ${body}`);
return;
}
res.writeHead(202).end("Accepted");
}
/**
* Handle a client message, regardless of how it arrived. This can be used to inform the server of messages that arrive via a means different than HTTP POST.
*/
async handleMessage(message) {
var _a, _b;
let parsedMessage;
try {
parsedMessage = JSONRPCMessageSchema.parse(message);
}
catch (error) {
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
throw error;
}
(_b = this.onmessage) === null || _b === void 0 ? void 0 : _b.call(this, parsedMessage);
}
async close() {
var _a, _b;
(_a = this._sseResponse) === null || _a === void 0 ? void 0 : _a.end();
this._sseResponse = undefined;
(_b = this.onclose) === null || _b === void 0 ? void 0 : _b.call(this);
}
async send(message) {
if (!this._sseResponse) {
throw new Error("Not connected");
}
this._sseResponse.write(`event: message\ndata: ${JSON.stringify(message)}\n\n`);
}
/**
* Returns the session ID for this transport.
*
* This can be used to route incoming POST requests.
*/
get sessionId() {
return this._sessionId;
}
}
//# sourceMappingURL=sse.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/server/sse.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,28 @@
import { Readable, Writable } from "node:stream";
import { JSONRPCMessage } from "../types.js";
import { Transport } from "../shared/transport.js";
/**
* Server transport for stdio: this communicates with a MCP client by reading from the current process' stdin and writing to stdout.
*
* This transport is only available in Node.js environments.
*/
export declare class StdioServerTransport implements Transport {
private _stdin;
private _stdout;
private _readBuffer;
private _started;
constructor(_stdin?: Readable, _stdout?: Writable);
onclose?: () => void;
onerror?: (error: Error) => void;
onmessage?: (message: JSONRPCMessage) => void;
_ondata: (chunk: Buffer) => void;
_onerror: (error: Error) => void;
/**
* Starts listening for messages on stdin.
*/
start(): Promise<void>;
private processReadBuffer;
close(): Promise<void>;
send(message: JSONRPCMessage): Promise<void>;
}
//# sourceMappingURL=stdio.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/server/stdio.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD;;;;GAIG;AACH,qBAAa,oBAAqB,YAAW,SAAS;IAKlD,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO;IALjB,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,QAAQ,CAAS;gBAGf,MAAM,GAAE,QAAwB,EAChC,OAAO,GAAE,QAAyB;IAG5C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IAG9C,OAAO,UAAW,MAAM,UAGtB;IACF,QAAQ,UAAW,KAAK,UAEtB;IAEF;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAY5B,OAAO,CAAC,iBAAiB;IAenB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAU7C"}

View File

@@ -0,0 +1,69 @@
import process from "node:process";
import { ReadBuffer, serializeMessage } from "../shared/stdio.js";
/**
* Server transport for stdio: this communicates with a MCP client by reading from the current process' stdin and writing to stdout.
*
* This transport is only available in Node.js environments.
*/
export class StdioServerTransport {
constructor(_stdin = process.stdin, _stdout = process.stdout) {
this._stdin = _stdin;
this._stdout = _stdout;
this._readBuffer = new ReadBuffer();
this._started = false;
// Arrow functions to bind `this` properly, while maintaining function identity.
this._ondata = (chunk) => {
this._readBuffer.append(chunk);
this.processReadBuffer();
};
this._onerror = (error) => {
var _a;
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
};
}
/**
* Starts listening for messages on stdin.
*/
async start() {
if (this._started) {
throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");
}
this._started = true;
this._stdin.on("data", this._ondata);
this._stdin.on("error", this._onerror);
}
processReadBuffer() {
var _a, _b;
while (true) {
try {
const message = this._readBuffer.readMessage();
if (message === null) {
break;
}
(_a = this.onmessage) === null || _a === void 0 ? void 0 : _a.call(this, message);
}
catch (error) {
(_b = this.onerror) === null || _b === void 0 ? void 0 : _b.call(this, error);
}
}
}
async close() {
var _a;
this._stdin.off("data", this._ondata);
this._stdin.off("error", this._onerror);
this._readBuffer.clear();
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
}
send(message) {
return new Promise((resolve) => {
const json = serializeMessage(message);
if (this._stdout.write(json)) {
resolve();
}
else {
this._stdout.once("drain", resolve);
}
});
}
}
//# sourceMappingURL=stdio.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/server/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAIlE;;;;GAIG;AACH,MAAM,OAAO,oBAAoB;IAI/B,YACU,SAAmB,OAAO,CAAC,KAAK,EAChC,UAAoB,OAAO,CAAC,MAAM;QADlC,WAAM,GAAN,MAAM,CAA0B;QAChC,YAAO,GAAP,OAAO,CAA2B;QALpC,gBAAW,GAAe,IAAI,UAAU,EAAE,CAAC;QAC3C,aAAQ,GAAG,KAAK,CAAC;QAWzB,gFAAgF;QAChF,YAAO,GAAG,CAAC,KAAa,EAAE,EAAE;YAC1B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC/B,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,CAAC,CAAC;QACF,aAAQ,GAAG,CAAC,KAAY,EAAE,EAAE;;YAC1B,MAAA,IAAI,CAAC,OAAO,qDAAG,KAAK,CAAC,CAAC;QACxB,CAAC,CAAC;IAbC,CAAC;IAeJ;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CACb,+GAA+G,CAChH,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;IAEO,iBAAiB;;QACvB,OAAO,IAAI,EAAE,CAAC;YACZ,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;gBAC/C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;oBACrB,MAAM;gBACR,CAAC;gBAED,MAAA,IAAI,CAAC,SAAS,qDAAG,OAAO,CAAC,CAAC;YAC5B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAA,IAAI,CAAC,OAAO,qDAAG,KAAc,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;;QACT,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;QACzB,MAAA,IAAI,CAAC,OAAO,oDAAI,CAAC;IACnB,CAAC;IAED,IAAI,CAAC,OAAuB;QAC1B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,MAAM,IAAI,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;YACvC,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7B,OAAO,EAAE,CAAC;YACZ,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACtC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=stdio.test.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stdio.test.d.ts","sourceRoot":"","sources":["../../src/server/stdio.test.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,87 @@
import { Readable, Writable } from "node:stream";
import { ReadBuffer, serializeMessage } from "../shared/stdio.js";
import { StdioServerTransport } from "./stdio.js";
let input;
let outputBuffer;
let output;
beforeEach(() => {
input = new Readable({
// We'll use input.push() instead.
read: () => { },
});
outputBuffer = new ReadBuffer();
output = new Writable({
write(chunk, encoding, callback) {
outputBuffer.append(chunk);
callback();
},
});
});
test("should start then close cleanly", async () => {
const server = new StdioServerTransport(input, output);
server.onerror = (error) => {
throw error;
};
let didClose = false;
server.onclose = () => {
didClose = true;
};
await server.start();
expect(didClose).toBeFalsy();
await server.close();
expect(didClose).toBeTruthy();
});
test("should not read until started", async () => {
const server = new StdioServerTransport(input, output);
server.onerror = (error) => {
throw error;
};
let didRead = false;
const readMessage = new Promise((resolve) => {
server.onmessage = (message) => {
didRead = true;
resolve(message);
};
});
const message = {
jsonrpc: "2.0",
id: 1,
method: "ping",
};
input.push(serializeMessage(message));
expect(didRead).toBeFalsy();
await server.start();
expect(await readMessage).toEqual(message);
});
test("should read multiple messages", async () => {
const server = new StdioServerTransport(input, output);
server.onerror = (error) => {
throw error;
};
const messages = [
{
jsonrpc: "2.0",
id: 1,
method: "ping",
},
{
jsonrpc: "2.0",
method: "notifications/initialized",
},
];
const readMessages = [];
const finished = new Promise((resolve) => {
server.onmessage = (message) => {
readMessages.push(message);
if (JSON.stringify(message) === JSON.stringify(messages[1])) {
resolve();
}
};
});
input.push(serializeMessage(messages[0]));
input.push(serializeMessage(messages[1]));
await server.start();
await finished;
expect(readMessages).toEqual(messages);
});
//# sourceMappingURL=stdio.test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stdio.test.js","sourceRoot":"","sources":["../../src/server/stdio.test.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,149 @@
import { ZodLiteral, ZodObject, ZodType, z } from "zod";
import { Notification, Progress, Request, Result } from "../types.js";
import { Transport } from "./transport.js";
/**
* Callback for progress notifications.
*/
export type ProgressCallback = (progress: Progress) => void;
/**
* Additional initialization options.
*/
export type ProtocolOptions = {
/**
* Whether to restrict emitted requests to only those that the remote side has indicated that they can handle, through their advertised capabilities.
*
* Note that this DOES NOT affect checking of _local_ side capabilities, as it is considered a logic error to mis-specify those.
*
* Currently this defaults to false, for backwards compatibility with SDK versions that did not advertise capabilities correctly. In future, this will default to true.
*/
enforceStrictCapabilities?: boolean;
};
/**
* Options that can be given per request.
*/
export type RequestOptions = {
/**
* If set, requests progress notifications from the remote end (if supported). When progress notifications are received, this callback will be invoked.
*/
onprogress?: ProgressCallback;
/**
* Can be used to cancel an in-flight request. This will cause an AbortError to be raised from request().
*
* Use abortAfterTimeout() to easily implement timeouts using this signal.
*/
signal?: AbortSignal;
};
/**
* Extra data given to request handlers.
*/
export type RequestHandlerExtra = {
/**
* An abort signal used to communicate if the request was cancelled from the sender's side.
*/
signal: AbortSignal;
};
/**
* Implements MCP protocol framing on top of a pluggable transport, including
* features like request/response linking, notifications, and progress.
*/
export declare abstract class Protocol<SendRequestT extends Request, SendNotificationT extends Notification, SendResultT extends Result> {
private _options?;
private _transport?;
private _requestMessageId;
private _requestHandlers;
private _requestHandlerAbortControllers;
private _notificationHandlers;
private _responseHandlers;
private _progressHandlers;
/**
* Callback for when the connection is closed for any reason.
*
* This is invoked when close() is called as well.
*/
onclose?: () => void;
/**
* Callback for when an error occurs.
*
* Note that errors are not necessarily fatal; they are used for reporting any kind of exceptional condition out of band.
*/
onerror?: (error: Error) => void;
/**
* A handler to invoke for any request types that do not have their own handler installed.
*/
fallbackRequestHandler?: (request: Request) => Promise<SendResultT>;
/**
* A handler to invoke for any notification types that do not have their own handler installed.
*/
fallbackNotificationHandler?: (notification: Notification) => Promise<void>;
constructor(_options?: ProtocolOptions | undefined);
/**
* Attaches to the given transport, starts it, and starts listening for messages.
*
* The Protocol object assumes ownership of the Transport, replacing any callbacks that have already been set, and expects that it is the only user of the Transport instance going forward.
*/
connect(transport: Transport): Promise<void>;
private _onclose;
private _onerror;
private _onnotification;
private _onrequest;
private _onprogress;
private _onresponse;
get transport(): Transport | undefined;
/**
* Closes the connection.
*/
close(): Promise<void>;
/**
* A method to check if a capability is supported by the remote side, for the given method to be called.
*
* This should be implemented by subclasses.
*/
protected abstract assertCapabilityForMethod(method: SendRequestT["method"]): void;
/**
* A method to check if a notification is supported by the local side, for the given method to be sent.
*
* This should be implemented by subclasses.
*/
protected abstract assertNotificationCapability(method: SendNotificationT["method"]): void;
/**
* A method to check if a request handler is supported by the local side, for the given method to be handled.
*
* This should be implemented by subclasses.
*/
protected abstract assertRequestHandlerCapability(method: string): void;
/**
* Sends a request and wait for a response.
*
* Do not use this method to emit notifications! Use notification() instead.
*/
request<T extends ZodType<object>>(request: SendRequestT, resultSchema: T, options?: RequestOptions): Promise<z.infer<T>>;
/**
* Emits a notification, which is a one-way message that does not expect a response.
*/
notification(notification: SendNotificationT): Promise<void>;
/**
* Registers a handler to invoke when this protocol object receives a request with the given method.
*
* Note that this will replace any previous request handler for the same method.
*/
setRequestHandler<T extends ZodObject<{
method: ZodLiteral<string>;
}>>(requestSchema: T, handler: (request: z.infer<T>, extra: RequestHandlerExtra) => SendResultT | Promise<SendResultT>): void;
/**
* Removes the request handler for the given method.
*/
removeRequestHandler(method: string): void;
/**
* Registers a handler to invoke when this protocol object receives a notification with the given method.
*
* Note that this will replace any previous notification handler for the same method.
*/
setNotificationHandler<T extends ZodObject<{
method: ZodLiteral<string>;
}>>(notificationSchema: T, handler: (notification: z.infer<T>) => void | Promise<void>): void;
/**
* Removes the notification handler for the given method.
*/
removeNotificationHandler(method: string): void;
}
//# sourceMappingURL=protocol.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/shared/protocol.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,274 @@
import { CancelledNotificationSchema, ErrorCode, McpError, PingRequestSchema, ProgressNotificationSchema, } from "../types.js";
/**
* Implements MCP protocol framing on top of a pluggable transport, including
* features like request/response linking, notifications, and progress.
*/
export class Protocol {
constructor(_options) {
this._options = _options;
this._requestMessageId = 0;
this._requestHandlers = new Map();
this._requestHandlerAbortControllers = new Map();
this._notificationHandlers = new Map();
this._responseHandlers = new Map();
this._progressHandlers = new Map();
this.setNotificationHandler(CancelledNotificationSchema, (notification) => {
const controller = this._requestHandlerAbortControllers.get(notification.params.requestId);
controller === null || controller === void 0 ? void 0 : controller.abort(notification.params.reason);
});
this.setNotificationHandler(ProgressNotificationSchema, (notification) => {
this._onprogress(notification);
});
this.setRequestHandler(PingRequestSchema,
// Automatic pong by default.
(_request) => ({}));
}
/**
* Attaches to the given transport, starts it, and starts listening for messages.
*
* The Protocol object assumes ownership of the Transport, replacing any callbacks that have already been set, and expects that it is the only user of the Transport instance going forward.
*/
async connect(transport) {
this._transport = transport;
this._transport.onclose = () => {
this._onclose();
};
this._transport.onerror = (error) => {
this._onerror(error);
};
this._transport.onmessage = (message) => {
if (!("method" in message)) {
this._onresponse(message);
}
else if ("id" in message) {
this._onrequest(message);
}
else {
this._onnotification(message);
}
};
await this._transport.start();
}
_onclose() {
var _a;
const responseHandlers = this._responseHandlers;
this._responseHandlers = new Map();
this._progressHandlers.clear();
this._transport = undefined;
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
const error = new McpError(ErrorCode.ConnectionClosed, "Connection closed");
for (const handler of responseHandlers.values()) {
handler(error);
}
}
_onerror(error) {
var _a;
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
}
_onnotification(notification) {
var _a;
const handler = (_a = this._notificationHandlers.get(notification.method)) !== null && _a !== void 0 ? _a : this.fallbackNotificationHandler;
// Ignore notifications not being subscribed to.
if (handler === undefined) {
return;
}
// Starting with Promise.resolve() puts any synchronous errors into the monad as well.
Promise.resolve()
.then(() => handler(notification))
.catch((error) => this._onerror(new Error(`Uncaught error in notification handler: ${error}`)));
}
_onrequest(request) {
var _a, _b;
const handler = (_a = this._requestHandlers.get(request.method)) !== null && _a !== void 0 ? _a : this.fallbackRequestHandler;
if (handler === undefined) {
(_b = this._transport) === null || _b === void 0 ? void 0 : _b.send({
jsonrpc: "2.0",
id: request.id,
error: {
code: ErrorCode.MethodNotFound,
message: "Method not found",
},
}).catch((error) => this._onerror(new Error(`Failed to send an error response: ${error}`)));
return;
}
const abortController = new AbortController();
this._requestHandlerAbortControllers.set(request.id, abortController);
// Starting with Promise.resolve() puts any synchronous errors into the monad as well.
Promise.resolve()
.then(() => handler(request, { signal: abortController.signal }))
.then((result) => {
var _a;
if (abortController.signal.aborted) {
return;
}
return (_a = this._transport) === null || _a === void 0 ? void 0 : _a.send({
result,
jsonrpc: "2.0",
id: request.id,
});
}, (error) => {
var _a, _b;
if (abortController.signal.aborted) {
return;
}
return (_a = this._transport) === null || _a === void 0 ? void 0 : _a.send({
jsonrpc: "2.0",
id: request.id,
error: {
code: Number.isSafeInteger(error["code"])
? error["code"]
: ErrorCode.InternalError,
message: (_b = error.message) !== null && _b !== void 0 ? _b : "Internal error",
},
});
})
.catch((error) => this._onerror(new Error(`Failed to send response: ${error}`)))
.finally(() => {
this._requestHandlerAbortControllers.delete(request.id);
});
}
_onprogress(notification) {
const { progress, total, progressToken } = notification.params;
const handler = this._progressHandlers.get(Number(progressToken));
if (handler === undefined) {
this._onerror(new Error(`Received a progress notification for an unknown token: ${JSON.stringify(notification)}`));
return;
}
handler({ progress, total });
}
_onresponse(response) {
const messageId = response.id;
const handler = this._responseHandlers.get(Number(messageId));
if (handler === undefined) {
this._onerror(new Error(`Received a response for an unknown message ID: ${JSON.stringify(response)}`));
return;
}
this._responseHandlers.delete(Number(messageId));
this._progressHandlers.delete(Number(messageId));
if ("result" in response) {
handler(response);
}
else {
const error = new McpError(response.error.code, response.error.message, response.error.data);
handler(error);
}
}
get transport() {
return this._transport;
}
/**
* Closes the connection.
*/
async close() {
var _a;
await ((_a = this._transport) === null || _a === void 0 ? void 0 : _a.close());
}
/**
* Sends a request and wait for a response.
*
* Do not use this method to emit notifications! Use notification() instead.
*/
request(request, resultSchema, options) {
return new Promise((resolve, reject) => {
var _a, _b, _c;
if (!this._transport) {
reject(new Error("Not connected"));
return;
}
if (((_a = this._options) === null || _a === void 0 ? void 0 : _a.enforceStrictCapabilities) === true) {
this.assertCapabilityForMethod(request.method);
}
(_b = options === null || options === void 0 ? void 0 : options.signal) === null || _b === void 0 ? void 0 : _b.throwIfAborted();
const messageId = this._requestMessageId++;
const jsonrpcRequest = {
...request,
jsonrpc: "2.0",
id: messageId,
};
if (options === null || options === void 0 ? void 0 : options.onprogress) {
this._progressHandlers.set(messageId, options.onprogress);
jsonrpcRequest.params = {
...request.params,
_meta: { progressToken: messageId },
};
}
this._responseHandlers.set(messageId, (response) => {
var _a;
if ((_a = options === null || options === void 0 ? void 0 : options.signal) === null || _a === void 0 ? void 0 : _a.aborted) {
return;
}
if (response instanceof Error) {
return reject(response);
}
try {
const result = resultSchema.parse(response.result);
resolve(result);
}
catch (error) {
reject(error);
}
});
(_c = options === null || options === void 0 ? void 0 : options.signal) === null || _c === void 0 ? void 0 : _c.addEventListener("abort", () => {
var _a, _b;
const reason = (_a = options === null || options === void 0 ? void 0 : options.signal) === null || _a === void 0 ? void 0 : _a.reason;
this._responseHandlers.delete(messageId);
this._progressHandlers.delete(messageId);
(_b = this._transport) === null || _b === void 0 ? void 0 : _b.send({
jsonrpc: "2.0",
method: "cancelled",
params: {
requestId: messageId,
reason: String(reason),
},
});
reject(reason);
});
this._transport.send(jsonrpcRequest).catch(reject);
});
}
/**
* Emits a notification, which is a one-way message that does not expect a response.
*/
async notification(notification) {
if (!this._transport) {
throw new Error("Not connected");
}
this.assertNotificationCapability(notification.method);
const jsonrpcNotification = {
...notification,
jsonrpc: "2.0",
};
await this._transport.send(jsonrpcNotification);
}
/**
* Registers a handler to invoke when this protocol object receives a request with the given method.
*
* Note that this will replace any previous request handler for the same method.
*/
setRequestHandler(requestSchema, handler) {
const method = requestSchema.shape.method.value;
this.assertRequestHandlerCapability(method);
this._requestHandlers.set(method, (request, extra) => Promise.resolve(handler(requestSchema.parse(request), extra)));
}
/**
* Removes the request handler for the given method.
*/
removeRequestHandler(method) {
this._requestHandlers.delete(method);
}
/**
* Registers a handler to invoke when this protocol object receives a notification with the given method.
*
* Note that this will replace any previous notification handler for the same method.
*/
setNotificationHandler(notificationSchema, handler) {
this._notificationHandlers.set(notificationSchema.shape.method.value, (notification) => Promise.resolve(handler(notificationSchema.parse(notification))));
}
/**
* Removes the notification handler for the given method.
*/
removeNotificationHandler(method) {
this._notificationHandlers.delete(method);
}
}
//# sourceMappingURL=protocol.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,13 @@
import { JSONRPCMessage } from "../types.js";
/**
* Buffers a continuous stdio stream into discrete JSON-RPC messages.
*/
export declare class ReadBuffer {
private _buffer?;
append(chunk: Buffer): void;
readMessage(): JSONRPCMessage | null;
clear(): void;
}
export declare function deserializeMessage(line: string): JSONRPCMessage;
export declare function serializeMessage(message: JSONRPCMessage): string;
//# sourceMappingURL=stdio.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/shared/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAwB,MAAM,aAAa,CAAC;AAEnE;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAC,CAAS;IAEzB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI3B,WAAW,IAAI,cAAc,GAAG,IAAI;IAepC,KAAK,IAAI,IAAI;CAGd;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAE/D;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAEhE"}

View File

@@ -0,0 +1,31 @@
import { JSONRPCMessageSchema } from "../types.js";
/**
* Buffers a continuous stdio stream into discrete JSON-RPC messages.
*/
export class ReadBuffer {
append(chunk) {
this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
}
readMessage() {
if (!this._buffer) {
return null;
}
const index = this._buffer.indexOf("\n");
if (index === -1) {
return null;
}
const line = this._buffer.toString("utf8", 0, index);
this._buffer = this._buffer.subarray(index + 1);
return deserializeMessage(line);
}
clear() {
this._buffer = undefined;
}
}
export function deserializeMessage(line) {
return JSONRPCMessageSchema.parse(JSON.parse(line));
}
export function serializeMessage(message) {
return JSON.stringify(message) + "\n";
}
//# sourceMappingURL=stdio.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/shared/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnE;;GAEG;AACH,MAAM,OAAO,UAAU;IAGrB,MAAM,CAAC,KAAa;QAClB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC7E,CAAC;IAED,WAAW;QACT,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QACrD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAChD,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,OAAO,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAuB;IACtD,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;AACxC,CAAC"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=stdio.test.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stdio.test.d.ts","sourceRoot":"","sources":["../../src/shared/stdio.test.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,27 @@
import { ReadBuffer } from "./stdio.js";
const testMessage = {
jsonrpc: "2.0",
method: "foobar",
};
test("should have no messages after initialization", () => {
const readBuffer = new ReadBuffer();
expect(readBuffer.readMessage()).toBeNull();
});
test("should only yield a message after a newline", () => {
const readBuffer = new ReadBuffer();
readBuffer.append(Buffer.from(JSON.stringify(testMessage)));
expect(readBuffer.readMessage()).toBeNull();
readBuffer.append(Buffer.from("\n"));
expect(readBuffer.readMessage()).toEqual(testMessage);
expect(readBuffer.readMessage()).toBeNull();
});
test("should be reusable after clearing", () => {
const readBuffer = new ReadBuffer();
readBuffer.append(Buffer.from("foobar"));
readBuffer.clear();
expect(readBuffer.readMessage()).toBeNull();
readBuffer.append(Buffer.from(JSON.stringify(testMessage)));
readBuffer.append(Buffer.from("\n"));
expect(readBuffer.readMessage()).toEqual(testMessage);
});
//# sourceMappingURL=stdio.test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stdio.test.js","sourceRoot":"","sources":["../../src/shared/stdio.test.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,GAAmB;IAClC,OAAO,EAAE,KAAK;IACd,MAAM,EAAE,QAAQ;CACjB,CAAC;AAEF,IAAI,CAAC,8CAA8C,EAAE,GAAG,EAAE;IACxD,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC;IACpC,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;AAC9C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,6CAA6C,EAAE,GAAG,EAAE;IACvD,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC;IAEpC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAC5D,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAE5C,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACrC,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACtD,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;AAC9C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,mCAAmC,EAAE,GAAG,EAAE;IAC7C,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC;IAEpC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzC,UAAU,CAAC,KAAK,EAAE,CAAC;IACnB,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAE5C,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAC5D,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACrC,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;AACxD,CAAC,CAAC,CAAC"}

View File

@@ -0,0 +1,39 @@
import { JSONRPCMessage } from "../types.js";
/**
* Describes the minimal contract for a MCP transport that a client or server can communicate over.
*/
export interface Transport {
/**
* Starts processing messages on the transport, including any connection steps that might need to be taken.
*
* This method should only be called after callbacks are installed, or else messages may be lost.
*
* NOTE: This method should not be called explicitly when using Client, Server, or Protocol classes, as they will implicitly call start().
*/
start(): Promise<void>;
/**
* Sends a JSON-RPC message (request or response).
*/
send(message: JSONRPCMessage): Promise<void>;
/**
* Closes the connection.
*/
close(): Promise<void>;
/**
* Callback for when the connection is closed for any reason.
*
* This should be invoked when close() is called as well.
*/
onclose?: () => void;
/**
* Callback for when an error occurs.
*
* Note that errors are not necessarily fatal; they are used for reporting any kind of exceptional condition out of band.
*/
onerror?: (error: Error) => void;
/**
* Callback for when a message (request or response) is received over the connection.
*/
onmessage?: (message: JSONRPCMessage) => void;
}
//# sourceMappingURL=transport.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/shared/transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;;OAMG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAEjC;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;CAC/C"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=transport.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/shared/transport.ts"],"names":[],"mappings":""}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,996 @@
import { z } from "zod";
export const LATEST_PROTOCOL_VERSION = "2024-11-05";
export const SUPPORTED_PROTOCOL_VERSIONS = [
LATEST_PROTOCOL_VERSION,
"2024-10-07",
];
/* JSON-RPC types */
export const JSONRPC_VERSION = "2.0";
/**
* A progress token, used to associate progress notifications with the original request.
*/
export const ProgressTokenSchema = z.union([z.string(), z.number().int()]);
/**
* An opaque token used to represent a cursor for pagination.
*/
export const CursorSchema = z.string();
const BaseRequestParamsSchema = z
.object({
_meta: z.optional(z
.object({
/**
* If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.
*/
progressToken: z.optional(ProgressTokenSchema),
})
.passthrough()),
})
.passthrough();
export const RequestSchema = z.object({
method: z.string(),
params: z.optional(BaseRequestParamsSchema),
});
const BaseNotificationParamsSchema = z
.object({
/**
* This parameter name is reserved by MCP to allow clients and servers to attach additional metadata to their notifications.
*/
_meta: z.optional(z.object({}).passthrough()),
})
.passthrough();
export const NotificationSchema = z.object({
method: z.string(),
params: z.optional(BaseNotificationParamsSchema),
});
export const ResultSchema = z
.object({
/**
* This result property is reserved by the protocol to allow clients and servers to attach additional metadata to their responses.
*/
_meta: z.optional(z.object({}).passthrough()),
})
.passthrough();
/**
* A uniquely identifying ID for a request in JSON-RPC.
*/
export const RequestIdSchema = z.union([z.string(), z.number().int()]);
/**
* A request that expects a response.
*/
export const JSONRPCRequestSchema = z
.object({
jsonrpc: z.literal(JSONRPC_VERSION),
id: RequestIdSchema,
})
.merge(RequestSchema)
.strict();
/**
* A notification which does not expect a response.
*/
export const JSONRPCNotificationSchema = z
.object({
jsonrpc: z.literal(JSONRPC_VERSION),
})
.merge(NotificationSchema)
.strict();
/**
* A successful (non-error) response to a request.
*/
export const JSONRPCResponseSchema = z
.object({
jsonrpc: z.literal(JSONRPC_VERSION),
id: RequestIdSchema,
result: ResultSchema,
})
.strict();
/**
* An incomplete set of error codes that may appear in JSON-RPC responses.
*/
export var ErrorCode;
(function (ErrorCode) {
// SDK error codes
ErrorCode[ErrorCode["ConnectionClosed"] = -1] = "ConnectionClosed";
// Standard JSON-RPC error codes
ErrorCode[ErrorCode["ParseError"] = -32700] = "ParseError";
ErrorCode[ErrorCode["InvalidRequest"] = -32600] = "InvalidRequest";
ErrorCode[ErrorCode["MethodNotFound"] = -32601] = "MethodNotFound";
ErrorCode[ErrorCode["InvalidParams"] = -32602] = "InvalidParams";
ErrorCode[ErrorCode["InternalError"] = -32603] = "InternalError";
})(ErrorCode || (ErrorCode = {}));
/**
* A response to a request that indicates an error occurred.
*/
export const JSONRPCErrorSchema = z
.object({
jsonrpc: z.literal(JSONRPC_VERSION),
id: RequestIdSchema,
error: z.object({
/**
* The error type that occurred.
*/
code: z.number().int(),
/**
* A short description of the error. The message SHOULD be limited to a concise single sentence.
*/
message: z.string(),
/**
* Additional information about the error. The value of this member is defined by the sender (e.g. detailed error information, nested errors etc.).
*/
data: z.optional(z.unknown()),
}),
})
.strict();
export const JSONRPCMessageSchema = z.union([
JSONRPCRequestSchema,
JSONRPCNotificationSchema,
JSONRPCResponseSchema,
JSONRPCErrorSchema,
]);
/* Empty result */
/**
* A response that indicates success but carries no data.
*/
export const EmptyResultSchema = ResultSchema.strict();
/* Cancellation */
/**
* This notification can be sent by either side to indicate that it is cancelling a previously-issued request.
*
* The request SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished.
*
* This notification indicates that the result will be unused, so any associated processing SHOULD cease.
*
* A client MUST NOT attempt to cancel its `initialize` request.
*/
export const CancelledNotificationSchema = NotificationSchema.extend({
method: z.literal("notifications/cancelled"),
params: BaseNotificationParamsSchema.extend({
/**
* The ID of the request to cancel.
*
* This MUST correspond to the ID of a request previously issued in the same direction.
*/
requestId: RequestIdSchema,
/**
* An optional string describing the reason for the cancellation. This MAY be logged or presented to the user.
*/
reason: z.string().optional(),
}),
});
/* Initialization */
/**
* Describes the name and version of an MCP implementation.
*/
export const ImplementationSchema = z
.object({
name: z.string(),
version: z.string(),
})
.passthrough();
/**
* Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.
*/
export const ClientCapabilitiesSchema = z
.object({
/**
* Experimental, non-standard capabilities that the client supports.
*/
experimental: z.optional(z.object({}).passthrough()),
/**
* Present if the client supports sampling from an LLM.
*/
sampling: z.optional(z.object({}).passthrough()),
/**
* Present if the client supports listing roots.
*/
roots: z.optional(z
.object({
/**
* Whether the client supports issuing notifications for changes to the roots list.
*/
listChanged: z.optional(z.boolean()),
})
.passthrough()),
})
.passthrough();
/**
* This request is sent from the client to the server when it first connects, asking it to begin initialization.
*/
export const InitializeRequestSchema = RequestSchema.extend({
method: z.literal("initialize"),
params: BaseRequestParamsSchema.extend({
/**
* The latest version of the Model Context Protocol that the client supports. The client MAY decide to support older versions as well.
*/
protocolVersion: z.string(),
capabilities: ClientCapabilitiesSchema,
clientInfo: ImplementationSchema,
}),
});
/**
* Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.
*/
export const ServerCapabilitiesSchema = z
.object({
/**
* Experimental, non-standard capabilities that the server supports.
*/
experimental: z.optional(z.object({}).passthrough()),
/**
* Present if the server supports sending log messages to the client.
*/
logging: z.optional(z.object({}).passthrough()),
/**
* Present if the server offers any prompt templates.
*/
prompts: z.optional(z
.object({
/**
* Whether this server supports issuing notifications for changes to the prompt list.
*/
listChanged: z.optional(z.boolean()),
})
.passthrough()),
/**
* Present if the server offers any resources to read.
*/
resources: z.optional(z
.object({
/**
* Whether this server supports clients subscribing to resource updates.
*/
subscribe: z.optional(z.boolean()),
/**
* Whether this server supports issuing notifications for changes to the resource list.
*/
listChanged: z.optional(z.boolean()),
})
.passthrough()),
/**
* Present if the server offers any tools to call.
*/
tools: z.optional(z
.object({
/**
* Whether this server supports issuing notifications for changes to the tool list.
*/
listChanged: z.optional(z.boolean()),
})
.passthrough()),
})
.passthrough();
/**
* After receiving an initialize request from the client, the server sends this response.
*/
export const InitializeResultSchema = ResultSchema.extend({
/**
* The version of the Model Context Protocol that the server wants to use. This may not match the version that the client requested. If the client cannot support this version, it MUST disconnect.
*/
protocolVersion: z.string(),
capabilities: ServerCapabilitiesSchema,
serverInfo: ImplementationSchema,
});
/**
* This notification is sent from the client to the server after initialization has finished.
*/
export const InitializedNotificationSchema = NotificationSchema.extend({
method: z.literal("notifications/initialized"),
});
/* Ping */
/**
* A ping, issued by either the server or the client, to check that the other party is still alive. The receiver must promptly respond, or else may be disconnected.
*/
export const PingRequestSchema = RequestSchema.extend({
method: z.literal("ping"),
});
/* Progress notifications */
export const ProgressSchema = z
.object({
/**
* The progress thus far. This should increase every time progress is made, even if the total is unknown.
*/
progress: z.number(),
/**
* Total number of items to process (or total progress required), if known.
*/
total: z.optional(z.number()),
})
.passthrough();
/**
* An out-of-band notification used to inform the receiver of a progress update for a long-running request.
*/
export const ProgressNotificationSchema = NotificationSchema.extend({
method: z.literal("notifications/progress"),
params: BaseNotificationParamsSchema.merge(ProgressSchema).extend({
/**
* The progress token which was given in the initial request, used to associate this notification with the request that is proceeding.
*/
progressToken: ProgressTokenSchema,
}),
});
/* Pagination */
export const PaginatedRequestSchema = RequestSchema.extend({
params: BaseRequestParamsSchema.extend({
/**
* An opaque token representing the current pagination position.
* If provided, the server should return results starting after this cursor.
*/
cursor: z.optional(CursorSchema),
}).optional(),
});
export const PaginatedResultSchema = ResultSchema.extend({
/**
* An opaque token representing the pagination position after the last returned result.
* If present, there may be more results available.
*/
nextCursor: z.optional(CursorSchema),
});
/* Resources */
/**
* The contents of a specific resource or sub-resource.
*/
export const ResourceContentsSchema = z
.object({
/**
* The URI of this resource.
*/
uri: z.string(),
/**
* The MIME type of this resource, if known.
*/
mimeType: z.optional(z.string()),
})
.passthrough();
export const TextResourceContentsSchema = ResourceContentsSchema.extend({
/**
* The text of the item. This must only be set if the item can actually be represented as text (not binary data).
*/
text: z.string(),
});
export const BlobResourceContentsSchema = ResourceContentsSchema.extend({
/**
* A base64-encoded string representing the binary data of the item.
*/
blob: z.string().base64(),
});
/**
* A known resource that the server is capable of reading.
*/
export const ResourceSchema = z
.object({
/**
* The URI of this resource.
*/
uri: z.string(),
/**
* A human-readable name for this resource.
*
* This can be used by clients to populate UI elements.
*/
name: z.string(),
/**
* A description of what this resource represents.
*
* This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a "hint" to the model.
*/
description: z.optional(z.string()),
/**
* The MIME type of this resource, if known.
*/
mimeType: z.optional(z.string()),
})
.passthrough();
/**
* A template description for resources available on the server.
*/
export const ResourceTemplateSchema = z
.object({
/**
* A URI template (according to RFC 6570) that can be used to construct resource URIs.
*/
uriTemplate: z.string(),
/**
* A human-readable name for the type of resource this template refers to.
*
* This can be used by clients to populate UI elements.
*/
name: z.string(),
/**
* A description of what this template is for.
*
* This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a "hint" to the model.
*/
description: z.optional(z.string()),
/**
* The MIME type for all resources that match this template. This should only be included if all resources matching this template have the same type.
*/
mimeType: z.optional(z.string()),
})
.passthrough();
/**
* Sent from the client to request a list of resources the server has.
*/
export const ListResourcesRequestSchema = PaginatedRequestSchema.extend({
method: z.literal("resources/list"),
});
/**
* The server's response to a resources/list request from the client.
*/
export const ListResourcesResultSchema = PaginatedResultSchema.extend({
resources: z.array(ResourceSchema),
});
/**
* Sent from the client to request a list of resource templates the server has.
*/
export const ListResourceTemplatesRequestSchema = PaginatedRequestSchema.extend({
method: z.literal("resources/templates/list"),
});
/**
* The server's response to a resources/templates/list request from the client.
*/
export const ListResourceTemplatesResultSchema = PaginatedResultSchema.extend({
resourceTemplates: z.array(ResourceTemplateSchema),
});
/**
* Sent from the client to the server, to read a specific resource URI.
*/
export const ReadResourceRequestSchema = RequestSchema.extend({
method: z.literal("resources/read"),
params: BaseRequestParamsSchema.extend({
/**
* The URI of the resource to read. The URI can use any protocol; it is up to the server how to interpret it.
*/
uri: z.string(),
}),
});
/**
* The server's response to a resources/read request from the client.
*/
export const ReadResourceResultSchema = ResultSchema.extend({
contents: z.array(z.union([TextResourceContentsSchema, BlobResourceContentsSchema])),
});
/**
* An optional notification from the server to the client, informing it that the list of resources it can read from has changed. This may be issued by servers without any previous subscription from the client.
*/
export const ResourceListChangedNotificationSchema = NotificationSchema.extend({
method: z.literal("notifications/resources/list_changed"),
});
/**
* Sent from the client to request resources/updated notifications from the server whenever a particular resource changes.
*/
export const SubscribeRequestSchema = RequestSchema.extend({
method: z.literal("resources/subscribe"),
params: BaseRequestParamsSchema.extend({
/**
* The URI of the resource to subscribe to. The URI can use any protocol; it is up to the server how to interpret it.
*/
uri: z.string(),
}),
});
/**
* Sent from the client to request cancellation of resources/updated notifications from the server. This should follow a previous resources/subscribe request.
*/
export const UnsubscribeRequestSchema = RequestSchema.extend({
method: z.literal("resources/unsubscribe"),
params: BaseRequestParamsSchema.extend({
/**
* The URI of the resource to unsubscribe from.
*/
uri: z.string(),
}),
});
/**
* A notification from the server to the client, informing it that a resource has changed and may need to be read again. This should only be sent if the client previously sent a resources/subscribe request.
*/
export const ResourceUpdatedNotificationSchema = NotificationSchema.extend({
method: z.literal("notifications/resources/updated"),
params: BaseNotificationParamsSchema.extend({
/**
* The URI of the resource that has been updated. This might be a sub-resource of the one that the client actually subscribed to.
*/
uri: z.string(),
}),
});
/* Prompts */
/**
* Describes an argument that a prompt can accept.
*/
export const PromptArgumentSchema = z
.object({
/**
* The name of the argument.
*/
name: z.string(),
/**
* A human-readable description of the argument.
*/
description: z.optional(z.string()),
/**
* Whether this argument must be provided.
*/
required: z.optional(z.boolean()),
})
.passthrough();
/**
* A prompt or prompt template that the server offers.
*/
export const PromptSchema = z
.object({
/**
* The name of the prompt or prompt template.
*/
name: z.string(),
/**
* An optional description of what this prompt provides
*/
description: z.optional(z.string()),
/**
* A list of arguments to use for templating the prompt.
*/
arguments: z.optional(z.array(PromptArgumentSchema)),
})
.passthrough();
/**
* Sent from the client to request a list of prompts and prompt templates the server has.
*/
export const ListPromptsRequestSchema = PaginatedRequestSchema.extend({
method: z.literal("prompts/list"),
});
/**
* The server's response to a prompts/list request from the client.
*/
export const ListPromptsResultSchema = PaginatedResultSchema.extend({
prompts: z.array(PromptSchema),
});
/**
* Used by the client to get a prompt provided by the server.
*/
export const GetPromptRequestSchema = RequestSchema.extend({
method: z.literal("prompts/get"),
params: BaseRequestParamsSchema.extend({
/**
* The name of the prompt or prompt template.
*/
name: z.string(),
/**
* Arguments to use for templating the prompt.
*/
arguments: z.optional(z.record(z.string())),
}),
});
/**
* Text provided to or from an LLM.
*/
export const TextContentSchema = z
.object({
type: z.literal("text"),
/**
* The text content of the message.
*/
text: z.string(),
})
.passthrough();
/**
* An image provided to or from an LLM.
*/
export const ImageContentSchema = z
.object({
type: z.literal("image"),
/**
* The base64-encoded image data.
*/
data: z.string().base64(),
/**
* The MIME type of the image. Different providers may support different image types.
*/
mimeType: z.string(),
})
.passthrough();
/**
* The contents of a resource, embedded into a prompt or tool call result.
*/
export const EmbeddedResourceSchema = z
.object({
type: z.literal("resource"),
resource: z.union([TextResourceContentsSchema, BlobResourceContentsSchema]),
})
.passthrough();
/**
* Describes a message returned as part of a prompt.
*/
export const PromptMessageSchema = z
.object({
role: z.enum(["user", "assistant"]),
content: z.union([
TextContentSchema,
ImageContentSchema,
EmbeddedResourceSchema,
]),
})
.passthrough();
/**
* The server's response to a prompts/get request from the client.
*/
export const GetPromptResultSchema = ResultSchema.extend({
/**
* An optional description for the prompt.
*/
description: z.optional(z.string()),
messages: z.array(PromptMessageSchema),
});
/**
* An optional notification from the server to the client, informing it that the list of prompts it offers has changed. This may be issued by servers without any previous subscription from the client.
*/
export const PromptListChangedNotificationSchema = NotificationSchema.extend({
method: z.literal("notifications/prompts/list_changed"),
});
/* Tools */
/**
* Definition for a tool the client can call.
*/
export const ToolSchema = z
.object({
/**
* The name of the tool.
*/
name: z.string(),
/**
* A human-readable description of the tool.
*/
description: z.optional(z.string()),
/**
* A JSON Schema object defining the expected parameters for the tool.
*/
inputSchema: z
.object({
type: z.literal("object"),
properties: z.optional(z.object({}).passthrough()),
})
.passthrough(),
})
.passthrough();
/**
* Sent from the client to request a list of tools the server has.
*/
export const ListToolsRequestSchema = PaginatedRequestSchema.extend({
method: z.literal("tools/list"),
});
/**
* The server's response to a tools/list request from the client.
*/
export const ListToolsResultSchema = PaginatedResultSchema.extend({
tools: z.array(ToolSchema),
});
/**
* The server's response to a tool call.
*/
export const CallToolResultSchema = ResultSchema.extend({
content: z.array(z.union([TextContentSchema, ImageContentSchema, EmbeddedResourceSchema])),
isError: z.boolean().default(false).optional(),
});
/**
* CallToolResultSchema extended with backwards compatibility to protocol version 2024-10-07.
*/
export const CompatibilityCallToolResultSchema = CallToolResultSchema.or(ResultSchema.extend({
toolResult: z.unknown(),
}));
/**
* Used by the client to invoke a tool provided by the server.
*/
export const CallToolRequestSchema = RequestSchema.extend({
method: z.literal("tools/call"),
params: BaseRequestParamsSchema.extend({
name: z.string(),
arguments: z.optional(z.record(z.unknown())),
}),
});
/**
* An optional notification from the server to the client, informing it that the list of tools it offers has changed. This may be issued by servers without any previous subscription from the client.
*/
export const ToolListChangedNotificationSchema = NotificationSchema.extend({
method: z.literal("notifications/tools/list_changed"),
});
/* Logging */
/**
* The severity of a log message.
*/
export const LoggingLevelSchema = z.enum([
"debug",
"info",
"notice",
"warning",
"error",
"critical",
"alert",
"emergency",
]);
/**
* A request from the client to the server, to enable or adjust logging.
*/
export const SetLevelRequestSchema = RequestSchema.extend({
method: z.literal("logging/setLevel"),
params: BaseRequestParamsSchema.extend({
/**
* The level of logging that the client wants to receive from the server. The server should send all logs at this level and higher (i.e., more severe) to the client as notifications/logging/message.
*/
level: LoggingLevelSchema,
}),
});
/**
* Notification of a log message passed from server to client. If no logging/setLevel request has been sent from the client, the server MAY decide which messages to send automatically.
*/
export const LoggingMessageNotificationSchema = NotificationSchema.extend({
method: z.literal("notifications/message"),
params: BaseNotificationParamsSchema.extend({
/**
* The severity of this log message.
*/
level: LoggingLevelSchema,
/**
* An optional name of the logger issuing this message.
*/
logger: z.optional(z.string()),
/**
* The data to be logged, such as a string message or an object. Any JSON serializable type is allowed here.
*/
data: z.unknown(),
}),
});
/* Sampling */
/**
* Hints to use for model selection.
*/
export const ModelHintSchema = z
.object({
/**
* A hint for a model name.
*/
name: z.string().optional(),
})
.passthrough();
/**
* The server's preferences for model selection, requested of the client during sampling.
*/
export const ModelPreferencesSchema = z
.object({
/**
* Optional hints to use for model selection.
*/
hints: z.optional(z.array(ModelHintSchema)),
/**
* How much to prioritize cost when selecting a model.
*/
costPriority: z.optional(z.number().min(0).max(1)),
/**
* How much to prioritize sampling speed (latency) when selecting a model.
*/
speedPriority: z.optional(z.number().min(0).max(1)),
/**
* How much to prioritize intelligence and capabilities when selecting a model.
*/
intelligencePriority: z.optional(z.number().min(0).max(1)),
})
.passthrough();
/**
* Describes a message issued to or received from an LLM API.
*/
export const SamplingMessageSchema = z
.object({
role: z.enum(["user", "assistant"]),
content: z.union([TextContentSchema, ImageContentSchema]),
})
.passthrough();
/**
* A request from the server to sample an LLM via the client. The client has full discretion over which model to select. The client should also inform the user before beginning sampling, to allow them to inspect the request (human in the loop) and decide whether to approve it.
*/
export const CreateMessageRequestSchema = RequestSchema.extend({
method: z.literal("sampling/createMessage"),
params: BaseRequestParamsSchema.extend({
messages: z.array(SamplingMessageSchema),
/**
* An optional system prompt the server wants to use for sampling. The client MAY modify or omit this prompt.
*/
systemPrompt: z.optional(z.string()),
/**
* A request to include context from one or more MCP servers (including the caller), to be attached to the prompt. The client MAY ignore this request.
*/
includeContext: z.optional(z.enum(["none", "thisServer", "allServers"])),
temperature: z.optional(z.number()),
/**
* The maximum number of tokens to sample, as requested by the server. The client MAY choose to sample fewer tokens than requested.
*/
maxTokens: z.number().int(),
stopSequences: z.optional(z.array(z.string())),
/**
* Optional metadata to pass through to the LLM provider. The format of this metadata is provider-specific.
*/
metadata: z.optional(z.object({}).passthrough()),
/**
* The server's preferences for which model to select.
*/
modelPreferences: z.optional(ModelPreferencesSchema),
}),
});
/**
* The client's response to a sampling/create_message request from the server. The client should inform the user before returning the sampled message, to allow them to inspect the response (human in the loop) and decide whether to allow the server to see it.
*/
export const CreateMessageResultSchema = ResultSchema.extend({
/**
* The name of the model that generated the message.
*/
model: z.string(),
/**
* The reason why sampling stopped.
*/
stopReason: z.optional(z.enum(["endTurn", "stopSequence", "maxTokens"]).or(z.string())),
role: z.enum(["user", "assistant"]),
content: z.discriminatedUnion("type", [
TextContentSchema,
ImageContentSchema,
]),
});
/* Autocomplete */
/**
* A reference to a resource or resource template definition.
*/
export const ResourceReferenceSchema = z
.object({
type: z.literal("ref/resource"),
/**
* The URI or URI template of the resource.
*/
uri: z.string(),
})
.passthrough();
/**
* Identifies a prompt.
*/
export const PromptReferenceSchema = z
.object({
type: z.literal("ref/prompt"),
/**
* The name of the prompt or prompt template
*/
name: z.string(),
})
.passthrough();
/**
* A request from the client to the server, to ask for completion options.
*/
export const CompleteRequestSchema = RequestSchema.extend({
method: z.literal("completion/complete"),
params: BaseRequestParamsSchema.extend({
ref: z.union([PromptReferenceSchema, ResourceReferenceSchema]),
/**
* The argument's information
*/
argument: z
.object({
/**
* The name of the argument
*/
name: z.string(),
/**
* The value of the argument to use for completion matching.
*/
value: z.string(),
})
.passthrough(),
}),
});
/**
* The server's response to a completion/complete request
*/
export const CompleteResultSchema = ResultSchema.extend({
completion: z
.object({
/**
* An array of completion values. Must not exceed 100 items.
*/
values: z.array(z.string()).max(100),
/**
* The total number of completion options available. This can exceed the number of values actually sent in the response.
*/
total: z.optional(z.number().int()),
/**
* Indicates whether there are additional completion options beyond those provided in the current response, even if the exact total is unknown.
*/
hasMore: z.optional(z.boolean()),
})
.passthrough(),
});
/* Roots */
/**
* Represents a root directory or file that the server can operate on.
*/
export const RootSchema = z
.object({
/**
* The URI identifying the root. This *must* start with file:// for now.
*/
uri: z.string().startsWith("file://"),
/**
* An optional name for the root.
*/
name: z.optional(z.string()),
})
.passthrough();
/**
* Sent from the server to request a list of root URIs from the client.
*/
export const ListRootsRequestSchema = RequestSchema.extend({
method: z.literal("roots/list"),
});
/**
* The client's response to a roots/list request from the server.
*/
export const ListRootsResultSchema = ResultSchema.extend({
roots: z.array(RootSchema),
});
/**
* A notification from the client to the server, informing it that the list of roots has changed.
*/
export const RootsListChangedNotificationSchema = NotificationSchema.extend({
method: z.literal("notifications/roots/list_changed"),
});
/* Client messages */
export const ClientRequestSchema = z.union([
PingRequestSchema,
InitializeRequestSchema,
CompleteRequestSchema,
SetLevelRequestSchema,
GetPromptRequestSchema,
ListPromptsRequestSchema,
ListResourcesRequestSchema,
ListResourceTemplatesRequestSchema,
ReadResourceRequestSchema,
SubscribeRequestSchema,
UnsubscribeRequestSchema,
CallToolRequestSchema,
ListToolsRequestSchema,
]);
export const ClientNotificationSchema = z.union([
CancelledNotificationSchema,
ProgressNotificationSchema,
InitializedNotificationSchema,
RootsListChangedNotificationSchema,
]);
export const ClientResultSchema = z.union([
EmptyResultSchema,
CreateMessageResultSchema,
ListRootsResultSchema,
]);
/* Server messages */
export const ServerRequestSchema = z.union([
PingRequestSchema,
CreateMessageRequestSchema,
ListRootsRequestSchema,
]);
export const ServerNotificationSchema = z.union([
CancelledNotificationSchema,
ProgressNotificationSchema,
LoggingMessageNotificationSchema,
ResourceUpdatedNotificationSchema,
ResourceListChangedNotificationSchema,
ToolListChangedNotificationSchema,
PromptListChangedNotificationSchema,
]);
export const ServerResultSchema = z.union([
EmptyResultSchema,
InitializeResultSchema,
CompleteResultSchema,
GetPromptResultSchema,
ListPromptsResultSchema,
ListResourcesResultSchema,
ListResourceTemplatesResultSchema,
ReadResourceResultSchema,
CallToolResultSchema,
ListToolsResultSchema,
]);
export class McpError extends Error {
constructor(code, message, data) {
super(`MCP error ${code}: ${message}`);
this.code = code;
this.data = data;
}
}
//# sourceMappingURL=types.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
/**
* Returns an AbortSignal that will enter aborted state after `timeoutMs` milliseconds.
*/
export declare function abortAfterTimeout(timeoutMs: number): AbortSignal;
//# sourceMappingURL=utils.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,CAOhE"}

View File

@@ -0,0 +1,11 @@
/**
* Returns an AbortSignal that will enter aborted state after `timeoutMs` milliseconds.
*/
export function abortAfterTimeout(timeoutMs) {
const controller = new AbortController();
setTimeout(() => {
controller.abort();
}, timeoutMs);
return controller.signal;
}
//# sourceMappingURL=utils.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,UAAU,CAAC,GAAG,EAAE;QACd,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC,EAAE,SAAS,CAAC,CAAC;IAEd,OAAO,UAAU,CAAC,MAAM,CAAC;AAC3B,CAAC"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=utils.test.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../src/utils.test.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,14 @@
import { abortAfterTimeout } from "./utils.js";
describe("abortAfterTimeout", () => {
it("should abort after timeout", () => {
const signal = abortAfterTimeout(0);
expect(signal.aborted).toBe(false);
return new Promise((resolve) => {
setTimeout(() => {
expect(signal.aborted).toBe(true);
resolve(true);
}, 0);
});
});
});
//# sourceMappingURL=utils.test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../src/utils.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,MAAM,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEnC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,UAAU,CAAC,GAAG,EAAE;gBACd,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClC,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC,EAAE,CAAC,CAAC,CAAC;QACR,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}