mirror of
https://github.com/tvytlx/ai-agent-deep-dive.git
synced 2026-04-04 16:14:50 +08:00
Add extracted source directory and README navigation
This commit is contained in:
180
extracted-source/node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/errors.js
generated
vendored
Normal file
180
extracted-source/node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/errors.js
generated
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* Base class for all OAuth errors
|
||||
*/
|
||||
export class OAuthError extends Error {
|
||||
constructor(message, errorUri) {
|
||||
super(message);
|
||||
this.errorUri = errorUri;
|
||||
this.name = this.constructor.name;
|
||||
}
|
||||
/**
|
||||
* Converts the error to a standard OAuth error response object
|
||||
*/
|
||||
toResponseObject() {
|
||||
const response = {
|
||||
error: this.errorCode,
|
||||
error_description: this.message
|
||||
};
|
||||
if (this.errorUri) {
|
||||
response.error_uri = this.errorUri;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
get errorCode() {
|
||||
return this.constructor.errorCode;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Invalid request error - The request is missing a required parameter,
|
||||
* includes an invalid parameter value, includes a parameter more than once,
|
||||
* or is otherwise malformed.
|
||||
*/
|
||||
export class InvalidRequestError extends OAuthError {
|
||||
}
|
||||
InvalidRequestError.errorCode = 'invalid_request';
|
||||
/**
|
||||
* Invalid client error - Client authentication failed (e.g., unknown client, no client
|
||||
* authentication included, or unsupported authentication method).
|
||||
*/
|
||||
export class InvalidClientError extends OAuthError {
|
||||
}
|
||||
InvalidClientError.errorCode = 'invalid_client';
|
||||
/**
|
||||
* Invalid grant error - The provided authorization grant or refresh token is
|
||||
* invalid, expired, revoked, does not match the redirection URI used in the
|
||||
* authorization request, or was issued to another client.
|
||||
*/
|
||||
export class InvalidGrantError extends OAuthError {
|
||||
}
|
||||
InvalidGrantError.errorCode = 'invalid_grant';
|
||||
/**
|
||||
* Unauthorized client error - The authenticated client is not authorized to use
|
||||
* this authorization grant type.
|
||||
*/
|
||||
export class UnauthorizedClientError extends OAuthError {
|
||||
}
|
||||
UnauthorizedClientError.errorCode = 'unauthorized_client';
|
||||
/**
|
||||
* Unsupported grant type error - The authorization grant type is not supported
|
||||
* by the authorization server.
|
||||
*/
|
||||
export class UnsupportedGrantTypeError extends OAuthError {
|
||||
}
|
||||
UnsupportedGrantTypeError.errorCode = 'unsupported_grant_type';
|
||||
/**
|
||||
* Invalid scope error - The requested scope is invalid, unknown, malformed, or
|
||||
* exceeds the scope granted by the resource owner.
|
||||
*/
|
||||
export class InvalidScopeError extends OAuthError {
|
||||
}
|
||||
InvalidScopeError.errorCode = 'invalid_scope';
|
||||
/**
|
||||
* Access denied error - The resource owner or authorization server denied the request.
|
||||
*/
|
||||
export class AccessDeniedError extends OAuthError {
|
||||
}
|
||||
AccessDeniedError.errorCode = 'access_denied';
|
||||
/**
|
||||
* Server error - The authorization server encountered an unexpected condition
|
||||
* that prevented it from fulfilling the request.
|
||||
*/
|
||||
export class ServerError extends OAuthError {
|
||||
}
|
||||
ServerError.errorCode = 'server_error';
|
||||
/**
|
||||
* Temporarily unavailable error - The authorization server is currently unable to
|
||||
* handle the request due to a temporary overloading or maintenance of the server.
|
||||
*/
|
||||
export class TemporarilyUnavailableError extends OAuthError {
|
||||
}
|
||||
TemporarilyUnavailableError.errorCode = 'temporarily_unavailable';
|
||||
/**
|
||||
* Unsupported response type error - The authorization server does not support
|
||||
* obtaining an authorization code using this method.
|
||||
*/
|
||||
export class UnsupportedResponseTypeError extends OAuthError {
|
||||
}
|
||||
UnsupportedResponseTypeError.errorCode = 'unsupported_response_type';
|
||||
/**
|
||||
* Unsupported token type error - The authorization server does not support
|
||||
* the requested token type.
|
||||
*/
|
||||
export class UnsupportedTokenTypeError extends OAuthError {
|
||||
}
|
||||
UnsupportedTokenTypeError.errorCode = 'unsupported_token_type';
|
||||
/**
|
||||
* Invalid token error - The access token provided is expired, revoked, malformed,
|
||||
* or invalid for other reasons.
|
||||
*/
|
||||
export class InvalidTokenError extends OAuthError {
|
||||
}
|
||||
InvalidTokenError.errorCode = 'invalid_token';
|
||||
/**
|
||||
* Method not allowed error - The HTTP method used is not allowed for this endpoint.
|
||||
* (Custom, non-standard error)
|
||||
*/
|
||||
export class MethodNotAllowedError extends OAuthError {
|
||||
}
|
||||
MethodNotAllowedError.errorCode = 'method_not_allowed';
|
||||
/**
|
||||
* Too many requests error - Rate limit exceeded.
|
||||
* (Custom, non-standard error based on RFC 6585)
|
||||
*/
|
||||
export class TooManyRequestsError extends OAuthError {
|
||||
}
|
||||
TooManyRequestsError.errorCode = 'too_many_requests';
|
||||
/**
|
||||
* Invalid client metadata error - The client metadata is invalid.
|
||||
* (Custom error for dynamic client registration - RFC 7591)
|
||||
*/
|
||||
export class InvalidClientMetadataError extends OAuthError {
|
||||
}
|
||||
InvalidClientMetadataError.errorCode = 'invalid_client_metadata';
|
||||
/**
|
||||
* Insufficient scope error - The request requires higher privileges than provided by the access token.
|
||||
*/
|
||||
export class InsufficientScopeError extends OAuthError {
|
||||
}
|
||||
InsufficientScopeError.errorCode = 'insufficient_scope';
|
||||
/**
|
||||
* Invalid target error - The requested resource is invalid, missing, unknown, or malformed.
|
||||
* (Custom error for resource indicators - RFC 8707)
|
||||
*/
|
||||
export class InvalidTargetError extends OAuthError {
|
||||
}
|
||||
InvalidTargetError.errorCode = 'invalid_target';
|
||||
/**
|
||||
* A utility class for defining one-off error codes
|
||||
*/
|
||||
export class CustomOAuthError extends OAuthError {
|
||||
constructor(customErrorCode, message, errorUri) {
|
||||
super(message, errorUri);
|
||||
this.customErrorCode = customErrorCode;
|
||||
}
|
||||
get errorCode() {
|
||||
return this.customErrorCode;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* A full list of all OAuthErrors, enabling parsing from error responses
|
||||
*/
|
||||
export const OAUTH_ERRORS = {
|
||||
[InvalidRequestError.errorCode]: InvalidRequestError,
|
||||
[InvalidClientError.errorCode]: InvalidClientError,
|
||||
[InvalidGrantError.errorCode]: InvalidGrantError,
|
||||
[UnauthorizedClientError.errorCode]: UnauthorizedClientError,
|
||||
[UnsupportedGrantTypeError.errorCode]: UnsupportedGrantTypeError,
|
||||
[InvalidScopeError.errorCode]: InvalidScopeError,
|
||||
[AccessDeniedError.errorCode]: AccessDeniedError,
|
||||
[ServerError.errorCode]: ServerError,
|
||||
[TemporarilyUnavailableError.errorCode]: TemporarilyUnavailableError,
|
||||
[UnsupportedResponseTypeError.errorCode]: UnsupportedResponseTypeError,
|
||||
[UnsupportedTokenTypeError.errorCode]: UnsupportedTokenTypeError,
|
||||
[InvalidTokenError.errorCode]: InvalidTokenError,
|
||||
[MethodNotAllowedError.errorCode]: MethodNotAllowedError,
|
||||
[TooManyRequestsError.errorCode]: TooManyRequestsError,
|
||||
[InvalidClientMetadataError.errorCode]: InvalidClientMetadataError,
|
||||
[InsufficientScopeError.errorCode]: InsufficientScopeError,
|
||||
[InvalidTargetError.errorCode]: InvalidTargetError
|
||||
};
|
||||
//# sourceMappingURL=errors.js.map
|
||||
440
extracted-source/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
generated
vendored
Normal file
440
extracted-source/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
generated
vendored
Normal file
@@ -0,0 +1,440 @@
|
||||
import { mergeCapabilities, Protocol } from '../shared/protocol.js';
|
||||
import { CreateMessageResultSchema, CreateMessageResultWithToolsSchema, ElicitResultSchema, EmptyResultSchema, ErrorCode, InitializedNotificationSchema, InitializeRequestSchema, LATEST_PROTOCOL_VERSION, ListRootsResultSchema, LoggingLevelSchema, McpError, SetLevelRequestSchema, SUPPORTED_PROTOCOL_VERSIONS, CallToolRequestSchema, CallToolResultSchema, CreateTaskResultSchema } from '../types.js';
|
||||
import { AjvJsonSchemaValidator } from '../validation/ajv-provider.js';
|
||||
import { getObjectShape, isZ4Schema, safeParse } from './zod-compat.js';
|
||||
import { ExperimentalServerTasks } from '../experimental/tasks/server.js';
|
||||
import { assertToolsCallTaskCapability, assertClientRequestTaskCapability } from '../experimental/tasks/helpers.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"
|
||||
* })
|
||||
* ```
|
||||
* @deprecated Use `McpServer` instead for the high-level API. Only use `Server` for advanced use cases.
|
||||
*/
|
||||
export class Server extends Protocol {
|
||||
/**
|
||||
* Initializes this server with the given name and version information.
|
||||
*/
|
||||
constructor(_serverInfo, options) {
|
||||
super(options);
|
||||
this._serverInfo = _serverInfo;
|
||||
// Map log levels by session id
|
||||
this._loggingLevels = new Map();
|
||||
// Map LogLevelSchema to severity index
|
||||
this.LOG_LEVEL_SEVERITY = new Map(LoggingLevelSchema.options.map((level, index) => [level, index]));
|
||||
// Is a message with the given level ignored in the log level set for the given session id?
|
||||
this.isMessageIgnored = (level, sessionId) => {
|
||||
const currentLevel = this._loggingLevels.get(sessionId);
|
||||
return currentLevel ? this.LOG_LEVEL_SEVERITY.get(level) < this.LOG_LEVEL_SEVERITY.get(currentLevel) : false;
|
||||
};
|
||||
this._capabilities = options?.capabilities ?? {};
|
||||
this._instructions = options?.instructions;
|
||||
this._jsonSchemaValidator = options?.jsonSchemaValidator ?? new AjvJsonSchemaValidator();
|
||||
this.setRequestHandler(InitializeRequestSchema, request => this._oninitialize(request));
|
||||
this.setNotificationHandler(InitializedNotificationSchema, () => this.oninitialized?.());
|
||||
if (this._capabilities.logging) {
|
||||
this.setRequestHandler(SetLevelRequestSchema, async (request, extra) => {
|
||||
const transportSessionId = extra.sessionId || extra.requestInfo?.headers['mcp-session-id'] || undefined;
|
||||
const { level } = request.params;
|
||||
const parseResult = LoggingLevelSchema.safeParse(level);
|
||||
if (parseResult.success) {
|
||||
this._loggingLevels.set(transportSessionId, parseResult.data);
|
||||
}
|
||||
return {};
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Access experimental features.
|
||||
*
|
||||
* WARNING: These APIs are experimental and may change without notice.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
get experimental() {
|
||||
if (!this._experimental) {
|
||||
this._experimental = {
|
||||
tasks: new ExperimentalServerTasks(this)
|
||||
};
|
||||
}
|
||||
return this._experimental;
|
||||
}
|
||||
/**
|
||||
* Registers new capabilities. This can only be called before connecting to a transport.
|
||||
*
|
||||
* The new capabilities will be merged with any existing capabilities previously given (e.g., at initialization).
|
||||
*/
|
||||
registerCapabilities(capabilities) {
|
||||
if (this.transport) {
|
||||
throw new Error('Cannot register capabilities after connecting to transport');
|
||||
}
|
||||
this._capabilities = mergeCapabilities(this._capabilities, capabilities);
|
||||
}
|
||||
/**
|
||||
* Override request handler registration to enforce server-side validation for tools/call.
|
||||
*/
|
||||
setRequestHandler(requestSchema, handler) {
|
||||
const shape = getObjectShape(requestSchema);
|
||||
const methodSchema = shape?.method;
|
||||
if (!methodSchema) {
|
||||
throw new Error('Schema is missing a method literal');
|
||||
}
|
||||
// Extract literal value using type-safe property access
|
||||
let methodValue;
|
||||
if (isZ4Schema(methodSchema)) {
|
||||
const v4Schema = methodSchema;
|
||||
const v4Def = v4Schema._zod?.def;
|
||||
methodValue = v4Def?.value ?? v4Schema.value;
|
||||
}
|
||||
else {
|
||||
const v3Schema = methodSchema;
|
||||
const legacyDef = v3Schema._def;
|
||||
methodValue = legacyDef?.value ?? v3Schema.value;
|
||||
}
|
||||
if (typeof methodValue !== 'string') {
|
||||
throw new Error('Schema method literal must be a string');
|
||||
}
|
||||
const method = methodValue;
|
||||
if (method === 'tools/call') {
|
||||
const wrappedHandler = async (request, extra) => {
|
||||
const validatedRequest = safeParse(CallToolRequestSchema, request);
|
||||
if (!validatedRequest.success) {
|
||||
const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
|
||||
throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call request: ${errorMessage}`);
|
||||
}
|
||||
const { params } = validatedRequest.data;
|
||||
const result = await Promise.resolve(handler(request, extra));
|
||||
// When task creation is requested, validate and return CreateTaskResult
|
||||
if (params.task) {
|
||||
const taskValidationResult = safeParse(CreateTaskResultSchema, result);
|
||||
if (!taskValidationResult.success) {
|
||||
const errorMessage = taskValidationResult.error instanceof Error
|
||||
? taskValidationResult.error.message
|
||||
: String(taskValidationResult.error);
|
||||
throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
|
||||
}
|
||||
return taskValidationResult.data;
|
||||
}
|
||||
// For non-task requests, validate against CallToolResultSchema
|
||||
const validationResult = safeParse(CallToolResultSchema, result);
|
||||
if (!validationResult.success) {
|
||||
const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
|
||||
throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call result: ${errorMessage}`);
|
||||
}
|
||||
return validationResult.data;
|
||||
};
|
||||
// Install the wrapped handler
|
||||
return super.setRequestHandler(requestSchema, wrappedHandler);
|
||||
}
|
||||
// Other handlers use default behavior
|
||||
return super.setRequestHandler(requestSchema, handler);
|
||||
}
|
||||
assertCapabilityForMethod(method) {
|
||||
switch (method) {
|
||||
case 'sampling/createMessage':
|
||||
if (!this._clientCapabilities?.sampling) {
|
||||
throw new Error(`Client does not support sampling (required for ${method})`);
|
||||
}
|
||||
break;
|
||||
case 'elicitation/create':
|
||||
if (!this._clientCapabilities?.elicitation) {
|
||||
throw new Error(`Client does not support elicitation (required for ${method})`);
|
||||
}
|
||||
break;
|
||||
case 'roots/list':
|
||||
if (!this._clientCapabilities?.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/elicitation/complete':
|
||||
if (!this._clientCapabilities?.elicitation?.url) {
|
||||
throw new Error(`Client does not support URL elicitation (required for ${method})`);
|
||||
}
|
||||
break;
|
||||
case 'notifications/cancelled':
|
||||
// Cancellation notifications are always allowed
|
||||
break;
|
||||
case 'notifications/progress':
|
||||
// Progress notifications are always allowed
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertRequestHandlerCapability(method) {
|
||||
// Task handlers are registered in Protocol constructor before _capabilities is initialized
|
||||
// Skip capability check for task methods during initialization
|
||||
if (!this._capabilities) {
|
||||
return;
|
||||
}
|
||||
switch (method) {
|
||||
case 'completion/complete':
|
||||
if (!this._capabilities.completions) {
|
||||
throw new Error(`Server does not support completions (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 'tasks/get':
|
||||
case 'tasks/list':
|
||||
case 'tasks/result':
|
||||
case 'tasks/cancel':
|
||||
if (!this._capabilities.tasks) {
|
||||
throw new Error(`Server does not support tasks capability (required for ${method})`);
|
||||
}
|
||||
break;
|
||||
case 'ping':
|
||||
case 'initialize':
|
||||
// No specific capability required for these methods
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertTaskCapability(method) {
|
||||
assertClientRequestTaskCapability(this._clientCapabilities?.tasks?.requests, method, 'Client');
|
||||
}
|
||||
assertTaskHandlerCapability(method) {
|
||||
// Task handlers are registered in Protocol constructor before _capabilities is initialized
|
||||
// Skip capability check for task methods during initialization
|
||||
if (!this._capabilities) {
|
||||
return;
|
||||
}
|
||||
assertToolsCallTaskCapability(this._capabilities.tasks?.requests, method, 'Server');
|
||||
}
|
||||
async _oninitialize(request) {
|
||||
const requestedVersion = request.params.protocolVersion;
|
||||
this._clientCapabilities = request.params.capabilities;
|
||||
this._clientVersion = request.params.clientInfo;
|
||||
const protocolVersion = SUPPORTED_PROTOCOL_VERSIONS.includes(requestedVersion) ? requestedVersion : LATEST_PROTOCOL_VERSION;
|
||||
return {
|
||||
protocolVersion,
|
||||
capabilities: this.getCapabilities(),
|
||||
serverInfo: this._serverInfo,
|
||||
...(this._instructions && { instructions: this._instructions })
|
||||
};
|
||||
}
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
// Implementation
|
||||
async createMessage(params, options) {
|
||||
// Capability check - only required when tools/toolChoice are provided
|
||||
if (params.tools || params.toolChoice) {
|
||||
if (!this._clientCapabilities?.sampling?.tools) {
|
||||
throw new Error('Client does not support sampling tools capability.');
|
||||
}
|
||||
}
|
||||
// Message structure validation - always validate tool_use/tool_result pairs.
|
||||
// These may appear even without tools/toolChoice in the current request when
|
||||
// a previous sampling request returned tool_use and this is a follow-up with results.
|
||||
if (params.messages.length > 0) {
|
||||
const lastMessage = params.messages[params.messages.length - 1];
|
||||
const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [lastMessage.content];
|
||||
const hasToolResults = lastContent.some(c => c.type === 'tool_result');
|
||||
const previousMessage = params.messages.length > 1 ? params.messages[params.messages.length - 2] : undefined;
|
||||
const previousContent = previousMessage
|
||||
? Array.isArray(previousMessage.content)
|
||||
? previousMessage.content
|
||||
: [previousMessage.content]
|
||||
: [];
|
||||
const hasPreviousToolUse = previousContent.some(c => c.type === 'tool_use');
|
||||
if (hasToolResults) {
|
||||
if (lastContent.some(c => c.type !== 'tool_result')) {
|
||||
throw new Error('The last message must contain only tool_result content if any is present');
|
||||
}
|
||||
if (!hasPreviousToolUse) {
|
||||
throw new Error('tool_result blocks are not matching any tool_use from the previous message');
|
||||
}
|
||||
}
|
||||
if (hasPreviousToolUse) {
|
||||
const toolUseIds = new Set(previousContent.filter(c => c.type === 'tool_use').map(c => c.id));
|
||||
const toolResultIds = new Set(lastContent.filter(c => c.type === 'tool_result').map(c => c.toolUseId));
|
||||
if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every(id => toolResultIds.has(id))) {
|
||||
throw new Error('ids of tool_result blocks and tool_use blocks from previous message do not match');
|
||||
}
|
||||
}
|
||||
}
|
||||
// Use different schemas based on whether tools are provided
|
||||
if (params.tools) {
|
||||
return this.request({ method: 'sampling/createMessage', params }, CreateMessageResultWithToolsSchema, options);
|
||||
}
|
||||
return this.request({ method: 'sampling/createMessage', params }, CreateMessageResultSchema, options);
|
||||
}
|
||||
/**
|
||||
* Creates an elicitation request for the given parameters.
|
||||
* For backwards compatibility, `mode` may be omitted for form requests and will default to `'form'`.
|
||||
* @param params The parameters for the elicitation request.
|
||||
* @param options Optional request options.
|
||||
* @returns The result of the elicitation request.
|
||||
*/
|
||||
async elicitInput(params, options) {
|
||||
const mode = (params.mode ?? 'form');
|
||||
switch (mode) {
|
||||
case 'url': {
|
||||
if (!this._clientCapabilities?.elicitation?.url) {
|
||||
throw new Error('Client does not support url elicitation.');
|
||||
}
|
||||
const urlParams = params;
|
||||
return this.request({ method: 'elicitation/create', params: urlParams }, ElicitResultSchema, options);
|
||||
}
|
||||
case 'form': {
|
||||
if (!this._clientCapabilities?.elicitation?.form) {
|
||||
throw new Error('Client does not support form elicitation.');
|
||||
}
|
||||
const formParams = params.mode === 'form' ? params : { ...params, mode: 'form' };
|
||||
const result = await this.request({ method: 'elicitation/create', params: formParams }, ElicitResultSchema, options);
|
||||
if (result.action === 'accept' && result.content && formParams.requestedSchema) {
|
||||
try {
|
||||
const validator = this._jsonSchemaValidator.getValidator(formParams.requestedSchema);
|
||||
const validationResult = validator(result.content);
|
||||
if (!validationResult.valid) {
|
||||
throw new McpError(ErrorCode.InvalidParams, `Elicitation response content does not match requested schema: ${validationResult.errorMessage}`);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof McpError) {
|
||||
throw error;
|
||||
}
|
||||
throw new McpError(ErrorCode.InternalError, `Error validating elicitation response: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates a reusable callback that, when invoked, will send a `notifications/elicitation/complete`
|
||||
* notification for the specified elicitation ID.
|
||||
*
|
||||
* @param elicitationId The ID of the elicitation to mark as complete.
|
||||
* @param options Optional notification options. Useful when the completion notification should be related to a prior request.
|
||||
* @returns A function that emits the completion notification when awaited.
|
||||
*/
|
||||
createElicitationCompletionNotifier(elicitationId, options) {
|
||||
if (!this._clientCapabilities?.elicitation?.url) {
|
||||
throw new Error('Client does not support URL elicitation (required for notifications/elicitation/complete)');
|
||||
}
|
||||
return () => this.notification({
|
||||
method: 'notifications/elicitation/complete',
|
||||
params: {
|
||||
elicitationId
|
||||
}
|
||||
}, options);
|
||||
}
|
||||
async listRoots(params, options) {
|
||||
return this.request({ method: 'roots/list', params }, ListRootsResultSchema, options);
|
||||
}
|
||||
/**
|
||||
* Sends a logging message to the client, if connected.
|
||||
* Note: You only need to send the parameters object, not the entire JSON RPC message
|
||||
* @see LoggingMessageNotification
|
||||
* @param params
|
||||
* @param sessionId optional for stateless and backward compatibility
|
||||
*/
|
||||
async sendLoggingMessage(params, sessionId) {
|
||||
if (this._capabilities.logging) {
|
||||
if (!this.isMessageIgnored(params.level, sessionId)) {
|
||||
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
|
||||
75
extracted-source/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
generated
vendored
Normal file
75
extracted-source/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
import process from 'node:process';
|
||||
import { ReadBuffer, serializeMessage } from '../shared/stdio.js';
|
||||
/**
|
||||
* Server transport for stdio: this communicates with an 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) => {
|
||||
this.onerror?.(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() {
|
||||
while (true) {
|
||||
try {
|
||||
const message = this._readBuffer.readMessage();
|
||||
if (message === null) {
|
||||
break;
|
||||
}
|
||||
this.onmessage?.(message);
|
||||
}
|
||||
catch (error) {
|
||||
this.onerror?.(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
async close() {
|
||||
// Remove our event listeners first
|
||||
this._stdin.off('data', this._ondata);
|
||||
this._stdin.off('error', this._onerror);
|
||||
// Check if we were the only data listener
|
||||
const remainingDataListeners = this._stdin.listenerCount('data');
|
||||
if (remainingDataListeners === 0) {
|
||||
// Only pause stdin if we were the only listener
|
||||
// This prevents interfering with other parts of the application that might be using stdin
|
||||
this._stdin.pause();
|
||||
}
|
||||
// Clear the buffer and notify closure
|
||||
this._readBuffer.clear();
|
||||
this.onclose?.();
|
||||
}
|
||||
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
|
||||
209
extracted-source/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
generated
vendored
Normal file
209
extracted-source/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
generated
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
// zod-compat.ts
|
||||
// ----------------------------------------------------
|
||||
// Unified types + helpers to accept Zod v3 and v4 (Mini)
|
||||
// ----------------------------------------------------
|
||||
import * as z3rt from 'zod/v3';
|
||||
import * as z4mini from 'zod/v4-mini';
|
||||
// --- Runtime detection ---
|
||||
export function isZ4Schema(s) {
|
||||
// Present on Zod 4 (Classic & Mini) schemas; absent on Zod 3
|
||||
const schema = s;
|
||||
return !!schema._zod;
|
||||
}
|
||||
// --- Schema construction ---
|
||||
export function objectFromShape(shape) {
|
||||
const values = Object.values(shape);
|
||||
if (values.length === 0)
|
||||
return z4mini.object({}); // default to v4 Mini
|
||||
const allV4 = values.every(isZ4Schema);
|
||||
const allV3 = values.every(s => !isZ4Schema(s));
|
||||
if (allV4)
|
||||
return z4mini.object(shape);
|
||||
if (allV3)
|
||||
return z3rt.object(shape);
|
||||
throw new Error('Mixed Zod versions detected in object shape.');
|
||||
}
|
||||
// --- Unified parsing ---
|
||||
export function safeParse(schema, data) {
|
||||
if (isZ4Schema(schema)) {
|
||||
// Mini exposes top-level safeParse
|
||||
const result = z4mini.safeParse(schema, data);
|
||||
return result;
|
||||
}
|
||||
const v3Schema = schema;
|
||||
const result = v3Schema.safeParse(data);
|
||||
return result;
|
||||
}
|
||||
export async function safeParseAsync(schema, data) {
|
||||
if (isZ4Schema(schema)) {
|
||||
// Mini exposes top-level safeParseAsync
|
||||
const result = await z4mini.safeParseAsync(schema, data);
|
||||
return result;
|
||||
}
|
||||
const v3Schema = schema;
|
||||
const result = await v3Schema.safeParseAsync(data);
|
||||
return result;
|
||||
}
|
||||
// --- Shape extraction ---
|
||||
export function getObjectShape(schema) {
|
||||
if (!schema)
|
||||
return undefined;
|
||||
// Zod v3 exposes `.shape`; Zod v4 keeps the shape on `_zod.def.shape`
|
||||
let rawShape;
|
||||
if (isZ4Schema(schema)) {
|
||||
const v4Schema = schema;
|
||||
rawShape = v4Schema._zod?.def?.shape;
|
||||
}
|
||||
else {
|
||||
const v3Schema = schema;
|
||||
rawShape = v3Schema.shape;
|
||||
}
|
||||
if (!rawShape)
|
||||
return undefined;
|
||||
if (typeof rawShape === 'function') {
|
||||
try {
|
||||
return rawShape();
|
||||
}
|
||||
catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
return rawShape;
|
||||
}
|
||||
// --- Schema normalization ---
|
||||
/**
|
||||
* Normalizes a schema to an object schema. Handles both:
|
||||
* - Already-constructed object schemas (v3 or v4)
|
||||
* - Raw shapes that need to be wrapped into object schemas
|
||||
*/
|
||||
export function normalizeObjectSchema(schema) {
|
||||
if (!schema)
|
||||
return undefined;
|
||||
// First check if it's a raw shape (Record<string, AnySchema>)
|
||||
// Raw shapes don't have _def or _zod properties and aren't schemas themselves
|
||||
if (typeof schema === 'object') {
|
||||
// Check if it's actually a ZodRawShapeCompat (not a schema instance)
|
||||
// by checking if it lacks schema-like internal properties
|
||||
const asV3 = schema;
|
||||
const asV4 = schema;
|
||||
// If it's not a schema instance (no _def or _zod), it might be a raw shape
|
||||
if (!asV3._def && !asV4._zod) {
|
||||
// Check if all values are schemas (heuristic to confirm it's a raw shape)
|
||||
const values = Object.values(schema);
|
||||
if (values.length > 0 &&
|
||||
values.every(v => typeof v === 'object' &&
|
||||
v !== null &&
|
||||
(v._def !== undefined ||
|
||||
v._zod !== undefined ||
|
||||
typeof v.parse === 'function'))) {
|
||||
return objectFromShape(schema);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we get here, it should be an AnySchema (not a raw shape)
|
||||
// Check if it's already an object schema
|
||||
if (isZ4Schema(schema)) {
|
||||
// Check if it's a v4 object
|
||||
const v4Schema = schema;
|
||||
const def = v4Schema._zod?.def;
|
||||
if (def && (def.type === 'object' || def.shape !== undefined)) {
|
||||
return schema;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Check if it's a v3 object
|
||||
const v3Schema = schema;
|
||||
if (v3Schema.shape !== undefined) {
|
||||
return schema;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
// --- Error message extraction ---
|
||||
/**
|
||||
* Safely extracts an error message from a parse result error.
|
||||
* Zod errors can have different structures, so we handle various cases.
|
||||
*/
|
||||
export function getParseErrorMessage(error) {
|
||||
if (error && typeof error === 'object') {
|
||||
// Try common error structures
|
||||
if ('message' in error && typeof error.message === 'string') {
|
||||
return error.message;
|
||||
}
|
||||
if ('issues' in error && Array.isArray(error.issues) && error.issues.length > 0) {
|
||||
const firstIssue = error.issues[0];
|
||||
if (firstIssue && typeof firstIssue === 'object' && 'message' in firstIssue) {
|
||||
return String(firstIssue.message);
|
||||
}
|
||||
}
|
||||
// Fallback: try to stringify the error
|
||||
try {
|
||||
return JSON.stringify(error);
|
||||
}
|
||||
catch {
|
||||
return String(error);
|
||||
}
|
||||
}
|
||||
return String(error);
|
||||
}
|
||||
// --- Schema metadata access ---
|
||||
/**
|
||||
* Gets the description from a schema, if available.
|
||||
* Works with both Zod v3 and v4.
|
||||
*
|
||||
* Both versions expose a `.description` getter that returns the description
|
||||
* from their respective internal storage (v3: _def, v4: globalRegistry).
|
||||
*/
|
||||
export function getSchemaDescription(schema) {
|
||||
return schema.description;
|
||||
}
|
||||
/**
|
||||
* Checks if a schema is optional.
|
||||
* Works with both Zod v3 and v4.
|
||||
*/
|
||||
export function isSchemaOptional(schema) {
|
||||
if (isZ4Schema(schema)) {
|
||||
const v4Schema = schema;
|
||||
return v4Schema._zod?.def?.type === 'optional';
|
||||
}
|
||||
const v3Schema = schema;
|
||||
// v3 has isOptional() method
|
||||
if (typeof schema.isOptional === 'function') {
|
||||
return schema.isOptional();
|
||||
}
|
||||
return v3Schema._def?.typeName === 'ZodOptional';
|
||||
}
|
||||
/**
|
||||
* Gets the literal value from a schema, if it's a literal schema.
|
||||
* Works with both Zod v3 and v4.
|
||||
* Returns undefined if the schema is not a literal or the value cannot be determined.
|
||||
*/
|
||||
export function getLiteralValue(schema) {
|
||||
if (isZ4Schema(schema)) {
|
||||
const v4Schema = schema;
|
||||
const def = v4Schema._zod?.def;
|
||||
if (def) {
|
||||
// Try various ways to get the literal value
|
||||
if (def.value !== undefined)
|
||||
return def.value;
|
||||
if (Array.isArray(def.values) && def.values.length > 0) {
|
||||
return def.values[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
const v3Schema = schema;
|
||||
const def = v3Schema._def;
|
||||
if (def) {
|
||||
if (def.value !== undefined)
|
||||
return def.value;
|
||||
if (Array.isArray(def.values) && def.values.length > 0) {
|
||||
return def.values[0];
|
||||
}
|
||||
}
|
||||
// Fallback: check for direct value property (some Zod versions)
|
||||
const directValue = schema.value;
|
||||
if (directValue !== undefined)
|
||||
return directValue;
|
||||
return undefined;
|
||||
}
|
||||
//# sourceMappingURL=zod-compat.js.map
|
||||
51
extracted-source/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
generated
vendored
Normal file
51
extracted-source/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
// zod-json-schema-compat.ts
|
||||
// ----------------------------------------------------
|
||||
// JSON Schema conversion for both Zod v3 and Zod v4 (Mini)
|
||||
// v3 uses your vendored converter; v4 uses Mini's toJSONSchema
|
||||
// ----------------------------------------------------
|
||||
import * as z4mini from 'zod/v4-mini';
|
||||
import { getObjectShape, safeParse, isZ4Schema, getLiteralValue } from './zod-compat.js';
|
||||
import { zodToJsonSchema } from 'zod-to-json-schema';
|
||||
function mapMiniTarget(t) {
|
||||
if (!t)
|
||||
return 'draft-7';
|
||||
if (t === 'jsonSchema7' || t === 'draft-7')
|
||||
return 'draft-7';
|
||||
if (t === 'jsonSchema2019-09' || t === 'draft-2020-12')
|
||||
return 'draft-2020-12';
|
||||
return 'draft-7'; // fallback
|
||||
}
|
||||
export function toJsonSchemaCompat(schema, opts) {
|
||||
if (isZ4Schema(schema)) {
|
||||
// v4 branch — use Mini's built-in toJSONSchema
|
||||
return z4mini.toJSONSchema(schema, {
|
||||
target: mapMiniTarget(opts?.target),
|
||||
io: opts?.pipeStrategy ?? 'input'
|
||||
});
|
||||
}
|
||||
// v3 branch — use vendored converter
|
||||
return zodToJsonSchema(schema, {
|
||||
strictUnions: opts?.strictUnions ?? true,
|
||||
pipeStrategy: opts?.pipeStrategy ?? 'input'
|
||||
});
|
||||
}
|
||||
export function getMethodLiteral(schema) {
|
||||
const shape = getObjectShape(schema);
|
||||
const methodSchema = shape?.method;
|
||||
if (!methodSchema) {
|
||||
throw new Error('Schema is missing a method literal');
|
||||
}
|
||||
const value = getLiteralValue(methodSchema);
|
||||
if (typeof value !== 'string') {
|
||||
throw new Error('Schema method literal must be a string');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
export function parseWithCompat(schema, data) {
|
||||
const result = safeParse(schema, data);
|
||||
if (!result.success) {
|
||||
throw result.error;
|
||||
}
|
||||
return result.data;
|
||||
}
|
||||
//# sourceMappingURL=zod-json-schema-compat.js.map
|
||||
Reference in New Issue
Block a user