🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@ai-sdk/mcp

Package Overview
Dependencies
Maintainers
3
Versions
240
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ai-sdk/mcp - npm Package Compare versions

Comparing version
1.0.65
to
1.0.66
+6
-0
CHANGELOG.md
# @ai-sdk/mcp
## 1.0.66
### Patch Changes
- e8d2654: Honor MCP request deadlines and support bounding or aborting client initialization.
## 1.0.65

@@ -4,0 +10,0 @@

+33
-3

@@ -221,2 +221,26 @@ import { z } from 'zod/v4';

*/
type MCPTransportSendOptions = {
/**
* Cancels the transport operation for this message.
*/
signal?: AbortSignal;
/**
* Associates an outgoing message with an incoming request.
*/
relatedRequestId?: string | number;
/**
* Resumes a previously interrupted request.
*/
resumptionToken?: string;
/**
* Receives updated resumption tokens from transports that support them.
*/
onresumptiontoken?: (token: string) => void;
};
type MCPTransportCloseOptions = {
/**
* Cancels transport cleanup.
*/
signal?: AbortSignal;
};
interface MCPTransport {

@@ -230,8 +254,10 @@ /**

* @param message The JSON-RPC message to send
* @param options Optional request-scoped cancellation options
*/
send(message: JSONRPCMessage): Promise<void>;
send(message: JSONRPCMessage, options?: MCPTransportSendOptions): Promise<void>;
/**
* Clean up and close the transport
* @param options Optional cancellation options for transport cleanup
*/
close(): Promise<void>;
close(options?: MCPTransportCloseOptions): Promise<void>;
/**

@@ -538,2 +564,6 @@ * Event handler for transport closure

transport: MCPTransportConfig | MCPTransport;
/**
* Options that bound or cancel transport startup and the initialize request.
*/
initializationOptions?: RequestOptions;
/** Optional callback for uncaught errors */

@@ -626,2 +656,2 @@ onUncaughtError?: (error: unknown) => void;

export { type CallToolResult, type CompleteRequestParams, type CompleteResult, type Configuration, type ElicitResult, ElicitResultSchema, type ElicitationRequest, ElicitationRequestSchema, type JSONRPCError, type JSONRPCMessage, type JSONRPCNotification, type JSONRPCRequest, type JSONRPCResponse, type ListToolsResult, type MCPClient, type ClientCapabilities as MCPClientCapabilities, type MCPClientConfig, type MCPTransport, type OAuthAuthorizationServerInformation, type OAuthClientInformation, type OAuthClientMetadata, type OAuthClientProvider, type OAuthTokens, UnauthorizedError, auth, createMCPClient, type MCPClient as experimental_MCPClient, type ClientCapabilities as experimental_MCPClientCapabilities, type MCPClientConfig as experimental_MCPClientConfig, createMCPClient as experimental_createMCPClient, validateJSONRPCMessage };
export { type CallToolResult, type CompleteRequestParams, type CompleteResult, type Configuration, type ElicitResult, ElicitResultSchema, type ElicitationRequest, ElicitationRequestSchema, type JSONRPCError, type JSONRPCMessage, type JSONRPCNotification, type JSONRPCRequest, type JSONRPCResponse, type ListToolsResult, type MCPClient, type ClientCapabilities as MCPClientCapabilities, type MCPClientConfig, type MCPTransport, type MCPTransportCloseOptions, type MCPTransportSendOptions, type OAuthAuthorizationServerInformation, type OAuthClientInformation, type OAuthClientMetadata, type OAuthClientProvider, type OAuthTokens, UnauthorizedError, auth, createMCPClient, type MCPClient as experimental_MCPClient, type ClientCapabilities as experimental_MCPClientCapabilities, type MCPClientConfig as experimental_MCPClientConfig, createMCPClient as experimental_createMCPClient, validateJSONRPCMessage };

@@ -221,2 +221,26 @@ import { z } from 'zod/v4';

*/
type MCPTransportSendOptions = {
/**
* Cancels the transport operation for this message.
*/
signal?: AbortSignal;
/**
* Associates an outgoing message with an incoming request.
*/
relatedRequestId?: string | number;
/**
* Resumes a previously interrupted request.
*/
resumptionToken?: string;
/**
* Receives updated resumption tokens from transports that support them.
*/
onresumptiontoken?: (token: string) => void;
};
type MCPTransportCloseOptions = {
/**
* Cancels transport cleanup.
*/
signal?: AbortSignal;
};
interface MCPTransport {

@@ -230,8 +254,10 @@ /**

* @param message The JSON-RPC message to send
* @param options Optional request-scoped cancellation options
*/
send(message: JSONRPCMessage): Promise<void>;
send(message: JSONRPCMessage, options?: MCPTransportSendOptions): Promise<void>;
/**
* Clean up and close the transport
* @param options Optional cancellation options for transport cleanup
*/
close(): Promise<void>;
close(options?: MCPTransportCloseOptions): Promise<void>;
/**

@@ -538,2 +564,6 @@ * Event handler for transport closure

transport: MCPTransportConfig | MCPTransport;
/**
* Options that bound or cancel transport startup and the initialize request.
*/
initializationOptions?: RequestOptions;
/** Optional callback for uncaught errors */

@@ -626,2 +656,2 @@ onUncaughtError?: (error: unknown) => void;

export { type CallToolResult, type CompleteRequestParams, type CompleteResult, type Configuration, type ElicitResult, ElicitResultSchema, type ElicitationRequest, ElicitationRequestSchema, type JSONRPCError, type JSONRPCMessage, type JSONRPCNotification, type JSONRPCRequest, type JSONRPCResponse, type ListToolsResult, type MCPClient, type ClientCapabilities as MCPClientCapabilities, type MCPClientConfig, type MCPTransport, type OAuthAuthorizationServerInformation, type OAuthClientInformation, type OAuthClientMetadata, type OAuthClientProvider, type OAuthTokens, UnauthorizedError, auth, createMCPClient, type MCPClient as experimental_MCPClient, type ClientCapabilities as experimental_MCPClientCapabilities, type MCPClientConfig as experimental_MCPClientConfig, createMCPClient as experimental_createMCPClient, validateJSONRPCMessage };
export { type CallToolResult, type CompleteRequestParams, type CompleteResult, type Configuration, type ElicitResult, ElicitResultSchema, type ElicitationRequest, ElicitationRequestSchema, type JSONRPCError, type JSONRPCMessage, type JSONRPCNotification, type JSONRPCRequest, type JSONRPCResponse, type ListToolsResult, type MCPClient, type ClientCapabilities as MCPClientCapabilities, type MCPClientConfig, type MCPTransport, type MCPTransportCloseOptions, type MCPTransportSendOptions, type OAuthAuthorizationServerInformation, type OAuthClientInformation, type OAuthClientMetadata, type OAuthClientProvider, type OAuthTokens, UnauthorizedError, auth, createMCPClient, type MCPClient as experimental_MCPClient, type ClientCapabilities as experimental_MCPClientCapabilities, type MCPClientConfig as experimental_MCPClientConfig, createMCPClient as experimental_createMCPClient, validateJSONRPCMessage };

@@ -39,2 +39,26 @@ import { IOType } from 'node:child_process';

*/
type MCPTransportSendOptions = {
/**
* Cancels the transport operation for this message.
*/
signal?: AbortSignal;
/**
* Associates an outgoing message with an incoming request.
*/
relatedRequestId?: string | number;
/**
* Resumes a previously interrupted request.
*/
resumptionToken?: string;
/**
* Receives updated resumption tokens from transports that support them.
*/
onresumptiontoken?: (token: string) => void;
};
type MCPTransportCloseOptions = {
/**
* Cancels transport cleanup.
*/
signal?: AbortSignal;
};
interface MCPTransport {

@@ -48,8 +72,10 @@ /**

* @param message The JSON-RPC message to send
* @param options Optional request-scoped cancellation options
*/
send(message: JSONRPCMessage): Promise<void>;
send(message: JSONRPCMessage, options?: MCPTransportSendOptions): Promise<void>;
/**
* Clean up and close the transport
* @param options Optional cancellation options for transport cleanup
*/
close(): Promise<void>;
close(options?: MCPTransportCloseOptions): Promise<void>;
/**

@@ -56,0 +82,0 @@ * Event handler for transport closure

@@ -39,2 +39,26 @@ import { IOType } from 'node:child_process';

*/
type MCPTransportSendOptions = {
/**
* Cancels the transport operation for this message.
*/
signal?: AbortSignal;
/**
* Associates an outgoing message with an incoming request.
*/
relatedRequestId?: string | number;
/**
* Resumes a previously interrupted request.
*/
resumptionToken?: string;
/**
* Receives updated resumption tokens from transports that support them.
*/
onresumptiontoken?: (token: string) => void;
};
type MCPTransportCloseOptions = {
/**
* Cancels transport cleanup.
*/
signal?: AbortSignal;
};
interface MCPTransport {

@@ -48,8 +72,10 @@ /**

* @param message The JSON-RPC message to send
* @param options Optional request-scoped cancellation options
*/
send(message: JSONRPCMessage): Promise<void>;
send(message: JSONRPCMessage, options?: MCPTransportSendOptions): Promise<void>;
/**
* Clean up and close the transport
* @param options Optional cancellation options for transport cleanup
*/
close(): Promise<void>;
close(options?: MCPTransportCloseOptions): Promise<void>;
/**

@@ -56,0 +82,0 @@ * Event handler for transport closure

+1
-1
{
"name": "@ai-sdk/mcp",
"version": "1.0.65",
"version": "1.0.66",
"license": "Apache-2.0",

@@ -5,0 +5,0 @@ "sideEffects": false,

@@ -37,3 +37,7 @@ export { validateJSONRPCMessage } from './tool/json-rpc-message';

} from './tool/oauth-types';
export type { MCPTransport } from './tool/mcp-transport';
export type {
MCPTransport,
MCPTransportCloseOptions,
MCPTransportSendOptions,
} from './tool/mcp-transport';

@@ -40,0 +44,0 @@ /**

@@ -19,2 +19,3 @@ import type { JSONSchema7, JSONValue } from '@ai-sdk/provider';

JSONRPCError,
JSONRPCMessage,
JSONRPCNotification,

@@ -146,2 +147,52 @@ JSONRPCRequest,

function getEffectiveTimeout({
timeout,
maxTotalTimeout,
}: RequestOptions): number | undefined {
if (timeout == null) {
return maxTotalTimeout;
}
if (maxTotalTimeout == null) {
return timeout;
}
return Math.min(timeout, maxTotalTimeout);
}
function waitForAbort<T>(
promise: Promise<T>,
signal: AbortSignal | undefined,
): Promise<T> {
if (signal == null) {
return promise;
}
return new Promise((resolve, reject) => {
const cleanup = () => {
signal.removeEventListener('abort', onAbort);
};
const onAbort = () => {
cleanup();
reject(signal.reason);
};
if (signal.aborted) {
onAbort();
return;
}
signal.addEventListener('abort', onAbort, { once: true });
promise
.then(value => {
cleanup();
resolve(value);
})
.catch(error => {
cleanup();
reject(error);
});
});
}
function mcpToModelOutput({

@@ -182,2 +233,6 @@ output,

transport: MCPTransportConfig | MCPTransport;
/**
* Options that bound or cancel transport startup and the initialize request.
*/
initializationOptions?: RequestOptions;
/** Optional callback for uncaught errors */

@@ -320,2 +375,3 @@ onUncaughtError?: (error: unknown) => void;

private clientCapabilities: ClientCapabilities;
private initializationOptions?: RequestOptions;
private requestMessageId = 0;

@@ -342,2 +398,3 @@ private responseHandlers: Map<

capabilities,
initializationOptions,
}: MCPClientConfig) {

@@ -347,2 +404,3 @@ this.onUncaughtError = onUncaughtError;

this.clientCapabilities = capabilities ?? {};
this.initializationOptions = initializationOptions;

@@ -389,5 +447,30 @@ if (isCustomMcpTransport(transportConfig)) {

async init(): Promise<this> {
const externalSignal = this.initializationOptions?.signal;
const timeout = this.initializationOptions
? getEffectiveTimeout(this.initializationOptions)
: undefined;
const timeoutController =
timeout == null ? undefined : new AbortController();
const signal =
externalSignal == null
? timeoutController?.signal
: timeoutController == null
? externalSignal
: AbortSignal.any([externalSignal, timeoutController.signal]);
let timeoutId: ReturnType<typeof setTimeout> | undefined;
let timeoutError: MCPClientError | undefined;
if (timeout != null) {
timeoutId = setTimeout(() => {
timeoutError = new MCPClientError({
message: `MCP client initialization timed out after ${timeout}ms`,
});
timeoutController?.abort(timeoutError);
}, timeout);
}
try {
await this.transport.start();
this.isClosed = false;
signal?.throwIfAborted();
await waitForAbort(this.transport.start(), signal);

@@ -404,2 +487,3 @@ const result = await this.request({

resultSchema: InitializeResultSchema,
options: { signal },
});

@@ -429,10 +513,32 @@

// Complete initialization handshake:
await this.notification({
method: 'notifications/initialized',
});
await this.notification(
{
method: 'notifications/initialized',
},
{ signal },
);
return this;
} catch (error) {
await this.close();
try {
await waitForAbort(this.transport.close({ signal }), signal);
} catch {}
this.onClose();
if (timeoutError != null) {
throw timeoutError;
}
if (externalSignal?.aborted) {
throw new MCPClientError({
message: 'MCP client initialization was aborted',
cause: externalSignal.reason,
});
}
throw error;
} finally {
if (timeoutId != null) {
clearTimeout(timeoutId);
}
}

@@ -447,2 +553,12 @@ }

private send(
message: JSONRPCMessage,
signal: AbortSignal | undefined,
): Promise<void> {
return this.transport.send(
message,
signal == null ? undefined : { signal },
);
}
private assertCapability(method: string): void {

@@ -513,2 +629,13 @@ switch (method) {

signal?.throwIfAborted();
const timeout =
options == null ? undefined : getEffectiveTimeout(options);
const timeoutController =
timeout == null ? undefined : new AbortController();
const transportSignal =
signal == null
? timeoutController?.signal
: timeoutController == null
? signal
: AbortSignal.any([signal, timeoutController.signal]);
let timeoutId: ReturnType<typeof setTimeout> | undefined;

@@ -534,2 +661,5 @@ const messageId = this.requestMessageId++;

signal?.removeEventListener('abort', onAbort);
if (timeoutId != null) {
clearTimeout(timeoutId);
}
};

@@ -547,2 +677,10 @@

const onTimeout = () => {
const error = new MCPClientError({
message: `Request timed out after ${timeout}ms`,
});
timeoutController?.abort(error);
rejectAndCleanup(error);
};
this.responseHandlers.set(messageId, response => {

@@ -573,3 +711,12 @@ if (signal?.aborted) {

this.transport.send(jsonrpcRequest).catch(error => {
if (timeout != null) {
timeoutId = setTimeout(onTimeout, timeout);
}
const sendPromise =
transportSignal == null
? this.transport.send(jsonrpcRequest)
: this.send(jsonrpcRequest, transportSignal);
sendPromise.catch(error => {
rejectAndCleanup(error);

@@ -749,3 +896,6 @@ });

private async notification(notification: Notification): Promise<void> {
private async notification(
notification: Notification,
options?: { signal?: AbortSignal },
): Promise<void> {
const jsonrpcNotification: JSONRPCNotification = {

@@ -755,3 +905,6 @@ ...notification,

};
await this.transport.send(jsonrpcNotification);
await waitForAbort(
this.send(jsonrpcNotification, options?.signal),
options?.signal,
);
}

@@ -758,0 +911,0 @@

@@ -146,15 +146,15 @@ import {

async close(): Promise<void> {
async close(options?: { signal?: AbortSignal }): Promise<void> {
this.inboundSseConnection?.close();
this.abortController?.abort();
try {
if (
this.sessionId &&
this.abortController &&
!this.abortController.signal.aborted
) {
if (this.sessionId && this.abortController) {
options?.signal?.throwIfAborted();
const headers = await this.commonHeaders({});
options?.signal?.throwIfAborted();
await this.fetchFn(this.url.href, {
method: 'DELETE',
headers,
signal: this.abortController.signal,
signal: options?.signal,
redirect: this.redirectMode,

@@ -165,7 +165,19 @@ }).catch(() => undefined);

this.abortController?.abort();
this.onclose?.();
}
async send(message: JSONRPCMessage): Promise<void> {
async send(
message: JSONRPCMessage,
options?: { signal?: AbortSignal },
): Promise<void> {
options?.signal?.throwIfAborted();
const transportSignal = this.abortController?.signal;
const requestSignal =
options?.signal == null
? transportSignal
: transportSignal == null
? options.signal
: AbortSignal.any([transportSignal, options.signal]);
const attempt = async (triedAuth: boolean = false): Promise<void> => {

@@ -182,3 +194,3 @@ try {

body: JSON.stringify(message),
signal: this.abortController?.signal,
signal: requestSignal,
redirect: this.redirectMode,

@@ -296,3 +308,6 @@ } satisfies RequestInit;

} catch (error) {
if (error instanceof Error && error.name === 'AbortError') {
if (
options?.signal?.aborted ||
(error instanceof Error && error.name === 'AbortError')
) {
return;

@@ -305,3 +320,6 @@ }

void processEvents().catch(error => {
if (error instanceof Error && error.name === 'AbortError') {
if (
options?.signal?.aborted ||
(error instanceof Error && error.name === 'AbortError')
) {
return;

@@ -322,2 +340,5 @@ }

} catch (error) {
if (options?.signal?.aborted) {
throw error;
}
this.onerror?.(error);

@@ -324,0 +345,0 @@ throw error;

@@ -239,3 +239,8 @@ import {

async send(message: JSONRPCMessage): Promise<void> {
async send(
message: JSONRPCMessage,
options?: { signal?: AbortSignal },
): Promise<void> {
options?.signal?.throwIfAborted();
if (!this.endpoint || !this.connected) {

@@ -248,2 +253,9 @@ throw new MCPClientError({

const endpoint = this.endpoint as URL;
const transportSignal = this.abortController?.signal;
const requestSignal =
options?.signal == null
? transportSignal
: transportSignal == null
? options.signal
: AbortSignal.any([transportSignal, options.signal]);

@@ -259,3 +271,3 @@ const attempt = async (triedAuth: boolean = false): Promise<void> => {

body: JSON.stringify(message),
signal: this.abortController?.signal,
signal: requestSignal,
redirect: this.redirectMode,

@@ -295,2 +307,5 @@ };

} catch (error) {
if (options?.signal?.aborted) {
throw error;
}
this.onerror?.(error);

@@ -297,0 +312,0 @@ return;

@@ -12,2 +12,31 @@ import type { FetchFunction } from '@ai-sdk/provider-utils';

*/
export type MCPTransportSendOptions = {
/**
* Cancels the transport operation for this message.
*/
signal?: AbortSignal;
/**
* Associates an outgoing message with an incoming request.
*/
relatedRequestId?: string | number;
/**
* Resumes a previously interrupted request.
*/
resumptionToken?: string;
/**
* Receives updated resumption tokens from transports that support them.
*/
onresumptiontoken?: (token: string) => void;
};
export type MCPTransportCloseOptions = {
/**
* Cancels transport cleanup.
*/
signal?: AbortSignal;
};
export interface MCPTransport {

@@ -22,9 +51,14 @@ /**

* @param message The JSON-RPC message to send
* @param options Optional request-scoped cancellation options
*/
send(message: JSONRPCMessage): Promise<void>;
send(
message: JSONRPCMessage,
options?: MCPTransportSendOptions,
): Promise<void>;
/**
* Clean up and close the transport
* @param options Optional cancellation options for transport cleanup
*/
close(): Promise<void>;
close(options?: MCPTransportCloseOptions): Promise<void>;

@@ -31,0 +65,0 @@ /**

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display