Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Include what changed, why, and how to migrate. Search for related sections and g
- **TypeScript**: Strict type checking, ES modules, explicit return types
- **Naming**: PascalCase for classes/types, camelCase for functions/variables
- **Files**: Lowercase with hyphens, test files with `.test.ts` suffix
- **Imports**: ES module style, include `.js` extension, group imports logically
- **Imports**: ES module style, no `.js` extension on relative imports (project uses `moduleResolution: bundler`), group imports logically
- **Formatting**: 2-space indentation, semicolons required, single quotes preferred
- **Testing**: Place tests under each package's `test/` directory (vitest only includes `test/**/*.test.ts`), use descriptive test names
- **Comments**: JSDoc for public APIs, inline comments for complex logic
Expand Down
4 changes: 2 additions & 2 deletions common/tsconfig/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"compilerOptions": {
"target": "esnext",
"lib": ["esnext"],
"module": "NodeNext",
"moduleResolution": "NodeNext",
"module": "ESNext",
"moduleResolution": "bundler",
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
Expand Down
12 changes: 7 additions & 5 deletions docs/client-quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@
```json
{
"compilerOptions": {
"target": "ES2023",
"lib": ["ES2023"],

Check warning on line 92 in docs/client-quickstart.md

View check run for this annotation

Claude / Claude Code Review

Quickstart docs tsconfig target/lib drift after extending shared base

After consolidating the quickstart tsconfigs onto `@modelcontextprotocol/tsconfig`, the examples now inherit `target: esnext` / `lib: [esnext]` from the shared base, but `docs/client-quickstart.md` still shows `target: ES2023` / `lib: [ES2023]` and `docs/server-quickstart.md` still shows `target: ES2022` (no `lib`). This is the same kind of doc/tsconfig drift the PR already fixed for `module`/`moduleResolution` — either bump the docs to `esnext` or pin `target`/`lib` overrides in the example tsc
Comment on lines 91 to 92
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 After consolidating the quickstart tsconfigs onto @modelcontextprotocol/tsconfig, the examples now inherit target: esnext / lib: [esnext] from the shared base, but docs/client-quickstart.md still shows target: ES2023 / lib: [ES2023] and docs/server-quickstart.md still shows target: ES2022 (no lib). This is the same kind of doc/tsconfig drift the PR already fixed for module/moduleResolution — either bump the docs to esnext or pin target/lib overrides in the example tsconfigs to keep them aligned with what the docs advertise.

Extended reasoning...

What the bug is

Before this PR, examples/client-quickstart/tsconfig.json and examples/server-quickstart/tsconfig.json were standalone configs that matched the tsconfig.json blocks in their respective quickstart docs field-for-field on target/lib (client: ES2023/[ES2023]; server: ES2022/no lib). After this PR, both example tsconfigs were rewritten to "extends": "@modelcontextprotocol/tsconfig" and dropped their own target/lib entries. The shared base at common/tsconfig/tsconfig.json:3-4 sets "target": "esnext" and "lib": ["esnext"], and the example overrides only touch outDir, rootDir, declaration, declarationMap, types, and paths — not target/lib. So both examples now compile with an effective target of esnext, while the docs still tell users to use ES2023 / ES2022.

The specific code path

  • docs/client-quickstart.md:91-92"target": "ES2023", "lib": ["ES2023"]
  • examples/client-quickstart/tsconfig.json → extends @modelcontextprotocol/tsconfig, no target/lib override → effective esnext/[esnext]
  • docs/server-quickstart.md:106"target": "ES2022", no lib
  • examples/server-quickstart/tsconfig.json → extends @modelcontextprotocol/tsconfig, no target/lib override → effective esnext/[esnext]

This is a new drift introduced by the PR. The PR already fixed the module/moduleResolution drift in the same doc blocks (raised in an earlier review comment), but the consolidation onto the shared base introduced fresh drift on target/lib that wasn't propagated.

Why existing checks don't catch it

The tsconfig.json blocks in both docs are plain ```json fences with no source= attribute, so `pnpm sync:snippets --check` does not compare them against the example files. The `.ts` code snippets in the docs are `source=`-tagged and synced from the example sources — which means CI typechecks those snippets under the example's effective `target: esnext`, while the doc tells the user to compile with `ES2023`/`ES2022`.

Step-by-step proof

  1. Open common/tsconfig/tsconfig.json — lines 3-4 set "target": "esnext", "lib": ["esnext"].
  2. Open examples/client-quickstart/tsconfig.json after this PR — it has "extends": "@modelcontextprotocol/tsconfig" and its compilerOptions override sets outDir, rootDir, declaration, declarationMap, types, paths but not target or lib. Effective target is therefore esnext.
  3. Open docs/client-quickstart.md:91-92 — it still shows "target": "ES2023", "lib": ["ES2023"].
  4. Same chain for the server quickstart: examples/server-quickstart/tsconfig.json inherits esnext, but docs/server-quickstart.md:106 shows "target": "ES2022" with no lib.
  5. Before the PR (git show HEAD~3:examples/client-quickstart/tsconfig.json), the example was standalone with "target": "ES2023", "lib": ["ES2023"] — identical to the doc block. The drift is introduced here.

Impact

No runtime breakage today — the quickstart code uses no post-ES2022/ES2023 syntax. The latent risk is that CI now typechecks the doc-synced .ts snippets under target: esnext, so a future edit using post-ES2023 syntax (e.g., a new ECMAScript proposal) would compile cleanly in CI but fail for a user who copies the doc tsconfig.json verbatim. It's primarily a documentation-consistency issue, the same class as the module/moduleResolution drift already addressed in this PR.

How to fix

Either:

  • Update the doc tsconfig.json blocks to "target": "esnext" / "lib": ["esnext"] so they match the example's effective config, or
  • Add "target": "ES2023" / "lib": ["ES2023"] (and "target": "ES2022") overrides back into the example compilerOptions so the example matches what the docs advertise.

Optionally, give the doc tsconfig blocks a source= attribute (or similar) so sync:snippets can catch this class of drift going forward.

"module": "Node16",
"moduleResolution": "Node16",
"module": "ESNext",
"moduleResolution": "bundler",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
Expand Down Expand Up @@ -236,7 +236,8 @@
messages,
});

