Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
fa77d2e
initial draft: limit public exports
KKonstantinov Mar 14, 2026
d32bc9f
remove schemas from public exports
KKonstantinov Mar 14, 2026
b2b1e72
comments fix
KKonstantinov Mar 14, 2026
7f8082b
public exports - no wildcard exports; header instructions; update CLA…
KKonstantinov Mar 14, 2026
7c3542e
public export on core package - named exports, types.ts - add header …
KKonstantinov Mar 14, 2026
25e73e6
merge commit
KKonstantinov Mar 21, 2026
7689c21
Address PR #1680 review feedback: parseJSONRPCMessage, migration docs…
KKonstantinov Mar 21, 2026
847eaf4
lint fix
KKonstantinov Mar 21, 2026
d49f7e2
remove utility type from exports
KKonstantinov Mar 21, 2026
1b23d33
merge commit
KKonstantinov Mar 25, 2026
434d914
Merge branch 'main' into feature/v2-limit-public-api-exports
KKonstantinov Mar 25, 2026
4449c77
stdio public exports
KKonstantinov Mar 25, 2026
9468791
docs: fix migration guide core imports, add fromJsonSchema export
felixweinberger Mar 25, 2026
8980103
fix: use explicit named exports for auth/errors, fix migration-SKILL …
felixweinberger Mar 25, 2026
0318c95
fix: export StandardSchemaWithJSON type, add typedoc external link ma…
felixweinberger Mar 25, 2026
37d1b4f
docs: fix AuthInfo references in migration.md to point to client/server
felixweinberger Mar 25, 2026
dd6c5ce
Merge branch 'main' into feature/v2-limit-public-api-exports
felixweinberger Mar 25, 2026
227bf4c
Remove @linkcode to internal Protocol methods in ProtocolOptions.task…
felixweinberger Mar 25, 2026
a8b1087
Merge branch 'main' into feature/v2-limit-public-api-exports
felixweinberger Mar 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ The SDK is organized into three main layers:
- `Server` (`packages/server/src/server/server.ts`) - Server implementation extending Protocol with request handler registration
- `McpServer` (`packages/server/src/server/mcp.ts`) - High-level server API with simplified resource/tool/prompt registration

### Public API Exports

The SDK has a two-layer export structure to separate internal code from the public API:

- **`@modelcontextprotocol/core`** (main entry, `packages/core/src/index.ts`) — Internal barrel. Exports everything (including Zod schemas, Protocol class, stdio utils). Only consumed by sibling packages within the monorepo (`private: true`).
- **`@modelcontextprotocol/core/public`** (`packages/core/src/exports/public/index.ts`) — Curated public API. Exports only TypeScript types, error classes, constants, and guards. Re-exported by client and server packages.
- **`@modelcontextprotocol/client`** and **`@modelcontextprotocol/server`** (`packages/*/src/index.ts`) — Final public surface. Package-specific exports (named explicitly) plus re-exports from `core/public`.

When modifying exports:
- Use explicit named exports, not `export *`, in package `index.ts` files and `core/public`.
- Adding a symbol to a package `index.ts` makes it public API — do so intentionally.
- Internal helpers should stay in the core internal barrel and not be added to `core/public` or package index files.

### Transport System

Transports (`packages/core/src/shared/transport.ts`) provide the communication layer:
Expand Down
27 changes: 13 additions & 14 deletions docs/migration-SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,17 @@ Replace all `@modelcontextprotocol/sdk/...` imports using this table.

