From 6a98c9b57ed2b9639c4ccdcf92362c3da3cf45a0 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Wed, 15 Apr 2026 12:02:48 +0000 Subject: [PATCH 1/7] feat(compat): add @modelcontextprotocol/sdk meta-package with v1 deep-import subpaths Adds packages/sdk as the primary v2 entry point. Re-exports the full server + client + node surface from a single root barrel (TS2308-safe named re-exports for client/node) and preserves v1 deep-import subpaths (/types.js, /server/mcp.js, /client/index.js, /shared/transport.js, /shared/protocol.js, /server/auth/errors.js with the 17 OAuth error subclasses, etc.). Folds in the C3/C6 schema-arg shims: the sdk-exported Server and Client are thin subclasses that additionally accept the deprecated v1 calling conventions setRequestHandler(ZodSchema, h), setNotificationHandler( ZodSchema, h) and request(req, ResultSchema, opts), extracting the method literal and forwarding to the v2 string-based API with a one-time deprecation warning. --- .changeset/sdk-meta-package.md | 5 + packages/sdk/README.md | 20 ++ packages/sdk/eslint.config.mjs | 27 ++ packages/sdk/package.json | 312 ++++++++++++++++++ packages/sdk/src/client/auth.ts | 1 + packages/sdk/src/client/index.ts | 1 + packages/sdk/src/client/sse.ts | 1 + packages/sdk/src/client/stdio.ts | 2 + packages/sdk/src/client/streamableHttp.ts | 6 + packages/sdk/src/experimental/tasks.ts | 5 + packages/sdk/src/inMemory.ts | 1 + packages/sdk/src/index.ts | 92 ++++++ packages/sdk/src/server/auth/clients.ts | 2 + packages/sdk/src/server/auth/errors.ts | 54 +++ .../src/server/auth/middleware/bearerAuth.ts | 2 + packages/sdk/src/server/auth/provider.ts | 2 + packages/sdk/src/server/auth/router.ts | 2 + packages/sdk/src/server/auth/types.ts | 1 + packages/sdk/src/server/completable.ts | 1 + packages/sdk/src/server/index.ts | 1 + packages/sdk/src/server/mcp.ts | 21 ++ packages/sdk/src/server/sse.ts | 1 + packages/sdk/src/server/stdio.ts | 1 + packages/sdk/src/server/streamableHttp.ts | 4 + .../src/server/webStandardStreamableHttp.ts | 4 + packages/sdk/src/shared/auth.ts | 33 ++ packages/sdk/src/shared/protocol.ts | 17 + packages/sdk/src/shared/stdio.ts | 1 + packages/sdk/src/shared/transport.ts | 2 + packages/sdk/src/stdio.ts | 3 + packages/sdk/src/types.ts | 20 ++ packages/sdk/src/validation/ajv-provider.ts | 1 + .../sdk/src/validation/cfworker-provider.ts | 1 + packages/sdk/src/validation/types.ts | 2 + packages/sdk/test/compat.test.ts | 93 ++++++ packages/sdk/tsconfig.build.json | 14 + packages/sdk/tsconfig.json | 25 ++ packages/sdk/tsdown.config.ts | 45 +++ packages/sdk/vitest.config.js | 3 + pnpm-lock.yaml | 74 ++++- test/integration/package.json | 2 + .../integration/test/compat/v1Surface.test.ts | 120 +++++++ test/integration/tsconfig.json | 7 + typedoc.config.mjs | 7 +- 44 files changed, 1033 insertions(+), 6 deletions(-) create mode 100644 .changeset/sdk-meta-package.md create mode 100644 packages/sdk/README.md create mode 100644 packages/sdk/eslint.config.mjs create mode 100644 packages/sdk/package.json create mode 100644 packages/sdk/src/client/auth.ts create mode 100644 packages/sdk/src/client/index.ts create mode 100644 packages/sdk/src/client/sse.ts create mode 100644 packages/sdk/src/client/stdio.ts create mode 100644 packages/sdk/src/client/streamableHttp.ts create mode 100644 packages/sdk/src/experimental/tasks.ts create mode 100644 packages/sdk/src/inMemory.ts create mode 100644 packages/sdk/src/index.ts create mode 100644 packages/sdk/src/server/auth/clients.ts create mode 100644 packages/sdk/src/server/auth/errors.ts create mode 100644 packages/sdk/src/server/auth/middleware/bearerAuth.ts create mode 100644 packages/sdk/src/server/auth/provider.ts create mode 100644 packages/sdk/src/server/auth/router.ts create mode 100644 packages/sdk/src/server/auth/types.ts create mode 100644 packages/sdk/src/server/completable.ts create mode 100644 packages/sdk/src/server/index.ts create mode 100644 packages/sdk/src/server/mcp.ts create mode 100644 packages/sdk/src/server/sse.ts create mode 100644 packages/sdk/src/server/stdio.ts create mode 100644 packages/sdk/src/server/streamableHttp.ts create mode 100644 packages/sdk/src/server/webStandardStreamableHttp.ts create mode 100644 packages/sdk/src/shared/auth.ts create mode 100644 packages/sdk/src/shared/protocol.ts create mode 100644 packages/sdk/src/shared/stdio.ts create mode 100644 packages/sdk/src/shared/transport.ts create mode 100644 packages/sdk/src/stdio.ts create mode 100644 packages/sdk/src/types.ts create mode 100644 packages/sdk/src/validation/ajv-provider.ts create mode 100644 packages/sdk/src/validation/cfworker-provider.ts create mode 100644 packages/sdk/src/validation/types.ts create mode 100644 packages/sdk/test/compat.test.ts create mode 100644 packages/sdk/tsconfig.build.json create mode 100644 packages/sdk/tsconfig.json create mode 100644 packages/sdk/tsdown.config.ts create mode 100644 packages/sdk/vitest.config.js create mode 100644 test/integration/test/compat/v1Surface.test.ts diff --git a/.changeset/sdk-meta-package.md b/.changeset/sdk-meta-package.md new file mode 100644 index 000000000..20d085fbe --- /dev/null +++ b/.changeset/sdk-meta-package.md @@ -0,0 +1,5 @@ +--- +'@modelcontextprotocol/sdk': patch +--- + +Add `@modelcontextprotocol/sdk` meta-package: re-exports `@modelcontextprotocol/server` + `client` + `node` and preserves v1 deep-import subpaths (`/types.js`, `/server/mcp.js`, `/client/index.js`, `/shared/transport.js`, `/server/auth/errors.js`, etc.). The package is the recommended primary entry point; the split packages remain available for bundle-conscious consumers. diff --git a/packages/sdk/README.md b/packages/sdk/README.md new file mode 100644 index 000000000..cb4333fcc --- /dev/null +++ b/packages/sdk/README.md @@ -0,0 +1,20 @@ +# @modelcontextprotocol/sdk + +The **primary entry point** for the Model Context Protocol TypeScript SDK. + +This meta-package re-exports the full public surface of [`@modelcontextprotocol/server`](../server), [`@modelcontextprotocol/client`](../client), and [`@modelcontextprotocol/node`](../middleware/node), so most applications can depend on this package alone: + +```ts +import { McpServer, Client, NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk'; +``` + +## Upgrading from v1 + +`@modelcontextprotocol/sdk` v2 is a drop-in upgrade for most v1 servers — just bump the version. v1 deep-import paths (`@modelcontextprotocol/sdk/types.js`, `/server/mcp.js`, `/client/index.js`, `/shared/transport.js`, etc.) are preserved as compatibility subpaths that re-export +the matching v2 symbols and emit one-time deprecation warnings where the API shape changed. + +See [`docs/migration.md`](../../docs/migration.md) for the full mapping. + +## When to use the sub-packages directly + +Bundle-sensitive targets (browsers, Cloudflare Workers) should import from `@modelcontextprotocol/client` or `@modelcontextprotocol/server` directly to avoid pulling in Node-only transports. diff --git a/packages/sdk/eslint.config.mjs b/packages/sdk/eslint.config.mjs new file mode 100644 index 000000000..e34a2a51a --- /dev/null +++ b/packages/sdk/eslint.config.mjs @@ -0,0 +1,27 @@ +// @ts-check + +import baseConfig from '@modelcontextprotocol/eslint-config'; + +export default [ + ...baseConfig, + { + settings: { + 'import/internal-regex': '^@modelcontextprotocol/' + } + }, + { + // This package is the v1-compat surface; deprecated re-exports are intentional. + // import/no-unresolved: subpaths re-export from sibling packages (server-auth-legacy, + // node/sse, server/zod-schemas) that don't exist on this branch standalone — they + // land via separate PRs in this BC series. Resolves once those merge. + // import/export: types.ts deliberately shadows `export *` names with v1-compat aliases + // (TS spec: named export wins over re-export). + // unicorn/filename-case: validation/ajv-provider.ts etc. match v1 subpath names. + rules: { + '@typescript-eslint/no-deprecated': 'off', + 'import/no-unresolved': 'off', + 'import/export': 'off', + 'unicorn/filename-case': 'off' + } + } +]; diff --git a/packages/sdk/package.json b/packages/sdk/package.json new file mode 100644 index 000000000..9a796e2b8 --- /dev/null +++ b/packages/sdk/package.json @@ -0,0 +1,312 @@ +{ + "name": "@modelcontextprotocol/sdk", + "version": "2.0.0-alpha.2", + "description": "Model Context Protocol implementation for TypeScript - Full SDK (re-exports client, server, and node middleware)", + "license": "MIT", + "author": "Anthropic, PBC (https://anthropic.com)", + "homepage": "https://modelcontextprotocol.io", + "bugs": "https://github.com/modelcontextprotocol/typescript-sdk/issues", + "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/modelcontextprotocol/typescript-sdk.git" + }, + "engines": { + "node": ">=20" + }, + "keywords": [ + "modelcontextprotocol", + "mcp" + ], + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs" + }, + "./stdio": { + "types": "./dist/stdio.d.ts", + "import": "./dist/stdio.mjs" + }, + "./types.js": { + "types": "./dist/types.d.ts", + "import": "./dist/types.mjs" + }, + "./types": { + "types": "./dist/types.d.ts", + "import": "./dist/types.mjs" + }, + "./server/index.js": { + "types": "./dist/server/index.d.ts", + "import": "./dist/server/index.mjs" + }, + "./server/index": { + "types": "./dist/server/index.d.ts", + "import": "./dist/server/index.mjs" + }, + "./server/mcp.js": { + "types": "./dist/server/mcp.d.ts", + "import": "./dist/server/mcp.mjs" + }, + "./server/mcp": { + "types": "./dist/server/mcp.d.ts", + "import": "./dist/server/mcp.mjs" + }, + "./server/stdio.js": { + "types": "./dist/server/stdio.d.ts", + "import": "./dist/server/stdio.mjs" + }, + "./server/stdio": { + "types": "./dist/server/stdio.d.ts", + "import": "./dist/server/stdio.mjs" + }, + "./server/streamableHttp.js": { + "types": "./dist/server/streamableHttp.d.ts", + "import": "./dist/server/streamableHttp.mjs" + }, + "./server/streamableHttp": { + "types": "./dist/server/streamableHttp.d.ts", + "import": "./dist/server/streamableHttp.mjs" + }, + "./server/auth/types.js": { + "types": "./dist/server/auth/types.d.ts", + "import": "./dist/server/auth/types.mjs" + }, + "./server/auth/types": { + "types": "./dist/server/auth/types.d.ts", + "import": "./dist/server/auth/types.mjs" + }, + "./server/auth/errors.js": { + "types": "./dist/server/auth/errors.d.ts", + "import": "./dist/server/auth/errors.mjs" + }, + "./server/auth/errors": { + "types": "./dist/server/auth/errors.d.ts", + "import": "./dist/server/auth/errors.mjs" + }, + "./client": { + "types": "./dist/client/index.d.ts", + "import": "./dist/client/index.mjs" + }, + "./client/index.js": { + "types": "./dist/client/index.d.ts", + "import": "./dist/client/index.mjs" + }, + "./client/index": { + "types": "./dist/client/index.d.ts", + "import": "./dist/client/index.mjs" + }, + "./client/stdio.js": { + "types": "./dist/client/stdio.d.ts", + "import": "./dist/client/stdio.mjs" + }, + "./client/stdio": { + "types": "./dist/client/stdio.d.ts", + "import": "./dist/client/stdio.mjs" + }, + "./client/streamableHttp.js": { + "types": "./dist/client/streamableHttp.d.ts", + "import": "./dist/client/streamableHttp.mjs" + }, + "./client/streamableHttp": { + "types": "./dist/client/streamableHttp.d.ts", + "import": "./dist/client/streamableHttp.mjs" + }, + "./client/sse.js": { + "types": "./dist/client/sse.d.ts", + "import": "./dist/client/sse.mjs" + }, + "./client/sse": { + "types": "./dist/client/sse.d.ts", + "import": "./dist/client/sse.mjs" + }, + "./client/auth.js": { + "types": "./dist/client/auth.d.ts", + "import": "./dist/client/auth.mjs" + }, + "./client/auth": { + "types": "./dist/client/auth.d.ts", + "import": "./dist/client/auth.mjs" + }, + "./shared/protocol.js": { + "types": "./dist/shared/protocol.d.ts", + "import": "./dist/shared/protocol.mjs" + }, + "./shared/protocol": { + "types": "./dist/shared/protocol.d.ts", + "import": "./dist/shared/protocol.mjs" + }, + "./shared/transport.js": { + "types": "./dist/shared/transport.d.ts", + "import": "./dist/shared/transport.mjs" + }, + "./shared/transport": { + "types": "./dist/shared/transport.d.ts", + "import": "./dist/shared/transport.mjs" + }, + "./shared/auth.js": { + "types": "./dist/shared/auth.d.ts", + "import": "./dist/shared/auth.mjs" + }, + "./shared/auth": { + "types": "./dist/shared/auth.d.ts", + "import": "./dist/shared/auth.mjs" + }, + "./server/auth/middleware/bearerAuth.js": { + "types": "./dist/server/auth/middleware/bearerAuth.d.ts", + "import": "./dist/server/auth/middleware/bearerAuth.mjs" + }, + "./server/auth/middleware/bearerAuth": { + "types": "./dist/server/auth/middleware/bearerAuth.d.ts", + "import": "./dist/server/auth/middleware/bearerAuth.mjs" + }, + "./server/auth/router.js": { + "types": "./dist/server/auth/router.d.ts", + "import": "./dist/server/auth/router.mjs" + }, + "./server/auth/router": { + "types": "./dist/server/auth/router.d.ts", + "import": "./dist/server/auth/router.mjs" + }, + "./server/auth/provider.js": { + "types": "./dist/server/auth/provider.d.ts", + "import": "./dist/server/auth/provider.mjs" + }, + "./server/auth/provider": { + "types": "./dist/server/auth/provider.d.ts", + "import": "./dist/server/auth/provider.mjs" + }, + "./server/auth/clients.js": { + "types": "./dist/server/auth/clients.d.ts", + "import": "./dist/server/auth/clients.mjs" + }, + "./server/auth/clients": { + "types": "./dist/server/auth/clients.d.ts", + "import": "./dist/server/auth/clients.mjs" + }, + "./inMemory.js": { + "types": "./dist/inMemory.d.ts", + "import": "./dist/inMemory.mjs" + }, + "./inMemory": { + "types": "./dist/inMemory.d.ts", + "import": "./dist/inMemory.mjs" + }, + "./server/completable.js": { + "types": "./dist/server/completable.d.ts", + "import": "./dist/server/completable.mjs" + }, + "./server/completable": { + "types": "./dist/server/completable.d.ts", + "import": "./dist/server/completable.mjs" + }, + "./server/sse.js": { + "types": "./dist/server/sse.d.ts", + "import": "./dist/server/sse.mjs" + }, + "./server/sse": { + "types": "./dist/server/sse.d.ts", + "import": "./dist/server/sse.mjs" + }, + "./experimental/tasks": { + "types": "./dist/experimental/tasks.d.ts", + "import": "./dist/experimental/tasks.mjs" + }, + "./server": { + "types": "./dist/server/index.d.ts", + "import": "./dist/server/index.mjs" + }, + "./server.js": { + "types": "./dist/server/index.d.ts", + "import": "./dist/server/index.mjs" + }, + "./client.js": { + "types": "./dist/client/index.d.ts", + "import": "./dist/client/index.mjs" + }, + "./server/webStandardStreamableHttp.js": { + "types": "./dist/server/webStandardStreamableHttp.d.ts", + "import": "./dist/server/webStandardStreamableHttp.mjs" + }, + "./server/webStandardStreamableHttp": { + "types": "./dist/server/webStandardStreamableHttp.d.ts", + "import": "./dist/server/webStandardStreamableHttp.mjs" + }, + "./shared/stdio.js": { + "types": "./dist/shared/stdio.d.ts", + "import": "./dist/shared/stdio.mjs" + }, + "./shared/stdio": { + "types": "./dist/shared/stdio.d.ts", + "import": "./dist/shared/stdio.mjs" + }, + "./validation/types.js": { + "types": "./dist/validation/types.d.ts", + "import": "./dist/validation/types.mjs" + }, + "./validation/types": { + "types": "./dist/validation/types.d.ts", + "import": "./dist/validation/types.mjs" + }, + "./validation/cfworker-provider.js": { + "types": "./dist/validation/cfworker-provider.d.ts", + "import": "./dist/validation/cfworker-provider.mjs" + }, + "./validation/cfworker-provider": { + "types": "./dist/validation/cfworker-provider.d.ts", + "import": "./dist/validation/cfworker-provider.mjs" + }, + "./validation/ajv-provider.js": { + "types": "./dist/validation/ajv-provider.d.ts", + "import": "./dist/validation/ajv-provider.mjs" + }, + "./validation/ajv-provider": { + "types": "./dist/validation/ajv-provider.d.ts", + "import": "./dist/validation/ajv-provider.mjs" + } + }, + "files": [ + "dist" + ], + "scripts": { + "typecheck": "tsgo -p tsconfig.json --noEmit", + "build": "tsdown && tsc -p tsconfig.build.json", + "lint": "eslint src/ && prettier --ignore-path ../../.prettierignore --check .", + "lint:fix": "eslint src/ --fix && prettier --ignore-path ../../.prettierignore --write .", + "check": "pnpm run typecheck && pnpm run lint", + "test": "vitest run", + "test:watch": "vitest", + "prepack": "pnpm run build" + }, + "dependencies": { + "@modelcontextprotocol/client": "workspace:^", + "@modelcontextprotocol/express": "workspace:^", + "@modelcontextprotocol/node": "workspace:^", + "@modelcontextprotocol/server": "workspace:^", + "@modelcontextprotocol/server-auth-legacy": "workspace:^" + }, + "devDependencies": { + "@modelcontextprotocol/core": "workspace:^", + "@modelcontextprotocol/eslint-config": "workspace:^", + "@modelcontextprotocol/test-helpers": "workspace:^", + "@modelcontextprotocol/tsconfig": "workspace:^", + "@modelcontextprotocol/vitest-config": "workspace:^", + "@typescript/native-preview": "catalog:devTools", + "eslint": "catalog:devTools", + "prettier": "catalog:devTools", + "tsdown": "catalog:devTools", + "typescript": "catalog:devTools", + "vitest": "catalog:devTools", + "zod": "catalog:runtimeShared" + }, + "typesVersions": { + "*": { + "*.js": [ + "dist/*.d.ts" + ], + "*": [ + "dist/*.d.ts", + "dist/*/index.d.ts" + ] + } + } +} diff --git a/packages/sdk/src/client/auth.ts b/packages/sdk/src/client/auth.ts new file mode 100644 index 000000000..55eaaedf6 --- /dev/null +++ b/packages/sdk/src/client/auth.ts @@ -0,0 +1 @@ +export * from '@modelcontextprotocol/client'; diff --git a/packages/sdk/src/client/index.ts b/packages/sdk/src/client/index.ts new file mode 100644 index 000000000..55eaaedf6 --- /dev/null +++ b/packages/sdk/src/client/index.ts @@ -0,0 +1 @@ +export * from '@modelcontextprotocol/client'; diff --git a/packages/sdk/src/client/sse.ts b/packages/sdk/src/client/sse.ts new file mode 100644 index 000000000..9e752ea8c --- /dev/null +++ b/packages/sdk/src/client/sse.ts @@ -0,0 +1 @@ +export { SSEClientTransport, type SSEClientTransportOptions } from '@modelcontextprotocol/client'; diff --git a/packages/sdk/src/client/stdio.ts b/packages/sdk/src/client/stdio.ts new file mode 100644 index 000000000..456ea8cf1 --- /dev/null +++ b/packages/sdk/src/client/stdio.ts @@ -0,0 +1,2 @@ +export type { StdioServerParameters } from '@modelcontextprotocol/client/stdio'; +export { DEFAULT_INHERITED_ENV_VARS, getDefaultEnvironment, StdioClientTransport } from '@modelcontextprotocol/client/stdio'; diff --git a/packages/sdk/src/client/streamableHttp.ts b/packages/sdk/src/client/streamableHttp.ts new file mode 100644 index 000000000..0570cd738 --- /dev/null +++ b/packages/sdk/src/client/streamableHttp.ts @@ -0,0 +1,6 @@ +export { + StreamableHTTPClientTransport, + type StreamableHTTPClientTransportOptions, + StreamableHTTPError, + type StreamableHTTPReconnectionOptions +} from '@modelcontextprotocol/client'; diff --git a/packages/sdk/src/experimental/tasks.ts b/packages/sdk/src/experimental/tasks.ts new file mode 100644 index 000000000..cf883d266 --- /dev/null +++ b/packages/sdk/src/experimental/tasks.ts @@ -0,0 +1,5 @@ +// v1 compat: `@modelcontextprotocol/sdk/experimental/tasks` +// Re-exports the full server surface (task stores, handlers, and related types +// are scattered between core/public and server/experimental/tasks; the root +// barrel includes both). +export * from '@modelcontextprotocol/server'; diff --git a/packages/sdk/src/inMemory.ts b/packages/sdk/src/inMemory.ts new file mode 100644 index 000000000..7f2e9c6be --- /dev/null +++ b/packages/sdk/src/inMemory.ts @@ -0,0 +1 @@ +export { InMemoryTransport } from '@modelcontextprotocol/server'; diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts new file mode 100644 index 000000000..5607b931f --- /dev/null +++ b/packages/sdk/src/index.ts @@ -0,0 +1,92 @@ +// Root barrel for @modelcontextprotocol/sdk — the everything package. +// +// Re-exports the full public surface of the server, client, and node packages +// so consumers can `import { McpServer, Client, NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk'` +// without choosing a sub-package. +// +// Bundle-sensitive consumers (browser, Workers) should import from +// @modelcontextprotocol/client or @modelcontextprotocol/server directly instead. + +// Server gives us all server-specific exports + the entire core/public surface +// (spec types, error classes, transport interface, constants, guards). +export * from '@modelcontextprotocol/server'; + +// Node middleware — explicit named exports only. Not `export *`, because the +// node package re-exports core types from server and `export *` from both +// packages would collide on overlapping symbols (TS2308). +export { NodeStreamableHTTPServerTransport, type StreamableHTTPServerTransportOptions } from '@modelcontextprotocol/node'; +/** @deprecated Renamed to {@linkcode NodeStreamableHTTPServerTransport}. */ +export { NodeStreamableHTTPServerTransport as StreamableHTTPServerTransport } from '@modelcontextprotocol/node'; + +// Client-specific exports only — NOT `export *`, because client also re-exports +// core/public and the duplicate runtime-value identities (each package bundles +// core separately) trigger TS2308. core/public is already covered by server above. +export type { + AddClientAuthentication, + AssertionCallback, + AuthProvider, + AuthResult, + ClientAuthMethod, + ClientCredentialsProviderOptions, + ClientOptions, + CrossAppAccessContext, + CrossAppAccessProviderOptions, + DiscoverAndRequestJwtAuthGrantOptions, + JwtAuthGrantResult, + LoggingOptions, + Middleware, + OAuthClientProvider, + OAuthDiscoveryState, + OAuthServerInfo, + PrivateKeyJwtProviderOptions, + ReconnectionScheduler, + RequestJwtAuthGrantOptions, + RequestLogger, + SSEClientTransportOptions, + StartSSEOptions, + StaticPrivateKeyJwtProviderOptions, + StreamableHTTPClientTransportOptions, + StreamableHTTPReconnectionOptions +} from '@modelcontextprotocol/client'; +export { + applyMiddlewares, + auth, + buildDiscoveryUrls, + Client, + ClientCredentialsProvider, + createMiddleware, + createPrivateKeyJwtAuth, + CrossAppAccessProvider, + discoverAndRequestJwtAuthGrant, + discoverAuthorizationServerMetadata, + discoverOAuthMetadata, + discoverOAuthProtectedResourceMetadata, + discoverOAuthServerInfo, + exchangeAuthorization, + exchangeJwtAuthGrant, + ExperimentalClientTasks, + extractResourceMetadataUrl, + extractWWWAuthenticateParams, + fetchToken, + getSupportedElicitationModes, + isHttpsUrl, + parseErrorResponse, + prepareAuthorizationCodeRequest, + PrivateKeyJwtProvider, + refreshAuthorization, + registerClient, + requestJwtAuthorizationGrant, + selectClientAuthMethod, + selectResourceURL, + SSEClientTransport, + SseError, + startAuthorization, + StaticPrivateKeyJwtProvider, + StreamableHTTPClientTransport, + UnauthorizedError, + validateClientMetadataUrl, + withLogging, + withOAuth +} from '@modelcontextprotocol/client'; +export type { StdioServerParameters } from '@modelcontextprotocol/client/stdio'; +export { DEFAULT_INHERITED_ENV_VARS, getDefaultEnvironment, StdioClientTransport } from '@modelcontextprotocol/client/stdio'; diff --git a/packages/sdk/src/server/auth/clients.ts b/packages/sdk/src/server/auth/clients.ts new file mode 100644 index 000000000..7e5518907 --- /dev/null +++ b/packages/sdk/src/server/auth/clients.ts @@ -0,0 +1,2 @@ +// v1 compat: `@modelcontextprotocol/sdk/server/auth/clients.js` +export * from '@modelcontextprotocol/server-auth-legacy'; diff --git a/packages/sdk/src/server/auth/errors.ts b/packages/sdk/src/server/auth/errors.ts new file mode 100644 index 000000000..9206ff573 --- /dev/null +++ b/packages/sdk/src/server/auth/errors.ts @@ -0,0 +1,54 @@ +// v1 compat: `@modelcontextprotocol/sdk/server/auth/errors.js` +// v2 consolidated 17 OAuth error subclasses into OAuthError + OAuthErrorCode. +// These deprecated subclasses preserve `instanceof` and `throw new InvalidTokenError(msg)` patterns. + +import { OAuthError, OAuthErrorCode } from '@modelcontextprotocol/server'; + +/** @deprecated Construct-signature type for the v1 OAuth error subclasses below. */ +export type OAuthErrorSubclass = new (message: string, errorUri?: string) => OAuthError; + +function sub(code: OAuthErrorCode): OAuthErrorSubclass { + return class extends OAuthError { + constructor(message: string, errorUri?: string) { + super(code, message, errorUri); + } + }; +} + +/** @deprecated Use `new OAuthError(OAuthErrorCode.InvalidRequest, ...)` */ +export const InvalidRequestError = sub(OAuthErrorCode.InvalidRequest); +/** @deprecated Use `new OAuthError(OAuthErrorCode.InvalidClient, ...)` */ +export const InvalidClientError = sub(OAuthErrorCode.InvalidClient); +/** @deprecated Use `new OAuthError(OAuthErrorCode.InvalidGrant, ...)` */ +export const InvalidGrantError = sub(OAuthErrorCode.InvalidGrant); +/** @deprecated Use `new OAuthError(OAuthErrorCode.UnauthorizedClient, ...)` */ +export const UnauthorizedClientError = sub(OAuthErrorCode.UnauthorizedClient); +/** @deprecated Use `new OAuthError(OAuthErrorCode.UnsupportedGrantType, ...)` */ +export const UnsupportedGrantTypeError = sub(OAuthErrorCode.UnsupportedGrantType); +/** @deprecated Use `new OAuthError(OAuthErrorCode.InvalidScope, ...)` */ +export const InvalidScopeError = sub(OAuthErrorCode.InvalidScope); +/** @deprecated Use `new OAuthError(OAuthErrorCode.AccessDenied, ...)` */ +export const AccessDeniedError = sub(OAuthErrorCode.AccessDenied); +/** @deprecated Use `new OAuthError(OAuthErrorCode.ServerError, ...)` */ +export const ServerError = sub(OAuthErrorCode.ServerError); +/** @deprecated Use `new OAuthError(OAuthErrorCode.TemporarilyUnavailable, ...)` */ +export const TemporarilyUnavailableError = sub(OAuthErrorCode.TemporarilyUnavailable); +/** @deprecated Use `new OAuthError(OAuthErrorCode.UnsupportedResponseType, ...)` */ +export const UnsupportedResponseTypeError = sub(OAuthErrorCode.UnsupportedResponseType); +/** @deprecated Use `new OAuthError(OAuthErrorCode.UnsupportedTokenType, ...)` */ +export const UnsupportedTokenTypeError = sub(OAuthErrorCode.UnsupportedTokenType); +/** @deprecated Use `new OAuthError(OAuthErrorCode.InvalidToken, ...)` */ +export const InvalidTokenError = sub(OAuthErrorCode.InvalidToken); +/** @deprecated Use `new OAuthError(OAuthErrorCode.MethodNotAllowed, ...)` */ +export const MethodNotAllowedError = sub(OAuthErrorCode.MethodNotAllowed); +/** @deprecated Use `new OAuthError(OAuthErrorCode.TooManyRequests, ...)` */ +export const TooManyRequestsError = sub(OAuthErrorCode.TooManyRequests); +/** @deprecated Use `new OAuthError(OAuthErrorCode.InvalidClientMetadata, ...)` */ +export const InvalidClientMetadataError = sub(OAuthErrorCode.InvalidClientMetadata); +/** @deprecated Use `new OAuthError(OAuthErrorCode.InsufficientScope, ...)` */ +export const InsufficientScopeError = sub(OAuthErrorCode.InsufficientScope); + +/** @deprecated Construct {@link OAuthError} directly. */ +export class CustomOAuthError extends OAuthError {} + +export { OAuthError, OAuthErrorCode } from '@modelcontextprotocol/server'; diff --git a/packages/sdk/src/server/auth/middleware/bearerAuth.ts b/packages/sdk/src/server/auth/middleware/bearerAuth.ts new file mode 100644 index 000000000..4db07b0b4 --- /dev/null +++ b/packages/sdk/src/server/auth/middleware/bearerAuth.ts @@ -0,0 +1,2 @@ +// v1 compat: `@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js` +export * from '@modelcontextprotocol/express'; diff --git a/packages/sdk/src/server/auth/provider.ts b/packages/sdk/src/server/auth/provider.ts new file mode 100644 index 000000000..c166221f3 --- /dev/null +++ b/packages/sdk/src/server/auth/provider.ts @@ -0,0 +1,2 @@ +// v1 compat: `@modelcontextprotocol/sdk/server/auth/provider.js` +export * from '@modelcontextprotocol/server-auth-legacy'; diff --git a/packages/sdk/src/server/auth/router.ts b/packages/sdk/src/server/auth/router.ts new file mode 100644 index 000000000..12fa9dc7b --- /dev/null +++ b/packages/sdk/src/server/auth/router.ts @@ -0,0 +1,2 @@ +// v1 compat: `@modelcontextprotocol/sdk/server/auth/router.js` +export * from '@modelcontextprotocol/server-auth-legacy'; diff --git a/packages/sdk/src/server/auth/types.ts b/packages/sdk/src/server/auth/types.ts new file mode 100644 index 000000000..11ed919d2 --- /dev/null +++ b/packages/sdk/src/server/auth/types.ts @@ -0,0 +1 @@ +export type { AuthInfo } from '@modelcontextprotocol/server'; diff --git a/packages/sdk/src/server/completable.ts b/packages/sdk/src/server/completable.ts new file mode 100644 index 000000000..84eee372f --- /dev/null +++ b/packages/sdk/src/server/completable.ts @@ -0,0 +1 @@ +export { completable, type CompletableSchema, type CompleteCallback, isCompletable } from '@modelcontextprotocol/server'; diff --git a/packages/sdk/src/server/index.ts b/packages/sdk/src/server/index.ts new file mode 100644 index 000000000..6ecbcce01 --- /dev/null +++ b/packages/sdk/src/server/index.ts @@ -0,0 +1 @@ +export * from '@modelcontextprotocol/server'; diff --git a/packages/sdk/src/server/mcp.ts b/packages/sdk/src/server/mcp.ts new file mode 100644 index 000000000..56a5c924d --- /dev/null +++ b/packages/sdk/src/server/mcp.ts @@ -0,0 +1,21 @@ +export { + type AnyToolHandler, + type BaseToolCallback, + completable, + type CompletableSchema, + type CompleteCallback, + type CompleteResourceTemplateCallback, + isCompletable, + type ListResourcesCallback, + McpServer, + type PromptCallback, + type ReadResourceCallback, + type ReadResourceTemplateCallback, + type RegisteredPrompt, + type RegisteredResource, + type RegisteredResourceTemplate, + type RegisteredTool, + type ResourceMetadata, + ResourceTemplate, + type ToolCallback +} from '@modelcontextprotocol/server'; diff --git a/packages/sdk/src/server/sse.ts b/packages/sdk/src/server/sse.ts new file mode 100644 index 000000000..d3eddfbc3 --- /dev/null +++ b/packages/sdk/src/server/sse.ts @@ -0,0 +1 @@ +export { SSEServerTransport } from '@modelcontextprotocol/node/sse'; diff --git a/packages/sdk/src/server/stdio.ts b/packages/sdk/src/server/stdio.ts new file mode 100644 index 000000000..b45cc492d --- /dev/null +++ b/packages/sdk/src/server/stdio.ts @@ -0,0 +1 @@ +export { StdioServerTransport } from '@modelcontextprotocol/server/stdio'; diff --git a/packages/sdk/src/server/streamableHttp.ts b/packages/sdk/src/server/streamableHttp.ts new file mode 100644 index 000000000..4cfda1b20 --- /dev/null +++ b/packages/sdk/src/server/streamableHttp.ts @@ -0,0 +1,4 @@ +// v1 compat: `@modelcontextprotocol/sdk/server/streamableHttp.js` +export * from '@modelcontextprotocol/node'; +/** @deprecated Renamed to {@link NodeStreamableHTTPServerTransport} and moved to `@modelcontextprotocol/node` in v2. */ +export { NodeStreamableHTTPServerTransport as StreamableHTTPServerTransport } from '@modelcontextprotocol/node'; diff --git a/packages/sdk/src/server/webStandardStreamableHttp.ts b/packages/sdk/src/server/webStandardStreamableHttp.ts new file mode 100644 index 000000000..75870a36b --- /dev/null +++ b/packages/sdk/src/server/webStandardStreamableHttp.ts @@ -0,0 +1,4 @@ +export { + WebStandardStreamableHTTPServerTransport, + type WebStandardStreamableHTTPServerTransportOptions +} from '@modelcontextprotocol/server'; diff --git a/packages/sdk/src/shared/auth.ts b/packages/sdk/src/shared/auth.ts new file mode 100644 index 000000000..3c8b49505 --- /dev/null +++ b/packages/sdk/src/shared/auth.ts @@ -0,0 +1,33 @@ +// v1 compat: `@modelcontextprotocol/sdk/shared/auth.js` +export type { + AuthorizationServerMetadata, + OAuthClientInformation, + OAuthClientInformationFull, + OAuthClientInformationMixed, + OAuthClientMetadata, + OAuthClientRegistrationError, + OAuthErrorResponse, + OAuthMetadata, + OAuthProtectedResourceMetadata, + OAuthTokenRevocationRequest, + OAuthTokens, + OpenIdProviderDiscoveryMetadata, + OpenIdProviderMetadata +} from '@modelcontextprotocol/server'; +export { OAuthError, OAuthErrorCode } from '@modelcontextprotocol/server'; +export { + IdJagTokenExchangeResponseSchema, + OAuthClientInformationFullSchema, + OAuthClientInformationSchema, + OAuthClientMetadataSchema, + OAuthClientRegistrationErrorSchema, + OAuthErrorResponseSchema, + OAuthMetadataSchema, + OAuthProtectedResourceMetadataSchema, + OAuthTokenRevocationRequestSchema, + OAuthTokensSchema, + OpenIdProviderDiscoveryMetadataSchema, + OpenIdProviderMetadataSchema, + OptionalSafeUrlSchema, + SafeUrlSchema +} from '@modelcontextprotocol/server/zod-schemas'; diff --git a/packages/sdk/src/shared/protocol.ts b/packages/sdk/src/shared/protocol.ts new file mode 100644 index 000000000..8a428d5e5 --- /dev/null +++ b/packages/sdk/src/shared/protocol.ts @@ -0,0 +1,17 @@ +// v1 compat: `@modelcontextprotocol/sdk/shared/protocol.js` +// Protocol class is no longer public in v2; subclass Client or Server instead. +// Re-exporting the option types and context types that v1 callers commonly +// imported from this path. + +export type { + BaseContext, + ClientContext, + NotificationOptions, + ProtocolOptions, + RequestOptions, + ServerContext +} from '@modelcontextprotocol/server'; + +/** @deprecated Use {@link ServerContext} (server handlers) or {@link ClientContext} (client handlers) in v2. */ +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export type RequestHandlerExtra<_ReqT = unknown, _NotifT = unknown> = import('@modelcontextprotocol/server').ServerContext; diff --git a/packages/sdk/src/shared/stdio.ts b/packages/sdk/src/shared/stdio.ts new file mode 100644 index 000000000..87ff5ce32 --- /dev/null +++ b/packages/sdk/src/shared/stdio.ts @@ -0,0 +1 @@ +export { deserializeMessage, ReadBuffer, serializeMessage } from '@modelcontextprotocol/server'; diff --git a/packages/sdk/src/shared/transport.ts b/packages/sdk/src/shared/transport.ts new file mode 100644 index 000000000..2cee788b9 --- /dev/null +++ b/packages/sdk/src/shared/transport.ts @@ -0,0 +1,2 @@ +export type { FetchLike, Transport, TransportSendOptions } from '@modelcontextprotocol/server'; +export { createFetchWithInit } from '@modelcontextprotocol/server'; diff --git a/packages/sdk/src/stdio.ts b/packages/sdk/src/stdio.ts new file mode 100644 index 000000000..c5ba37441 --- /dev/null +++ b/packages/sdk/src/stdio.ts @@ -0,0 +1,3 @@ +export type { StdioServerParameters } from '@modelcontextprotocol/client/stdio'; +export { DEFAULT_INHERITED_ENV_VARS, getDefaultEnvironment, StdioClientTransport } from '@modelcontextprotocol/client/stdio'; +export { StdioServerTransport } from '@modelcontextprotocol/server/stdio'; diff --git a/packages/sdk/src/types.ts b/packages/sdk/src/types.ts new file mode 100644 index 000000000..42a0f2c78 --- /dev/null +++ b/packages/sdk/src/types.ts @@ -0,0 +1,20 @@ +// v1 compat: `@modelcontextprotocol/sdk/types.js` +// In v1 this was the giant types.ts file with all spec types + Zod schemas. +// v2 dropped the Zod schema constants from the public surface; spec TypeScript +// types are re-exported here from the server package. + +export * from '@modelcontextprotocol/server'; +// v1's types.js also exported the Zod *Schema constants used with +// setRequestHandler/setNotificationHandler. v2 moved those to a separate +// subpath; re-export them here for v1-compat. +export * from '@modelcontextprotocol/server/zod-schemas'; +/** + * @deprecated Use {@link ResourceTemplateType}. + * + * v1's `types.js` exported the spec-derived ResourceTemplate data type under + * this name. v2 renamed it to `ResourceTemplateType` to avoid clashing with the + * `ResourceTemplate` helper class exported by `@modelcontextprotocol/server`. + * This alias lives only in the meta-package compat subpath; exporting it from + * core/public causes tsdown to mark server's class as type-only in bundled .d.mts. + */ +export type { ResourceTemplateType as ResourceTemplate } from '@modelcontextprotocol/server'; diff --git a/packages/sdk/src/validation/ajv-provider.ts b/packages/sdk/src/validation/ajv-provider.ts new file mode 100644 index 000000000..8f6e0f51e --- /dev/null +++ b/packages/sdk/src/validation/ajv-provider.ts @@ -0,0 +1 @@ +export { AjvJsonSchemaValidator } from '@modelcontextprotocol/server'; diff --git a/packages/sdk/src/validation/cfworker-provider.ts b/packages/sdk/src/validation/cfworker-provider.ts new file mode 100644 index 000000000..08b23bf34 --- /dev/null +++ b/packages/sdk/src/validation/cfworker-provider.ts @@ -0,0 +1 @@ +export { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/server/validators/cf-worker'; diff --git a/packages/sdk/src/validation/types.ts b/packages/sdk/src/validation/types.ts new file mode 100644 index 000000000..a696f02bd --- /dev/null +++ b/packages/sdk/src/validation/types.ts @@ -0,0 +1,2 @@ +export type { JsonSchemaType, JsonSchemaValidator, jsonSchemaValidator, JsonSchemaValidatorResult } from '@modelcontextprotocol/server'; +export { AjvJsonSchemaValidator, fromJsonSchema } from '@modelcontextprotocol/server'; diff --git a/packages/sdk/test/compat.test.ts b/packages/sdk/test/compat.test.ts new file mode 100644 index 000000000..f6b290cb5 --- /dev/null +++ b/packages/sdk/test/compat.test.ts @@ -0,0 +1,93 @@ +import { afterEach, beforeEach, describe, expect, it, vi, type MockInstance } from 'vitest'; +import { z } from 'zod'; + +// Exercise the v1 deep-import subpaths. +import { McpError, ErrorCode, type CallToolRequest } from '../src/types.js'; +import { Server } from '../src/server/index.js'; +import { Client } from '../src/client/index.js'; +import { McpServer } from '../src/server/mcp.js'; +import { InvalidTokenError } from '../src/server/auth/errors.js'; +import { StreamableHTTPServerTransport } from '../src/server/streamableHttp.js'; +import type { Transport } from '../src/shared/transport.js'; +import type { RequestHandlerExtra } from '../src/shared/protocol.js'; +import { OAuthError, OAuthErrorCode, ProtocolError } from '../src/index.js'; + +describe('@modelcontextprotocol/sdk meta-package', () => { + let warnSpy: MockInstance; + + beforeEach(() => { + warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); + }); + + afterEach(() => { + warnSpy.mockRestore(); + }); + + it('re-exports v1 deep-import subpaths', () => { + // ./types.js — McpError/ErrorCode aliases + const err = new McpError(ErrorCode.InvalidParams, 'x'); + expect(err).toBeInstanceOf(ProtocolError); + + // ./server/mcp.js + expect(typeof McpServer).toBe('function'); + + // ./server/auth/errors.js — OAuth subclasses + const tokenErr = new InvalidTokenError('bad'); + expect(tokenErr).toBeInstanceOf(OAuthError); + expect(tokenErr.code).toBe(OAuthErrorCode.InvalidToken); + + // ./server/streamableHttp.js — alias to NodeStreamableHTTPServerTransport + expect(typeof StreamableHTTPServerTransport).toBe('function'); + + // ./shared/transport.js + ./shared/protocol.js — type-only re-exports compile + const _t: Transport | undefined = undefined; + const _ctx: RequestHandlerExtra | undefined = undefined; + const _req: CallToolRequest | undefined = undefined; + void _t; + void _ctx; + void _req; + }); + + describe('Server.setRequestHandler (Zod-schema form)', () => { + it('accepts a Zod request schema and registers by extracted method (first-class, no warning)', () => { + const server = new Server({ name: 't', version: '1' }, { capabilities: { tools: {} } }); + const ListToolsRequestSchema = z.object({ method: z.literal('tools/list') }); + + server.setRequestHandler(ListToolsRequestSchema, () => ({ tools: [] })); + + expect(warnSpy).not.toHaveBeenCalled(); + expect(() => server.assertCanSetRequestHandler('tools/list')).toThrow(); + }); + + it('accepts the v2 string-method form without warning', () => { + const server = new Server({ name: 't', version: '1' }, { capabilities: { tools: {} } }); + server.setRequestHandler('tools/list', () => ({ tools: [] })); + expect(warnSpy).not.toHaveBeenCalled(); + }); + }); + + describe('McpServer.server reaches the schema-arg overload', () => { + it('accepts a Zod request schema on .server.setRequestHandler (no warning)', () => { + const mcp = new McpServer({ name: 't', version: '1' }, { capabilities: { resources: {} } }); + const ListResourcesRequestSchema = z.object({ method: z.literal('resources/list') }); + + mcp.server.setRequestHandler(ListResourcesRequestSchema, () => ({ resources: [] })); + + expect(warnSpy).not.toHaveBeenCalled(); + expect(() => mcp.server.assertCanSetRequestHandler('resources/list')).toThrow(); + expect(mcp.server).toBeInstanceOf(Server); + }); + }); + + describe('Client.request (result-schema form)', () => { + it('accepts (req, ResultSchema, opts) call shape (first-class, no warning)', async () => { + const client = new Client({ name: 't', version: '1' }); + const ResultSchema = z.object({}); + + // Not connected — rejects, but the call shape is accepted at the type/dispatch level. + await expect(client.request({ method: 'ping' }, ResultSchema, { timeout: 10 })).rejects.toThrow(); + + expect(warnSpy).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/sdk/tsconfig.build.json b/packages/sdk/tsconfig.build.json new file mode 100644 index 000000000..ad0d8e637 --- /dev/null +++ b/packages/sdk/tsconfig.build.json @@ -0,0 +1,14 @@ +{ + "extends": "@modelcontextprotocol/tsconfig", + "compilerOptions": { + "noEmit": false, + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "dist", + "rootDir": "src", + "incremental": false, + "paths": {} + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/sdk/tsconfig.json b/packages/sdk/tsconfig.json new file mode 100644 index 000000000..392629e46 --- /dev/null +++ b/packages/sdk/tsconfig.json @@ -0,0 +1,25 @@ +{ + "extends": "@modelcontextprotocol/tsconfig", + "include": ["./"], + "exclude": ["node_modules", "dist"], + "compilerOptions": { + "paths": { + "*": ["./*"], + "@modelcontextprotocol/core": ["./node_modules/@modelcontextprotocol/core/src/index.ts"], + "@modelcontextprotocol/core/public": ["./node_modules/@modelcontextprotocol/core/src/exports/public/index.ts"], + "@modelcontextprotocol/client": ["./node_modules/@modelcontextprotocol/client/src/index.ts"], + "@modelcontextprotocol/client/stdio": ["./node_modules/@modelcontextprotocol/client/src/client/stdio.ts"], + "@modelcontextprotocol/server": ["./node_modules/@modelcontextprotocol/server/src/index.ts"], + "@modelcontextprotocol/server/stdio": ["./node_modules/@modelcontextprotocol/server/src/server/stdio.ts"], + "@modelcontextprotocol/server/zod-schemas": ["./node_modules/@modelcontextprotocol/server/src/zodSchemas.ts"], + "@modelcontextprotocol/server/validators/cf-worker": ["./node_modules/@modelcontextprotocol/server/src/validators/cfWorker.ts"], + "@modelcontextprotocol/node": ["./node_modules/@modelcontextprotocol/node/src/index.ts"], + "@modelcontextprotocol/node/sse": ["./node_modules/@modelcontextprotocol/node/src/sse.ts"], + "@modelcontextprotocol/express": ["./node_modules/@modelcontextprotocol/express/src/index.ts"], + "@modelcontextprotocol/server-auth-legacy": ["./node_modules/@modelcontextprotocol/server-auth-legacy/src/index.ts"], + "@modelcontextprotocol/client/_shims": ["./node_modules/@modelcontextprotocol/client/src/shimsNode.ts"], + "@modelcontextprotocol/server/_shims": ["./node_modules/@modelcontextprotocol/server/src/shimsNode.ts"], + "@modelcontextprotocol/test-helpers": ["./node_modules/@modelcontextprotocol/test-helpers/src/index.ts"] + } + } +} diff --git a/packages/sdk/tsdown.config.ts b/packages/sdk/tsdown.config.ts new file mode 100644 index 000000000..4f5d4e609 --- /dev/null +++ b/packages/sdk/tsdown.config.ts @@ -0,0 +1,45 @@ +import { defineConfig } from 'tsdown'; + +export default defineConfig({ + failOnWarn: false, + entry: [ + 'src/index.ts', + 'src/stdio.ts', + 'src/types.ts', + 'src/inMemory.ts', + 'src/experimental/tasks.ts', + 'src/server/index.ts', + 'src/server/mcp.ts', + 'src/server/completable.ts', + 'src/server/sse.ts', + 'src/server/stdio.ts', + 'src/server/streamableHttp.ts', + 'src/server/auth/types.ts', + 'src/server/auth/errors.ts', + 'src/server/auth/middleware/bearerAuth.ts', + 'src/server/auth/router.ts', + 'src/server/auth/provider.ts', + 'src/server/auth/clients.ts', + 'src/client/index.ts', + 'src/client/stdio.ts', + 'src/client/streamableHttp.ts', + 'src/client/sse.ts', + 'src/client/auth.ts', + 'src/shared/protocol.ts', + 'src/shared/transport.ts', + 'src/shared/auth.ts', + 'src/shared/stdio.ts', + 'src/server/webStandardStreamableHttp.ts', + 'src/validation/types.ts', + 'src/validation/cfworker-provider.ts', + 'src/validation/ajv-provider.ts' + ], + format: ['esm'], + outDir: 'dist', + clean: true, + sourcemap: true, + target: 'esnext', + platform: 'node', + dts: false, + external: [/^@modelcontextprotocol\//] +}); diff --git a/packages/sdk/vitest.config.js b/packages/sdk/vitest.config.js new file mode 100644 index 000000000..496fca320 --- /dev/null +++ b/packages/sdk/vitest.config.js @@ -0,0 +1,3 @@ +import baseConfig from '@modelcontextprotocol/vitest-config'; + +export default baseConfig; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d63c27f7f..7c29c8415 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -257,7 +257,7 @@ importers: version: 4.4.4(eslint-plugin-import@2.32.0)(eslint@9.39.4) eslint-plugin-import: specifier: ^2.32.0 - version: 2.32.0(eslint-import-resolver-typescript@4.4.4)(eslint@9.39.4) + version: 2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.39.4) eslint-plugin-n: specifier: catalog:devTools version: 17.24.0(eslint@9.39.4)(typescript@5.9.3) @@ -889,6 +889,61 @@ importers: specifier: catalog:devTools version: 4.1.2(@opentelemetry/api@1.9.1)(@types/node@25.5.0)(vite@7.3.0(@types/node@25.5.0)(tsx@4.21.0)(yaml@2.8.3)) + packages/sdk: + dependencies: + '@modelcontextprotocol/client': + specifier: workspace:^ + version: link:../client + '@modelcontextprotocol/express': + specifier: workspace:^ + version: link:../middleware/express + '@modelcontextprotocol/node': + specifier: workspace:^ + version: link:../middleware/node + '@modelcontextprotocol/server': + specifier: workspace:^ + version: link:../server + '@modelcontextprotocol/server-auth-legacy': + specifier: workspace:^ + version: link:../server-auth-legacy + devDependencies: + '@modelcontextprotocol/core': + specifier: workspace:^ + version: link:../core + '@modelcontextprotocol/eslint-config': + specifier: workspace:^ + version: link:../../common/eslint-config + '@modelcontextprotocol/test-helpers': + specifier: workspace:^ + version: link:../../test/helpers + '@modelcontextprotocol/tsconfig': + specifier: workspace:^ + version: link:../../common/tsconfig + '@modelcontextprotocol/vitest-config': + specifier: workspace:^ + version: link:../../common/vitest-config + '@typescript/native-preview': + specifier: catalog:devTools + version: 7.0.0-dev.20260327.2 + eslint: + specifier: catalog:devTools + version: 9.39.4 + prettier: + specifier: catalog:devTools + version: 3.6.2 + tsdown: + specifier: catalog:devTools + version: 0.18.4(@typescript/native-preview@7.0.0-dev.20260327.2)(typescript@5.9.3) + typescript: + specifier: catalog:devTools + version: 5.9.3 + vitest: + specifier: catalog:devTools + version: 4.1.2(@opentelemetry/api@1.9.1)(@types/node@25.5.0)(vite@7.3.0(@types/node@25.5.0)(tsx@4.21.0)(yaml@2.8.3)) + zod: + specifier: catalog:runtimeShared + version: 4.3.6 + packages/server: dependencies: zod: @@ -1115,9 +1170,15 @@ importers: '@modelcontextprotocol/node': specifier: workspace:^ version: link:../../packages/middleware/node + '@modelcontextprotocol/sdk': + specifier: workspace:^ + version: link:../../packages/sdk '@modelcontextprotocol/server': specifier: workspace:^ version: link:../../packages/server + '@modelcontextprotocol/server-auth-legacy': + specifier: workspace:^ + version: link:../../packages/server-auth-legacy '@modelcontextprotocol/test-helpers': specifier: workspace:^ version: link:../helpers @@ -7177,14 +7238,15 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(eslint-import-resolver-typescript@4.4.4)(eslint@9.39.4) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.39.4) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.39.4): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.39.4): dependencies: debug: 3.2.7 optionalDependencies: + '@typescript-eslint/parser': 8.57.2(eslint@9.39.4)(typescript@5.9.3) eslint: 9.39.4 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import@2.32.0)(eslint@9.39.4) @@ -7198,7 +7260,7 @@ snapshots: eslint: 9.39.4 eslint-compat-utils: 0.5.1(eslint@9.39.4) - eslint-plugin-import@2.32.0(eslint-import-resolver-typescript@4.4.4)(eslint@9.39.4): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.39.4): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -7209,7 +7271,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.39.4 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.39.4) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.39.4) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -7220,6 +7282,8 @@ snapshots: semver: 6.3.1 string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 8.57.2(eslint@9.39.4)(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack diff --git a/test/integration/package.json b/test/integration/package.json index 8618d0580..62757d1e5 100644 --- a/test/integration/package.json +++ b/test/integration/package.json @@ -40,7 +40,9 @@ "@modelcontextprotocol/eslint-config": "workspace:^", "@modelcontextprotocol/express": "workspace:^", "@modelcontextprotocol/node": "workspace:^", + "@modelcontextprotocol/sdk": "workspace:^", "@modelcontextprotocol/server": "workspace:^", + "@modelcontextprotocol/server-auth-legacy": "workspace:^", "@modelcontextprotocol/test-helpers": "workspace:^", "@modelcontextprotocol/tsconfig": "workspace:^", "@modelcontextprotocol/vitest-config": "workspace:^", diff --git a/test/integration/test/compat/v1Surface.test.ts b/test/integration/test/compat/v1Surface.test.ts new file mode 100644 index 000000000..e002621f2 --- /dev/null +++ b/test/integration/test/compat/v1Surface.test.ts @@ -0,0 +1,120 @@ +/* eslint-disable import/no-unresolved -- + This test's purpose is to import from `@modelcontextprotocol/sdk/...` v1 subpaths. + eslint can't resolve them until the sdk package is built; tsconfig `paths` covers TS. */ +/** + * v1 API surface compat test. + * + * Every import in this file uses a v1 deep-import path under + * `@modelcontextprotocol/sdk/...`. The fact that it typechecks and runs IS the + * primary assertion: a v1 consumer can bump `@modelcontextprotocol/sdk` to + * 2.x and keep their existing imports and call shapes. + * + * Covers (by BC track): + * - D1 meta-package subpath re-exports (every import below) + * - C2 McpServer.tool() variadic + * - C4 registerTool raw-shape inputSchema + * - C5 flat ctx.* getters + RequestHandlerExtra type alias + * - C7 McpError/ErrorCode/JSONRPCError/StreamableHTTPError aliases + * - C8 StreamableHTTPServerTransport alias (from /node) + * - C10 *RequestSchema constants in sdk/types.js + OAuth schemas in shared/auth.js + * - A1 setRequestHandler(ZodSchema, h) + callTool(params, ResultSchema) + */ +import { Client } from '@modelcontextprotocol/sdk/client/index.js'; +import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js'; +import { Server } from '@modelcontextprotocol/sdk/server/index.js'; +import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; +import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; +import { OAuthTokensSchema } from '@modelcontextprotocol/sdk/shared/auth.js'; +import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js'; +import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'; +import type { CallToolResult, JSONRPCError } from '@modelcontextprotocol/sdk/types.js'; +import { + CallToolRequestSchema, + CallToolResultSchema, + ErrorCode, + LATEST_PROTOCOL_VERSION, + ListToolsRequestSchema, + McpError, + StreamableHTTPError +} from '@modelcontextprotocol/sdk/types.js'; +import { describe, expect, it, vi } from 'vitest'; +import { z } from 'zod'; + +void StdioServerTransport; // type-level: import resolves +const _t: Transport | undefined = undefined; +void _t; + +describe('v1 API surface (bump-only compat)', () => { + it('McpServer.tool() variadic + raw-shape + InMemory roundtrip + callTool(_, ResultSchema)', async () => { + const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}); + const server = new McpServer({ name: 't', version: '1.0.0' }); + // C2 variadic + C4 raw-shape (object of ZodTypes, not z.object) + server.tool('echo', { msg: z.string() }, async ({ msg }) => ({ + content: [{ type: 'text', text: msg }] + })); + + const [clientT, serverT] = InMemoryTransport.createLinkedPair(); + const client = new Client({ name: 'c', version: '1.0.0' }); + await Promise.all([server.connect(serverT), client.connect(clientT)]); + + // A1: callTool(params, ResultSchema) overload (first-class, no warning) + const result = (await client.callTool({ name: 'echo', arguments: { msg: 'hi' } }, CallToolResultSchema)) as CallToolResult; + expect(result.content[0]).toEqual({ type: 'text', text: 'hi' }); + warn.mockRestore(); + await Promise.all([client.close(), server.close()]); + }); + + it('low-level Server.setRequestHandler(ZodSchema, h) + flat ctx.* getters', async () => { + const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}); + const server = new Server({ name: 't', version: '1.0.0' }, { capabilities: { tools: {} } }); + let sawExtra: RequestHandlerExtra | undefined; + // A1: deprecated schema-arg form + server.setRequestHandler(ListToolsRequestSchema, async (_req, extra) => { + sawExtra = extra; + // C5: flat getters + expect(extra.signal).toBeInstanceOf(AbortSignal); + expect(typeof extra.requestId === 'number' || typeof extra.requestId === 'string').toBe(true); + expect(typeof extra.sendNotification).toBe('function'); + expect(typeof extra.sendRequest).toBe('function'); + return { tools: [] }; + }); + server.setRequestHandler(CallToolRequestSchema, async () => ({ content: [] })); + + const [clientT, serverT] = InMemoryTransport.createLinkedPair(); + const client = new Client({ name: 'c', version: '1.0.0' }); + await Promise.all([server.connect(serverT), client.connect(clientT)]); + const tools = await client.listTools(); + expect(tools.tools).toEqual([]); + expect(sawExtra).toBeDefined(); + warn.mockRestore(); + await Promise.all([client.close(), server.close()]); + }); + + it('McpError/ErrorCode/JSONRPCError/StreamableHTTPError aliases', () => { + const e = new McpError(ErrorCode.InvalidParams, 'x'); + expect(e.code).toBe(ErrorCode.InvalidParams); + // C7: ConnectionClosed/RequestTimeout shimmed onto ErrorCode + expect(ErrorCode.ConnectionClosed).toBeDefined(); + expect(ErrorCode.RequestTimeout).toBeDefined(); + const httpErr = new StreamableHTTPError(404, 'nf'); + expect(httpErr).toBeInstanceOf(Error); + // JSONRPCError is a type alias — assignable to the v2 shape + const _je: JSONRPCError = { jsonrpc: '2.0', id: 1, error: { code: -32_600, message: 'x' } }; + void _je; + }); + + it('OAuth Zod schemas available for runtime parse (shared/auth.js)', () => { + const parsed = OAuthTokensSchema.safeParse({ access_token: 'x', token_type: 'Bearer' }); + expect(parsed.success).toBe(true); + }); + + it('extensionless subpath imports resolve (claude-ai pattern)', async () => { + const types = await import('@modelcontextprotocol/sdk/types'); + expect(types.LATEST_PROTOCOL_VERSION).toBe(LATEST_PROTOCOL_VERSION); + }); + + it('StreamableHTTPServerTransport alias available from /node-style import', async () => { + const node = await import('@modelcontextprotocol/sdk/server/streamableHttp.js'); + expect(node.StreamableHTTPServerTransport).toBeDefined(); + }); +}); diff --git a/test/integration/tsconfig.json b/test/integration/tsconfig.json index 210bb0111..347032187 100644 --- a/test/integration/tsconfig.json +++ b/test/integration/tsconfig.json @@ -13,6 +13,13 @@ "@modelcontextprotocol/server": ["./node_modules/@modelcontextprotocol/server/src/index.ts"], "@modelcontextprotocol/server/stdio": ["./node_modules/@modelcontextprotocol/server/src/stdio.ts"], "@modelcontextprotocol/server/_shims": ["./node_modules/@modelcontextprotocol/server/src/shimsNode.ts"], + "@modelcontextprotocol/server/zod-schemas": ["./node_modules/@modelcontextprotocol/server/src/zodSchemas.ts"], + "@modelcontextprotocol/server/validators/cf-worker": ["./node_modules/@modelcontextprotocol/server/src/validators/cfWorker.ts"], + "@modelcontextprotocol/server-auth-legacy": ["./node_modules/@modelcontextprotocol/server-auth-legacy/src/index.ts"], + "@modelcontextprotocol/node/sse": ["./node_modules/@modelcontextprotocol/node/src/sse.ts"], + "@modelcontextprotocol/sdk": ["./node_modules/@modelcontextprotocol/sdk/src/index.ts"], + "@modelcontextprotocol/sdk/*.js": ["./node_modules/@modelcontextprotocol/sdk/src/*.ts"], + "@modelcontextprotocol/sdk/*": ["./node_modules/@modelcontextprotocol/sdk/src/*.ts"], "@modelcontextprotocol/express": ["./node_modules/@modelcontextprotocol/express/src/index.ts"], "@modelcontextprotocol/node": ["./node_modules/@modelcontextprotocol/node/src/index.ts"], "@modelcontextprotocol/vitest-config": ["./node_modules/@modelcontextprotocol/vitest-config/tsconfig.json"], diff --git a/typedoc.config.mjs b/typedoc.config.mjs index f2a4e50f5..a3709f24b 100644 --- a/typedoc.config.mjs +++ b/typedoc.config.mjs @@ -14,7 +14,12 @@ const packages = packageJsonPaths.map(p => { return { rootDir, manifest }; }); -const publicPackages = packages.filter(p => p.manifest.private !== true); +// `sdk` is a pure re-export meta-package; its docs are the underlying packages'. +// Re-exported symbols' inherited `{@link}` JSDoc resolves in the source package's +// module structure, not the re-exporting package's, so including it here yields +// spurious link warnings without adding any documentation value. +const TYPEDOC_EXCLUDED = new Set(['@modelcontextprotocol/sdk']); +const publicPackages = packages.filter(p => p.manifest.private !== true && !TYPEDOC_EXCLUDED.has(p.manifest.name)); const entryPoints = publicPackages.map(p => p.rootDir); console.log( From 0342b8a5bae16057c2256542e44c81e9ed3d39a3 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Thu, 16 Apr 2026 23:36:56 +0000 Subject: [PATCH 2/7] fix(sdk): unify server/auth/* on server-auth-legacy; drop stdio from root; optional express/hono peers - All five server/auth/* subpaths now re-export from @modelcontextprotocol/server-auth-legacy so OAuth error subclasses share the same OAuthError identity that the legacy router and requireBearerAuth check with instanceof. Previously errors.ts defined local subclasses extending core's OAuthError and bearerAuth.ts re-exported /express, causing instanceof to fail (HTTP 500 instead of 400/401). - Drop @modelcontextprotocol/express dependency (no longer imported). - Forward express and hono as optional peerDependencies so consumers who do not use the auth or hono-adapter subpaths get no unmet-peer warnings. - Add top-level types field for legacy moduleResolution: node. - Revert 87d4f17c's stdio re-exports from the root barrel; stdio remains subpath-only to match the underlying client/server packages. --- packages/sdk/package.json | 14 ++++- packages/sdk/src/index.ts | 2 - packages/sdk/src/server/auth/errors.ts | 58 ++----------------- .../src/server/auth/middleware/bearerAuth.ts | 5 +- packages/sdk/test/compat.test.ts | 10 ++-- packages/sdk/tsconfig.json | 1 - pnpm-lock.yaml | 9 ++- 7 files changed, 33 insertions(+), 66 deletions(-) diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 9a796e2b8..934ecba60 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -264,6 +264,7 @@ "import": "./dist/validation/ajv-provider.mjs" } }, + "types": "./dist/index.d.ts", "files": [ "dist" ], @@ -279,11 +280,22 @@ }, "dependencies": { "@modelcontextprotocol/client": "workspace:^", - "@modelcontextprotocol/express": "workspace:^", "@modelcontextprotocol/node": "workspace:^", "@modelcontextprotocol/server": "workspace:^", "@modelcontextprotocol/server-auth-legacy": "workspace:^" }, + "peerDependencies": { + "express": "^4.18.0 || ^5.0.0", + "hono": "*" + }, + "peerDependenciesMeta": { + "express": { + "optional": true + }, + "hono": { + "optional": true + } + }, "devDependencies": { "@modelcontextprotocol/core": "workspace:^", "@modelcontextprotocol/eslint-config": "workspace:^", diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 5607b931f..71126956f 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -88,5 +88,3 @@ export { withLogging, withOAuth } from '@modelcontextprotocol/client'; -export type { StdioServerParameters } from '@modelcontextprotocol/client/stdio'; -export { DEFAULT_INHERITED_ENV_VARS, getDefaultEnvironment, StdioClientTransport } from '@modelcontextprotocol/client/stdio'; diff --git a/packages/sdk/src/server/auth/errors.ts b/packages/sdk/src/server/auth/errors.ts index 9206ff573..5ca4eea12 100644 --- a/packages/sdk/src/server/auth/errors.ts +++ b/packages/sdk/src/server/auth/errors.ts @@ -1,54 +1,6 @@ // v1 compat: `@modelcontextprotocol/sdk/server/auth/errors.js` -// v2 consolidated 17 OAuth error subclasses into OAuthError + OAuthErrorCode. -// These deprecated subclasses preserve `instanceof` and `throw new InvalidTokenError(msg)` patterns. - -import { OAuthError, OAuthErrorCode } from '@modelcontextprotocol/server'; - -/** @deprecated Construct-signature type for the v1 OAuth error subclasses below. */ -export type OAuthErrorSubclass = new (message: string, errorUri?: string) => OAuthError; - -function sub(code: OAuthErrorCode): OAuthErrorSubclass { - return class extends OAuthError { - constructor(message: string, errorUri?: string) { - super(code, message, errorUri); - } - }; -} - -/** @deprecated Use `new OAuthError(OAuthErrorCode.InvalidRequest, ...)` */ -export const InvalidRequestError = sub(OAuthErrorCode.InvalidRequest); -/** @deprecated Use `new OAuthError(OAuthErrorCode.InvalidClient, ...)` */ -export const InvalidClientError = sub(OAuthErrorCode.InvalidClient); -/** @deprecated Use `new OAuthError(OAuthErrorCode.InvalidGrant, ...)` */ -export const InvalidGrantError = sub(OAuthErrorCode.InvalidGrant); -/** @deprecated Use `new OAuthError(OAuthErrorCode.UnauthorizedClient, ...)` */ -export const UnauthorizedClientError = sub(OAuthErrorCode.UnauthorizedClient); -/** @deprecated Use `new OAuthError(OAuthErrorCode.UnsupportedGrantType, ...)` */ -export const UnsupportedGrantTypeError = sub(OAuthErrorCode.UnsupportedGrantType); -/** @deprecated Use `new OAuthError(OAuthErrorCode.InvalidScope, ...)` */ -export const InvalidScopeError = sub(OAuthErrorCode.InvalidScope); -/** @deprecated Use `new OAuthError(OAuthErrorCode.AccessDenied, ...)` */ -export const AccessDeniedError = sub(OAuthErrorCode.AccessDenied); -/** @deprecated Use `new OAuthError(OAuthErrorCode.ServerError, ...)` */ -export const ServerError = sub(OAuthErrorCode.ServerError); -/** @deprecated Use `new OAuthError(OAuthErrorCode.TemporarilyUnavailable, ...)` */ -export const TemporarilyUnavailableError = sub(OAuthErrorCode.TemporarilyUnavailable); -/** @deprecated Use `new OAuthError(OAuthErrorCode.UnsupportedResponseType, ...)` */ -export const UnsupportedResponseTypeError = sub(OAuthErrorCode.UnsupportedResponseType); -/** @deprecated Use `new OAuthError(OAuthErrorCode.UnsupportedTokenType, ...)` */ -export const UnsupportedTokenTypeError = sub(OAuthErrorCode.UnsupportedTokenType); -/** @deprecated Use `new OAuthError(OAuthErrorCode.InvalidToken, ...)` */ -export const InvalidTokenError = sub(OAuthErrorCode.InvalidToken); -/** @deprecated Use `new OAuthError(OAuthErrorCode.MethodNotAllowed, ...)` */ -export const MethodNotAllowedError = sub(OAuthErrorCode.MethodNotAllowed); -/** @deprecated Use `new OAuthError(OAuthErrorCode.TooManyRequests, ...)` */ -export const TooManyRequestsError = sub(OAuthErrorCode.TooManyRequests); -/** @deprecated Use `new OAuthError(OAuthErrorCode.InvalidClientMetadata, ...)` */ -export const InvalidClientMetadataError = sub(OAuthErrorCode.InvalidClientMetadata); -/** @deprecated Use `new OAuthError(OAuthErrorCode.InsufficientScope, ...)` */ -export const InsufficientScopeError = sub(OAuthErrorCode.InsufficientScope); - -/** @deprecated Construct {@link OAuthError} directly. */ -export class CustomOAuthError extends OAuthError {} - -export { OAuthError, OAuthErrorCode } from '@modelcontextprotocol/server'; +// Re-exports the frozen v1 OAuth error classes from the legacy package so that +// errors thrown from this subpath share the same `OAuthError` identity that +// `mcpAuthRouter`/`requireBearerAuth` (re-exported by sibling subpaths) check +// with `instanceof`. +export * from '@modelcontextprotocol/server-auth-legacy'; diff --git a/packages/sdk/src/server/auth/middleware/bearerAuth.ts b/packages/sdk/src/server/auth/middleware/bearerAuth.ts index 4db07b0b4..104581785 100644 --- a/packages/sdk/src/server/auth/middleware/bearerAuth.ts +++ b/packages/sdk/src/server/auth/middleware/bearerAuth.ts @@ -1,2 +1,5 @@ // v1 compat: `@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js` -export * from '@modelcontextprotocol/express'; +// Re-exports from server-auth-legacy (not @modelcontextprotocol/express) so that +// `requireBearerAuth`'s `instanceof OAuthError` check matches the error classes +// re-exported by the sibling `server/auth/*` subpaths. +export * from '@modelcontextprotocol/server-auth-legacy'; diff --git a/packages/sdk/test/compat.test.ts b/packages/sdk/test/compat.test.ts index f6b290cb5..b15098468 100644 --- a/packages/sdk/test/compat.test.ts +++ b/packages/sdk/test/compat.test.ts @@ -6,11 +6,11 @@ import { McpError, ErrorCode, type CallToolRequest } from '../src/types.js'; import { Server } from '../src/server/index.js'; import { Client } from '../src/client/index.js'; import { McpServer } from '../src/server/mcp.js'; -import { InvalidTokenError } from '../src/server/auth/errors.js'; +import { InvalidTokenError, OAuthError as LegacyOAuthError } from '../src/server/auth/errors.js'; import { StreamableHTTPServerTransport } from '../src/server/streamableHttp.js'; import type { Transport } from '../src/shared/transport.js'; import type { RequestHandlerExtra } from '../src/shared/protocol.js'; -import { OAuthError, OAuthErrorCode, ProtocolError } from '../src/index.js'; +import { ProtocolError } from '../src/index.js'; describe('@modelcontextprotocol/sdk meta-package', () => { let warnSpy: MockInstance; @@ -31,10 +31,10 @@ describe('@modelcontextprotocol/sdk meta-package', () => { // ./server/mcp.js expect(typeof McpServer).toBe('function'); - // ./server/auth/errors.js — OAuth subclasses + // ./server/auth/errors.js — v1 OAuth subclasses (legacy hierarchy, shared with sibling auth subpaths) const tokenErr = new InvalidTokenError('bad'); - expect(tokenErr).toBeInstanceOf(OAuthError); - expect(tokenErr.code).toBe(OAuthErrorCode.InvalidToken); + expect(tokenErr).toBeInstanceOf(LegacyOAuthError); + expect(tokenErr.errorCode).toBe('invalid_token'); // ./server/streamableHttp.js — alias to NodeStreamableHTTPServerTransport expect(typeof StreamableHTTPServerTransport).toBe('function'); diff --git a/packages/sdk/tsconfig.json b/packages/sdk/tsconfig.json index 392629e46..5a30e6c18 100644 --- a/packages/sdk/tsconfig.json +++ b/packages/sdk/tsconfig.json @@ -15,7 +15,6 @@ "@modelcontextprotocol/server/validators/cf-worker": ["./node_modules/@modelcontextprotocol/server/src/validators/cfWorker.ts"], "@modelcontextprotocol/node": ["./node_modules/@modelcontextprotocol/node/src/index.ts"], "@modelcontextprotocol/node/sse": ["./node_modules/@modelcontextprotocol/node/src/sse.ts"], - "@modelcontextprotocol/express": ["./node_modules/@modelcontextprotocol/express/src/index.ts"], "@modelcontextprotocol/server-auth-legacy": ["./node_modules/@modelcontextprotocol/server-auth-legacy/src/index.ts"], "@modelcontextprotocol/client/_shims": ["./node_modules/@modelcontextprotocol/client/src/shimsNode.ts"], "@modelcontextprotocol/server/_shims": ["./node_modules/@modelcontextprotocol/server/src/shimsNode.ts"], diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7c29c8415..f89e9bef8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -894,9 +894,6 @@ importers: '@modelcontextprotocol/client': specifier: workspace:^ version: link:../client - '@modelcontextprotocol/express': - specifier: workspace:^ - version: link:../middleware/express '@modelcontextprotocol/node': specifier: workspace:^ version: link:../middleware/node @@ -906,6 +903,12 @@ importers: '@modelcontextprotocol/server-auth-legacy': specifier: workspace:^ version: link:../server-auth-legacy + express: + specifier: ^4.18.0 || ^5.0.0 + version: 5.2.1 + hono: + specifier: '*' + version: 4.12.9 devDependencies: '@modelcontextprotocol/core': specifier: workspace:^ From d82c17dc230858d39b2789fe05336f2ed2cf4135 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Fri, 17 Apr 2026 08:04:23 +0000 Subject: [PATCH 3/7] fix(sdk): add top-level types field for legacy moduleResolution --- packages/sdk/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 934ecba60..7fd4f72ae 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -7,6 +7,7 @@ "homepage": "https://modelcontextprotocol.io", "bugs": "https://github.com/modelcontextprotocol/typescript-sdk/issues", "type": "module", + "types": "./dist/index.d.ts", "repository": { "type": "git", "url": "git+https://github.com/modelcontextprotocol/typescript-sdk.git" From 6f8c2a1b8f334e888451aff62df4424008959354 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Fri, 17 Apr 2026 08:19:15 +0000 Subject: [PATCH 4/7] feat(sdk): re-export Protocol/ProtocolSpec from shared/protocol; add server/zod-compat subpath --- packages/sdk/package.json | 8 ++++++++ packages/sdk/src/server/zod-compat.ts | 16 ++++++++++++++++ packages/sdk/src/shared/protocol.ts | 5 ++--- packages/sdk/tsdown.config.ts | 1 + 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 packages/sdk/src/server/zod-compat.ts diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 7fd4f72ae..f2265bf5f 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -52,6 +52,14 @@ "types": "./dist/server/mcp.d.ts", "import": "./dist/server/mcp.mjs" }, + "./server/zod-compat.js": { + "types": "./dist/server/zod-compat.d.ts", + "import": "./dist/server/zod-compat.mjs" + }, + "./server/zod-compat": { + "types": "./dist/server/zod-compat.d.ts", + "import": "./dist/server/zod-compat.mjs" + }, "./server/stdio.js": { "types": "./dist/server/stdio.d.ts", "import": "./dist/server/stdio.mjs" diff --git a/packages/sdk/src/server/zod-compat.ts b/packages/sdk/src/server/zod-compat.ts new file mode 100644 index 000000000..5486bac0e --- /dev/null +++ b/packages/sdk/src/server/zod-compat.ts @@ -0,0 +1,16 @@ +// v1 compat: `@modelcontextprotocol/sdk/server/zod-compat.js` +// v1 unified Zod v3 + v4 types. v2 is Zod v4-only, so these collapse to the +// v4 types. Prefer `StandardSchemaV1` / `StandardSchemaWithJSON` for new code. + +import type * as z from 'zod'; + +/** @deprecated Use `StandardSchemaV1` (any Standard Schema) or a Zod type directly in v2. */ +export type AnySchema = z.core.$ZodType; + +/** @deprecated Use `Record` directly in v2. */ +export type ZodRawShapeCompat = Record; + +/** @deprecated */ +export type AnyObjectSchema = z.core.$ZodObject | AnySchema; + +export type { StandardSchemaV1, StandardSchemaWithJSON } from '@modelcontextprotocol/server'; diff --git a/packages/sdk/src/shared/protocol.ts b/packages/sdk/src/shared/protocol.ts index 8a428d5e5..2667a6389 100644 --- a/packages/sdk/src/shared/protocol.ts +++ b/packages/sdk/src/shared/protocol.ts @@ -1,16 +1,15 @@ // v1 compat: `@modelcontextprotocol/sdk/shared/protocol.js` -// Protocol class is no longer public in v2; subclass Client or Server instead. -// Re-exporting the option types and context types that v1 callers commonly -// imported from this path. export type { BaseContext, ClientContext, NotificationOptions, ProtocolOptions, + ProtocolSpec, RequestOptions, ServerContext } from '@modelcontextprotocol/server'; +export { DEFAULT_REQUEST_TIMEOUT_MSEC, Protocol } from '@modelcontextprotocol/server'; /** @deprecated Use {@link ServerContext} (server handlers) or {@link ClientContext} (client handlers) in v2. */ // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/packages/sdk/tsdown.config.ts b/packages/sdk/tsdown.config.ts index 4f5d4e609..8c6595654 100644 --- a/packages/sdk/tsdown.config.ts +++ b/packages/sdk/tsdown.config.ts @@ -10,6 +10,7 @@ export default defineConfig({ 'src/experimental/tasks.ts', 'src/server/index.ts', 'src/server/mcp.ts', + 'src/server/zod-compat.ts', 'src/server/completable.ts', 'src/server/sse.ts', 'src/server/stdio.ts', From ec3650ce2003ec41befabe9814fb30188c93c5c1 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Fri, 17 Apr 2026 08:25:46 +0000 Subject: [PATCH 5/7] fix(sdk): dedupe types field; add SseError/SSEServerTransportOptions/StartSSEOptions to subpaths --- packages/sdk/package.json | 1 - packages/sdk/src/client/sse.ts | 2 +- packages/sdk/src/client/streamableHttp.ts | 1 + packages/sdk/src/server/sse.ts | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/sdk/package.json b/packages/sdk/package.json index f2265bf5f..fc1aec119 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -273,7 +273,6 @@ "import": "./dist/validation/ajv-provider.mjs" } }, - "types": "./dist/index.d.ts", "files": [ "dist" ], diff --git a/packages/sdk/src/client/sse.ts b/packages/sdk/src/client/sse.ts index 9e752ea8c..de4e3b56e 100644 --- a/packages/sdk/src/client/sse.ts +++ b/packages/sdk/src/client/sse.ts @@ -1 +1 @@ -export { SSEClientTransport, type SSEClientTransportOptions } from '@modelcontextprotocol/client'; +export { SSEClientTransport, type SSEClientTransportOptions, SseError } from '@modelcontextprotocol/client'; diff --git a/packages/sdk/src/client/streamableHttp.ts b/packages/sdk/src/client/streamableHttp.ts index 0570cd738..0d2d4d14b 100644 --- a/packages/sdk/src/client/streamableHttp.ts +++ b/packages/sdk/src/client/streamableHttp.ts @@ -1,4 +1,5 @@ export { + type StartSSEOptions, StreamableHTTPClientTransport, type StreamableHTTPClientTransportOptions, StreamableHTTPError, diff --git a/packages/sdk/src/server/sse.ts b/packages/sdk/src/server/sse.ts index d3eddfbc3..1a817e66d 100644 --- a/packages/sdk/src/server/sse.ts +++ b/packages/sdk/src/server/sse.ts @@ -1 +1 @@ -export { SSEServerTransport } from '@modelcontextprotocol/node/sse'; +export { SSEServerTransport, type SSEServerTransportOptions } from '@modelcontextprotocol/node/sse'; From 55f40680baf60b7b7ebae0b9b123ed95e76adc8e Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Fri, 17 Apr 2026 08:43:21 +0000 Subject: [PATCH 6/7] docs(sdk): note optional express/hono peers for auth and sse subpaths --- packages/sdk/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/sdk/README.md b/packages/sdk/README.md index cb4333fcc..a64d003cb 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -18,3 +18,8 @@ See [`docs/migration.md`](../../docs/migration.md) for the full mapping. ## When to use the sub-packages directly Bundle-sensitive targets (browsers, Cloudflare Workers) should import from `@modelcontextprotocol/client` or `@modelcontextprotocol/server` directly to avoid pulling in Node-only transports. + +## Optional subpaths + +The `./server/auth/*` subpaths re-export the legacy Authorization Server helpers from `@modelcontextprotocol/server-auth-legacy`, which require `express` to be installed by the consumer. Similarly, `./server/sse.js` (the deprecated `SSEServerTransport`) is provided by +`@modelcontextprotocol/node`. Both `express` and `hono` are optional peer dependencies — install them only if you use those subpaths. From 677968c2a10623c1198ee1db3129f9cf7249b6f8 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Fri, 17 Apr 2026 14:45:06 +0000 Subject: [PATCH 7/7] feat(sdk): re-export LegacyToolCallback/LegacyPromptCallback from sdk/server/mcp --- packages/sdk/src/server/mcp.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/sdk/src/server/mcp.ts b/packages/sdk/src/server/mcp.ts index 56a5c924d..5ce074972 100644 --- a/packages/sdk/src/server/mcp.ts +++ b/packages/sdk/src/server/mcp.ts @@ -6,6 +6,8 @@ export { type CompleteCallback, type CompleteResourceTemplateCallback, isCompletable, + type LegacyPromptCallback, + type LegacyToolCallback, type ListResourcesCallback, McpServer, type PromptCallback,