finalText.push(followUp.content[0].type === 'text' ? followUp.content[0].text : '');
const firstBlock = followUp.content[0];
finalText.push(firstBlock?.type === 'text' ? firstBlock.text : '');
}
}

Expand Down Expand Up @@ -284,13 +285,14 @@

```ts source="../examples/client-quickstart/src/index.ts#main"
async function main() {
if (process.argv.length < 3) {
const serverScriptPath = process.argv[2];
if (!serverScriptPath) {
console.log('Usage: node build/index.js <path_to_server_script>');
return;
}
const mcpClient = new MCPClient();
try {
await mcpClient.connectToServer(process.argv[2]);
await mcpClient.connectToServer(serverScriptPath);

// Check if we have a valid API key to continue
const apiKey = process.env.ANTHROPIC_API_KEY;
Expand Down
4 changes: 2 additions & 2 deletions docs/server-quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ Create a `tsconfig.json` in the root of your project:
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"module": "ESNext",
"moduleResolution": "bundler",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
Expand Down
1 change: 1 addition & 0 deletions examples/client-quickstart/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@modelcontextprotocol/client": "workspace:^"
},
"devDependencies": {
"@modelcontextprotocol/tsconfig": "workspace:^",
"@types/node": "^24.10.1",
"typescript": "catalog:devTools"
}
Expand Down
8 changes: 5 additions & 3 deletions examples/client-quickstart/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ class MCPClient {
messages,
});

finalText.push(followUp.content[0].type === 'text' ? followUp.content[0].text : '');
const firstBlock = followUp.content[0];
finalText.push(firstBlock?.type === 'text' ? firstBlock.text : '');
}
}

Expand Down Expand Up @@ -156,13 +157,14 @@ class MCPClient {

//#region main
async function main() {
if (process.argv.length < 3) {
const serverScriptPath = process.argv[2];
if (!serverScriptPath) {
console.log('Usage: node build/index.js <path_to_server_script>');
return;
}
const mcpClient = new MCPClient();
try {
await mcpClient.connectToServer(process.argv[2]);
await mcpClient.connectToServer(serverScriptPath);

// Check if we have a valid API key to continue
const apiKey = process.env.ANTHROPIC_API_KEY;
Expand Down
12 changes: 4 additions & 8 deletions examples/client-quickstart/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
{
"extends": "@modelcontextprotocol/tsconfig",
"compilerOptions": {
"target": "ES2023",
"lib": ["ES2023"],
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": false,
"declarationMap": false,
"types": ["node"],
"paths": {
"@modelcontextprotocol/client": ["./node_modules/@modelcontextprotocol/client/src/index.ts"],
"@modelcontextprotocol/client/stdio": ["./node_modules/@modelcontextprotocol/client/src/stdio.ts"],
Comment thread
claude[bot] marked this conversation as resolved.
Expand Down
2 changes: 1 addition & 1 deletion examples/client/src/elicitationUrlExample.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
} from '@modelcontextprotocol/client';
import open from 'open';

import { InMemoryOAuthClientProvider } from './simpleOAuthClientProvider.js';
import { InMemoryOAuthClientProvider } from './simpleOAuthClientProvider';

// Set up OAuth (required for this example)
const OAUTH_CALLBACK_PORT = 8090; // Use different port than auth server (3001)
Expand Down
2 changes: 1 addition & 1 deletion examples/client/src/simpleOAuthClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { CallToolResult, ListToolsRequest, OAuthClientMetadata } from '@mod
import { Client, StreamableHTTPClientTransport, UnauthorizedError } from '@modelcontextprotocol/client';
import open from 'open';

import { InMemoryOAuthClientProvider } from './simpleOAuthClientProvider.js';
import { InMemoryOAuthClientProvider } from './simpleOAuthClientProvider';

// Configuration
const DEFAULT_SERVER_URL = 'http://localhost:3000/mcp';
Expand Down
1 change: 1 addition & 0 deletions examples/server-quickstart/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"zod": "catalog:runtimeShared"
},
"devDependencies": {
"@modelcontextprotocol/tsconfig": "workspace:^",
"@types/node": "^24.10.1",
"typescript": "catalog:devTools"
}
Expand Down
11 changes: 4 additions & 7 deletions examples/server-quickstart/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
{
"extends": "@modelcontextprotocol/tsconfig",
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": false,
"declarationMap": false,
"types": ["node"],
"paths": {
"@modelcontextprotocol/server": ["./node_modules/@modelcontextprotocol/server/src/index.ts"],
"@modelcontextprotocol/server/stdio": ["./node_modules/@modelcontextprotocol/server/src/stdio.ts"],
Expand Down
2 changes: 1 addition & 1 deletion examples/server/src/elicitationUrlExample.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import type { Request, Response } from 'express';
import express from 'express';
import * as z from 'zod/v4';

import { InMemoryEventStore } from './inMemoryEventStore.js';
import { InMemoryEventStore } from './inMemoryEventStore';

// Create an MCP server with implementation details
const getServer = () => {
Expand Down
2 changes: 1 addition & 1 deletion examples/server/src/simpleStreamableHttp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import cors from 'cors';
import type { Request, Response } from 'express';
import * as z from 'zod/v4';

import { InMemoryEventStore } from './inMemoryEventStore.js';
import { InMemoryEventStore } from './inMemoryEventStore';

// Check for OAuth flag
const useOAuth = process.argv.includes('--oauth');
Expand Down
2 changes: 1 addition & 1 deletion examples/server/src/ssePollingExample.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { McpServer } from '@modelcontextprotocol/server';
import cors from 'cors';
import type { Request, Response } from 'express';

import { InMemoryEventStore } from './inMemoryEventStore.js';
import { InMemoryEventStore } from './inMemoryEventStore';

// Create a fresh MCP server per client connection to avoid shared state between clients
const getServer = () => {
Expand Down
4 changes: 2 additions & 2 deletions examples/shared/src/authServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import cors from 'cors';
import type { Request, Response as ExpressResponse, Router } from 'express';
import express from 'express';

import type { DemoAuth } from './auth.js';
import { createDemoAuth, DEMO_USER_CREDENTIALS } from './auth.js';
import type { DemoAuth } from './auth';
import { createDemoAuth, DEMO_USER_CREDENTIALS } from './auth';

export interface SetupAuthServerOptions {
authServerUrl: URL;
Expand Down
8 changes: 4 additions & 4 deletions examples/shared/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Auth configuration
export type { CreateDemoAuthOptions, DemoAuth } from './auth.js';
export { createDemoAuth } from './auth.js';
export type { CreateDemoAuthOptions, DemoAuth } from './auth';
export { createDemoAuth } from './auth';

// Auth server setup + demo token verifier (pass to `requireBearerAuth` from @modelcontextprotocol/express)
export type { SetupAuthServerOptions } from './authServer.js';
export { createProtectedResourceMetadataRouter, demoTokenVerifier, getAuth, setupAuthServer } from './authServer.js';
export type { SetupAuthServerOptions } from './authServer';
export { createProtectedResourceMetadataRouter, demoTokenVerifier, getAuth, setupAuthServer } from './authServer';
4 changes: 2 additions & 2 deletions examples/shared/test/demoInMemoryOAuthProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

import { describe, expect, it } from 'vitest';

import type { CreateDemoAuthOptions } from '../src/auth.js';
import { createDemoAuth } from '../src/auth.js';
import type { CreateDemoAuthOptions } from '../src/auth';
import { createDemoAuth } from '../src/auth';

describe('createDemoAuth', () => {
const validOptions: CreateDemoAuthOptions = {
Expand Down
4 changes: 2 additions & 2 deletions packages/client/src/client/auth.examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

import type { AuthorizationServerMetadata } from '@modelcontextprotocol/core';

import type { OAuthClientProvider } from './auth.js';
import { fetchToken } from './auth.js';
import type { OAuthClientProvider } from './auth';
import { fetchToken } from './auth';

/**
* Base class providing no-op implementations of required OAuthClientProvider methods.
Expand Down
4 changes: 2 additions & 2 deletions packages/client/src/client/authExtensions.examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
* @module
*/

import { ClientCredentialsProvider, createPrivateKeyJwtAuth, PrivateKeyJwtProvider } from './authExtensions.js';
import { StreamableHTTPClientTransport } from './streamableHttp.js';
import { ClientCredentialsProvider, createPrivateKeyJwtAuth, PrivateKeyJwtProvider } from './authExtensions';
import { StreamableHTTPClientTransport } from './streamableHttp';

/**
* Example: Creating a private key JWT authentication function.
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/client/authExtensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import type { FetchLike, OAuthClientInformation, OAuthClientMetadata, OAuthTokens } from '@modelcontextprotocol/core';
import type { CryptoKey, JWK } from 'jose';

import type { AddClientAuthentication, OAuthClientProvider } from './auth.js';
import type { AddClientAuthentication, OAuthClientProvider } from './auth';

/**
* Helper to produce a `private_key_jwt` client authentication function.
Expand Down
8 changes: 4 additions & 4 deletions packages/client/src/client/client.examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@

import type { Prompt, Resource, Tool } from '@modelcontextprotocol/core';

import { Client } from './client.js';
import { SSEClientTransport } from './sse.js';
import { StdioClientTransport } from './stdio.js';
import { StreamableHTTPClientTransport } from './streamableHttp.js';
import { Client } from './client';
import { SSEClientTransport } from './sse';
import { StdioClientTransport } from './stdio';
import { StreamableHTTPClientTransport } from './streamableHttp';

/**
* Example: Using listChanged to automatically track tool and prompt updates.
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ import {
SdkErrorCode
} from '@modelcontextprotocol/core';

import { ExperimentalClientTasks } from '../experimental/tasks/client.js';
import { ExperimentalClientTasks } from '../experimental/tasks/client';

/**
* Elicitation default application helper. Applies defaults to the `data` based on the `schema`.
Expand Down
4 changes: 2 additions & 2 deletions packages/client/src/client/crossAppAccess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
import type { FetchLike } from '@modelcontextprotocol/core';
import { IdJagTokenExchangeResponseSchema, OAuthErrorResponseSchema, OAuthTokensSchema } from '@modelcontextprotocol/core';

import type { ClientAuthMethod } from './auth.js';
import { applyClientAuthentication, discoverAuthorizationServerMetadata } from './auth.js';
import type { ClientAuthMethod } from './auth';
import { applyClientAuthentication, discoverAuthorizationServerMetadata } from './auth';

/**
* Options for requesting a JWT Authorization Grant via RFC 8693 Token Exchange.
Expand Down
4 changes: 2 additions & 2 deletions packages/client/src/client/middleware.examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
* @module
*/

import type { Middleware } from './middleware.js';
import { applyMiddlewares, createMiddleware } from './middleware.js';
import type { Middleware } from './middleware';
import { applyMiddlewares, createMiddleware } from './middleware';

// Stubs for hypothetical application middleware
declare function withOAuth(provider: unknown, url: string): Middleware;
Expand Down
4 changes: 2 additions & 2 deletions packages/client/src/client/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { FetchLike } from '@modelcontextprotocol/core';

import type { OAuthClientProvider } from './auth.js';
import { auth, extractWWWAuthenticateParams, UnauthorizedError } from './auth.js';
import type { OAuthClientProvider } from './auth';
import { auth, extractWWWAuthenticateParams, UnauthorizedError } from './auth';

/**
* Middleware function that wraps and enhances fetch functionality.
Expand Down
4 changes: 2 additions & 2 deletions packages/client/src/client/sse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { createFetchWithInit, JSONRPCMessageSchema, normalizeHeaders, SdkError,
import type { ErrorEvent, EventSourceInit } from 'eventsource';
import { EventSource } from 'eventsource';

import type { AuthProvider, OAuthClientProvider } from './auth.js';
import { adaptOAuthProvider, auth, extractWWWAuthenticateParams, isOAuthClientProvider, UnauthorizedError } from './auth.js';
import type { AuthProvider, OAuthClientProvider } from './auth';
import { adaptOAuthProvider, auth, extractWWWAuthenticateParams, isOAuthClientProvider, UnauthorizedError } from './auth';

export class SseError extends Error {
constructor(
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/client/streamableHttp.examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

/* eslint-disable unicorn/consistent-function-scoping -- examples must live inside region blocks */

import type { ReconnectionScheduler } from './streamableHttp.js';
import type { ReconnectionScheduler } from './streamableHttp';

// Stub for a hypothetical platform-specific background scheduling API
declare const platformBackgroundTask: {
Expand Down
4 changes: 2 additions & 2 deletions packages/client/src/client/streamableHttp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import {
} from '@modelcontextprotocol/core';
import { EventSourceParserStream } from 'eventsource-parser/stream';

import type { AuthProvider, OAuthClientProvider } from './auth.js';
import { adaptOAuthProvider, auth, extractWWWAuthenticateParams, isOAuthClientProvider, UnauthorizedError } from './auth.js';
import type { AuthProvider, OAuthClientProvider } from './auth';
import { adaptOAuthProvider, auth, extractWWWAuthenticateParams, isOAuthClientProvider, UnauthorizedError } from './auth';

// Default reconnection options for StreamableHTTP connections
const DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS: StreamableHTTPReconnectionOptions = {
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/experimental/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
* @experimental
*/

export * from './tasks/client.js';
export * from './tasks/client';
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import type { RequestOptions } from '@modelcontextprotocol/core';

import type { Client } from '../../client/client.js';
import type { Client } from '../../client/client';

/**
* Example: Using callToolStream to execute a tool with task lifecycle events.
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/experimental/tasks/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
ProtocolErrorCode
} from '@modelcontextprotocol/core';

import type { Client } from '../../client/client.js';
import type { Client } from '../../client/client';

/**
* Internal interface for accessing {@linkcode Client}'s private methods.
Expand Down
Loading
Loading