| v1 import path | v2 package |
| ------------------------------------------------- | ---------------------------- |
| `@modelcontextprotocol/sdk/types.js` | `@modelcontextprotocol/core` |
| `@modelcontextprotocol/sdk/shared/protocol.js` | `@modelcontextprotocol/core` |
| `@modelcontextprotocol/sdk/shared/transport.js` | `@modelcontextprotocol/core` |
| `@modelcontextprotocol/sdk/shared/stdio.js` | `@modelcontextprotocol/core` |
| `@modelcontextprotocol/sdk/shared/uriTemplate.js` | `@modelcontextprotocol/core` |
| `@modelcontextprotocol/sdk/shared/auth.js` | `@modelcontextprotocol/core` |
| `@modelcontextprotocol/sdk/types.js` | `@modelcontextprotocol/client` or `@modelcontextprotocol/server` |
| `@modelcontextprotocol/sdk/shared/protocol.js` | `@modelcontextprotocol/client` or `@modelcontextprotocol/server` |
| `@modelcontextprotocol/sdk/shared/transport.js` | `@modelcontextprotocol/client` or `@modelcontextprotocol/server` |
| `@modelcontextprotocol/sdk/shared/uriTemplate.js` | `@modelcontextprotocol/client` or `@modelcontextprotocol/server` |
| `@modelcontextprotocol/sdk/shared/auth.js` | `@modelcontextprotocol/client` or `@modelcontextprotocol/server` |
| `@modelcontextprotocol/sdk/shared/stdio.js` | `@modelcontextprotocol/client` or `@modelcontextprotocol/server` |

Notes:

- `@modelcontextprotocol/client` and `@modelcontextprotocol/server` both re-export everything from `@modelcontextprotocol/core`, so you can import types from whichever package you already depend on.
- `@modelcontextprotocol/client` and `@modelcontextprotocol/server` both re-export shared types from `@modelcontextprotocol/core`, so import from whichever package you already depend on. Do not import from `@modelcontextprotocol/core` directly — it is an internal package.
- When multiple v1 imports map to the same v2 package, consolidate them into a single import statement.
- If code imports from `sdk/client/...`, install `@modelcontextprotocol/client`. If from `sdk/server/...`, install `@modelcontextprotocol/server`. If from `sdk/types.js` or `sdk/shared/...` only, install `@modelcontextprotocol/core`.

## 4. Renamed Symbols

Expand All @@ -91,7 +90,7 @@ Notes:
| `ResourceReference` | `ResourceTemplateReference` |
| `ResourceReferenceSchema` | `ResourceTemplateReferenceSchema` |
| `IsomorphicHeaders` | REMOVED (use Web Standard `Headers`) |
| `AuthInfo` (from `server/auth/types.js`) | `AuthInfo` (now in `@modelcontextprotocol/core`) |
| `AuthInfo` (from `server/auth/types.js`) | `AuthInfo` (now re-exported by `@modelcontextprotocol/client` and `@modelcontextprotocol/server`) |
| `McpError` | `ProtocolError` |
| `ErrorCode` | `ProtocolErrorCode` |
| `ErrorCode.RequestTimeout` | `SdkErrorCode.RequestTimeout` |
Expand Down Expand Up @@ -144,7 +143,7 @@ Update error handling:
if (error instanceof McpError && error.code === ErrorCode.RequestTimeout) { ... }

// v2
import { SdkError, SdkErrorCode } from '@modelcontextprotocol/core';
import { SdkError, SdkErrorCode } from '@modelcontextprotocol/client';
if (error instanceof SdkError && error.code === SdkErrorCode.RequestTimeout) { ... }
```

Expand All @@ -158,7 +157,7 @@ if (error instanceof StreamableHTTPError) {
}

// v2
import { SdkError, SdkErrorCode } from '@modelcontextprotocol/core';
import { SdkError, SdkErrorCode } from '@modelcontextprotocol/client';
if (error instanceof SdkError && error.code === SdkErrorCode.ClientHttpFailedToOpenStream) {
const status = (error.data as { status?: number })?.status;
}
Expand Down Expand Up @@ -195,11 +194,11 @@ Update OAuth error handling:

```typescript
// v1
import { InvalidClientError, InvalidGrantError } from '@modelcontextprotocol/core';
import { InvalidClientError, InvalidGrantError } from '@modelcontextprotocol/client';
if (error instanceof InvalidClientError) { ... }

