Merge branch 'main' into fix/1
This commit is contained in:
commit
4607f37953
15 changed files with 141 additions and 86 deletions
|
|
@ -1041,7 +1041,7 @@ Client-side: Handle elicitation requests
|
|||
```typescript
|
||||
// This is a placeholder - implement based on your UI framework
|
||||
async function getInputFromUser(message: string, schema: any): Promise<{
|
||||
action: "accept" | "reject" | "cancel";
|
||||
action: "accept" | "decline" | "cancel";
|
||||
data?: Record<string, any>;
|
||||
}> {
|
||||
// This should be implemented depending on the app
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "@modelcontextprotocol/sdk",
|
||||
"version": "1.13.3",
|
||||
"version": "1.15.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@modelcontextprotocol/sdk",
|
||||
"version": "1.13.3",
|
||||
"version": "1.15.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.6",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@modelcontextprotocol/sdk",
|
||||
"version": "1.13.3",
|
||||
"version": "1.15.0",
|
||||
"description": "Model Context Protocol implementation for TypeScript",
|
||||
"license": "MIT",
|
||||
"author": "Anthropic, PBC (https://anthropic.com)",
|
||||
|
|
|
|||
|
|
@ -262,6 +262,38 @@ describe("SSEClientTransport", () => {
|
|||
expect(lastServerRequest.headers.authorization).toBe(authToken);
|
||||
});
|
||||
|
||||
it("uses custom fetch implementation from options", async () => {
|
||||
const authToken = "Bearer custom-token";
|
||||
|
||||
const fetchWithAuth = jest.fn((url: string | URL, init?: RequestInit) => {
|
||||
const headers = new Headers(init?.headers);
|
||||
headers.set("Authorization", authToken);
|
||||
return fetch(url.toString(), { ...init, headers });
|
||||
});
|
||||
|
||||
transport = new SSEClientTransport(resourceBaseUrl, {
|
||||
fetch: fetchWithAuth,
|
||||
});
|
||||
|
||||
await transport.start();
|
||||
|
||||
expect(lastServerRequest.headers.authorization).toBe(authToken);
|
||||
|
||||
// Send a message to verify fetchWithAuth used for POST as well
|
||||
const message: JSONRPCMessage = {
|
||||
jsonrpc: "2.0",
|
||||
id: "1",
|
||||
method: "test",
|
||||
params: {},
|
||||
};
|
||||
|
||||
await transport.send(message);
|
||||
|
||||
expect(fetchWithAuth).toHaveBeenCalledTimes(2);
|
||||
expect(lastServerRequest.method).toBe("POST");
|
||||
expect(lastServerRequest.headers.authorization).toBe(authToken);
|
||||
});
|
||||
|
||||
it("passes custom headers to fetch requests", async () => {
|
||||
const customHeaders = {
|
||||
Authorization: "Bearer test-token",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { EventSource, type ErrorEvent, type EventSourceInit } from "eventsource";
|
||||
import { Transport } from "../shared/transport.js";
|
||||
import { Transport, FetchLike } from "../shared/transport.js";
|
||||
import { JSONRPCMessage, JSONRPCMessageSchema } from "../types.js";
|
||||
import { auth, AuthResult, extractResourceMetadataUrl, OAuthClientProvider, UnauthorizedError } from "./auth.js";
|
||||
|
||||
|
|
@ -47,6 +47,11 @@ export type SSEClientTransportOptions = {
|
|||
* Customizes recurring POST requests to the server.
|
||||
*/
|
||||
requestInit?: RequestInit;
|
||||
|
||||
/**
|
||||
* Custom fetch implementation used for all network requests.
|
||||
*/
|
||||
fetch?: FetchLike;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -62,6 +67,7 @@ export class SSEClientTransport implements Transport {
|
|||
private _eventSourceInit?: EventSourceInit;
|
||||
private _requestInit?: RequestInit;
|
||||
private _authProvider?: OAuthClientProvider;
|
||||
private _fetch?: FetchLike;
|
||||
private _protocolVersion?: string;
|
||||
|
||||
onclose?: () => void;
|
||||
|
|
@ -77,6 +83,7 @@ export class SSEClientTransport implements Transport {
|
|||
this._eventSourceInit = opts?.eventSourceInit;
|
||||
this._requestInit = opts?.requestInit;
|
||||
this._authProvider = opts?.authProvider;
|
||||
this._fetch = opts?.fetch;
|
||||
}
|
||||
|
||||
private async _authThenStart(): Promise<void> {
|
||||
|
|
@ -117,7 +124,7 @@ export class SSEClientTransport implements Transport {
|
|||
}
|
||||
|
||||
private _startOrAuth(): Promise<void> {
|
||||
const fetchImpl = (this?._eventSourceInit?.fetch || fetch) as typeof fetch
|
||||
const fetchImpl = (this?._eventSourceInit?.fetch ?? this._fetch ?? fetch) as typeof fetch
|
||||
return new Promise((resolve, reject) => {
|
||||
this._eventSource = new EventSource(
|
||||
this._url.href,
|
||||
|
|
@ -242,7 +249,7 @@ export class SSEClientTransport implements Transport {
|
|||
signal: this._abortController?.signal,
|
||||
};
|
||||
|
||||
const response = await fetch(this._endpoint, init);
|
||||
const response = await (this._fetch ?? fetch)(this._endpoint, init);
|
||||
if (!response.ok) {
|
||||
if (response.status === 401 && this._authProvider) {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { StreamableHTTPClientTransport, StreamableHTTPReconnectionOptions } from "./streamableHttp.js";
|
||||
import { StreamableHTTPClientTransport, StreamableHTTPReconnectionOptions, StartSSEOptions } from "./streamableHttp.js";
|
||||
import { OAuthClientProvider, UnauthorizedError } from "./auth.js";
|
||||
import { JSONRPCMessage } from "../types.js";
|
||||
|
||||
|
|
@ -443,6 +443,35 @@ describe("StreamableHTTPClientTransport", () => {
|
|||
expect(errorSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("uses custom fetch implementation", async () => {
|
||||
const authToken = "Bearer custom-token";
|
||||
|
||||
const fetchWithAuth = jest.fn((url: string | URL, init?: RequestInit) => {
|
||||
const headers = new Headers(init?.headers);
|
||||
headers.set("Authorization", authToken);
|
||||
return (global.fetch as jest.Mock)(url, { ...init, headers });
|
||||
});
|
||||
|
||||
(global.fetch as jest.Mock)
|
||||
.mockResolvedValueOnce(
|
||||
new Response(null, { status: 200, headers: { "content-type": "text/event-stream" } })
|
||||
)
|
||||
.mockResolvedValueOnce(new Response(null, { status: 202 }));
|
||||
|
||||
transport = new StreamableHTTPClientTransport(new URL("http://localhost:1234/mcp"), { fetch: fetchWithAuth });
|
||||
|
||||
await transport.start();
|
||||
await (transport as unknown as { _startOrAuthSse: (opts: StartSSEOptions) => Promise<void> })._startOrAuthSse({});
|
||||
|
||||
await transport.send({ jsonrpc: "2.0", method: "test", params: {}, id: "1" } as JSONRPCMessage);
|
||||
|
||||
expect(fetchWithAuth).toHaveBeenCalled();
|
||||
for (const call of (global.fetch as jest.Mock).mock.calls) {
|
||||
const headers = call[1].headers as Headers;
|
||||
expect(headers.get("Authorization")).toBe(authToken);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
it("should always send specified custom headers", async () => {
|
||||
const requestInit = {
|
||||
|
|
@ -530,7 +559,7 @@ describe("StreamableHTTPClientTransport", () => {
|
|||
// Second retry - should double (2^1 * 100 = 200)
|
||||
expect(getDelay(1)).toBe(200);
|
||||
|
||||
// Third retry - should double again (2^2 * 100 = 400)
|
||||
// Third retry - should double again (2^2 * 100 = 400)
|
||||
expect(getDelay(2)).toBe(400);
|
||||
|
||||
// Fourth retry - should double again (2^3 * 100 = 800)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Transport } from "../shared/transport.js";
|
||||
import { Transport, FetchLike } from "../shared/transport.js";
|
||||
import { isInitializedNotification, isJSONRPCRequest, isJSONRPCResponse, JSONRPCMessage, JSONRPCMessageSchema } from "../types.js";
|
||||
import { auth, AuthResult, extractResourceMetadataUrl, OAuthClientProvider, UnauthorizedError } from "./auth.js";
|
||||
import { EventSourceParserStream } from "eventsource-parser/stream";
|
||||
|
|
@ -23,7 +23,7 @@ export class StreamableHTTPError extends Error {
|
|||
/**
|
||||
* Options for starting or authenticating an SSE connection
|
||||
*/
|
||||
interface StartSSEOptions {
|
||||
export interface StartSSEOptions {
|
||||
/**
|
||||
* The resumption token used to continue long-running requests that were interrupted.
|
||||
*
|
||||
|
|
@ -99,6 +99,11 @@ export type StreamableHTTPClientTransportOptions = {
|
|||
*/
|
||||
requestInit?: RequestInit;
|
||||
|
||||
/**
|
||||
* Custom fetch implementation used for all network requests.
|
||||
*/
|
||||
fetch?: FetchLike;
|
||||
|
||||
/**
|
||||
* Options to configure the reconnection behavior.
|
||||
*/
|
||||
|
|
@ -122,6 +127,7 @@ export class StreamableHTTPClientTransport implements Transport {
|
|||
private _resourceMetadataUrl?: URL;
|
||||
private _requestInit?: RequestInit;
|
||||
private _authProvider?: OAuthClientProvider;
|
||||
private _fetch?: FetchLike;
|
||||
private _sessionId?: string;
|
||||
private _reconnectionOptions: StreamableHTTPReconnectionOptions;
|
||||
private _protocolVersion?: string;
|
||||
|
|
@ -138,6 +144,7 @@ export class StreamableHTTPClientTransport implements Transport {
|
|||
this._resourceMetadataUrl = undefined;
|
||||
this._requestInit = opts?.requestInit;
|
||||
this._authProvider = opts?.authProvider;
|
||||
this._fetch = opts?.fetch;
|
||||
this._sessionId = opts?.sessionId;
|
||||
this._reconnectionOptions = opts?.reconnectionOptions ?? DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS;
|
||||
}
|
||||
|
|
@ -200,7 +207,7 @@ export class StreamableHTTPClientTransport implements Transport {
|
|||
headers.set("last-event-id", resumptionToken);
|
||||
}
|
||||
|
||||
const response = await fetch(this._url, {
|
||||
const response = await (this._fetch ?? fetch)(this._url, {
|
||||
method: "GET",
|
||||
headers,
|
||||
signal: this._abortController?.signal,
|
||||
|
|
@ -251,15 +258,15 @@ export class StreamableHTTPClientTransport implements Transport {
|
|||
|
||||
private _normalizeHeaders(headers: HeadersInit | undefined): Record<string, string> {
|
||||
if (!headers) return {};
|
||||
|
||||
|
||||
if (headers instanceof Headers) {
|
||||
return Object.fromEntries(headers.entries());
|
||||
}
|
||||
|
||||
|
||||
if (Array.isArray(headers)) {
|
||||
return Object.fromEntries(headers);
|
||||
}
|
||||
|
||||
|
||||
return { ...headers as Record<string, string> };
|
||||
}
|
||||
|
||||
|
|
@ -414,7 +421,7 @@ export class StreamableHTTPClientTransport implements Transport {
|
|||
signal: this._abortController?.signal,
|
||||
};
|
||||
|
||||
const response = await fetch(this._url, init);
|
||||
const response = await (this._fetch ?? fetch)(this._url, init);
|
||||
|
||||
// Handle session ID received during initialization
|
||||
const sessionId = response.headers.get("mcp-session-id");
|
||||
|
|
@ -520,7 +527,7 @@ export class StreamableHTTPClientTransport implements Transport {
|
|||
signal: this._abortController?.signal,
|
||||
};
|
||||
|
||||
const response = await fetch(this._url, init);
|
||||
const response = await (this._fetch ?? fetch)(this._url, init);
|
||||
|
||||
// We specifically handle 405 as a valid response according to the spec,
|
||||
// meaning the server does not support explicit session termination
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ async function connect(url?: string): Promise<void> {
|
|||
continue;
|
||||
} else {
|
||||
console.log('Maximum attempts reached. Declining request.');
|
||||
return { action: 'reject' };
|
||||
return { action: 'decline' };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -381,7 +381,7 @@ async function connect(url?: string): Promise<void> {
|
|||
continue;
|
||||
} else {
|
||||
console.log('Maximum attempts reached. Declining request.');
|
||||
return { action: 'reject' };
|
||||
return { action: 'decline' };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -408,13 +408,13 @@ async function connect(url?: string): Promise<void> {
|
|||
console.log('Please re-enter the information...');
|
||||
continue;
|
||||
} else {
|
||||
return { action: 'reject' };
|
||||
return { action: 'decline' };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Maximum attempts reached. Declining request.');
|
||||
return { action: 'reject' };
|
||||
return { action: 'decline' };
|
||||
});
|
||||
|
||||
transport = new StreamableHTTPClientTransport(
|
||||
|
|
|
|||
|
|
@ -43,14 +43,7 @@ server.registerTool(
|
|||
void country;
|
||||
// Simulate weather API call
|
||||
const temp_c = Math.round((Math.random() * 35 - 5) * 10) / 10;
|
||||
const conditionCandidates = [
|
||||
"sunny",
|
||||
"cloudy",
|
||||
"rainy",
|
||||
"stormy",
|
||||
"snowy",
|
||||
] as const;
|
||||
const conditions = conditionCandidates[Math.floor(Math.random() * conditionCandidates.length)];
|
||||
const conditions = ["sunny", "cloudy", "rainy", "stormy", "snowy"][Math.floor(Math.random() * 5)];
|
||||
|
||||
const structuredContent = {
|
||||
temperature: {
|
||||
|
|
@ -84,4 +77,4 @@ async function main() {
|
|||
main().catch((error) => {
|
||||
console.error("Server error:", error);
|
||||
process.exit(1);
|
||||
});
|
||||
});
|
||||
|
|
@ -206,12 +206,12 @@ const getServer = () => {
|
|||
},
|
||||
],
|
||||
};
|
||||
} else if (result.action === 'reject') {
|
||||
} else if (result.action === 'decline') {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `No information was collected. User rejected ${infoType} information request.`,
|
||||
text: `No information was collected. User declined ${infoType} information request.`,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
@ -433,7 +433,7 @@ if (useOAuth) {
|
|||
const mcpServerUrl = new URL(`http://localhost:${MCP_PORT}/mcp`);
|
||||
const authServerUrl = new URL(`http://localhost:${AUTH_PORT}`);
|
||||
|
||||
const oauthMetadata: OAuthMetadata = setupAuthServer({authServerUrl, mcpServerUrl, strictResource: strictOAuth});
|
||||
const oauthMetadata: OAuthMetadata = setupAuthServer({ authServerUrl, mcpServerUrl, strictResource: strictOAuth });
|
||||
|
||||
const tokenVerifier = {
|
||||
verifyAccessToken: async (token: string) => {
|
||||
|
|
@ -499,7 +499,12 @@ const transports: { [sessionId: string]: StreamableHTTPServerTransport } = {};
|
|||
// MCP POST endpoint with optional auth
|
||||
const mcpPostHandler = async (req: Request, res: Response) => {
|
||||
const sessionId = req.headers['mcp-session-id'] as string | undefined;
|
||||
console.log(sessionId? `Received MCP request for session: ${sessionId}`: 'Received MCP request:', req.body);
|
||||
if (sessionId) {
|
||||
console.log(`Received MCP request for session: ${sessionId}`);
|
||||
} else {
|
||||
console.log('Request body:', req.body);
|
||||
}
|
||||
|
||||
if (useOAuth && req.auth) {
|
||||
console.log('Authenticated user:', req.auth);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -538,7 +538,7 @@ test("should allow elicitation reject and cancel without validation", async () =
|
|||
client.setRequestHandler(ElicitRequestSchema, (request) => {
|
||||
requestCount++;
|
||||
if (requestCount === 1) {
|
||||
return { action: "reject" };
|
||||
return { action: "decline" };
|
||||
} else {
|
||||
return { action: "cancel" };
|
||||
}
|
||||
|
|
@ -566,7 +566,7 @@ test("should allow elicitation reject and cancel without validation", async () =
|
|||
requestedSchema: schema,
|
||||
}),
|
||||
).resolves.toEqual({
|
||||
action: "reject",
|
||||
action: "decline",
|
||||
});
|
||||
|
||||
// Test cancel - should not validate
|
||||
|
|
|
|||
|
|
@ -1312,7 +1312,7 @@ describe("tool()", () => {
|
|||
resultType: "structured",
|
||||
// Missing required 'timestamp' field
|
||||
someExtraField: "unexpected" // Extra field not in schema
|
||||
} as unknown as { processedInput: string; resultType: string; timestamp: string }, // Type assertion to bypass TypeScript validation for testing purposes
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ export class McpServer {
|
|||
}
|
||||
|
||||
const args = parseResult.data;
|
||||
const cb = tool.callback as ToolCallback<ZodRawShape, ZodRawShape>;
|
||||
const cb = tool.callback as ToolCallback<ZodRawShape>;
|
||||
try {
|
||||
result = await Promise.resolve(cb(args, extra));
|
||||
} catch (error) {
|
||||
|
|
@ -184,7 +184,7 @@ export class McpServer {
|
|||
};
|
||||
}
|
||||
} else {
|
||||
const cb = tool.callback as ToolCallback<undefined, ZodRawShape>;
|
||||
const cb = tool.callback as ToolCallback<undefined>;
|
||||
try {
|
||||
result = await Promise.resolve(cb(extra));
|
||||
} catch (error) {
|
||||
|
|
@ -772,7 +772,7 @@ export class McpServer {
|
|||
inputSchema: ZodRawShape | undefined,
|
||||
outputSchema: ZodRawShape | undefined,
|
||||
annotations: ToolAnnotations | undefined,
|
||||
callback: ToolCallback<ZodRawShape | undefined, ZodRawShape | undefined>
|
||||
callback: ToolCallback<ZodRawShape | undefined>
|
||||
): RegisteredTool {
|
||||
const registeredTool: RegisteredTool = {
|
||||
title,
|
||||
|
|
@ -929,7 +929,7 @@ export class McpServer {
|
|||
outputSchema?: OutputArgs;
|
||||
annotations?: ToolAnnotations;
|
||||
},
|
||||
cb: ToolCallback<InputArgs, OutputArgs>
|
||||
cb: ToolCallback<InputArgs>
|
||||
): RegisteredTool {
|
||||
if (this._registeredTools[name]) {
|
||||
throw new Error(`Tool ${name} is already registered`);
|
||||
|
|
@ -944,7 +944,7 @@ export class McpServer {
|
|||
inputSchema,
|
||||
outputSchema,
|
||||
annotations,
|
||||
cb as ToolCallback<ZodRawShape | undefined, ZodRawShape | undefined>
|
||||
cb as ToolCallback<ZodRawShape | undefined>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1138,16 +1138,6 @@ export class ResourceTemplate {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Type helper to create a strongly-typed CallToolResult with structuredContent
|
||||
*/
|
||||
type TypedCallToolResult<OutputArgs extends undefined | ZodRawShape> =
|
||||
OutputArgs extends ZodRawShape
|
||||
? CallToolResult & {
|
||||
structuredContent?: z.objectOutputType<OutputArgs, ZodTypeAny>;
|
||||
}
|
||||
: CallToolResult;
|
||||
|
||||
/**
|
||||
* Callback for a tool handler registered with Server.tool().
|
||||
*
|
||||
|
|
@ -1158,21 +1148,13 @@ type TypedCallToolResult<OutputArgs extends undefined | ZodRawShape> =
|
|||
* - `content` if the tool does not have an outputSchema
|
||||
* - Both fields are optional but typically one should be provided
|
||||
*/
|
||||
export type ToolCallback<
|
||||
InputArgs extends undefined | ZodRawShape = undefined,
|
||||
OutputArgs extends undefined | ZodRawShape = undefined
|
||||
> = InputArgs extends ZodRawShape
|
||||
export type ToolCallback<Args extends undefined | ZodRawShape = undefined> =
|
||||
Args extends ZodRawShape
|
||||
? (
|
||||
args: z.objectOutputType<InputArgs, ZodTypeAny>,
|
||||
extra: RequestHandlerExtra<ServerRequest, ServerNotification>
|
||||
) =>
|
||||
| TypedCallToolResult<OutputArgs>
|
||||
| Promise<TypedCallToolResult<OutputArgs>>
|
||||
: (
|
||||
extra: RequestHandlerExtra<ServerRequest, ServerNotification>
|
||||
) =>
|
||||
| TypedCallToolResult<OutputArgs>
|
||||
| Promise<TypedCallToolResult<OutputArgs>>;
|
||||
args: z.objectOutputType<Args, ZodTypeAny>,
|
||||
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
||||
) => CallToolResult | Promise<CallToolResult>
|
||||
: (extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => CallToolResult | Promise<CallToolResult>;
|
||||
|
||||
export type RegisteredTool = {
|
||||
title?: string;
|
||||
|
|
@ -1180,24 +1162,22 @@ export type RegisteredTool = {
|
|||
inputSchema?: AnyZodObject;
|
||||
outputSchema?: AnyZodObject;
|
||||
annotations?: ToolAnnotations;
|
||||
callback: ToolCallback<ZodRawShape | undefined, ZodRawShape | undefined>;
|
||||
callback: ToolCallback<undefined | ZodRawShape>;
|
||||
enabled: boolean;
|
||||
enable(): void;
|
||||
disable(): void;
|
||||
update<
|
||||
InputArgs extends ZodRawShape,
|
||||
OutputArgs extends ZodRawShape
|
||||
>(updates: {
|
||||
name?: string | null;
|
||||
title?: string;
|
||||
description?: string;
|
||||
paramsSchema?: InputArgs;
|
||||
outputSchema?: OutputArgs;
|
||||
annotations?: ToolAnnotations;
|
||||
callback?: ToolCallback<InputArgs, OutputArgs>
|
||||
enabled?: boolean
|
||||
}): void;
|
||||
remove(): void;
|
||||
update<InputArgs extends ZodRawShape, OutputArgs extends ZodRawShape>(
|
||||
updates: {
|
||||
name?: string | null,
|
||||
title?: string,
|
||||
description?: string,
|
||||
paramsSchema?: InputArgs,
|
||||
outputSchema?: OutputArgs,
|
||||
annotations?: ToolAnnotations,
|
||||
callback?: ToolCallback<InputArgs>,
|
||||
enabled?: boolean
|
||||
}): void
|
||||
remove(): void
|
||||
};
|
||||
|
||||
const EMPTY_OBJECT_JSON_SCHEMA = {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import { JSONRPCMessage, MessageExtraInfo, RequestId } from "../types.js";
|
||||
|
||||
export type FetchLike = (url: string | URL, init?: RequestInit) => Promise<Response>;
|
||||
|
||||
/**
|
||||
* Options for sending a JSON-RPC message.
|
||||
*/
|
||||
export type TransportSendOptions = {
|
||||
/**
|
||||
/**
|
||||
* If present, `relatedRequestId` is used to indicate to the transport which incoming request to associate this outgoing message with.
|
||||
*/
|
||||
relatedRequestId?: RequestId;
|
||||
|
|
@ -38,7 +40,7 @@ export interface Transport {
|
|||
|
||||
/**
|
||||
* Sends a JSON-RPC message (request or response).
|
||||
*
|
||||
*
|
||||
* If present, `relatedRequestId` is used to indicate to the transport which incoming request to associate this outgoing message with.
|
||||
*/
|
||||
send(message: JSONRPCMessage, options?: TransportSendOptions): Promise<void>;
|
||||
|
|
@ -64,9 +66,9 @@ export interface Transport {
|
|||
|
||||
/**
|
||||
* Callback for when a message (request or response) is received over the connection.
|
||||
*
|
||||
*
|
||||
* Includes the requestInfo and authInfo if the transport is authenticated.
|
||||
*
|
||||
*
|
||||
* The requestInfo can be used to get the original request information (headers, etc.)
|
||||
*/
|
||||
onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void;
|
||||
|
|
|
|||
|
|
@ -1238,7 +1238,7 @@ export const ElicitResultSchema = ResultSchema.extend({
|
|||
/**
|
||||
* The user's response action.
|
||||
*/
|
||||
action: z.enum(["accept", "reject", "cancel"]),
|
||||
action: z.enum(["accept", "decline", "cancel"]),
|
||||
/**
|
||||
* The collected user input content (only present if action is "accept").
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue