-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[RFC]: tighten public API surface with explicit named exports #1447
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@modelcontextprotocol/client
@modelcontextprotocol/server
@modelcontextprotocol/express
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
|
Problem: We currently use export * barrel files, which means ~460 symbols are importable by users. Many are internal (OAuth sub-steps, Zod compat layer, stdio parsing, completable internals). Every leaked internal is an Approach: Replace export * in client/server index.ts with explicit named exports. Core stays export * since it's "private": true. No code is deleted — deprecated functions remain in source, they're just not re-exported. What's removed from the public API (59 symbols):
What stays: All protocol types/schemas (~327), all transports, Client, McpServer, Server, middleware, auth providers, OAuth error classes, InMemoryTransport, getDisplayName, RELATED_TASK_META_KEY, validation providers. Questions:
|
- Move assertTaskCapability/assertTaskHandlerCapability from mutable properties on TaskManager to TaskManagerOptions constructor params, eliminating fragile post-construction wiring - Add _requireHost getter with clear error message instead of _host! non-null assertions throughout TaskManager - Extract duplicated relatedTask metadata injection in Protocol.notification() into _buildJsonRpcNotification() helper - Add @internal JSDoc to TaskManagerHost (will be removed from public exports in PR #1447) - Add changeset for the breaking changes - Revert unrelated pnpm-workspace.yaml change
…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.
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.
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.
b85d9de to
7719034
Compare
| @@ -0,0 +1,476 @@ | |||
| /** | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the most interesting file and what we should make sure to get right - i.e. the explicit exports from core that we knowingly make public.
7719034 to
d4dfef4
Compare
v2: tighten public API surface with explicit named exports| export type { AddClientAuthentication, AuthResult, OAuthClientProvider } from './client/auth.js'; | ||
| export { auth, extractWWWAuthenticateParams, UnauthorizedError } from './client/auth.js'; | ||
|
|
||
| // client/authExtensions.ts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
explicit exports from client
| 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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
explicit server exports
| CompleteRequestResourceTemplate, | ||
| CompleteResult, | ||
| ContentBlock, | ||
| CreateMessageRequest, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
validate that we can potentially delete all of these schemas after #1446
- Move assertTaskCapability/assertTaskHandlerCapability from mutable properties on TaskManager to TaskManagerOptions constructor params, eliminating fragile post-construction wiring - Add _requireHost getter with clear error message instead of _host! non-null assertions throughout TaskManager - Extract duplicated relatedTask metadata injection in Protocol.notification() into _buildJsonRpcNotification() helper - Add @internal JSDoc to TaskManagerHost (will be removed from public exports in PR #1447) - Add changeset for the breaking changes - Revert unrelated pnpm-workspace.yaml change
| export { UriTemplate } from './shared/uriTemplate.js'; | ||
|
|
||
| // --- types/types.ts --- | ||
| export type { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaving a note on our discussion - we could use this as a starting point; as opposed to enumerating all the export one by one and having to remember to add an export here, we could take an approach where we split large .ts files into two categories - publicly exportable, and private ones - we could then do export * from the ones we've chosen to be public. We could also feed that to CLAUDE.md and contributor guidelines
Replace blanket
export *barrel files in client and server packages with explicit named exports, removing 59 internal/deprecated symbols from the public API.Motivation and Context
The SDK currently uses
export *barrel files that re-export everything from every module, resulting in 400+ symbols visible to users. Many of these are internal implementation details (OAuth sub-steps, Zod v3/v4 compatibility layer, stdio parsing, completable internals) that users should never import directly. Every leaked internal symbol becomes an implicit API contract that blocks refactoring.v2 is the right time to fix this since we have a breaking change window.
Approach
export *inpackages/client/src/index.tsandpackages/server/src/index.tswith explicit named exports@modelcontextprotocol/coreasexport *since it is"private": trueand only consumed within the monorepodiscoverOAuthMetadata,extractResourceMetadataUrl,unwrapCompletable,McpZodTypeKind,CompletableDefWhat was removed (59 symbols)
Core internals (34): Zod compat layer (
AnySchema,safeParse,SchemaOutput, etc.), stdio parsing (ReadBuffer,deserializeMessage,serializeMessage),Protocolbase class,mergeCapabilities,normalizeHeaders,validateToolName,toJsonSchemaCompat, and other internal plumbingClient internals (16): 13 OAuth sub-step functions (
startAuthorization,exchangeAuthorization,refreshAuthorization,fetchToken,registerClient, etc.), 2 deprecated functions,getSupportedElicitationModesServer internals (10): Completable internals (
COMPLETABLE_SYMBOL,getCompleter, etc.), deprecated symbols,BaseToolCallback,AnyToolHandler,StreamId,EventIdWhat stays public
All protocol types/schemas (~327 from types.ts), all OAuth error classes, all transports,
Client,McpServer,Server, middleware, auth providers, and all user-facing utilities confirmed by example usage.How Has This Been Tested
pnpm typecheck:all— all packages pass (core, client, server, express, hono, node, examples)pnpm test:all— all tests pass (one pre-existing flake in authExtensions unrelated to this change)pnpm lint:all— cleanBreaking Changes
Users who import any of the 59 removed symbols from
@modelcontextprotocol/clientor@modelcontextprotocol/serverwill get import errors. These symbols were internal implementation details not intended for external use.Types of changes
Checklist