// v2
import { OAuthError, OAuthErrorCode } from '@modelcontextprotocol/core';
import { OAuthError, OAuthErrorCode } from '@modelcontextprotocol/client';
if (error instanceof OAuthError && error.code === OAuthErrorCode.InvalidClient) { ... }
```

Expand All @@ -210,7 +209,7 @@ Zod schemas, all callback return types. Note: `callTool()` and `request()` signa

The variadic `.tool()`, `.prompt()`, `.resource()` methods are removed. Use the `register*` methods with a config object.

**IMPORTANT**: v2 requires schema objects implementing [Standard Schema](https://standardschema.dev/) — raw shapes like `{ name: z.string() }` are no longer supported. Wrap with `z.object()` (Zod v4), or use ArkType's `type({...})`, or Valibot. For raw JSON Schema, wrap with `fromJsonSchema(schema, validator)` from `@modelcontextprotocol/core`. Applies to `inputSchema`, `outputSchema`, and `argsSchema`.
**IMPORTANT**: v2 requires schema objects implementing [Standard Schema](https://standardschema.dev/) — raw shapes like `{ name: z.string() }` are no longer supported. Wrap with `z.object()` (Zod v4), or use ArkType's `type({...})`, or Valibot. For raw JSON Schema, wrap with `fromJsonSchema(schema, validator)` from `@modelcontextprotocol/server`. Applies to `inputSchema`, `outputSchema`, and `argsSchema`.

### Tools

Expand Down
37 changes: 26 additions & 11 deletions docs/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,12 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
```typescript
import { Client, StreamableHTTPClientTransport, StdioClientTransport } from '@modelcontextprotocol/client';
import { McpServer, StdioServerTransport, WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/server';
import { CallToolResultSchema } from '@modelcontextprotocol/core';

// Node.js HTTP server transport is in the @modelcontextprotocol/node package
import { NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/node';
```

Note: `@modelcontextprotocol/client` and `@modelcontextprotocol/server` both re-export everything from `@modelcontextprotocol/core`, so you can import types from whichever package you already depend on.
Note: `@modelcontextprotocol/client` and `@modelcontextprotocol/server` both re-export shared types from `@modelcontextprotocol/core`, so you can import types and error classes from whichever package you already depend on. Do not import from `@modelcontextprotocol/core` directly — it is an internal package.

### Dropped Node.js 18 and CommonJS

Expand Down Expand Up @@ -117,7 +116,7 @@ Server-side OAuth/auth has been removed entirely from the SDK. This includes `mc

Use a dedicated auth library (e.g., `better-auth`) or a full Authorization Server instead. See the [examples](../examples/server/src/) for a working demo with `better-auth`.

Note: `AuthInfo` has moved from `server/auth/types.ts` to `@modelcontextprotocol/core` (it's now a core type).
Note: `AuthInfo` has moved from `server/auth/types.ts` to the core types and is now re-exported by `@modelcontextprotocol/client` and `@modelcontextprotocol/server`.

### `Headers` object instead of plain objects

Expand Down Expand Up @@ -252,7 +251,7 @@ server.registerTool('greet', {
}, async ({ name }) => { ... });

// Raw JSON Schema via fromJsonSchema
import { fromJsonSchema, AjvJsonSchemaValidator } from '@modelcontextprotocol/core';
import { fromJsonSchema, AjvJsonSchemaValidator } from '@modelcontextprotocol/server';
server.registerTool('greet', {
inputSchema: fromJsonSchema({ type: 'object', properties: { name: { type: 'string' } } }, new AjvJsonSchemaValidator())
}, handler);
Expand Down Expand Up @@ -434,6 +433,22 @@ const client = new Client(
);
```

### `InMemoryTransport` removed from public API

`InMemoryTransport` has been removed from the public API surface. It was previously used for in-process client-server connections and testing.

For **testing**, import it directly from the internal core package:

```typescript
// v1
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';

// v2 (testing only — @modelcontextprotocol/core is internal, not for production use)
import { InMemoryTransport } from '@modelcontextprotocol/core';
```

For **production in-process connections**, use `StreamableHTTPClientTransport` with a local server URL, or connect client and server via paired streams.

### Removed type aliases and deprecated exports

The following deprecated type aliases have been removed from `@modelcontextprotocol/core`:
Expand All @@ -447,9 +462,9 @@ The following deprecated type aliases have been removed from `@modelcontextproto
| `ResourceReferenceSchema` | `ResourceTemplateReferenceSchema` |
| `ResourceReference` | `ResourceTemplateReference` |
| `IsomorphicHeaders` | Use Web Standard `Headers` |
| `AuthInfo` (from `server/auth/types.js`) | `AuthInfo` (now in `@modelcontextprotocol/core`) |
| `AuthInfo` (from `server/auth/types.js`) | `AuthInfo` (now re-exported by `@modelcontextprotocol/client` and `@modelcontextprotocol/server`) |

All other types and schemas exported from `@modelcontextprotocol/sdk/types.js` retain their original names in `@modelcontextprotocol/core`.
All other types and schemas exported from `@modelcontextprotocol/sdk/types.js` retain their original names — import them from `@modelcontextprotocol/client` or `@modelcontextprotocol/server`.

**Before (v1):**

Expand All @@ -460,7 +475,7 @@ import { JSONRPCError, ResourceReference, isJSONRPCError } from '@modelcontextpr
**After (v2):**

```typescript
import { JSONRPCErrorResponse, ResourceTemplateReference, isJSONRPCErrorResponse } from '@modelcontextprotocol/core';
import { JSONRPCErrorResponse, ResourceTemplateReference, isJSONRPCErrorResponse } from '@modelcontextprotocol/server';
```

### Request handler context types
Expand Down Expand Up @@ -576,7 +591,7 @@ try {
**After (v2):**

```typescript
import { ProtocolError, ProtocolErrorCode, SdkError, SdkErrorCode } from '@modelcontextprotocol/core';
import { ProtocolError, ProtocolErrorCode, SdkError, SdkErrorCode } from '@modelcontextprotocol/client';

try {
await client.callTool({ name: 'test', arguments: {} });
Expand Down Expand Up @@ -633,7 +648,7 @@ try {
**After (v2):**

```typescript
import { SdkError, SdkErrorCode } from '@modelcontextprotocol/core';
import { SdkError, SdkErrorCode } from '@modelcontextprotocol/client';

try {
await transport.send(message);
Expand Down Expand Up @@ -703,7 +718,7 @@ The `OAUTH_ERRORS` constant has also been removed.
**Before (v1):**

```typescript
import { InvalidClientError, InvalidGrantError, ServerError } from '@modelcontextprotocol/core';
import { InvalidClientError, InvalidGrantError, ServerError } from '@modelcontextprotocol/client';

try {
await refreshToken();
Expand All @@ -721,7 +736,7 @@ try {
**After (v2):**

```typescript
import { OAuthError, OAuthErrorCode } from '@modelcontextprotocol/core';
import { OAuthError, OAuthErrorCode } from '@modelcontextprotocol/client';

try {
await refreshToken();
Expand Down
3 changes: 3 additions & 0 deletions examples/client-quickstart/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
"@modelcontextprotocol/client/_shims": ["./node_modules/@modelcontextprotocol/client/src/shimsNode.ts"],
"@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/exports/public/index.ts"
]
}
},
Expand Down
3 changes: 3 additions & 0 deletions examples/client/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,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/exports/public/index.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"]
Expand Down
3 changes: 3 additions & 0 deletions examples/server-quickstart/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
"@modelcontextprotocol/server/_shims": ["./node_modules/@modelcontextprotocol/server/src/shimsNode.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/exports/public/index.ts"
]
}
},
Expand Down
3 changes: 3 additions & 0 deletions examples/server/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,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/exports/public/index.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"]
Expand Down
3 changes: 3 additions & 0 deletions examples/shared/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -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/exports/public/index.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"],
Expand Down
82 changes: 70 additions & 12 deletions packages/client/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,73 @@
export * from './client/auth.js';
export * from './client/authExtensions.js';
export * from './client/client.js';
export * from './client/crossAppAccess.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';
// Public API for @modelcontextprotocol/client.
//
// This file defines the complete public surface. It consists of:
// - Package-specific exports: listed explicitly below (named imports)
// - Protocol-level types: re-exported from @modelcontextprotocol/core/public
//
// Any new export added here becomes public API. Use named exports, not wildcards.

export type {
AddClientAuthentication,
AuthProvider,
AuthResult,
ClientAuthMethod,
OAuthClientProvider,
OAuthDiscoveryState,
OAuthServerInfo
} from './client/auth.js';
export {
auth,
buildDiscoveryUrls,
discoverAuthorizationServerMetadata,
discoverOAuthMetadata,
discoverOAuthProtectedResourceMetadata,
discoverOAuthServerInfo,
exchangeAuthorization,
extractResourceMetadataUrl,
extractWWWAuthenticateParams,
fetchToken,
isHttpsUrl,
parseErrorResponse,
prepareAuthorizationCodeRequest,
refreshAuthorization,
registerClient,
selectClientAuthMethod,
selectResourceURL,
startAuthorization,
UnauthorizedError
} from './client/auth.js';
export type {
AssertionCallback,
ClientCredentialsProviderOptions,
CrossAppAccessContext,
CrossAppAccessProviderOptions,
PrivateKeyJwtProviderOptions,
StaticPrivateKeyJwtProviderOptions
} from './client/authExtensions.js';
export {
ClientCredentialsProvider,
createPrivateKeyJwtAuth,
CrossAppAccessProvider,
PrivateKeyJwtProvider,
StaticPrivateKeyJwtProvider
} from './client/authExtensions.js';
export type { ClientOptions } from './client/client.js';
export { Client } from './client/client.js';
export { getSupportedElicitationModes } from './client/client.js';
export type { DiscoverAndRequestJwtAuthGrantOptions, JwtAuthGrantResult, RequestJwtAuthGrantOptions } from './client/crossAppAccess.js';
export { discoverAndRequestJwtAuthGrant, exchangeJwtAuthGrant, requestJwtAuthorizationGrant } from './client/crossAppAccess.js';
export type { LoggingOptions, Middleware, RequestLogger } from './client/middleware.js';
export { applyMiddlewares, createMiddleware, withLogging, withOAuth } from './client/middleware.js';
export type { SSEClientTransportOptions } from './client/sse.js';
export { SSEClientTransport, SseError } from './client/sse.js';
export type { StdioServerParameters } from './client/stdio.js';
export { DEFAULT_INHERITED_ENV_VARS, getDefaultEnvironment, StdioClientTransport } from './client/stdio.js';
export type { StartSSEOptions, StreamableHTTPClientTransportOptions, StreamableHTTPReconnectionOptions } from './client/streamableHttp.js';
export { StreamableHTTPClientTransport } from './client/streamableHttp.js';
export { WebSocketClientTransport } from './client/websocket.js';

// experimental exports
export * from './experimental/index.js';
export { ExperimentalClientTasks } from './experimental/tasks/client.js';

// re-export shared types
export * from '@modelcontextprotocol/core';
// re-export curated public API from core
export * from '@modelcontextprotocol/core/public';
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Both packages/client/tsdown.config.ts and packages/server/tsdown.config.ts specify DTS compilerOptions.paths that only map @modelcontextprotocol/core but not the new @modelcontextprotocol/core/public subpath used in both package index files. While TypeScript's moduleResolution: "NodeNext" should fall through to the core package's exports field for resolution, adding the explicit path mapping would be consistent with the tsconfig.json updates and removes any dependency on tsdown's DTS resolver correctly supporting exports-based fallback.

Fix: add '@modelcontextprotocol/core/public': ['../core/src/exports/public/index.ts'] to dts.compilerOptions.paths in both tsdown configs.

Extended reasoning...

What the bug is

Both packages/client/tsdown.config.ts and packages/server/tsdown.config.ts define explicit DTS compilerOptions.paths that only map @modelcontextprotocol/core to ../core/src/index.ts. The PR changes both package index.ts files to export * from '@modelcontextprotocol/core/public', but the tsdown DTS configs were not updated to include a mapping for this new subpath import.

How it could be triggered

This would be triggered during pnpm build:all, which runs tsdown to generate DTS bundles for the client and server packages. The tsdown DTS resolver uses the compilerOptions.paths override (which replaces the tsconfig.json paths) to locate type sources for bundling. When it encounters @modelcontextprotocol/core/public in the entry point, it needs to resolve this specifier.

The PR author tested typecheck:all, lint:all, test:all, and check:all, but notably did not mention testing build:all. The tsconfig.json paths (which DO include the @modelcontextprotocol/core/public mapping) are used by typecheck:all, but the tsdown DTS config paths are separate and used during build.

Addressing the refutation

One verifier argued this is not a real bug because: (1) the base tsconfig uses moduleResolution: "NodeNext", (2) when @modelcontextprotocol/core/public doesn't match any paths entry, TypeScript falls through to node_modules resolution, and (3) the core package's package.json exports field correctly maps "./public" to "./src/exports/public/index.ts".

This is a reasonable argument. TypeScript's paths matching is exact — @modelcontextprotocol/core does NOT match @modelcontextprotocol/core/public — so TypeScript should indeed fall through to standard node_modules resolution. With moduleResolution: "NodeNext" inherited from the base tsconfig, the exports field resolution should work.

However, this fallback behavior depends on tsdown's DTS resolver (resolver: 'tsc') correctly inheriting moduleResolution: "NodeNext" from the base tsconfig and properly supporting exports-based resolution during DTS bundling. This is a tool-specific implementation detail. The existing @modelcontextprotocol/core mapping explicitly bypasses node_modules resolution (pointing to ../core/src/index.ts instead), suggesting the project intentionally uses direct source paths for DTS generation rather than relying on node_modules resolution.

Impact

If the tsdown DTS resolver does NOT correctly fall through to exports-based resolution, pnpm build:all would fail during DTS generation for both client and server packages, preventing publishable artifacts from being produced. Given the uncertainty, the impact is moderate — the build may or may not fail depending on tsdown's internal behavior.

Suggested fix

Add the missing path mapping to both tsdown configs:

// packages/client/tsdown.config.ts (and packages/server/tsdown.config.ts)
 dts: {
     resolver: 'tsc',
     compilerOptions: {
         baseUrl: '.',
         paths: {
-            '@modelcontextprotocol/core': ['../core/src/index.ts']
+            '@modelcontextprotocol/core': ['../core/src/index.ts'],
+            '@modelcontextprotocol/core/public': ['../core/src/exports/public/index.ts']
         }
     }
 },

Step-by-step proof

  1. packages/client/src/index.ts:66 has export * from '@modelcontextprotocol/core/public'
  2. packages/server/src/index.ts:47 has export * from '@modelcontextprotocol/core/public'
  3. When pnpm build:all runs, tsdown processes these entry points for DTS generation
  4. tsdown's DTS config specifies compilerOptions.paths with only @modelcontextprotocol/core mapped
  5. The TypeScript compiler resolving @modelcontextprotocol/core/public finds no matching paths entry
  6. It falls through to node_modules resolution — this is where the uncertainty lies
  7. If the fallback works (probable), the build succeeds via core's package.json exports
  8. If the fallback doesn't work in tsdown's DTS context, the build fails
  9. Either way, the explicit mapping is the safer approach and consistent with all other tsconfig.json updates in this PR

1 change: 1 addition & 0 deletions packages/client/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"paths": {
"*": ["./*"],
"@modelcontextprotocol/core": ["./node_modules/@modelcontextprotocol/core/src/index.ts"],
"@modelcontextprotocol/core/public": ["./node_modules/@modelcontextprotocol/core/src/exports/public/index.ts"],
"@modelcontextprotocol/test-helpers": ["./node_modules/@modelcontextprotocol/test-helpers/src/index.ts"],
"@modelcontextprotocol/client/_shims": ["./src/shimsNode.ts"]
}
Expand Down
Loading
Loading