From 1e730e0f5cb46ba023b3897fc34a9cc83348cca6 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Mon, 2 Feb 2026 16:30:17 +0000 Subject: [PATCH 1/3] `v2`: replace export * with explicit named exports to tighten public API surface Replace blanket `export *` barrel files in client and server packages with explicit named exports, removing 59 internal/deprecated symbols from the public API. This prevents SDK internals (OAuth sub-steps, Zod compat layer, stdio parsing, completable internals) from leaking to users while keeping all protocol types, schemas, and user-facing APIs intact. Deleted deprecated symbols: discoverOAuthMetadata, extractResourceMetadataUrl, unwrapCompletable, McpZodTypeKind, CompletableDef. --- packages/client/src/client/auth.ts | 77 --- packages/client/src/index.ts | 512 +++++++++++++++++- packages/client/test/client/auth.test.ts | 297 ---------- .../node/test/streamableHttp.test.ts | 38 +- packages/server/src/index.ts | 506 ++++++++++++++++- packages/server/src/server/completable.ts | 20 - test/integration/test/client/client.test.ts | 164 +++++- .../issues/test_1342OauthErrorHttp200.test.ts | 3 +- 8 files changed, 1182 insertions(+), 435 deletions(-) diff --git a/packages/client/src/client/auth.ts b/packages/client/src/client/auth.ts index 4589fcda2..2f7b2c1b0 100644 --- a/packages/client/src/client/auth.ts +++ b/packages/client/src/client/auth.ts @@ -5,7 +5,6 @@ import type { OAuthClientInformationFull, OAuthClientInformationMixed, OAuthClientMetadata, - OAuthMetadata, OAuthProtectedResourceMetadata, OAuthTokens } from '@modelcontextprotocol/core'; @@ -629,34 +628,6 @@ function extractFieldFromWwwAuth(response: Response, fieldName: string): string return null; } -/** - * Extract resource_metadata from response header. - * @deprecated Use `extractWWWAuthenticateParams` instead. - */ -export function extractResourceMetadataUrl(res: Response): URL | undefined { - const authenticateHeader = res.headers.get('WWW-Authenticate'); - if (!authenticateHeader) { - return undefined; - } - - const [type, scheme] = authenticateHeader.split(' '); - if (type?.toLowerCase() !== 'bearer' || !scheme) { - return undefined; - } - const regex = /resource_metadata="([^"]*)"/; - const match = regex.exec(authenticateHeader); - - if (!match || !match[1]) { - return undefined; - } - - try { - return new URL(match[1]); - } catch { - return undefined; - } -} - /** * Looks up RFC 9728 OAuth 2.0 Protected Resource Metadata. * @@ -767,54 +738,6 @@ async function discoverMetadataWithFallback( return response; } -/** - * Looks up RFC 8414 OAuth 2.0 Authorization Server Metadata. - * - * If the server returns a 404 for the well-known endpoint, this function will - * return `undefined`. Any other errors will be thrown as exceptions. - * - * @deprecated This function is deprecated in favor of `discoverAuthorizationServerMetadata`. - */ -export async function discoverOAuthMetadata( - issuer: string | URL, - { - authorizationServerUrl, - protocolVersion - }: { - authorizationServerUrl?: string | URL; - protocolVersion?: string; - } = {}, - fetchFn: FetchLike = fetch -): Promise { - if (typeof issuer === 'string') { - issuer = new URL(issuer); - } - if (!authorizationServerUrl) { - authorizationServerUrl = issuer; - } - if (typeof authorizationServerUrl === 'string') { - authorizationServerUrl = new URL(authorizationServerUrl); - } - protocolVersion ??= LATEST_PROTOCOL_VERSION; - - const response = await discoverMetadataWithFallback(authorizationServerUrl, 'oauth-authorization-server', fetchFn, { - protocolVersion, - metadataServerUrl: authorizationServerUrl - }); - - if (!response || response.status === 404) { - await response?.text?.().catch(() => {}); - return undefined; - } - - if (!response.ok) { - await response.text?.().catch(() => {}); - throw new Error(`HTTP ${response.status} trying to load well-known OAuth metadata`); - } - - return OAuthMetadataSchema.parse(await response.json()); -} - /** * Builds a list of discovery URLs to try for authorization server metadata. * URLs are returned in priority order: diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index 787cfd2f0..99c4e0e5e 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -1,14 +1,504 @@ -export * from './client/auth.js'; -export * from './client/authExtensions.js'; -export * from './client/client.js'; -export * from './client/middleware.js'; -export * from './client/sse.js'; -export * from './client/stdio.js'; -export * from './client/streamableHttp.js'; -export * from './client/websocket.js'; +// client/auth.ts — public OAuth API (internals are not re-exported) +export type { AddClientAuthentication, AuthResult, OAuthClientProvider } from './client/auth.js'; +export { auth, extractWWWAuthenticateParams, UnauthorizedError } from './client/auth.js'; + +// client/authExtensions.ts +export type { + ClientCredentialsProviderOptions, + PrivateKeyJwtProviderOptions, + StaticPrivateKeyJwtProviderOptions +} from './client/authExtensions.js'; +export { + ClientCredentialsProvider, + createPrivateKeyJwtAuth, + PrivateKeyJwtProvider, + StaticPrivateKeyJwtProvider +} from './client/authExtensions.js'; + +// client/client.ts +export type { ClientOptions } from './client/client.js'; +export { Client } from './client/client.js'; + +// client/middleware.ts +export type { LoggingOptions, Middleware, RequestLogger } from './client/middleware.js'; +export { applyMiddlewares, createMiddleware, withLogging, withOAuth } from './client/middleware.js'; + +// client/sse.ts +export type { SSEClientTransportOptions } from './client/sse.js'; +export { SSEClientTransport, SseError } from './client/sse.js'; + +// client/stdio.ts +export type { StdioServerParameters } from './client/stdio.js'; +export { DEFAULT_INHERITED_ENV_VARS, getDefaultEnvironment, StdioClientTransport } from './client/stdio.js'; + +// client/streamableHttp.ts +export type { StartSSEOptions, StreamableHTTPClientTransportOptions, StreamableHTTPReconnectionOptions } from './client/streamableHttp.js'; +export { StreamableHTTPClientTransport, StreamableHTTPError } from './client/streamableHttp.js'; + +// client/websocket.ts +export { WebSocketClientTransport } from './client/websocket.js'; // experimental exports -export * from './experimental/index.js'; +export { ExperimentalClientTasks } from './experimental/index.js'; + +// ============================================================================ +// Re-exports from @modelcontextprotocol/core +// Only symbols that are part of the public API are listed here. +// ============================================================================ + +// --- auth/errors.ts --- +export { + AccessDeniedError, + CustomOAuthError, + InsufficientScopeError, + InvalidClientError, + InvalidClientMetadataError, + InvalidGrantError, + InvalidRequestError, + InvalidScopeError, + InvalidTargetError, + InvalidTokenError, + MethodNotAllowedError, + OAuthError, + ServerError, + TemporarilyUnavailableError, + TooManyRequestsError, + UnauthorizedClientError, + UnsupportedGrantTypeError, + UnsupportedResponseTypeError, + UnsupportedTokenTypeError +} from '@modelcontextprotocol/core'; + +// --- shared/auth.ts --- +export type { + AuthorizationServerMetadata, + OAuthClientInformation, + OAuthClientInformationFull, + OAuthClientInformationMixed, + OAuthClientMetadata, + OAuthClientRegistrationError, + OAuthErrorResponse, + OAuthMetadata, + OAuthProtectedResourceMetadata, + OAuthTokenRevocationRequest, + OAuthTokens, + OpenIdProviderDiscoveryMetadata, + OpenIdProviderMetadata +} from '@modelcontextprotocol/core'; +export { + OAuthClientInformationFullSchema, + OAuthClientInformationSchema, + OAuthClientMetadataSchema, + OAuthClientRegistrationErrorSchema, + OAuthErrorResponseSchema, + OAuthMetadataSchema, + OAuthProtectedResourceMetadataSchema, + OAuthTokenRevocationRequestSchema, + OAuthTokensSchema, + OpenIdProviderDiscoveryMetadataSchema, + OpenIdProviderMetadataSchema +} from '@modelcontextprotocol/core'; + +// --- shared/authUtils.ts --- +export { checkResourceAllowed, resourceUrlFromServerUrl } from '@modelcontextprotocol/core'; + +// --- shared/metadataUtils.ts --- +export { getDisplayName } from '@modelcontextprotocol/core'; + +// --- shared/protocol.ts (excluding Protocol class, mergeCapabilities) --- +export type { + NotificationOptions, + ProgressCallback, + ProtocolOptions, + RequestHandlerExtra, + RequestOptions, + RequestTaskStore, + TaskRequestOptions +} from '@modelcontextprotocol/core'; +export { DEFAULT_REQUEST_TIMEOUT_MSEC } from '@modelcontextprotocol/core'; + +// --- shared/responseMessage.ts (excluding AsyncGeneratorValue) --- +export type { + BaseResponseMessage, + ErrorMessage, + ResponseMessage, + ResultMessage, + TaskCreatedMessage, + TaskStatusMessage +} from '@modelcontextprotocol/core'; +export { takeResult, toArrayAsync } from '@modelcontextprotocol/core'; + +// --- shared/transport.ts (excluding normalizeHeaders) --- +export type { FetchLike, Transport, TransportSendOptions } from '@modelcontextprotocol/core'; +export { createFetchWithInit } from '@modelcontextprotocol/core'; + +// --- shared/uriTemplate.ts --- +export type { Variables } from '@modelcontextprotocol/core'; +export { UriTemplate } from '@modelcontextprotocol/core'; + +// --- types/types.ts --- +export type { + Annotations, + AudioContent, + AuthInfo, + BaseMetadata, + BlobResourceContents, + BooleanSchema, + CallToolRequest, + CallToolRequestParams, + CallToolResult, + CancelledNotification, + CancelledNotificationParams, + CancelTaskRequest, + CancelTaskResult, + ClientCapabilities, + ClientNotification, + ClientRequest, + ClientResult, + CompatibilityCallToolResult, + CompleteRequest, + CompleteRequestParams, + CompleteRequestPrompt, + CompleteRequestResourceTemplate, + CompleteResult, + ContentBlock, + CreateMessageRequest, + CreateMessageRequestParams, + CreateMessageRequestParamsBase, + CreateMessageRequestParamsWithTools, + CreateMessageResult, + CreateMessageResultWithTools, + CreateTaskResult, + Cursor, + ElicitationCompleteNotification, + ElicitationCompleteNotificationParams, + ElicitRequest, + ElicitRequestFormParams, + ElicitRequestParams, + ElicitRequestURLParams, + ElicitResult, + EmbeddedResource, + EmptyResult, + EnumSchema, + GetPromptRequest, + GetPromptRequestParams, + GetPromptResult, + GetTaskPayloadRequest, + GetTaskPayloadResult, + GetTaskRequest, + GetTaskResult, + Icon, + Icons, + ImageContent, + Implementation, + InitializedNotification, + InitializeRequest, + InitializeRequestParams, + InitializeResult, + JSONRPCErrorResponse, + JSONRPCMessage, + JSONRPCNotification, + JSONRPCRequest, + JSONRPCResponse, + JSONRPCResultResponse, + LegacyTitledEnumSchema, + ListChangedCallback, + ListChangedHandlers, + ListChangedOptions, + ListPromptsRequest, + ListPromptsResult, + ListResourcesRequest, + ListResourcesResult, + ListResourceTemplatesRequest, + ListResourceTemplatesResult, + ListRootsRequest, + ListRootsResult, + ListTasksRequest, + ListTasksResult, + ListToolsRequest, + ListToolsResult, + LoggingLevel, + LoggingMessageNotification, + LoggingMessageNotificationParams, + MessageExtraInfo, + ModelHint, + ModelPreferences, + MultiSelectEnumSchema, + Notification, + NotificationParams, + NumberSchema, + PaginatedRequest, + PaginatedRequestParams, + PaginatedResult, + PingRequest, + PrimitiveSchemaDefinition, + Progress, + ProgressNotification, + ProgressNotificationParams, + ProgressToken, + Prompt, + PromptArgument, + PromptListChangedNotification, + PromptMessage, + PromptReference, + ReadResourceRequest, + ReadResourceRequestParams, + ReadResourceResult, + RelatedTaskMetadata, + Request, + RequestId, + RequestInfo, + RequestMeta, + RequestParams, + Resource, + ResourceContents, + ResourceLink, + ResourceListChangedNotification, + ResourceRequestParams, + ResourceTemplateReference, + ResourceTemplateType, + ResourceUpdatedNotification, + ResourceUpdatedNotificationParams, + Result, + Role, + Root, + RootsListChangedNotification, + SamplingContent, + SamplingMessage, + SamplingMessageContentBlock, + ServerCapabilities, + ServerNotification, + ServerRequest, + ServerResult, + SetLevelRequest, + SetLevelRequestParams, + SingleSelectEnumSchema, + StringSchema, + SubscribeRequest, + SubscribeRequestParams, + Task, + TaskAugmentedRequestParams, + TaskCreationParams, + TaskMetadata, + TaskStatus, + TaskStatusNotification, + TaskStatusNotificationParams, + TextContent, + TextResourceContents, + TitledMultiSelectEnumSchema, + TitledSingleSelectEnumSchema, + Tool, + ToolAnnotations, + ToolChoice, + ToolExecution, + ToolListChangedNotification, + ToolResultContent, + ToolUseContent, + UnsubscribeRequest, + UnsubscribeRequestParams, + UntitledMultiSelectEnumSchema, + UntitledSingleSelectEnumSchema +} from '@modelcontextprotocol/core'; +export { + AnnotationsSchema, + assertCompleteRequestPrompt, + assertCompleteRequestResourceTemplate, + AudioContentSchema, + BaseMetadataSchema, + BlobResourceContentsSchema, + BooleanSchemaSchema, + CallToolRequestParamsSchema, + CallToolRequestSchema, + CallToolResultSchema, + CancelledNotificationParamsSchema, + CancelledNotificationSchema, + CancelTaskRequestSchema, + CancelTaskResultSchema, + ClientCapabilitiesSchema, + ClientNotificationSchema, + ClientRequestSchema, + ClientResultSchema, + ClientTasksCapabilitySchema, + CompatibilityCallToolResultSchema, + CompleteRequestParamsSchema, + CompleteRequestSchema, + CompleteResultSchema, + ContentBlockSchema, + CreateMessageRequestParamsSchema, + CreateMessageRequestSchema, + CreateMessageResultSchema, + CreateMessageResultWithToolsSchema, + CreateTaskResultSchema, + CursorSchema, + DEFAULT_NEGOTIATED_PROTOCOL_VERSION, + ElicitationCompleteNotificationParamsSchema, + ElicitationCompleteNotificationSchema, + ElicitRequestFormParamsSchema, + ElicitRequestParamsSchema, + ElicitRequestSchema, + ElicitRequestURLParamsSchema, + ElicitResultSchema, + EmbeddedResourceSchema, + EmptyResultSchema, + EnumSchemaSchema, + ErrorCode, + GetPromptRequestParamsSchema, + GetPromptRequestSchema, + GetPromptResultSchema, + GetTaskPayloadRequestSchema, + GetTaskPayloadResultSchema, + GetTaskRequestSchema, + GetTaskResultSchema, + IconSchema, + IconsSchema, + ImageContentSchema, + ImplementationSchema, + InitializedNotificationSchema, + InitializeRequestParamsSchema, + InitializeRequestSchema, + InitializeResultSchema, + isInitializedNotification, + isInitializeRequest, + isJSONRPCErrorResponse, + isJSONRPCNotification, + isJSONRPCRequest, + isJSONRPCResultResponse, + isTaskAugmentedRequestParams, + JSONRPC_VERSION, + JSONRPCErrorResponseSchema, + JSONRPCMessageSchema, + JSONRPCNotificationSchema, + JSONRPCRequestSchema, + JSONRPCResponseSchema, + JSONRPCResultResponseSchema, + LATEST_PROTOCOL_VERSION, + LegacyTitledEnumSchemaSchema, + ListChangedOptionsBaseSchema, + ListPromptsRequestSchema, + ListPromptsResultSchema, + ListResourcesRequestSchema, + ListResourcesResultSchema, + ListResourceTemplatesRequestSchema, + ListResourceTemplatesResultSchema, + ListRootsRequestSchema, + ListRootsResultSchema, + ListTasksRequestSchema, + ListTasksResultSchema, + ListToolsRequestSchema, + ListToolsResultSchema, + LoggingLevelSchema, + LoggingMessageNotificationParamsSchema, + LoggingMessageNotificationSchema, + McpError, + ModelHintSchema, + ModelPreferencesSchema, + MultiSelectEnumSchemaSchema, + NotificationSchema, + NumberSchemaSchema, + PaginatedRequestParamsSchema, + PaginatedRequestSchema, + PaginatedResultSchema, + PingRequestSchema, + PrimitiveSchemaDefinitionSchema, + ProgressNotificationParamsSchema, + ProgressNotificationSchema, + ProgressSchema, + ProgressTokenSchema, + PromptArgumentSchema, + PromptListChangedNotificationSchema, + PromptMessageSchema, + PromptReferenceSchema, + PromptSchema, + ReadResourceRequestParamsSchema, + ReadResourceRequestSchema, + ReadResourceResultSchema, + RELATED_TASK_META_KEY, + RelatedTaskMetadataSchema, + RequestIdSchema, + RequestSchema, + ResourceContentsSchema, + ResourceLinkSchema, + ResourceListChangedNotificationSchema, + ResourceRequestParamsSchema, + ResourceSchema, + ResourceTemplateReferenceSchema, + ResourceTemplateSchema, + ResourceUpdatedNotificationParamsSchema, + ResourceUpdatedNotificationSchema, + ResultSchema, + RoleSchema, + RootSchema, + RootsListChangedNotificationSchema, + SamplingContentSchema, + SamplingMessageContentBlockSchema, + SamplingMessageSchema, + ServerCapabilitiesSchema, + ServerNotificationSchema, + ServerRequestSchema, + ServerResultSchema, + ServerTasksCapabilitySchema, + SetLevelRequestParamsSchema, + SetLevelRequestSchema, + SingleSelectEnumSchemaSchema, + StringSchemaSchema, + SubscribeRequestParamsSchema, + SubscribeRequestSchema, + SUPPORTED_PROTOCOL_VERSIONS, + TaskAugmentedRequestParamsSchema, + TaskCreationParamsSchema, + TaskMetadataSchema, + TaskSchema, + TaskStatusNotificationParamsSchema, + TaskStatusNotificationSchema, + TaskStatusSchema, + TextContentSchema, + TextResourceContentsSchema, + TitledMultiSelectEnumSchemaSchema, + TitledSingleSelectEnumSchemaSchema, + ToolAnnotationsSchema, + ToolChoiceSchema, + ToolExecutionSchema, + ToolListChangedNotificationSchema, + ToolResultContentSchema, + ToolSchema, + ToolUseContentSchema, + UnsubscribeRequestParamsSchema, + UnsubscribeRequestSchema, + UntitledMultiSelectEnumSchemaSchema, + UntitledSingleSelectEnumSchemaSchema, + UrlElicitationRequiredError +} from '@modelcontextprotocol/core'; + +// --- util/inMemory.ts --- +export { InMemoryTransport } from '@modelcontextprotocol/core'; + +// --- experimental/tasks (from core) --- +export type { + BaseQueuedMessage, + CreateTaskOptions, + CreateTaskRequestHandlerExtra, + QueuedError, + QueuedMessage, + QueuedNotification, + QueuedRequest, + QueuedResponse, + TaskMessageQueue, + TaskRequestHandlerExtra, + TaskStore, + TaskToolExecution +} from '@modelcontextprotocol/core'; +export { + assertClientRequestTaskCapability, + assertToolsCallTaskCapability, + InMemoryTaskMessageQueue, + InMemoryTaskStore, + isTerminal +} from '@modelcontextprotocol/core'; + +// --- validation/types.ts --- +export type { JsonSchemaType, JsonSchemaValidator, jsonSchemaValidator, JsonSchemaValidatorResult } from '@modelcontextprotocol/core'; -// re-export shared types -export * from '@modelcontextprotocol/core'; +// --- validation providers --- +export type { CfWorkerSchemaDraft } from '@modelcontextprotocol/core'; +export { AjvJsonSchemaValidator } from '@modelcontextprotocol/core'; +export { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/core'; diff --git a/packages/client/test/client/auth.test.ts b/packages/client/test/client/auth.test.ts index e29f5eabe..b9993e46a 100644 --- a/packages/client/test/client/auth.test.ts +++ b/packages/client/test/client/auth.test.ts @@ -6,7 +6,6 @@ import { auth, buildDiscoveryUrls, discoverAuthorizationServerMetadata, - discoverOAuthMetadata, discoverOAuthProtectedResourceMetadata, exchangeAuthorization, extractWWWAuthenticateParams, @@ -434,302 +433,6 @@ describe('OAuth Authorization', () => { }); }); - describe('discoverOAuthMetadata', () => { - const validMetadata = { - issuer: 'https://auth.example.com', - authorization_endpoint: 'https://auth.example.com/authorize', - token_endpoint: 'https://auth.example.com/token', - registration_endpoint: 'https://auth.example.com/register', - response_types_supported: ['code'], - code_challenge_methods_supported: ['S256'] - }; - - it('returns metadata when discovery succeeds', async () => { - mockFetch.mockResolvedValueOnce({ - ok: true, - status: 200, - json: async () => validMetadata - }); - - const metadata = await discoverOAuthMetadata('https://auth.example.com'); - expect(metadata).toEqual(validMetadata); - const calls = mockFetch.mock.calls; - expect(calls.length).toBe(1); - const [url, options] = calls[0]!; - expect(url.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server'); - expect(options.headers).toEqual({ - 'MCP-Protocol-Version': LATEST_PROTOCOL_VERSION - }); - }); - - it('returns metadata when discovery succeeds with path', async () => { - mockFetch.mockResolvedValueOnce({ - ok: true, - status: 200, - json: async () => validMetadata - }); - - const metadata = await discoverOAuthMetadata('https://auth.example.com/path/name'); - expect(metadata).toEqual(validMetadata); - const calls = mockFetch.mock.calls; - expect(calls.length).toBe(1); - const [url, options] = calls[0]!; - expect(url.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server/path/name'); - expect(options.headers).toEqual({ - 'MCP-Protocol-Version': LATEST_PROTOCOL_VERSION - }); - }); - - it('falls back to root discovery when path-aware discovery returns 404', async () => { - // First call (path-aware) returns 404 - mockFetch.mockResolvedValueOnce({ - ok: false, - status: 404 - }); - - // Second call (root fallback) succeeds - mockFetch.mockResolvedValueOnce({ - ok: true, - status: 200, - json: async () => validMetadata - }); - - const metadata = await discoverOAuthMetadata('https://auth.example.com/path/name'); - expect(metadata).toEqual(validMetadata); - - const calls = mockFetch.mock.calls; - expect(calls.length).toBe(2); - - // First call should be path-aware - const [firstUrl, firstOptions] = calls[0]!; - expect(firstUrl.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server/path/name'); - expect(firstOptions.headers).toEqual({ - 'MCP-Protocol-Version': LATEST_PROTOCOL_VERSION - }); - - // Second call should be root fallback - const [secondUrl, secondOptions] = calls[1]!; - expect(secondUrl.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server'); - expect(secondOptions.headers).toEqual({ - 'MCP-Protocol-Version': LATEST_PROTOCOL_VERSION - }); - }); - - it('returns undefined when both path-aware and root discovery return 404', async () => { - // First call (path-aware) returns 404 - mockFetch.mockResolvedValueOnce({ - ok: false, - status: 404 - }); - - // Second call (root fallback) also returns 404 - mockFetch.mockResolvedValueOnce({ - ok: false, - status: 404 - }); - - const metadata = await discoverOAuthMetadata('https://auth.example.com/path/name'); - expect(metadata).toBeUndefined(); - - const calls = mockFetch.mock.calls; - expect(calls.length).toBe(2); - }); - - it('does not fallback when the original URL is already at root path', async () => { - // First call (path-aware for root) returns 404 - mockFetch.mockResolvedValueOnce({ - ok: false, - status: 404 - }); - - const metadata = await discoverOAuthMetadata('https://auth.example.com/'); - expect(metadata).toBeUndefined(); - - const calls = mockFetch.mock.calls; - expect(calls.length).toBe(1); // Should not attempt fallback - - const [url] = calls[0]!; - expect(url.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server'); - }); - - it('does not fallback when the original URL has no path', async () => { - // First call (path-aware for no path) returns 404 - mockFetch.mockResolvedValueOnce({ - ok: false, - status: 404 - }); - - const metadata = await discoverOAuthMetadata('https://auth.example.com'); - expect(metadata).toBeUndefined(); - - const calls = mockFetch.mock.calls; - expect(calls.length).toBe(1); // Should not attempt fallback - - const [url] = calls[0]!; - expect(url.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server'); - }); - - it('falls back when path-aware discovery encounters CORS error', async () => { - // First call (path-aware) fails with TypeError (CORS) - mockFetch.mockImplementationOnce(() => Promise.reject(new TypeError('CORS error'))); - - // Retry path-aware without headers (simulating CORS retry) - mockFetch.mockResolvedValueOnce({ - ok: false, - status: 404 - }); - - // Second call (root fallback) succeeds - mockFetch.mockResolvedValueOnce({ - ok: true, - status: 200, - json: async () => validMetadata - }); - - const metadata = await discoverOAuthMetadata('https://auth.example.com/deep/path'); - expect(metadata).toEqual(validMetadata); - - const calls = mockFetch.mock.calls; - expect(calls.length).toBe(3); - - // Final call should be root fallback - const [lastUrl, lastOptions] = calls[2]!; - expect(lastUrl.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server'); - expect(lastOptions.headers).toEqual({ - 'MCP-Protocol-Version': LATEST_PROTOCOL_VERSION - }); - }); - - it('returns metadata when first fetch fails but second without MCP header succeeds', async () => { - // Set up a counter to control behavior - let callCount = 0; - - // Mock implementation that changes behavior based on call count - mockFetch.mockImplementation((_url, _options) => { - callCount++; - - if (callCount === 1) { - // First call with MCP header - fail with TypeError (simulating CORS error) - // We need to use TypeError specifically because that's what the implementation checks for - return Promise.reject(new TypeError('Network error')); - } else { - // Second call without header - succeed - return Promise.resolve({ - ok: true, - status: 200, - json: async () => validMetadata - }); - } - }); - - // Should succeed with the second call - const metadata = await discoverOAuthMetadata('https://auth.example.com'); - expect(metadata).toEqual(validMetadata); - - // Verify both calls were made - expect(mockFetch).toHaveBeenCalledTimes(2); - - // Verify first call had MCP header - expect(mockFetch.mock.calls[0]![1]?.headers).toHaveProperty('MCP-Protocol-Version'); - }); - - it('throws an error when all fetch attempts fail', async () => { - // Set up a counter to control behavior - let callCount = 0; - - // Mock implementation that changes behavior based on call count - mockFetch.mockImplementation((_url, _options) => { - callCount++; - - if (callCount === 1) { - // First call - fail with TypeError - return Promise.reject(new TypeError('First failure')); - } else { - // Second call - fail with different error - return Promise.reject(new Error('Second failure')); - } - }); - - // Should fail with the second error - await expect(discoverOAuthMetadata('https://auth.example.com')).rejects.toThrow('Second failure'); - - // Verify both calls were made - expect(mockFetch).toHaveBeenCalledTimes(2); - }); - - it('returns undefined when both CORS requests fail in fetchWithCorsRetry', async () => { - // fetchWithCorsRetry tries with headers (fails with CORS), then retries without headers (also fails with CORS) - // simulating a 404 w/o headers set. We want this to return undefined, not throw TypeError - mockFetch.mockImplementation(() => { - // Both the initial request with headers and retry without headers fail with CORS TypeError - return Promise.reject(new TypeError('Failed to fetch')); - }); - - // This should return undefined (the desired behavior after the fix) - const metadata = await discoverOAuthMetadata('https://auth.example.com/path'); - expect(metadata).toBeUndefined(); - }); - - it('returns undefined when discovery endpoint returns 404', async () => { - mockFetch.mockResolvedValueOnce({ - ok: false, - status: 404 - }); - - const metadata = await discoverOAuthMetadata('https://auth.example.com'); - expect(metadata).toBeUndefined(); - }); - - it('throws on non-404 errors', async () => { - mockFetch.mockResolvedValueOnce(new Response(null, { status: 500 })); - - await expect(discoverOAuthMetadata('https://auth.example.com')).rejects.toThrow('HTTP 500'); - }); - - it('validates metadata schema', async () => { - mockFetch.mockResolvedValueOnce( - Response.json( - { - // Missing required fields - issuer: 'https://auth.example.com' - }, - { status: 200 } - ) - ); - - await expect(discoverOAuthMetadata('https://auth.example.com')).rejects.toThrow(); - }); - - it('supports overriding the fetch function used for requests', async () => { - const validMetadata = { - issuer: 'https://auth.example.com', - authorization_endpoint: 'https://auth.example.com/authorize', - token_endpoint: 'https://auth.example.com/token', - registration_endpoint: 'https://auth.example.com/register', - response_types_supported: ['code'], - code_challenge_methods_supported: ['S256'] - }; - - const customFetch = vi.fn().mockResolvedValue({ - ok: true, - status: 200, - json: async () => validMetadata - }); - - const metadata = await discoverOAuthMetadata('https://auth.example.com', {}, customFetch); - - expect(metadata).toEqual(validMetadata); - expect(customFetch).toHaveBeenCalledTimes(1); - expect(mockFetch).not.toHaveBeenCalled(); - - const [url, options] = customFetch.mock.calls[0]!; - expect(url.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server'); - expect(options.headers).toEqual({ - 'MCP-Protocol-Version': LATEST_PROTOCOL_VERSION - }); - }); - }); - describe('buildDiscoveryUrls', () => { it('generates correct URLs for server without path', () => { const urls = buildDiscoveryUrls('https://auth.example.com'); diff --git a/packages/middleware/node/test/streamableHttp.test.ts b/packages/middleware/node/test/streamableHttp.test.ts index ca7728d88..765f8e2b5 100644 --- a/packages/middleware/node/test/streamableHttp.test.ts +++ b/packages/middleware/node/test/streamableHttp.test.ts @@ -12,7 +12,7 @@ import type { JSONRPCResultResponse, RequestId } from '@modelcontextprotocol/core'; -import type { EventId, EventStore, StreamId } from '@modelcontextprotocol/server'; +import type { EventStore } from '@modelcontextprotocol/server'; import { McpServer } from '@modelcontextprotocol/server'; import type { ZodMatrixEntry } from '@modelcontextprotocol/test-helpers'; import { listenOnRandomPort, zodTestMatrix } from '@modelcontextprotocol/test-helpers'; @@ -1328,18 +1328,18 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { }, async replayEventsAfter( - lastEventId: EventId, + laststring: string, { send }: { - send: (eventId: EventId, message: JSONRPCMessage) => Promise; + send: (eventId: string, message: JSONRPCMessage) => Promise; } - ): Promise { - const streamId = lastEventId.split('_')[0]!; + ): Promise { + const streamId = laststring.split('_')[0]!; // Extract stream ID from the event ID - // For test simplicity, just return all events with matching streamId that aren't the lastEventId + // For test simplicity, just return all events with matching streamId that aren't the laststring for (const [eventId, { message }] of storedEvents.entries()) { - if (eventId.startsWith(streamId) && eventId !== lastEventId) { + if (eventId.startsWith(streamId) && eventId !== laststring) { await send(eventId, message); } } @@ -1442,7 +1442,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { // Extract the event ID const idMatch = text.match(/id: ([^\n]+)/); expect(idMatch).toBeTruthy(); - const firstEventId = idMatch![1]!; + const firststring = idMatch![1]!; // Send a second notification await mcpServer.server.sendLoggingMessage({ level: 'info', data: 'Second notification from MCP server' }); @@ -1457,7 +1457,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { Accept: 'text/event-stream', 'mcp-session-id': sessionId, 'mcp-protocol-version': '2025-11-25', - 'last-event-id': firstEventId + 'last-event-id': firststring } }); @@ -1497,7 +1497,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { // Extract the event ID const idMatch = text.match(/id: ([^\n]+)/); expect(idMatch).toBeTruthy(); - const lastEventId = idMatch![1]!; + const laststring = idMatch![1]!; // Close the SSE stream to simulate a disconnect await reader!.cancel(); @@ -1514,7 +1514,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { Accept: 'text/event-stream', 'mcp-session-id': sessionId, 'mcp-protocol-version': '2025-11-25', - 'last-event-id': lastEventId + 'last-event-id': laststring } }); @@ -1656,14 +1656,14 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { return event?.streamId; }, async replayEventsAfter( - lastEventId: EventId, - { send }: { send: (eventId: EventId, message: JSONRPCMessage) => Promise } - ): Promise { - const event = storedEvents.get(lastEventId); - const streamId = event?.streamId || lastEventId.split('::')[0]!; + laststring: string, + { send }: { send: (eventId: string, message: JSONRPCMessage) => Promise } + ): Promise { + const event = storedEvents.get(laststring); + const streamId = event?.streamId || laststring.split('::')[0]!; const eventsToReplay: Array<[string, { message: JSONRPCMessage }]> = []; for (const [eventId, data] of storedEvents.entries()) { - if (data.streamId === streamId && eventId > lastEventId) { + if (data.streamId === streamId && eventId > laststring) { eventsToReplay.push([eventId, data]); } } @@ -2261,7 +2261,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { const text = new TextDecoder().decode(value); const idMatch = text.match(/id: ([^\n]+)/); expect(idMatch).toBeTruthy(); - const lastEventId = idMatch![1]!; + const laststring = idMatch![1]!; // Call the tool to close the standalone SSE stream const toolCallRequest: JSONRPCMessage = { @@ -2313,7 +2313,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { Accept: 'text/event-stream', 'mcp-session-id': sessionId, 'mcp-protocol-version': '2025-11-25', - 'last-event-id': lastEventId + 'last-event-id': laststring } }); expect(reconnectResponse.status).toBe(200); diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index 1a8dbf143..6b34d7678 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -1,12 +1,500 @@ -export * from './server/completable.js'; -export * from './server/mcp.js'; -export * from './server/middleware/hostHeaderValidation.js'; -export * from './server/server.js'; -export * from './server/stdio.js'; -export * from './server/streamableHttp.js'; +// server/completable.ts — public completion API (internals are not re-exported) +export type { CompletableSchema, CompleteCallback } from './server/completable.js'; +export { completable, isCompletable } from './server/completable.js'; + +// server/mcp.ts — high-level server API (internals are not re-exported) +export type { + CompleteResourceTemplateCallback, + ListResourcesCallback, + PromptCallback, + ReadResourceCallback, + ReadResourceTemplateCallback, + RegisteredPrompt, + RegisteredResource, + RegisteredResourceTemplate, + RegisteredTool, + ResourceMetadata, + ToolCallback +} from './server/mcp.js'; +export { McpServer, ResourceTemplate } from './server/mcp.js'; + +// server/middleware/hostHeaderValidation.ts +export type { HostHeaderValidationResult } from './server/middleware/hostHeaderValidation.js'; +export { hostHeaderValidationResponse, localhostAllowedHostnames, validateHostHeader } from './server/middleware/hostHeaderValidation.js'; + +// server/server.ts +export type { ServerOptions } from './server/server.js'; +export { Server } from './server/server.js'; + +// server/stdio.ts +export { StdioServerTransport } from './server/stdio.js'; + +// server/streamableHttp.ts — public transport API (StreamId, EventId are not re-exported) +export type { EventStore, HandleRequestOptions, WebStandardStreamableHTTPServerTransportOptions } from './server/streamableHttp.js'; +export { WebStandardStreamableHTTPServerTransport } from './server/streamableHttp.js'; // experimental exports -export * from './experimental/index.js'; +export type { CreateTaskRequestHandler, TaskRequestHandler, ToolTaskHandler } from './experimental/index.js'; +export { ExperimentalMcpServerTasks, ExperimentalServerTasks } from './experimental/index.js'; + +// ============================================================================ +// Re-exports from @modelcontextprotocol/core +// Only symbols that are part of the public API are listed here. +// ============================================================================ + +// --- auth/errors.ts --- +export { + AccessDeniedError, + CustomOAuthError, + InsufficientScopeError, + InvalidClientError, + InvalidClientMetadataError, + InvalidGrantError, + InvalidRequestError, + InvalidScopeError, + InvalidTargetError, + InvalidTokenError, + MethodNotAllowedError, + OAuthError, + ServerError, + TemporarilyUnavailableError, + TooManyRequestsError, + UnauthorizedClientError, + UnsupportedGrantTypeError, + UnsupportedResponseTypeError, + UnsupportedTokenTypeError +} from '@modelcontextprotocol/core'; + +// --- shared/auth.ts --- +export type { + AuthorizationServerMetadata, + OAuthClientInformation, + OAuthClientInformationFull, + OAuthClientInformationMixed, + OAuthClientMetadata, + OAuthClientRegistrationError, + OAuthErrorResponse, + OAuthMetadata, + OAuthProtectedResourceMetadata, + OAuthTokenRevocationRequest, + OAuthTokens, + OpenIdProviderDiscoveryMetadata, + OpenIdProviderMetadata +} from '@modelcontextprotocol/core'; +export { + OAuthClientInformationFullSchema, + OAuthClientInformationSchema, + OAuthClientMetadataSchema, + OAuthClientRegistrationErrorSchema, + OAuthErrorResponseSchema, + OAuthMetadataSchema, + OAuthProtectedResourceMetadataSchema, + OAuthTokenRevocationRequestSchema, + OAuthTokensSchema, + OpenIdProviderDiscoveryMetadataSchema, + OpenIdProviderMetadataSchema +} from '@modelcontextprotocol/core'; + +// --- shared/authUtils.ts --- +export { checkResourceAllowed, resourceUrlFromServerUrl } from '@modelcontextprotocol/core'; + +// --- shared/metadataUtils.ts --- +export { getDisplayName } from '@modelcontextprotocol/core'; + +// --- shared/protocol.ts (excluding Protocol class, mergeCapabilities) --- +export type { + NotificationOptions, + ProgressCallback, + ProtocolOptions, + RequestHandlerExtra, + RequestOptions, + RequestTaskStore, + TaskRequestOptions +} from '@modelcontextprotocol/core'; +export { DEFAULT_REQUEST_TIMEOUT_MSEC } from '@modelcontextprotocol/core'; + +// --- shared/responseMessage.ts (excluding AsyncGeneratorValue) --- +export type { + BaseResponseMessage, + ErrorMessage, + ResponseMessage, + ResultMessage, + TaskCreatedMessage, + TaskStatusMessage +} from '@modelcontextprotocol/core'; +export { takeResult, toArrayAsync } from '@modelcontextprotocol/core'; + +// --- shared/transport.ts (excluding normalizeHeaders) --- +export type { FetchLike, Transport, TransportSendOptions } from '@modelcontextprotocol/core'; +export { createFetchWithInit } from '@modelcontextprotocol/core'; + +// --- shared/uriTemplate.ts --- +export type { Variables } from '@modelcontextprotocol/core'; +export { UriTemplate } from '@modelcontextprotocol/core'; + +// --- types/types.ts --- +export type { + Annotations, + AudioContent, + AuthInfo, + BaseMetadata, + BlobResourceContents, + BooleanSchema, + CallToolRequest, + CallToolRequestParams, + CallToolResult, + CancelledNotification, + CancelledNotificationParams, + CancelTaskRequest, + CancelTaskResult, + ClientCapabilities, + ClientNotification, + ClientRequest, + ClientResult, + CompatibilityCallToolResult, + CompleteRequest, + CompleteRequestParams, + CompleteRequestPrompt, + CompleteRequestResourceTemplate, + CompleteResult, + ContentBlock, + CreateMessageRequest, + CreateMessageRequestParams, + CreateMessageRequestParamsBase, + CreateMessageRequestParamsWithTools, + CreateMessageResult, + CreateMessageResultWithTools, + CreateTaskResult, + Cursor, + ElicitationCompleteNotification, + ElicitationCompleteNotificationParams, + ElicitRequest, + ElicitRequestFormParams, + ElicitRequestParams, + ElicitRequestURLParams, + ElicitResult, + EmbeddedResource, + EmptyResult, + EnumSchema, + GetPromptRequest, + GetPromptRequestParams, + GetPromptResult, + GetTaskPayloadRequest, + GetTaskPayloadResult, + GetTaskRequest, + GetTaskResult, + Icon, + Icons, + ImageContent, + Implementation, + InitializedNotification, + InitializeRequest, + InitializeRequestParams, + InitializeResult, + JSONRPCErrorResponse, + JSONRPCMessage, + JSONRPCNotification, + JSONRPCRequest, + JSONRPCResponse, + JSONRPCResultResponse, + LegacyTitledEnumSchema, + ListChangedCallback, + ListChangedHandlers, + ListChangedOptions, + ListPromptsRequest, + ListPromptsResult, + ListResourcesRequest, + ListResourcesResult, + ListResourceTemplatesRequest, + ListResourceTemplatesResult, + ListRootsRequest, + ListRootsResult, + ListTasksRequest, + ListTasksResult, + ListToolsRequest, + ListToolsResult, + LoggingLevel, + LoggingMessageNotification, + LoggingMessageNotificationParams, + MessageExtraInfo, + ModelHint, + ModelPreferences, + MultiSelectEnumSchema, + Notification, + NotificationParams, + NumberSchema, + PaginatedRequest, + PaginatedRequestParams, + PaginatedResult, + PingRequest, + PrimitiveSchemaDefinition, + Progress, + ProgressNotification, + ProgressNotificationParams, + ProgressToken, + Prompt, + PromptArgument, + PromptListChangedNotification, + PromptMessage, + PromptReference, + ReadResourceRequest, + ReadResourceRequestParams, + ReadResourceResult, + RelatedTaskMetadata, + Request, + RequestId, + RequestInfo, + RequestMeta, + RequestParams, + Resource, + ResourceContents, + ResourceLink, + ResourceListChangedNotification, + ResourceRequestParams, + ResourceTemplateReference, + ResourceTemplateType, + ResourceUpdatedNotification, + ResourceUpdatedNotificationParams, + Result, + Role, + Root, + RootsListChangedNotification, + SamplingContent, + SamplingMessage, + SamplingMessageContentBlock, + ServerCapabilities, + ServerNotification, + ServerRequest, + ServerResult, + SetLevelRequest, + SetLevelRequestParams, + SingleSelectEnumSchema, + StringSchema, + SubscribeRequest, + SubscribeRequestParams, + Task, + TaskAugmentedRequestParams, + TaskCreationParams, + TaskMetadata, + TaskStatus, + TaskStatusNotification, + TaskStatusNotificationParams, + TextContent, + TextResourceContents, + TitledMultiSelectEnumSchema, + TitledSingleSelectEnumSchema, + Tool, + ToolAnnotations, + ToolChoice, + ToolExecution, + ToolListChangedNotification, + ToolResultContent, + ToolUseContent, + UnsubscribeRequest, + UnsubscribeRequestParams, + UntitledMultiSelectEnumSchema, + UntitledSingleSelectEnumSchema +} from '@modelcontextprotocol/core'; +export { + AnnotationsSchema, + assertCompleteRequestPrompt, + assertCompleteRequestResourceTemplate, + AudioContentSchema, + BaseMetadataSchema, + BlobResourceContentsSchema, + BooleanSchemaSchema, + CallToolRequestParamsSchema, + CallToolRequestSchema, + CallToolResultSchema, + CancelledNotificationParamsSchema, + CancelledNotificationSchema, + CancelTaskRequestSchema, + CancelTaskResultSchema, + ClientCapabilitiesSchema, + ClientNotificationSchema, + ClientRequestSchema, + ClientResultSchema, + ClientTasksCapabilitySchema, + CompatibilityCallToolResultSchema, + CompleteRequestParamsSchema, + CompleteRequestSchema, + CompleteResultSchema, + ContentBlockSchema, + CreateMessageRequestParamsSchema, + CreateMessageRequestSchema, + CreateMessageResultSchema, + CreateMessageResultWithToolsSchema, + CreateTaskResultSchema, + CursorSchema, + DEFAULT_NEGOTIATED_PROTOCOL_VERSION, + ElicitationCompleteNotificationParamsSchema, + ElicitationCompleteNotificationSchema, + ElicitRequestFormParamsSchema, + ElicitRequestParamsSchema, + ElicitRequestSchema, + ElicitRequestURLParamsSchema, + ElicitResultSchema, + EmbeddedResourceSchema, + EmptyResultSchema, + EnumSchemaSchema, + ErrorCode, + GetPromptRequestParamsSchema, + GetPromptRequestSchema, + GetPromptResultSchema, + GetTaskPayloadRequestSchema, + GetTaskPayloadResultSchema, + GetTaskRequestSchema, + GetTaskResultSchema, + IconSchema, + IconsSchema, + ImageContentSchema, + ImplementationSchema, + InitializedNotificationSchema, + InitializeRequestParamsSchema, + InitializeRequestSchema, + InitializeResultSchema, + isInitializedNotification, + isInitializeRequest, + isJSONRPCErrorResponse, + isJSONRPCNotification, + isJSONRPCRequest, + isJSONRPCResultResponse, + isTaskAugmentedRequestParams, + JSONRPC_VERSION, + JSONRPCErrorResponseSchema, + JSONRPCMessageSchema, + JSONRPCNotificationSchema, + JSONRPCRequestSchema, + JSONRPCResponseSchema, + JSONRPCResultResponseSchema, + LATEST_PROTOCOL_VERSION, + LegacyTitledEnumSchemaSchema, + ListChangedOptionsBaseSchema, + ListPromptsRequestSchema, + ListPromptsResultSchema, + ListResourcesRequestSchema, + ListResourcesResultSchema, + ListResourceTemplatesRequestSchema, + ListResourceTemplatesResultSchema, + ListRootsRequestSchema, + ListRootsResultSchema, + ListTasksRequestSchema, + ListTasksResultSchema, + ListToolsRequestSchema, + ListToolsResultSchema, + LoggingLevelSchema, + LoggingMessageNotificationParamsSchema, + LoggingMessageNotificationSchema, + McpError, + ModelHintSchema, + ModelPreferencesSchema, + MultiSelectEnumSchemaSchema, + NotificationSchema, + NumberSchemaSchema, + PaginatedRequestParamsSchema, + PaginatedRequestSchema, + PaginatedResultSchema, + PingRequestSchema, + PrimitiveSchemaDefinitionSchema, + ProgressNotificationParamsSchema, + ProgressNotificationSchema, + ProgressSchema, + ProgressTokenSchema, + PromptArgumentSchema, + PromptListChangedNotificationSchema, + PromptMessageSchema, + PromptReferenceSchema, + PromptSchema, + ReadResourceRequestParamsSchema, + ReadResourceRequestSchema, + ReadResourceResultSchema, + RELATED_TASK_META_KEY, + RelatedTaskMetadataSchema, + RequestIdSchema, + RequestSchema, + ResourceContentsSchema, + ResourceLinkSchema, + ResourceListChangedNotificationSchema, + ResourceRequestParamsSchema, + ResourceSchema, + ResourceTemplateReferenceSchema, + ResourceTemplateSchema, + ResourceUpdatedNotificationParamsSchema, + ResourceUpdatedNotificationSchema, + ResultSchema, + RoleSchema, + RootSchema, + RootsListChangedNotificationSchema, + SamplingContentSchema, + SamplingMessageContentBlockSchema, + SamplingMessageSchema, + ServerCapabilitiesSchema, + ServerNotificationSchema, + ServerRequestSchema, + ServerResultSchema, + ServerTasksCapabilitySchema, + SetLevelRequestParamsSchema, + SetLevelRequestSchema, + SingleSelectEnumSchemaSchema, + StringSchemaSchema, + SubscribeRequestParamsSchema, + SubscribeRequestSchema, + SUPPORTED_PROTOCOL_VERSIONS, + TaskAugmentedRequestParamsSchema, + TaskCreationParamsSchema, + TaskMetadataSchema, + TaskSchema, + TaskStatusNotificationParamsSchema, + TaskStatusNotificationSchema, + TaskStatusSchema, + TextContentSchema, + TextResourceContentsSchema, + TitledMultiSelectEnumSchemaSchema, + TitledSingleSelectEnumSchemaSchema, + ToolAnnotationsSchema, + ToolChoiceSchema, + ToolExecutionSchema, + ToolListChangedNotificationSchema, + ToolResultContentSchema, + ToolSchema, + ToolUseContentSchema, + UnsubscribeRequestParamsSchema, + UnsubscribeRequestSchema, + UntitledMultiSelectEnumSchemaSchema, + UntitledSingleSelectEnumSchemaSchema, + UrlElicitationRequiredError +} from '@modelcontextprotocol/core'; + +// --- util/inMemory.ts --- +export { InMemoryTransport } from '@modelcontextprotocol/core'; + +// --- experimental/tasks (from core) --- +export type { + BaseQueuedMessage, + CreateTaskOptions, + CreateTaskRequestHandlerExtra, + QueuedError, + QueuedMessage, + QueuedNotification, + QueuedRequest, + QueuedResponse, + TaskMessageQueue, + TaskRequestHandlerExtra, + TaskStore, + TaskToolExecution +} from '@modelcontextprotocol/core'; +export { + assertClientRequestTaskCapability, + assertToolsCallTaskCapability, + InMemoryTaskMessageQueue, + InMemoryTaskStore, + isTerminal +} from '@modelcontextprotocol/core'; + +// --- validation/types.ts --- +export type { JsonSchemaType, JsonSchemaValidator, jsonSchemaValidator, JsonSchemaValidatorResult } from '@modelcontextprotocol/core'; -// re-export shared types -export * from '@modelcontextprotocol/core'; +// --- validation providers --- +export type { CfWorkerSchemaDraft } from '@modelcontextprotocol/core'; +export { AjvJsonSchemaValidator } from '@modelcontextprotocol/core'; +export { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/core'; diff --git a/packages/server/src/server/completable.ts b/packages/server/src/server/completable.ts index 7174bff37..844484294 100644 --- a/packages/server/src/server/completable.ts +++ b/packages/server/src/server/completable.ts @@ -45,23 +45,3 @@ export function getCompleter(schema: T): CompleteCallback })[COMPLETABLE_SYMBOL]; return meta?.complete as CompleteCallback | undefined; } - -/** - * Unwraps a completable schema to get the underlying schema. - * For backward compatibility with code that called `.unwrap()`. - */ -export function unwrapCompletable(schema: CompletableSchema): T { - return schema; -} - -// Legacy exports for backward compatibility -// These types are deprecated but kept for existing code -export enum McpZodTypeKind { - Completable = 'McpCompletable' -} - -export interface CompletableDef { - type: T; - complete: CompleteCallback; - typeName: McpZodTypeKind.Completable; -} diff --git a/test/integration/test/client/client.test.ts b/test/integration/test/client/client.test.ts index a4d6943c1..45acfdd9e 100644 --- a/test/integration/test/client/client.test.ts +++ b/test/integration/test/client/client.test.ts @@ -1,4 +1,4 @@ -import { Client, getSupportedElicitationModes } from '@modelcontextprotocol/client'; +import { Client } from '@modelcontextprotocol/client'; import type { Prompt, Resource, Tool, Transport } from '@modelcontextprotocol/core'; import { CallToolResultSchema, @@ -14,6 +14,168 @@ import { import { InMemoryTaskStore, McpServer, Server } from '@modelcontextprotocol/server'; import * as z4 from 'zod/v4'; +<<<<<<< HEAD +======= +import { getSupportedElicitationModes } from '../../../../packages/client/src/client/client.js'; + +describe('Zod v4', () => { + /*** + * Test: Type Checking + * Test that custom request/notification/result schemas can be used with the Client class. + */ + test('should typecheck', () => { + const GetWeatherRequestSchema = RequestSchema.extend({ + method: z4.literal('weather/get'), + params: z4.object({ + city: z4.string() + }) + }); + + const GetForecastRequestSchema = RequestSchema.extend({ + method: z4.literal('weather/forecast'), + params: z4.object({ + city: z4.string(), + days: z4.number() + }) + }); + + const WeatherForecastNotificationSchema = NotificationSchema.extend({ + method: z4.literal('weather/alert'), + params: z4.object({ + severity: z4.enum(['warning', 'watch']), + message: z4.string() + }) + }); + + const WeatherRequestSchema = GetWeatherRequestSchema.or(GetForecastRequestSchema); + const WeatherNotificationSchema = WeatherForecastNotificationSchema; + const WeatherResultSchema = ResultSchema.extend({ + temperature: z4.number(), + conditions: z4.string() + }); + + type WeatherRequest = z4.infer; + type WeatherNotification = z4.infer; + type WeatherResult = z4.infer; + + // 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' + } + }); + }); +}); + +describe('Zod v3', () => { + /*** + * Test: Type Checking + * Test that custom request/notification/result schemas can be used with the Client class. + */ + test('should typecheck', () => { + const GetWeatherRequestSchema = z3.object({ + ...RequestSchema.shape, + method: z3.literal('weather/get'), + params: z3.object({ + city: z3.string() + }) + }); + + const GetForecastRequestSchema = z3.object({ + ...RequestSchema.shape, + method: z3.literal('weather/forecast'), + params: z3.object({ + city: z3.string(), + days: z3.number() + }) + }); + + const WeatherForecastNotificationSchema = z3.object({ + ...NotificationSchema.shape, + method: z3.literal('weather/alert'), + params: z3.object({ + severity: z3.enum(['warning', 'watch']), + message: z3.string() + }) + }); + + const WeatherRequestSchema = GetWeatherRequestSchema.or(GetForecastRequestSchema); + const WeatherNotificationSchema = WeatherForecastNotificationSchema; + const WeatherResultSchema = z3.object({ + ...ResultSchema.shape, + _meta: z3.record(z3.string(), z3.unknown()).optional(), + temperature: z3.number(), + conditions: z3.string() + }); + + type WeatherRequest = z3.infer; + type WeatherNotification = z3.infer; + type WeatherResult = z3.infer; + + // 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' + } + }); + }); +}); + +>>>>>>> 79c70fe5 (`v2`: replace export * with explicit named exports to tighten public API surface) /*** * Test: Initialize with Matching Protocol Version */ diff --git a/test/integration/test/issues/test_1342OauthErrorHttp200.test.ts b/test/integration/test/issues/test_1342OauthErrorHttp200.test.ts index fd509e6d6..e231c2014 100644 --- a/test/integration/test/issues/test_1342OauthErrorHttp200.test.ts +++ b/test/integration/test/issues/test_1342OauthErrorHttp200.test.ts @@ -7,9 +7,10 @@ * detects the error field and surfaces the actual OAuth error message. */ -import { exchangeAuthorization } from '@modelcontextprotocol/client'; import { describe, expect, it, vi } from 'vitest'; +import { exchangeAuthorization } from '../../../../packages/client/src/client/auth.js'; + const mockFetch = vi.fn(); vi.stubGlobal('fetch', mockFetch); From 7fb1f2cc3b01b3b27d057dca60f3a16cfaa663ea Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Mon, 2 Feb 2026 18:09:37 +0000 Subject: [PATCH 2/3] fix: restore deprecated source code, only tighten barrel exports Keep deprecated functions (discoverOAuthMetadata, extractResourceMetadataUrl, unwrapCompletable, McpZodTypeKind, CompletableDef) in source files. The API surface tightening should only control what is re-exported from barrel files, not delete functionality. Tests that reference internal symbols now import from source paths instead of the package barrel. --- packages/client/src/client/auth.ts | 77 +++++ packages/client/test/client/auth.test.ts | 297 ++++++++++++++++++ .../node/test/streamableHttp.test.ts | 37 +-- packages/server/src/server/completable.ts | 20 ++ test/integration/test/client/client.test.ts | 163 +--------- .../issues/test_1342OauthErrorHttp200.test.ts | 3 +- 6 files changed, 415 insertions(+), 182 deletions(-) diff --git a/packages/client/src/client/auth.ts b/packages/client/src/client/auth.ts index 2f7b2c1b0..4589fcda2 100644 --- a/packages/client/src/client/auth.ts +++ b/packages/client/src/client/auth.ts @@ -5,6 +5,7 @@ import type { OAuthClientInformationFull, OAuthClientInformationMixed, OAuthClientMetadata, + OAuthMetadata, OAuthProtectedResourceMetadata, OAuthTokens } from '@modelcontextprotocol/core'; @@ -628,6 +629,34 @@ function extractFieldFromWwwAuth(response: Response, fieldName: string): string return null; } +/** + * Extract resource_metadata from response header. + * @deprecated Use `extractWWWAuthenticateParams` instead. + */ +export function extractResourceMetadataUrl(res: Response): URL | undefined { + const authenticateHeader = res.headers.get('WWW-Authenticate'); + if (!authenticateHeader) { + return undefined; + } + + const [type, scheme] = authenticateHeader.split(' '); + if (type?.toLowerCase() !== 'bearer' || !scheme) { + return undefined; + } + const regex = /resource_metadata="([^"]*)"/; + const match = regex.exec(authenticateHeader); + + if (!match || !match[1]) { + return undefined; + } + + try { + return new URL(match[1]); + } catch { + return undefined; + } +} + /** * Looks up RFC 9728 OAuth 2.0 Protected Resource Metadata. * @@ -738,6 +767,54 @@ async function discoverMetadataWithFallback( return response; } +/** + * Looks up RFC 8414 OAuth 2.0 Authorization Server Metadata. + * + * If the server returns a 404 for the well-known endpoint, this function will + * return `undefined`. Any other errors will be thrown as exceptions. + * + * @deprecated This function is deprecated in favor of `discoverAuthorizationServerMetadata`. + */ +export async function discoverOAuthMetadata( + issuer: string | URL, + { + authorizationServerUrl, + protocolVersion + }: { + authorizationServerUrl?: string | URL; + protocolVersion?: string; + } = {}, + fetchFn: FetchLike = fetch +): Promise { + if (typeof issuer === 'string') { + issuer = new URL(issuer); + } + if (!authorizationServerUrl) { + authorizationServerUrl = issuer; + } + if (typeof authorizationServerUrl === 'string') { + authorizationServerUrl = new URL(authorizationServerUrl); + } + protocolVersion ??= LATEST_PROTOCOL_VERSION; + + const response = await discoverMetadataWithFallback(authorizationServerUrl, 'oauth-authorization-server', fetchFn, { + protocolVersion, + metadataServerUrl: authorizationServerUrl + }); + + if (!response || response.status === 404) { + await response?.text?.().catch(() => {}); + return undefined; + } + + if (!response.ok) { + await response.text?.().catch(() => {}); + throw new Error(`HTTP ${response.status} trying to load well-known OAuth metadata`); + } + + return OAuthMetadataSchema.parse(await response.json()); +} + /** * Builds a list of discovery URLs to try for authorization server metadata. * URLs are returned in priority order: diff --git a/packages/client/test/client/auth.test.ts b/packages/client/test/client/auth.test.ts index b9993e46a..e29f5eabe 100644 --- a/packages/client/test/client/auth.test.ts +++ b/packages/client/test/client/auth.test.ts @@ -6,6 +6,7 @@ import { auth, buildDiscoveryUrls, discoverAuthorizationServerMetadata, + discoverOAuthMetadata, discoverOAuthProtectedResourceMetadata, exchangeAuthorization, extractWWWAuthenticateParams, @@ -433,6 +434,302 @@ describe('OAuth Authorization', () => { }); }); + describe('discoverOAuthMetadata', () => { + const validMetadata = { + issuer: 'https://auth.example.com', + authorization_endpoint: 'https://auth.example.com/authorize', + token_endpoint: 'https://auth.example.com/token', + registration_endpoint: 'https://auth.example.com/register', + response_types_supported: ['code'], + code_challenge_methods_supported: ['S256'] + }; + + it('returns metadata when discovery succeeds', async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + status: 200, + json: async () => validMetadata + }); + + const metadata = await discoverOAuthMetadata('https://auth.example.com'); + expect(metadata).toEqual(validMetadata); + const calls = mockFetch.mock.calls; + expect(calls.length).toBe(1); + const [url, options] = calls[0]!; + expect(url.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server'); + expect(options.headers).toEqual({ + 'MCP-Protocol-Version': LATEST_PROTOCOL_VERSION + }); + }); + + it('returns metadata when discovery succeeds with path', async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + status: 200, + json: async () => validMetadata + }); + + const metadata = await discoverOAuthMetadata('https://auth.example.com/path/name'); + expect(metadata).toEqual(validMetadata); + const calls = mockFetch.mock.calls; + expect(calls.length).toBe(1); + const [url, options] = calls[0]!; + expect(url.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server/path/name'); + expect(options.headers).toEqual({ + 'MCP-Protocol-Version': LATEST_PROTOCOL_VERSION + }); + }); + + it('falls back to root discovery when path-aware discovery returns 404', async () => { + // First call (path-aware) returns 404 + mockFetch.mockResolvedValueOnce({ + ok: false, + status: 404 + }); + + // Second call (root fallback) succeeds + mockFetch.mockResolvedValueOnce({ + ok: true, + status: 200, + json: async () => validMetadata + }); + + const metadata = await discoverOAuthMetadata('https://auth.example.com/path/name'); + expect(metadata).toEqual(validMetadata); + + const calls = mockFetch.mock.calls; + expect(calls.length).toBe(2); + + // First call should be path-aware + const [firstUrl, firstOptions] = calls[0]!; + expect(firstUrl.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server/path/name'); + expect(firstOptions.headers).toEqual({ + 'MCP-Protocol-Version': LATEST_PROTOCOL_VERSION + }); + + // Second call should be root fallback + const [secondUrl, secondOptions] = calls[1]!; + expect(secondUrl.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server'); + expect(secondOptions.headers).toEqual({ + 'MCP-Protocol-Version': LATEST_PROTOCOL_VERSION + }); + }); + + it('returns undefined when both path-aware and root discovery return 404', async () => { + // First call (path-aware) returns 404 + mockFetch.mockResolvedValueOnce({ + ok: false, + status: 404 + }); + + // Second call (root fallback) also returns 404 + mockFetch.mockResolvedValueOnce({ + ok: false, + status: 404 + }); + + const metadata = await discoverOAuthMetadata('https://auth.example.com/path/name'); + expect(metadata).toBeUndefined(); + + const calls = mockFetch.mock.calls; + expect(calls.length).toBe(2); + }); + + it('does not fallback when the original URL is already at root path', async () => { + // First call (path-aware for root) returns 404 + mockFetch.mockResolvedValueOnce({ + ok: false, + status: 404 + }); + + const metadata = await discoverOAuthMetadata('https://auth.example.com/'); + expect(metadata).toBeUndefined(); + + const calls = mockFetch.mock.calls; + expect(calls.length).toBe(1); // Should not attempt fallback + + const [url] = calls[0]!; + expect(url.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server'); + }); + + it('does not fallback when the original URL has no path', async () => { + // First call (path-aware for no path) returns 404 + mockFetch.mockResolvedValueOnce({ + ok: false, + status: 404 + }); + + const metadata = await discoverOAuthMetadata('https://auth.example.com'); + expect(metadata).toBeUndefined(); + + const calls = mockFetch.mock.calls; + expect(calls.length).toBe(1); // Should not attempt fallback + + const [url] = calls[0]!; + expect(url.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server'); + }); + + it('falls back when path-aware discovery encounters CORS error', async () => { + // First call (path-aware) fails with TypeError (CORS) + mockFetch.mockImplementationOnce(() => Promise.reject(new TypeError('CORS error'))); + + // Retry path-aware without headers (simulating CORS retry) + mockFetch.mockResolvedValueOnce({ + ok: false, + status: 404 + }); + + // Second call (root fallback) succeeds + mockFetch.mockResolvedValueOnce({ + ok: true, + status: 200, + json: async () => validMetadata + }); + + const metadata = await discoverOAuthMetadata('https://auth.example.com/deep/path'); + expect(metadata).toEqual(validMetadata); + + const calls = mockFetch.mock.calls; + expect(calls.length).toBe(3); + + // Final call should be root fallback + const [lastUrl, lastOptions] = calls[2]!; + expect(lastUrl.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server'); + expect(lastOptions.headers).toEqual({ + 'MCP-Protocol-Version': LATEST_PROTOCOL_VERSION + }); + }); + + it('returns metadata when first fetch fails but second without MCP header succeeds', async () => { + // Set up a counter to control behavior + let callCount = 0; + + // Mock implementation that changes behavior based on call count + mockFetch.mockImplementation((_url, _options) => { + callCount++; + + if (callCount === 1) { + // First call with MCP header - fail with TypeError (simulating CORS error) + // We need to use TypeError specifically because that's what the implementation checks for + return Promise.reject(new TypeError('Network error')); + } else { + // Second call without header - succeed + return Promise.resolve({ + ok: true, + status: 200, + json: async () => validMetadata + }); + } + }); + + // Should succeed with the second call + const metadata = await discoverOAuthMetadata('https://auth.example.com'); + expect(metadata).toEqual(validMetadata); + + // Verify both calls were made + expect(mockFetch).toHaveBeenCalledTimes(2); + + // Verify first call had MCP header + expect(mockFetch.mock.calls[0]![1]?.headers).toHaveProperty('MCP-Protocol-Version'); + }); + + it('throws an error when all fetch attempts fail', async () => { + // Set up a counter to control behavior + let callCount = 0; + + // Mock implementation that changes behavior based on call count + mockFetch.mockImplementation((_url, _options) => { + callCount++; + + if (callCount === 1) { + // First call - fail with TypeError + return Promise.reject(new TypeError('First failure')); + } else { + // Second call - fail with different error + return Promise.reject(new Error('Second failure')); + } + }); + + // Should fail with the second error + await expect(discoverOAuthMetadata('https://auth.example.com')).rejects.toThrow('Second failure'); + + // Verify both calls were made + expect(mockFetch).toHaveBeenCalledTimes(2); + }); + + it('returns undefined when both CORS requests fail in fetchWithCorsRetry', async () => { + // fetchWithCorsRetry tries with headers (fails with CORS), then retries without headers (also fails with CORS) + // simulating a 404 w/o headers set. We want this to return undefined, not throw TypeError + mockFetch.mockImplementation(() => { + // Both the initial request with headers and retry without headers fail with CORS TypeError + return Promise.reject(new TypeError('Failed to fetch')); + }); + + // This should return undefined (the desired behavior after the fix) + const metadata = await discoverOAuthMetadata('https://auth.example.com/path'); + expect(metadata).toBeUndefined(); + }); + + it('returns undefined when discovery endpoint returns 404', async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + status: 404 + }); + + const metadata = await discoverOAuthMetadata('https://auth.example.com'); + expect(metadata).toBeUndefined(); + }); + + it('throws on non-404 errors', async () => { + mockFetch.mockResolvedValueOnce(new Response(null, { status: 500 })); + + await expect(discoverOAuthMetadata('https://auth.example.com')).rejects.toThrow('HTTP 500'); + }); + + it('validates metadata schema', async () => { + mockFetch.mockResolvedValueOnce( + Response.json( + { + // Missing required fields + issuer: 'https://auth.example.com' + }, + { status: 200 } + ) + ); + + await expect(discoverOAuthMetadata('https://auth.example.com')).rejects.toThrow(); + }); + + it('supports overriding the fetch function used for requests', async () => { + const validMetadata = { + issuer: 'https://auth.example.com', + authorization_endpoint: 'https://auth.example.com/authorize', + token_endpoint: 'https://auth.example.com/token', + registration_endpoint: 'https://auth.example.com/register', + response_types_supported: ['code'], + code_challenge_methods_supported: ['S256'] + }; + + const customFetch = vi.fn().mockResolvedValue({ + ok: true, + status: 200, + json: async () => validMetadata + }); + + const metadata = await discoverOAuthMetadata('https://auth.example.com', {}, customFetch); + + expect(metadata).toEqual(validMetadata); + expect(customFetch).toHaveBeenCalledTimes(1); + expect(mockFetch).not.toHaveBeenCalled(); + + const [url, options] = customFetch.mock.calls[0]!; + expect(url.toString()).toBe('https://auth.example.com/.well-known/oauth-authorization-server'); + expect(options.headers).toEqual({ + 'MCP-Protocol-Version': LATEST_PROTOCOL_VERSION + }); + }); + }); + describe('buildDiscoveryUrls', () => { it('generates correct URLs for server without path', () => { const urls = buildDiscoveryUrls('https://auth.example.com'); diff --git a/packages/middleware/node/test/streamableHttp.test.ts b/packages/middleware/node/test/streamableHttp.test.ts index 765f8e2b5..5ce38f663 100644 --- a/packages/middleware/node/test/streamableHttp.test.ts +++ b/packages/middleware/node/test/streamableHttp.test.ts @@ -13,6 +13,7 @@ import type { RequestId } from '@modelcontextprotocol/core'; import type { EventStore } from '@modelcontextprotocol/server'; +import type { EventId, StreamId } from '../../../../packages/server/src/server/streamableHttp.js'; import { McpServer } from '@modelcontextprotocol/server'; import type { ZodMatrixEntry } from '@modelcontextprotocol/test-helpers'; import { listenOnRandomPort, zodTestMatrix } from '@modelcontextprotocol/test-helpers'; @@ -1328,18 +1329,18 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { }, async replayEventsAfter( - laststring: string, + lastEventId: EventId, { send }: { - send: (eventId: string, message: JSONRPCMessage) => Promise; + send: (eventId: EventId, message: JSONRPCMessage) => Promise; } - ): Promise { - const streamId = laststring.split('_')[0]!; + ): Promise { + const streamId = lastEventId.split('_')[0]!; // Extract stream ID from the event ID - // For test simplicity, just return all events with matching streamId that aren't the laststring + // For test simplicity, just return all events with matching streamId that aren't the lastEventId for (const [eventId, { message }] of storedEvents.entries()) { - if (eventId.startsWith(streamId) && eventId !== laststring) { + if (eventId.startsWith(streamId) && eventId !== lastEventId) { await send(eventId, message); } } @@ -1442,7 +1443,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { // Extract the event ID const idMatch = text.match(/id: ([^\n]+)/); expect(idMatch).toBeTruthy(); - const firststring = idMatch![1]!; + const firstEventId = idMatch![1]!; // Send a second notification await mcpServer.server.sendLoggingMessage({ level: 'info', data: 'Second notification from MCP server' }); @@ -1457,7 +1458,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { Accept: 'text/event-stream', 'mcp-session-id': sessionId, 'mcp-protocol-version': '2025-11-25', - 'last-event-id': firststring + 'last-event-id': firstEventId } }); @@ -1497,7 +1498,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { // Extract the event ID const idMatch = text.match(/id: ([^\n]+)/); expect(idMatch).toBeTruthy(); - const laststring = idMatch![1]!; + const lastEventId = idMatch![1]!; // Close the SSE stream to simulate a disconnect await reader!.cancel(); @@ -1514,7 +1515,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { Accept: 'text/event-stream', 'mcp-session-id': sessionId, 'mcp-protocol-version': '2025-11-25', - 'last-event-id': laststring + 'last-event-id': lastEventId } }); @@ -1656,14 +1657,14 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { return event?.streamId; }, async replayEventsAfter( - laststring: string, - { send }: { send: (eventId: string, message: JSONRPCMessage) => Promise } - ): Promise { - const event = storedEvents.get(laststring); - const streamId = event?.streamId || laststring.split('::')[0]!; + lastEventId: EventId, + { send }: { send: (eventId: EventId, message: JSONRPCMessage) => Promise } + ): Promise { + const event = storedEvents.get(lastEventId); + const streamId = event?.streamId || lastEventId.split('::')[0]!; const eventsToReplay: Array<[string, { message: JSONRPCMessage }]> = []; for (const [eventId, data] of storedEvents.entries()) { - if (data.streamId === streamId && eventId > laststring) { + if (data.streamId === streamId && eventId > lastEventId) { eventsToReplay.push([eventId, data]); } } @@ -2261,7 +2262,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { const text = new TextDecoder().decode(value); const idMatch = text.match(/id: ([^\n]+)/); expect(idMatch).toBeTruthy(); - const laststring = idMatch![1]!; + const lastEventId = idMatch![1]!; // Call the tool to close the standalone SSE stream const toolCallRequest: JSONRPCMessage = { @@ -2313,7 +2314,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => { Accept: 'text/event-stream', 'mcp-session-id': sessionId, 'mcp-protocol-version': '2025-11-25', - 'last-event-id': laststring + 'last-event-id': lastEventId } }); expect(reconnectResponse.status).toBe(200); diff --git a/packages/server/src/server/completable.ts b/packages/server/src/server/completable.ts index 844484294..7174bff37 100644 --- a/packages/server/src/server/completable.ts +++ b/packages/server/src/server/completable.ts @@ -45,3 +45,23 @@ export function getCompleter(schema: T): CompleteCallback })[COMPLETABLE_SYMBOL]; return meta?.complete as CompleteCallback | undefined; } + +/** + * Unwraps a completable schema to get the underlying schema. + * For backward compatibility with code that called `.unwrap()`. + */ +export function unwrapCompletable(schema: CompletableSchema): T { + return schema; +} + +// Legacy exports for backward compatibility +// These types are deprecated but kept for existing code +export enum McpZodTypeKind { + Completable = 'McpCompletable' +} + +export interface CompletableDef { + type: T; + complete: CompleteCallback; + typeName: McpZodTypeKind.Completable; +} diff --git a/test/integration/test/client/client.test.ts b/test/integration/test/client/client.test.ts index 45acfdd9e..568e4eea5 100644 --- a/test/integration/test/client/client.test.ts +++ b/test/integration/test/client/client.test.ts @@ -1,4 +1,5 @@ import { Client } from '@modelcontextprotocol/client'; +import { getSupportedElicitationModes } from '../../../../packages/client/src/client/client.js'; import type { Prompt, Resource, Tool, Transport } from '@modelcontextprotocol/core'; import { CallToolResultSchema, @@ -14,168 +15,6 @@ import { import { InMemoryTaskStore, McpServer, Server } from '@modelcontextprotocol/server'; import * as z4 from 'zod/v4'; -<<<<<<< HEAD -======= -import { getSupportedElicitationModes } from '../../../../packages/client/src/client/client.js'; - -describe('Zod v4', () => { - /*** - * Test: Type Checking - * Test that custom request/notification/result schemas can be used with the Client class. - */ - test('should typecheck', () => { - const GetWeatherRequestSchema = RequestSchema.extend({ - method: z4.literal('weather/get'), - params: z4.object({ - city: z4.string() - }) - }); - - const GetForecastRequestSchema = RequestSchema.extend({ - method: z4.literal('weather/forecast'), - params: z4.object({ - city: z4.string(), - days: z4.number() - }) - }); - - const WeatherForecastNotificationSchema = NotificationSchema.extend({ - method: z4.literal('weather/alert'), - params: z4.object({ - severity: z4.enum(['warning', 'watch']), - message: z4.string() - }) - }); - - const WeatherRequestSchema = GetWeatherRequestSchema.or(GetForecastRequestSchema); - const WeatherNotificationSchema = WeatherForecastNotificationSchema; - const WeatherResultSchema = ResultSchema.extend({ - temperature: z4.number(), - conditions: z4.string() - }); - - type WeatherRequest = z4.infer; - type WeatherNotification = z4.infer; - type WeatherResult = z4.infer; - - // 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' - } - }); - }); -}); - -describe('Zod v3', () => { - /*** - * Test: Type Checking - * Test that custom request/notification/result schemas can be used with the Client class. - */ - test('should typecheck', () => { - const GetWeatherRequestSchema = z3.object({ - ...RequestSchema.shape, - method: z3.literal('weather/get'), - params: z3.object({ - city: z3.string() - }) - }); - - const GetForecastRequestSchema = z3.object({ - ...RequestSchema.shape, - method: z3.literal('weather/forecast'), - params: z3.object({ - city: z3.string(), - days: z3.number() - }) - }); - - const WeatherForecastNotificationSchema = z3.object({ - ...NotificationSchema.shape, - method: z3.literal('weather/alert'), - params: z3.object({ - severity: z3.enum(['warning', 'watch']), - message: z3.string() - }) - }); - - const WeatherRequestSchema = GetWeatherRequestSchema.or(GetForecastRequestSchema); - const WeatherNotificationSchema = WeatherForecastNotificationSchema; - const WeatherResultSchema = z3.object({ - ...ResultSchema.shape, - _meta: z3.record(z3.string(), z3.unknown()).optional(), - temperature: z3.number(), - conditions: z3.string() - }); - - type WeatherRequest = z3.infer; - type WeatherNotification = z3.infer; - type WeatherResult = z3.infer; - - // 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' - } - }); - }); -}); - ->>>>>>> 79c70fe5 (`v2`: replace export * with explicit named exports to tighten public API surface) /*** * Test: Initialize with Matching Protocol Version */ diff --git a/test/integration/test/issues/test_1342OauthErrorHttp200.test.ts b/test/integration/test/issues/test_1342OauthErrorHttp200.test.ts index e231c2014..89c12f71f 100644 --- a/test/integration/test/issues/test_1342OauthErrorHttp200.test.ts +++ b/test/integration/test/issues/test_1342OauthErrorHttp200.test.ts @@ -7,9 +7,8 @@ * detects the error field and surfaces the actual OAuth error message. */ -import { describe, expect, it, vi } from 'vitest'; - import { exchangeAuthorization } from '../../../../packages/client/src/client/auth.js'; +import { describe, expect, it, vi } from 'vitest'; const mockFetch = vi.fn(); vi.stubGlobal('fetch', mockFetch); From d4dfef4a7aaffe23909a9af0551066bd71592868 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 3 Feb 2026 00:01:50 +0000 Subject: [PATCH 3/3] refactor: deduplicate core re-exports via publicExports.ts Both client and server barrel files had ~460 identical lines re-exporting curated symbols from @modelcontextprotocol/core. Extract these into a single packages/core/src/publicExports.ts file that both barrels re-export via `export * from '@modelcontextprotocol/core/public'`. Adding a new public symbol to core now means updating one file instead of two. --- examples/client/tsconfig.json | 3 + examples/server/tsconfig.json | 3 + examples/shared/tsconfig.json | 3 + packages/client/src/index.ts | 459 +-------------------- packages/client/tsconfig.json | 1 + packages/core/src/publicExports.ts | 468 ++++++++++++++++++++++ packages/middleware/express/tsconfig.json | 3 + packages/middleware/hono/tsconfig.json | 3 + packages/middleware/node/tsconfig.json | 1 + packages/server/src/index.ts | 459 +-------------------- packages/server/tsconfig.json | 1 + test/helpers/tsconfig.json | 1 + test/integration/tsconfig.json | 1 + 13 files changed, 492 insertions(+), 914 deletions(-) create mode 100644 packages/core/src/publicExports.ts diff --git a/examples/client/tsconfig.json b/examples/client/tsconfig.json index 30a050fe7..ca96e9d2f 100644 --- a/examples/client/tsconfig.json +++ b/examples/client/tsconfig.json @@ -9,6 +9,9 @@ "@modelcontextprotocol/core": [ "./node_modules/@modelcontextprotocol/client/node_modules/@modelcontextprotocol/core/src/index.ts" ], + "@modelcontextprotocol/core/public": [ + "./node_modules/@modelcontextprotocol/client/node_modules/@modelcontextprotocol/core/src/publicExports.ts" + ], "@modelcontextprotocol/eslint-config": ["./node_modules/@modelcontextprotocol/eslint-config/tsconfig.json"], "@modelcontextprotocol/vitest-config": ["./node_modules/@modelcontextprotocol/vitest-config/tsconfig.json"], "@modelcontextprotocol/examples-shared": ["./node_modules/@modelcontextprotocol/examples-shared/src/index.ts"] diff --git a/examples/server/tsconfig.json b/examples/server/tsconfig.json index e44d65ec5..917db4ac8 100644 --- a/examples/server/tsconfig.json +++ b/examples/server/tsconfig.json @@ -12,6 +12,9 @@ "@modelcontextprotocol/core": [ "./node_modules/@modelcontextprotocol/server/node_modules/@modelcontextprotocol/core/src/index.ts" ], + "@modelcontextprotocol/core/public": [ + "./node_modules/@modelcontextprotocol/server/node_modules/@modelcontextprotocol/core/src/publicExports.ts" + ], "@modelcontextprotocol/examples-shared": ["./node_modules/@modelcontextprotocol/examples-shared/src/index.ts"], "@modelcontextprotocol/eslint-config": ["./node_modules/@modelcontextprotocol/eslint-config/tsconfig.json"], "@modelcontextprotocol/vitest-config": ["./node_modules/@modelcontextprotocol/vitest-config/tsconfig.json"] diff --git a/examples/shared/tsconfig.json b/examples/shared/tsconfig.json index 74c1e1172..6d7f38f86 100644 --- a/examples/shared/tsconfig.json +++ b/examples/shared/tsconfig.json @@ -12,6 +12,9 @@ "@modelcontextprotocol/core": [ "./node_modules/@modelcontextprotocol/server/node_modules/@modelcontextprotocol/core/src/index.ts" ], + "@modelcontextprotocol/core/public": [ + "./node_modules/@modelcontextprotocol/server/node_modules/@modelcontextprotocol/core/src/publicExports.ts" + ], "@modelcontextprotocol/eslint-config": ["./node_modules/@modelcontextprotocol/eslint-config/tsconfig.json"], "@modelcontextprotocol/vitest-config": ["./node_modules/@modelcontextprotocol/vitest-config/tsconfig.json"], "@modelcontextprotocol/test-helpers": ["./node_modules/@modelcontextprotocol/test-helpers/src/index.ts"], diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index 99c4e0e5e..fb87da921 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -44,461 +44,6 @@ export { ExperimentalClientTasks } from './experimental/index.js'; // ============================================================================ // Re-exports from @modelcontextprotocol/core // Only symbols that are part of the public API are listed here. +// Maintained in a single file to avoid duplication across client and server. // ============================================================================ - -// --- auth/errors.ts --- -export { - AccessDeniedError, - CustomOAuthError, - InsufficientScopeError, - InvalidClientError, - InvalidClientMetadataError, - InvalidGrantError, - InvalidRequestError, - InvalidScopeError, - InvalidTargetError, - InvalidTokenError, - MethodNotAllowedError, - OAuthError, - ServerError, - TemporarilyUnavailableError, - TooManyRequestsError, - UnauthorizedClientError, - UnsupportedGrantTypeError, - UnsupportedResponseTypeError, - UnsupportedTokenTypeError -} from '@modelcontextprotocol/core'; - -// --- shared/auth.ts --- -export type { - AuthorizationServerMetadata, - OAuthClientInformation, - OAuthClientInformationFull, - OAuthClientInformationMixed, - OAuthClientMetadata, - OAuthClientRegistrationError, - OAuthErrorResponse, - OAuthMetadata, - OAuthProtectedResourceMetadata, - OAuthTokenRevocationRequest, - OAuthTokens, - OpenIdProviderDiscoveryMetadata, - OpenIdProviderMetadata -} from '@modelcontextprotocol/core'; -export { - OAuthClientInformationFullSchema, - OAuthClientInformationSchema, - OAuthClientMetadataSchema, - OAuthClientRegistrationErrorSchema, - OAuthErrorResponseSchema, - OAuthMetadataSchema, - OAuthProtectedResourceMetadataSchema, - OAuthTokenRevocationRequestSchema, - OAuthTokensSchema, - OpenIdProviderDiscoveryMetadataSchema, - OpenIdProviderMetadataSchema -} from '@modelcontextprotocol/core'; - -// --- shared/authUtils.ts --- -export { checkResourceAllowed, resourceUrlFromServerUrl } from '@modelcontextprotocol/core'; - -// --- shared/metadataUtils.ts --- -export { getDisplayName } from '@modelcontextprotocol/core'; - -// --- shared/protocol.ts (excluding Protocol class, mergeCapabilities) --- -export type { - NotificationOptions, - ProgressCallback, - ProtocolOptions, - RequestHandlerExtra, - RequestOptions, - RequestTaskStore, - TaskRequestOptions -} from '@modelcontextprotocol/core'; -export { DEFAULT_REQUEST_TIMEOUT_MSEC } from '@modelcontextprotocol/core'; - -// --- shared/responseMessage.ts (excluding AsyncGeneratorValue) --- -export type { - BaseResponseMessage, - ErrorMessage, - ResponseMessage, - ResultMessage, - TaskCreatedMessage, - TaskStatusMessage -} from '@modelcontextprotocol/core'; -export { takeResult, toArrayAsync } from '@modelcontextprotocol/core'; - -// --- shared/transport.ts (excluding normalizeHeaders) --- -export type { FetchLike, Transport, TransportSendOptions } from '@modelcontextprotocol/core'; -export { createFetchWithInit } from '@modelcontextprotocol/core'; - -// --- shared/uriTemplate.ts --- -export type { Variables } from '@modelcontextprotocol/core'; -export { UriTemplate } from '@modelcontextprotocol/core'; - -// --- types/types.ts --- -export type { - Annotations, - AudioContent, - AuthInfo, - BaseMetadata, - BlobResourceContents, - BooleanSchema, - CallToolRequest, - CallToolRequestParams, - CallToolResult, - CancelledNotification, - CancelledNotificationParams, - CancelTaskRequest, - CancelTaskResult, - ClientCapabilities, - ClientNotification, - ClientRequest, - ClientResult, - CompatibilityCallToolResult, - CompleteRequest, - CompleteRequestParams, - CompleteRequestPrompt, - CompleteRequestResourceTemplate, - CompleteResult, - ContentBlock, - CreateMessageRequest, - CreateMessageRequestParams, - CreateMessageRequestParamsBase, - CreateMessageRequestParamsWithTools, - CreateMessageResult, - CreateMessageResultWithTools, - CreateTaskResult, - Cursor, - ElicitationCompleteNotification, - ElicitationCompleteNotificationParams, - ElicitRequest, - ElicitRequestFormParams, - ElicitRequestParams, - ElicitRequestURLParams, - ElicitResult, - EmbeddedResource, - EmptyResult, - EnumSchema, - GetPromptRequest, - GetPromptRequestParams, - GetPromptResult, - GetTaskPayloadRequest, - GetTaskPayloadResult, - GetTaskRequest, - GetTaskResult, - Icon, - Icons, - ImageContent, - Implementation, - InitializedNotification, - InitializeRequest, - InitializeRequestParams, - InitializeResult, - JSONRPCErrorResponse, - JSONRPCMessage, - JSONRPCNotification, - JSONRPCRequest, - JSONRPCResponse, - JSONRPCResultResponse, - LegacyTitledEnumSchema, - ListChangedCallback, - ListChangedHandlers, - ListChangedOptions, - ListPromptsRequest, - ListPromptsResult, - ListResourcesRequest, - ListResourcesResult, - ListResourceTemplatesRequest, - ListResourceTemplatesResult, - ListRootsRequest, - ListRootsResult, - ListTasksRequest, - ListTasksResult, - ListToolsRequest, - ListToolsResult, - LoggingLevel, - LoggingMessageNotification, - LoggingMessageNotificationParams, - MessageExtraInfo, - ModelHint, - ModelPreferences, - MultiSelectEnumSchema, - Notification, - NotificationParams, - NumberSchema, - PaginatedRequest, - PaginatedRequestParams, - PaginatedResult, - PingRequest, - PrimitiveSchemaDefinition, - Progress, - ProgressNotification, - ProgressNotificationParams, - ProgressToken, - Prompt, - PromptArgument, - PromptListChangedNotification, - PromptMessage, - PromptReference, - ReadResourceRequest, - ReadResourceRequestParams, - ReadResourceResult, - RelatedTaskMetadata, - Request, - RequestId, - RequestInfo, - RequestMeta, - RequestParams, - Resource, - ResourceContents, - ResourceLink, - ResourceListChangedNotification, - ResourceRequestParams, - ResourceTemplateReference, - ResourceTemplateType, - ResourceUpdatedNotification, - ResourceUpdatedNotificationParams, - Result, - Role, - Root, - RootsListChangedNotification, - SamplingContent, - SamplingMessage, - SamplingMessageContentBlock, - ServerCapabilities, - ServerNotification, - ServerRequest, - ServerResult, - SetLevelRequest, - SetLevelRequestParams, - SingleSelectEnumSchema, - StringSchema, - SubscribeRequest, - SubscribeRequestParams, - Task, - TaskAugmentedRequestParams, - TaskCreationParams, - TaskMetadata, - TaskStatus, - TaskStatusNotification, - TaskStatusNotificationParams, - TextContent, - TextResourceContents, - TitledMultiSelectEnumSchema, - TitledSingleSelectEnumSchema, - Tool, - ToolAnnotations, - ToolChoice, - ToolExecution, - ToolListChangedNotification, - ToolResultContent, - ToolUseContent, - UnsubscribeRequest, - UnsubscribeRequestParams, - UntitledMultiSelectEnumSchema, - UntitledSingleSelectEnumSchema -} from '@modelcontextprotocol/core'; -export { - AnnotationsSchema, - assertCompleteRequestPrompt, - assertCompleteRequestResourceTemplate, - AudioContentSchema, - BaseMetadataSchema, - BlobResourceContentsSchema, - BooleanSchemaSchema, - CallToolRequestParamsSchema, - CallToolRequestSchema, - CallToolResultSchema, - CancelledNotificationParamsSchema, - CancelledNotificationSchema, - CancelTaskRequestSchema, - CancelTaskResultSchema, - ClientCapabilitiesSchema, - ClientNotificationSchema, - ClientRequestSchema, - ClientResultSchema, - ClientTasksCapabilitySchema, - CompatibilityCallToolResultSchema, - CompleteRequestParamsSchema, - CompleteRequestSchema, - CompleteResultSchema, - ContentBlockSchema, - CreateMessageRequestParamsSchema, - CreateMessageRequestSchema, - CreateMessageResultSchema, - CreateMessageResultWithToolsSchema, - CreateTaskResultSchema, - CursorSchema, - DEFAULT_NEGOTIATED_PROTOCOL_VERSION, - ElicitationCompleteNotificationParamsSchema, - ElicitationCompleteNotificationSchema, - ElicitRequestFormParamsSchema, - ElicitRequestParamsSchema, - ElicitRequestSchema, - ElicitRequestURLParamsSchema, - ElicitResultSchema, - EmbeddedResourceSchema, - EmptyResultSchema, - EnumSchemaSchema, - ErrorCode, - GetPromptRequestParamsSchema, - GetPromptRequestSchema, - GetPromptResultSchema, - GetTaskPayloadRequestSchema, - GetTaskPayloadResultSchema, - GetTaskRequestSchema, - GetTaskResultSchema, - IconSchema, - IconsSchema, - ImageContentSchema, - ImplementationSchema, - InitializedNotificationSchema, - InitializeRequestParamsSchema, - InitializeRequestSchema, - InitializeResultSchema, - isInitializedNotification, - isInitializeRequest, - isJSONRPCErrorResponse, - isJSONRPCNotification, - isJSONRPCRequest, - isJSONRPCResultResponse, - isTaskAugmentedRequestParams, - JSONRPC_VERSION, - JSONRPCErrorResponseSchema, - JSONRPCMessageSchema, - JSONRPCNotificationSchema, - JSONRPCRequestSchema, - JSONRPCResponseSchema, - JSONRPCResultResponseSchema, - LATEST_PROTOCOL_VERSION, - LegacyTitledEnumSchemaSchema, - ListChangedOptionsBaseSchema, - ListPromptsRequestSchema, - ListPromptsResultSchema, - ListResourcesRequestSchema, - ListResourcesResultSchema, - ListResourceTemplatesRequestSchema, - ListResourceTemplatesResultSchema, - ListRootsRequestSchema, - ListRootsResultSchema, - ListTasksRequestSchema, - ListTasksResultSchema, - ListToolsRequestSchema, - ListToolsResultSchema, - LoggingLevelSchema, - LoggingMessageNotificationParamsSchema, - LoggingMessageNotificationSchema, - McpError, - ModelHintSchema, - ModelPreferencesSchema, - MultiSelectEnumSchemaSchema, - NotificationSchema, - NumberSchemaSchema, - PaginatedRequestParamsSchema, - PaginatedRequestSchema, - PaginatedResultSchema, - PingRequestSchema, - PrimitiveSchemaDefinitionSchema, - ProgressNotificationParamsSchema, - ProgressNotificationSchema, - ProgressSchema, - ProgressTokenSchema, - PromptArgumentSchema, - PromptListChangedNotificationSchema, - PromptMessageSchema, - PromptReferenceSchema, - PromptSchema, - ReadResourceRequestParamsSchema, - ReadResourceRequestSchema, - ReadResourceResultSchema, - RELATED_TASK_META_KEY, - RelatedTaskMetadataSchema, - RequestIdSchema, - RequestSchema, - ResourceContentsSchema, - ResourceLinkSchema, - ResourceListChangedNotificationSchema, - ResourceRequestParamsSchema, - ResourceSchema, - ResourceTemplateReferenceSchema, - ResourceTemplateSchema, - ResourceUpdatedNotificationParamsSchema, - ResourceUpdatedNotificationSchema, - ResultSchema, - RoleSchema, - RootSchema, - RootsListChangedNotificationSchema, - SamplingContentSchema, - SamplingMessageContentBlockSchema, - SamplingMessageSchema, - ServerCapabilitiesSchema, - ServerNotificationSchema, - ServerRequestSchema, - ServerResultSchema, - ServerTasksCapabilitySchema, - SetLevelRequestParamsSchema, - SetLevelRequestSchema, - SingleSelectEnumSchemaSchema, - StringSchemaSchema, - SubscribeRequestParamsSchema, - SubscribeRequestSchema, - SUPPORTED_PROTOCOL_VERSIONS, - TaskAugmentedRequestParamsSchema, - TaskCreationParamsSchema, - TaskMetadataSchema, - TaskSchema, - TaskStatusNotificationParamsSchema, - TaskStatusNotificationSchema, - TaskStatusSchema, - TextContentSchema, - TextResourceContentsSchema, - TitledMultiSelectEnumSchemaSchema, - TitledSingleSelectEnumSchemaSchema, - ToolAnnotationsSchema, - ToolChoiceSchema, - ToolExecutionSchema, - ToolListChangedNotificationSchema, - ToolResultContentSchema, - ToolSchema, - ToolUseContentSchema, - UnsubscribeRequestParamsSchema, - UnsubscribeRequestSchema, - UntitledMultiSelectEnumSchemaSchema, - UntitledSingleSelectEnumSchemaSchema, - UrlElicitationRequiredError -} from '@modelcontextprotocol/core'; - -// --- util/inMemory.ts --- -export { InMemoryTransport } from '@modelcontextprotocol/core'; - -// --- experimental/tasks (from core) --- -export type { - BaseQueuedMessage, - CreateTaskOptions, - CreateTaskRequestHandlerExtra, - QueuedError, - QueuedMessage, - QueuedNotification, - QueuedRequest, - QueuedResponse, - TaskMessageQueue, - TaskRequestHandlerExtra, - TaskStore, - TaskToolExecution -} from '@modelcontextprotocol/core'; -export { - assertClientRequestTaskCapability, - assertToolsCallTaskCapability, - InMemoryTaskMessageQueue, - InMemoryTaskStore, - isTerminal -} from '@modelcontextprotocol/core'; - -// --- validation/types.ts --- -export type { JsonSchemaType, JsonSchemaValidator, jsonSchemaValidator, JsonSchemaValidatorResult } from '@modelcontextprotocol/core'; - -// --- validation providers --- -export type { CfWorkerSchemaDraft } from '@modelcontextprotocol/core'; -export { AjvJsonSchemaValidator } from '@modelcontextprotocol/core'; -export { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/core'; +export * from '@modelcontextprotocol/core/public'; diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json index a16bfd7d9..56a604713 100644 --- a/packages/client/tsconfig.json +++ b/packages/client/tsconfig.json @@ -6,6 +6,7 @@ "paths": { "*": ["./*"], "@modelcontextprotocol/core": ["./node_modules/@modelcontextprotocol/core/src/index.ts"], + "@modelcontextprotocol/core/public": ["./node_modules/@modelcontextprotocol/core/src/publicExports.ts"], "@modelcontextprotocol/test-helpers": ["./node_modules/@modelcontextprotocol/test-helpers/src/index.ts"] } } diff --git a/packages/core/src/publicExports.ts b/packages/core/src/publicExports.ts new file mode 100644 index 000000000..788f7e9b8 --- /dev/null +++ b/packages/core/src/publicExports.ts @@ -0,0 +1,468 @@ +/** + * Curated public API exports from @modelcontextprotocol/core. + * + * This file is re-exported by both @modelcontextprotocol/client and + * @modelcontextprotocol/server so that users can import any public symbol + * from either package. Internal utilities (Zod compat, stdio parsing, + * Protocol base class, etc.) are intentionally excluded. + * + * When adding new public symbols to core, add them here once — both + * client and server will pick them up automatically. + */ + +// --- auth/errors.ts --- +export { + AccessDeniedError, + CustomOAuthError, + InsufficientScopeError, + InvalidClientError, + InvalidClientMetadataError, + InvalidGrantError, + InvalidRequestError, + InvalidScopeError, + InvalidTargetError, + InvalidTokenError, + MethodNotAllowedError, + OAuthError, + ServerError, + TemporarilyUnavailableError, + TooManyRequestsError, + UnauthorizedClientError, + UnsupportedGrantTypeError, + UnsupportedResponseTypeError, + UnsupportedTokenTypeError +} from './auth/errors.js'; + +// --- shared/auth.ts --- +export type { + AuthorizationServerMetadata, + OAuthClientInformation, + OAuthClientInformationFull, + OAuthClientInformationMixed, + OAuthClientMetadata, + OAuthClientRegistrationError, + OAuthErrorResponse, + OAuthMetadata, + OAuthProtectedResourceMetadata, + OAuthTokenRevocationRequest, + OAuthTokens, + OpenIdProviderDiscoveryMetadata, + OpenIdProviderMetadata +} from './shared/auth.js'; +export { + OAuthClientInformationFullSchema, + OAuthClientInformationSchema, + OAuthClientMetadataSchema, + OAuthClientRegistrationErrorSchema, + OAuthErrorResponseSchema, + OAuthMetadataSchema, + OAuthProtectedResourceMetadataSchema, + OAuthTokenRevocationRequestSchema, + OAuthTokensSchema, + OpenIdProviderDiscoveryMetadataSchema, + OpenIdProviderMetadataSchema +} from './shared/auth.js'; + +// --- shared/authUtils.ts --- +export { checkResourceAllowed, resourceUrlFromServerUrl } from './shared/authUtils.js'; + +// --- shared/metadataUtils.ts --- +export { getDisplayName } from './shared/metadataUtils.js'; + +// --- shared/protocol.ts (excluding Protocol class, mergeCapabilities) --- +export type { + NotificationOptions, + ProgressCallback, + ProtocolOptions, + RequestHandlerExtra, + RequestOptions, + RequestTaskStore, + TaskRequestOptions +} from './shared/protocol.js'; +export { DEFAULT_REQUEST_TIMEOUT_MSEC } from './shared/protocol.js'; + +// --- shared/responseMessage.ts (excluding AsyncGeneratorValue) --- +export type { + BaseResponseMessage, + ErrorMessage, + ResponseMessage, + ResultMessage, + TaskCreatedMessage, + TaskStatusMessage +} from './shared/responseMessage.js'; +export { takeResult, toArrayAsync } from './shared/responseMessage.js'; + +// --- shared/transport.ts (excluding normalizeHeaders) --- +export type { FetchLike, Transport, TransportSendOptions } from './shared/transport.js'; +export { createFetchWithInit } from './shared/transport.js'; + +// --- shared/uriTemplate.ts --- +export type { Variables } from './shared/uriTemplate.js'; +export { UriTemplate } from './shared/uriTemplate.js'; + +// --- types/types.ts --- +export type { + Annotations, + AudioContent, + AuthInfo, + BaseMetadata, + BlobResourceContents, + BooleanSchema, + CallToolRequest, + CallToolRequestParams, + CallToolResult, + CancelledNotification, + CancelledNotificationParams, + CancelTaskRequest, + CancelTaskResult, + ClientCapabilities, + ClientNotification, + ClientRequest, + ClientResult, + CompatibilityCallToolResult, + CompleteRequest, + CompleteRequestParams, + CompleteRequestPrompt, + CompleteRequestResourceTemplate, + CompleteResult, + ContentBlock, + CreateMessageRequest, + CreateMessageRequestParams, + CreateMessageRequestParamsBase, + CreateMessageRequestParamsWithTools, + CreateMessageResult, + CreateMessageResultWithTools, + CreateTaskResult, + Cursor, + ElicitationCompleteNotification, + ElicitationCompleteNotificationParams, + ElicitRequest, + ElicitRequestFormParams, + ElicitRequestParams, + ElicitRequestURLParams, + ElicitResult, + EmbeddedResource, + EmptyResult, + EnumSchema, + GetPromptRequest, + GetPromptRequestParams, + GetPromptResult, + GetTaskPayloadRequest, + GetTaskPayloadResult, + GetTaskRequest, + GetTaskResult, + Icon, + Icons, + ImageContent, + Implementation, + InitializedNotification, + InitializeRequest, + InitializeRequestParams, + InitializeResult, + JSONRPCErrorResponse, + JSONRPCMessage, + JSONRPCNotification, + JSONRPCRequest, + JSONRPCResponse, + JSONRPCResultResponse, + LegacyTitledEnumSchema, + ListChangedCallback, + ListChangedHandlers, + ListChangedOptions, + ListPromptsRequest, + ListPromptsResult, + ListResourcesRequest, + ListResourcesResult, + ListResourceTemplatesRequest, + ListResourceTemplatesResult, + ListRootsRequest, + ListRootsResult, + ListTasksRequest, + ListTasksResult, + ListToolsRequest, + ListToolsResult, + LoggingLevel, + LoggingMessageNotification, + LoggingMessageNotificationParams, + MessageExtraInfo, + ModelHint, + ModelPreferences, + MultiSelectEnumSchema, + Notification, + NotificationParams, + NumberSchema, + PaginatedRequest, + PaginatedRequestParams, + PaginatedResult, + PingRequest, + PrimitiveSchemaDefinition, + Progress, + ProgressNotification, + ProgressNotificationParams, + ProgressToken, + Prompt, + PromptArgument, + PromptListChangedNotification, + PromptMessage, + PromptReference, + ReadResourceRequest, + ReadResourceRequestParams, + ReadResourceResult, + RelatedTaskMetadata, + Request, + RequestId, + RequestInfo, + RequestMeta, + RequestParams, + Resource, + ResourceContents, + ResourceLink, + ResourceListChangedNotification, + ResourceRequestParams, + ResourceTemplateReference, + ResourceTemplateType, + ResourceUpdatedNotification, + ResourceUpdatedNotificationParams, + Result, + Role, + Root, + RootsListChangedNotification, + SamplingContent, + SamplingMessage, + SamplingMessageContentBlock, + ServerCapabilities, + ServerNotification, + ServerRequest, + ServerResult, + SetLevelRequest, + SetLevelRequestParams, + SingleSelectEnumSchema, + StringSchema, + SubscribeRequest, + SubscribeRequestParams, + Task, + TaskAugmentedRequestParams, + TaskCreationParams, + TaskMetadata, + TaskStatus, + TaskStatusNotification, + TaskStatusNotificationParams, + TextContent, + TextResourceContents, + TitledMultiSelectEnumSchema, + TitledSingleSelectEnumSchema, + Tool, + ToolAnnotations, + ToolChoice, + ToolExecution, + ToolListChangedNotification, + ToolResultContent, + ToolUseContent, + UnsubscribeRequest, + UnsubscribeRequestParams, + UntitledMultiSelectEnumSchema, + UntitledSingleSelectEnumSchema +} from './types/types.js'; +export { + AnnotationsSchema, + assertCompleteRequestPrompt, + assertCompleteRequestResourceTemplate, + AudioContentSchema, + BaseMetadataSchema, + BlobResourceContentsSchema, + BooleanSchemaSchema, + CallToolRequestParamsSchema, + CallToolRequestSchema, + CallToolResultSchema, + CancelledNotificationParamsSchema, + CancelledNotificationSchema, + CancelTaskRequestSchema, + CancelTaskResultSchema, + ClientCapabilitiesSchema, + ClientNotificationSchema, + ClientRequestSchema, + ClientResultSchema, + ClientTasksCapabilitySchema, + CompatibilityCallToolResultSchema, + CompleteRequestParamsSchema, + CompleteRequestSchema, + CompleteResultSchema, + ContentBlockSchema, + CreateMessageRequestParamsSchema, + CreateMessageRequestSchema, + CreateMessageResultSchema, + CreateMessageResultWithToolsSchema, + CreateTaskResultSchema, + CursorSchema, + DEFAULT_NEGOTIATED_PROTOCOL_VERSION, + ElicitationCompleteNotificationParamsSchema, + ElicitationCompleteNotificationSchema, + ElicitRequestFormParamsSchema, + ElicitRequestParamsSchema, + ElicitRequestSchema, + ElicitRequestURLParamsSchema, + ElicitResultSchema, + EmbeddedResourceSchema, + EmptyResultSchema, + EnumSchemaSchema, + ErrorCode, + GetPromptRequestParamsSchema, + GetPromptRequestSchema, + GetPromptResultSchema, + GetTaskPayloadRequestSchema, + GetTaskPayloadResultSchema, + GetTaskRequestSchema, + GetTaskResultSchema, + IconSchema, + IconsSchema, + ImageContentSchema, + ImplementationSchema, + InitializedNotificationSchema, + InitializeRequestParamsSchema, + InitializeRequestSchema, + InitializeResultSchema, + isInitializedNotification, + isInitializeRequest, + isJSONRPCErrorResponse, + isJSONRPCNotification, + isJSONRPCRequest, + isJSONRPCResultResponse, + isTaskAugmentedRequestParams, + JSONRPC_VERSION, + JSONRPCErrorResponseSchema, + JSONRPCMessageSchema, + JSONRPCNotificationSchema, + JSONRPCRequestSchema, + JSONRPCResponseSchema, + JSONRPCResultResponseSchema, + LATEST_PROTOCOL_VERSION, + LegacyTitledEnumSchemaSchema, + ListChangedOptionsBaseSchema, + ListPromptsRequestSchema, + ListPromptsResultSchema, + ListResourcesRequestSchema, + ListResourcesResultSchema, + ListResourceTemplatesRequestSchema, + ListResourceTemplatesResultSchema, + ListRootsRequestSchema, + ListRootsResultSchema, + ListTasksRequestSchema, + ListTasksResultSchema, + ListToolsRequestSchema, + ListToolsResultSchema, + LoggingLevelSchema, + LoggingMessageNotificationParamsSchema, + LoggingMessageNotificationSchema, + McpError, + ModelHintSchema, + ModelPreferencesSchema, + MultiSelectEnumSchemaSchema, + NotificationSchema, + NumberSchemaSchema, + PaginatedRequestParamsSchema, + PaginatedRequestSchema, + PaginatedResultSchema, + PingRequestSchema, + PrimitiveSchemaDefinitionSchema, + ProgressNotificationParamsSchema, + ProgressNotificationSchema, + ProgressSchema, + ProgressTokenSchema, + PromptArgumentSchema, + PromptListChangedNotificationSchema, + PromptMessageSchema, + PromptReferenceSchema, + PromptSchema, + ReadResourceRequestParamsSchema, + ReadResourceRequestSchema, + ReadResourceResultSchema, + RELATED_TASK_META_KEY, + RelatedTaskMetadataSchema, + RequestIdSchema, + RequestSchema, + ResourceContentsSchema, + ResourceLinkSchema, + ResourceListChangedNotificationSchema, + ResourceRequestParamsSchema, + ResourceSchema, + ResourceTemplateReferenceSchema, + ResourceTemplateSchema, + ResourceUpdatedNotificationParamsSchema, + ResourceUpdatedNotificationSchema, + ResultSchema, + RoleSchema, + RootSchema, + RootsListChangedNotificationSchema, + SamplingContentSchema, + SamplingMessageContentBlockSchema, + SamplingMessageSchema, + ServerCapabilitiesSchema, + ServerNotificationSchema, + ServerRequestSchema, + ServerResultSchema, + ServerTasksCapabilitySchema, + SetLevelRequestParamsSchema, + SetLevelRequestSchema, + SingleSelectEnumSchemaSchema, + StringSchemaSchema, + SubscribeRequestParamsSchema, + SubscribeRequestSchema, + SUPPORTED_PROTOCOL_VERSIONS, + TaskAugmentedRequestParamsSchema, + TaskCreationParamsSchema, + TaskMetadataSchema, + TaskSchema, + TaskStatusNotificationParamsSchema, + TaskStatusNotificationSchema, + TaskStatusSchema, + TextContentSchema, + TextResourceContentsSchema, + TitledMultiSelectEnumSchemaSchema, + TitledSingleSelectEnumSchemaSchema, + ToolAnnotationsSchema, + ToolChoiceSchema, + ToolExecutionSchema, + ToolListChangedNotificationSchema, + ToolResultContentSchema, + ToolSchema, + ToolUseContentSchema, + UnsubscribeRequestParamsSchema, + UnsubscribeRequestSchema, + UntitledMultiSelectEnumSchemaSchema, + UntitledSingleSelectEnumSchemaSchema, + UrlElicitationRequiredError +} from './types/types.js'; + +// --- util/inMemory.ts --- +export { InMemoryTransport } from './util/inMemory.js'; + +// --- experimental/tasks (from core) --- +export type { + BaseQueuedMessage, + CreateTaskOptions, + CreateTaskRequestHandlerExtra, + QueuedError, + QueuedMessage, + QueuedNotification, + QueuedRequest, + QueuedResponse, + TaskMessageQueue, + TaskRequestHandlerExtra, + TaskStore, + TaskToolExecution +} from './experimental/index.js'; +export { + assertClientRequestTaskCapability, + assertToolsCallTaskCapability, + InMemoryTaskMessageQueue, + InMemoryTaskStore, + isTerminal +} from './experimental/index.js'; + +// --- validation/types.ts --- +export type { JsonSchemaType, JsonSchemaValidator, jsonSchemaValidator, JsonSchemaValidatorResult } from './validation/types.js'; + +// --- validation providers --- +export type { CfWorkerSchemaDraft } from './validation/cfWorkerProvider.js'; +export { AjvJsonSchemaValidator } from './validation/ajvProvider.js'; +export { CfWorkerJsonSchemaValidator } from './validation/cfWorkerProvider.js'; diff --git a/packages/middleware/express/tsconfig.json b/packages/middleware/express/tsconfig.json index 0d7fdd0c0..7071e1892 100644 --- a/packages/middleware/express/tsconfig.json +++ b/packages/middleware/express/tsconfig.json @@ -8,6 +8,9 @@ "@modelcontextprotocol/server": ["./node_modules/@modelcontextprotocol/server/src/index.ts"], "@modelcontextprotocol/core": [ "./node_modules/@modelcontextprotocol/server/node_modules/@modelcontextprotocol/core/src/index.ts" + ], + "@modelcontextprotocol/core/public": [ + "./node_modules/@modelcontextprotocol/server/node_modules/@modelcontextprotocol/core/src/publicExports.ts" ] } } diff --git a/packages/middleware/hono/tsconfig.json b/packages/middleware/hono/tsconfig.json index 0d7fdd0c0..7071e1892 100644 --- a/packages/middleware/hono/tsconfig.json +++ b/packages/middleware/hono/tsconfig.json @@ -8,6 +8,9 @@ "@modelcontextprotocol/server": ["./node_modules/@modelcontextprotocol/server/src/index.ts"], "@modelcontextprotocol/core": [ "./node_modules/@modelcontextprotocol/server/node_modules/@modelcontextprotocol/core/src/index.ts" + ], + "@modelcontextprotocol/core/public": [ + "./node_modules/@modelcontextprotocol/server/node_modules/@modelcontextprotocol/core/src/publicExports.ts" ] } } diff --git a/packages/middleware/node/tsconfig.json b/packages/middleware/node/tsconfig.json index 97790e3e1..c07f0f4be 100644 --- a/packages/middleware/node/tsconfig.json +++ b/packages/middleware/node/tsconfig.json @@ -7,6 +7,7 @@ "*": ["./*"], "@modelcontextprotocol/server": ["./node_modules/@modelcontextprotocol/server/src/index.ts"], "@modelcontextprotocol/core": ["./node_modules/@modelcontextprotocol/core/src/index.ts"], + "@modelcontextprotocol/core/public": ["./node_modules/@modelcontextprotocol/core/src/publicExports.ts"], "@modelcontextprotocol/test-helpers": ["./node_modules/@modelcontextprotocol/test-helpers/src/index.ts"] } } diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index 6b34d7678..76e72dafa 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -40,461 +40,6 @@ export { ExperimentalMcpServerTasks, ExperimentalServerTasks } from './experimen // ============================================================================ // Re-exports from @modelcontextprotocol/core // Only symbols that are part of the public API are listed here. +// Maintained in a single file to avoid duplication across client and server. // ============================================================================ - -// --- auth/errors.ts --- -export { - AccessDeniedError, - CustomOAuthError, - InsufficientScopeError, - InvalidClientError, - InvalidClientMetadataError, - InvalidGrantError, - InvalidRequestError, - InvalidScopeError, - InvalidTargetError, - InvalidTokenError, - MethodNotAllowedError, - OAuthError, - ServerError, - TemporarilyUnavailableError, - TooManyRequestsError, - UnauthorizedClientError, - UnsupportedGrantTypeError, - UnsupportedResponseTypeError, - UnsupportedTokenTypeError -} from '@modelcontextprotocol/core'; - -// --- shared/auth.ts --- -export type { - AuthorizationServerMetadata, - OAuthClientInformation, - OAuthClientInformationFull, - OAuthClientInformationMixed, - OAuthClientMetadata, - OAuthClientRegistrationError, - OAuthErrorResponse, - OAuthMetadata, - OAuthProtectedResourceMetadata, - OAuthTokenRevocationRequest, - OAuthTokens, - OpenIdProviderDiscoveryMetadata, - OpenIdProviderMetadata -} from '@modelcontextprotocol/core'; -export { - OAuthClientInformationFullSchema, - OAuthClientInformationSchema, - OAuthClientMetadataSchema, - OAuthClientRegistrationErrorSchema, - OAuthErrorResponseSchema, - OAuthMetadataSchema, - OAuthProtectedResourceMetadataSchema, - OAuthTokenRevocationRequestSchema, - OAuthTokensSchema, - OpenIdProviderDiscoveryMetadataSchema, - OpenIdProviderMetadataSchema -} from '@modelcontextprotocol/core'; - -// --- shared/authUtils.ts --- -export { checkResourceAllowed, resourceUrlFromServerUrl } from '@modelcontextprotocol/core'; - -// --- shared/metadataUtils.ts --- -export { getDisplayName } from '@modelcontextprotocol/core'; - -// --- shared/protocol.ts (excluding Protocol class, mergeCapabilities) --- -export type { - NotificationOptions, - ProgressCallback, - ProtocolOptions, - RequestHandlerExtra, - RequestOptions, - RequestTaskStore, - TaskRequestOptions -} from '@modelcontextprotocol/core'; -export { DEFAULT_REQUEST_TIMEOUT_MSEC } from '@modelcontextprotocol/core'; - -// --- shared/responseMessage.ts (excluding AsyncGeneratorValue) --- -export type { - BaseResponseMessage, - ErrorMessage, - ResponseMessage, - ResultMessage, - TaskCreatedMessage, - TaskStatusMessage -} from '@modelcontextprotocol/core'; -export { takeResult, toArrayAsync } from '@modelcontextprotocol/core'; - -// --- shared/transport.ts (excluding normalizeHeaders) --- -export type { FetchLike, Transport, TransportSendOptions } from '@modelcontextprotocol/core'; -export { createFetchWithInit } from '@modelcontextprotocol/core'; - -// --- shared/uriTemplate.ts --- -export type { Variables } from '@modelcontextprotocol/core'; -export { UriTemplate } from '@modelcontextprotocol/core'; - -// --- types/types.ts --- -export type { - Annotations, - AudioContent, - AuthInfo, - BaseMetadata, - BlobResourceContents, - BooleanSchema, - CallToolRequest, - CallToolRequestParams, - CallToolResult, - CancelledNotification, - CancelledNotificationParams, - CancelTaskRequest, - CancelTaskResult, - ClientCapabilities, - ClientNotification, - ClientRequest, - ClientResult, - CompatibilityCallToolResult, - CompleteRequest, - CompleteRequestParams, - CompleteRequestPrompt, - CompleteRequestResourceTemplate, - CompleteResult, - ContentBlock, - CreateMessageRequest, - CreateMessageRequestParams, - CreateMessageRequestParamsBase, - CreateMessageRequestParamsWithTools, - CreateMessageResult, - CreateMessageResultWithTools, - CreateTaskResult, - Cursor, - ElicitationCompleteNotification, - ElicitationCompleteNotificationParams, - ElicitRequest, - ElicitRequestFormParams, - ElicitRequestParams, - ElicitRequestURLParams, - ElicitResult, - EmbeddedResource, - EmptyResult, - EnumSchema, - GetPromptRequest, - GetPromptRequestParams, - GetPromptResult, - GetTaskPayloadRequest, - GetTaskPayloadResult, - GetTaskRequest, - GetTaskResult, - Icon, - Icons, - ImageContent, - Implementation, - InitializedNotification, - InitializeRequest, - InitializeRequestParams, - InitializeResult, - JSONRPCErrorResponse, - JSONRPCMessage, - JSONRPCNotification, - JSONRPCRequest, - JSONRPCResponse, - JSONRPCResultResponse, - LegacyTitledEnumSchema, - ListChangedCallback, - ListChangedHandlers, - ListChangedOptions, - ListPromptsRequest, - ListPromptsResult, - ListResourcesRequest, - ListResourcesResult, - ListResourceTemplatesRequest, - ListResourceTemplatesResult, - ListRootsRequest, - ListRootsResult, - ListTasksRequest, - ListTasksResult, - ListToolsRequest, - ListToolsResult, - LoggingLevel, - LoggingMessageNotification, - LoggingMessageNotificationParams, - MessageExtraInfo, - ModelHint, - ModelPreferences, - MultiSelectEnumSchema, - Notification, - NotificationParams, - NumberSchema, - PaginatedRequest, - PaginatedRequestParams, - PaginatedResult, - PingRequest, - PrimitiveSchemaDefinition, - Progress, - ProgressNotification, - ProgressNotificationParams, - ProgressToken, - Prompt, - PromptArgument, - PromptListChangedNotification, - PromptMessage, - PromptReference, - ReadResourceRequest, - ReadResourceRequestParams, - ReadResourceResult, - RelatedTaskMetadata, - Request, - RequestId, - RequestInfo, - RequestMeta, - RequestParams, - Resource, - ResourceContents, - ResourceLink, - ResourceListChangedNotification, - ResourceRequestParams, - ResourceTemplateReference, - ResourceTemplateType, - ResourceUpdatedNotification, - ResourceUpdatedNotificationParams, - Result, - Role, - Root, - RootsListChangedNotification, - SamplingContent, - SamplingMessage, - SamplingMessageContentBlock, - ServerCapabilities, - ServerNotification, - ServerRequest, - ServerResult, - SetLevelRequest, - SetLevelRequestParams, - SingleSelectEnumSchema, - StringSchema, - SubscribeRequest, - SubscribeRequestParams, - Task, - TaskAugmentedRequestParams, - TaskCreationParams, - TaskMetadata, - TaskStatus, - TaskStatusNotification, - TaskStatusNotificationParams, - TextContent, - TextResourceContents, - TitledMultiSelectEnumSchema, - TitledSingleSelectEnumSchema, - Tool, - ToolAnnotations, - ToolChoice, - ToolExecution, - ToolListChangedNotification, - ToolResultContent, - ToolUseContent, - UnsubscribeRequest, - UnsubscribeRequestParams, - UntitledMultiSelectEnumSchema, - UntitledSingleSelectEnumSchema -} from '@modelcontextprotocol/core'; -export { - AnnotationsSchema, - assertCompleteRequestPrompt, - assertCompleteRequestResourceTemplate, - AudioContentSchema, - BaseMetadataSchema, - BlobResourceContentsSchema, - BooleanSchemaSchema, - CallToolRequestParamsSchema, - CallToolRequestSchema, - CallToolResultSchema, - CancelledNotificationParamsSchema, - CancelledNotificationSchema, - CancelTaskRequestSchema, - CancelTaskResultSchema, - ClientCapabilitiesSchema, - ClientNotificationSchema, - ClientRequestSchema, - ClientResultSchema, - ClientTasksCapabilitySchema, - CompatibilityCallToolResultSchema, - CompleteRequestParamsSchema, - CompleteRequestSchema, - CompleteResultSchema, - ContentBlockSchema, - CreateMessageRequestParamsSchema, - CreateMessageRequestSchema, - CreateMessageResultSchema, - CreateMessageResultWithToolsSchema, - CreateTaskResultSchema, - CursorSchema, - DEFAULT_NEGOTIATED_PROTOCOL_VERSION, - ElicitationCompleteNotificationParamsSchema, - ElicitationCompleteNotificationSchema, - ElicitRequestFormParamsSchema, - ElicitRequestParamsSchema, - ElicitRequestSchema, - ElicitRequestURLParamsSchema, - ElicitResultSchema, - EmbeddedResourceSchema, - EmptyResultSchema, - EnumSchemaSchema, - ErrorCode, - GetPromptRequestParamsSchema, - GetPromptRequestSchema, - GetPromptResultSchema, - GetTaskPayloadRequestSchema, - GetTaskPayloadResultSchema, - GetTaskRequestSchema, - GetTaskResultSchema, - IconSchema, - IconsSchema, - ImageContentSchema, - ImplementationSchema, - InitializedNotificationSchema, - InitializeRequestParamsSchema, - InitializeRequestSchema, - InitializeResultSchema, - isInitializedNotification, - isInitializeRequest, - isJSONRPCErrorResponse, - isJSONRPCNotification, - isJSONRPCRequest, - isJSONRPCResultResponse, - isTaskAugmentedRequestParams, - JSONRPC_VERSION, - JSONRPCErrorResponseSchema, - JSONRPCMessageSchema, - JSONRPCNotificationSchema, - JSONRPCRequestSchema, - JSONRPCResponseSchema, - JSONRPCResultResponseSchema, - LATEST_PROTOCOL_VERSION, - LegacyTitledEnumSchemaSchema, - ListChangedOptionsBaseSchema, - ListPromptsRequestSchema, - ListPromptsResultSchema, - ListResourcesRequestSchema, - ListResourcesResultSchema, - ListResourceTemplatesRequestSchema, - ListResourceTemplatesResultSchema, - ListRootsRequestSchema, - ListRootsResultSchema, - ListTasksRequestSchema, - ListTasksResultSchema, - ListToolsRequestSchema, - ListToolsResultSchema, - LoggingLevelSchema, - LoggingMessageNotificationParamsSchema, - LoggingMessageNotificationSchema, - McpError, - ModelHintSchema, - ModelPreferencesSchema, - MultiSelectEnumSchemaSchema, - NotificationSchema, - NumberSchemaSchema, - PaginatedRequestParamsSchema, - PaginatedRequestSchema, - PaginatedResultSchema, - PingRequestSchema, - PrimitiveSchemaDefinitionSchema, - ProgressNotificationParamsSchema, - ProgressNotificationSchema, - ProgressSchema, - ProgressTokenSchema, - PromptArgumentSchema, - PromptListChangedNotificationSchema, - PromptMessageSchema, - PromptReferenceSchema, - PromptSchema, - ReadResourceRequestParamsSchema, - ReadResourceRequestSchema, - ReadResourceResultSchema, - RELATED_TASK_META_KEY, - RelatedTaskMetadataSchema, - RequestIdSchema, - RequestSchema, - ResourceContentsSchema, - ResourceLinkSchema, - ResourceListChangedNotificationSchema, - ResourceRequestParamsSchema, - ResourceSchema, - ResourceTemplateReferenceSchema, - ResourceTemplateSchema, - ResourceUpdatedNotificationParamsSchema, - ResourceUpdatedNotificationSchema, - ResultSchema, - RoleSchema, - RootSchema, - RootsListChangedNotificationSchema, - SamplingContentSchema, - SamplingMessageContentBlockSchema, - SamplingMessageSchema, - ServerCapabilitiesSchema, - ServerNotificationSchema, - ServerRequestSchema, - ServerResultSchema, - ServerTasksCapabilitySchema, - SetLevelRequestParamsSchema, - SetLevelRequestSchema, - SingleSelectEnumSchemaSchema, - StringSchemaSchema, - SubscribeRequestParamsSchema, - SubscribeRequestSchema, - SUPPORTED_PROTOCOL_VERSIONS, - TaskAugmentedRequestParamsSchema, - TaskCreationParamsSchema, - TaskMetadataSchema, - TaskSchema, - TaskStatusNotificationParamsSchema, - TaskStatusNotificationSchema, - TaskStatusSchema, - TextContentSchema, - TextResourceContentsSchema, - TitledMultiSelectEnumSchemaSchema, - TitledSingleSelectEnumSchemaSchema, - ToolAnnotationsSchema, - ToolChoiceSchema, - ToolExecutionSchema, - ToolListChangedNotificationSchema, - ToolResultContentSchema, - ToolSchema, - ToolUseContentSchema, - UnsubscribeRequestParamsSchema, - UnsubscribeRequestSchema, - UntitledMultiSelectEnumSchemaSchema, - UntitledSingleSelectEnumSchemaSchema, - UrlElicitationRequiredError -} from '@modelcontextprotocol/core'; - -// --- util/inMemory.ts --- -export { InMemoryTransport } from '@modelcontextprotocol/core'; - -// --- experimental/tasks (from core) --- -export type { - BaseQueuedMessage, - CreateTaskOptions, - CreateTaskRequestHandlerExtra, - QueuedError, - QueuedMessage, - QueuedNotification, - QueuedRequest, - QueuedResponse, - TaskMessageQueue, - TaskRequestHandlerExtra, - TaskStore, - TaskToolExecution -} from '@modelcontextprotocol/core'; -export { - assertClientRequestTaskCapability, - assertToolsCallTaskCapability, - InMemoryTaskMessageQueue, - InMemoryTaskStore, - isTerminal -} from '@modelcontextprotocol/core'; - -// --- validation/types.ts --- -export type { JsonSchemaType, JsonSchemaValidator, jsonSchemaValidator, JsonSchemaValidatorResult } from '@modelcontextprotocol/core'; - -// --- validation providers --- -export type { CfWorkerSchemaDraft } from '@modelcontextprotocol/core'; -export { AjvJsonSchemaValidator } from '@modelcontextprotocol/core'; -export { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/core'; +export * from '@modelcontextprotocol/core/public'; diff --git a/packages/server/tsconfig.json b/packages/server/tsconfig.json index a16bfd7d9..56a604713 100644 --- a/packages/server/tsconfig.json +++ b/packages/server/tsconfig.json @@ -6,6 +6,7 @@ "paths": { "*": ["./*"], "@modelcontextprotocol/core": ["./node_modules/@modelcontextprotocol/core/src/index.ts"], + "@modelcontextprotocol/core/public": ["./node_modules/@modelcontextprotocol/core/src/publicExports.ts"], "@modelcontextprotocol/test-helpers": ["./node_modules/@modelcontextprotocol/test-helpers/src/index.ts"] } } diff --git a/test/helpers/tsconfig.json b/test/helpers/tsconfig.json index c46b557df..ae4a76e66 100644 --- a/test/helpers/tsconfig.json +++ b/test/helpers/tsconfig.json @@ -6,6 +6,7 @@ "paths": { "*": ["./*"], "@modelcontextprotocol/core": ["./node_modules/@modelcontextprotocol/core/src/index.ts"], + "@modelcontextprotocol/core/public": ["./node_modules/@modelcontextprotocol/core/src/publicExports.ts"], "@modelcontextprotocol/vitest-config": ["./node_modules/@modelcontextprotocol/vitest-config/tsconfig.json"] } } diff --git a/test/integration/tsconfig.json b/test/integration/tsconfig.json index 5c22ec1be..5b35f9aae 100644 --- a/test/integration/tsconfig.json +++ b/test/integration/tsconfig.json @@ -6,6 +6,7 @@ "paths": { "*": ["./*"], "@modelcontextprotocol/core": ["./node_modules/@modelcontextprotocol/core/src/index.ts"], + "@modelcontextprotocol/core/public": ["./node_modules/@modelcontextprotocol/core/src/publicExports.ts"], "@modelcontextprotocol/client": ["./node_modules/@modelcontextprotocol/client/src/index.ts"], "@modelcontextprotocol/server": ["./node_modules/@modelcontextprotocol/server/src/index.ts"], "@modelcontextprotocol/express": ["./node_modules/@modelcontextprotocol/express/src/index.ts"],