{"owner":"modelcontextprotocol","repo":"typescript-sdk","hasSkills":true,"hasMcp":true,"mcpConfig":{"mcpServers":{"typescript-sdk":{"command":"npx","args":["-y","@modelcontextprotocol/server-typescript-sdk"]}}},"found":["CLAUDE.md"],"skills":{"CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Build & Test Commands\n\n```sh\npnpm install         # Install all workspace dependencies\n\npnpm build:all       # Build all packages\npnpm lint:all        # Run ESLint + Prettier checks across all packages\npnpm lint:fix:all    # Auto-fix lint and formatting issues across all packages\npnpm typecheck:all   # Type-check all packages\npnpm test:all        # Run all tests (vitest) across all packages\npnpm check:all       # typecheck + lint across all packages\n\n# Run a single package script (examples)\n# Run a single package script from the repo root with pnpm filter\npnpm --filter @modelcontextprotocol/core-internal test                # vitest run (core)\npnpm --filter @modelcontextprotocol/core-internal test:watch          # vitest (watch)\npnpm --filter @modelcontextprotocol/core-internal test -- path/to/file.test.ts\npnpm --filter @modelcontextprotocol/core-internal test -- -t \"test name\"\n```\n\n## Breaking Changes\n\nWhen making breaking changes, add to the relevant subsystem section in\n`docs/migration/upgrade-to-v2.md` (or `docs/migration/support-2026-07-28.md` if the\nchange is 2026-07-28-only). Mechanical renames go in\n`packages/codemod/src/migrations/v1-to-v2/mappings/` and the codemod handles them — do\nnot reproduce mapping tables in the guide; link to the mapping file instead.\n\nInclude what changed, why, and how to migrate. Search for related sections and group related changes together rather than adding new standalone sections.\n\n## Code Style Guidelines\n\n- **TypeScript**: Strict type checking, ES modules, explicit return types\n- **Naming**: PascalCase for classes/types, camelCase for functions/variables\n- **Files**: Lowercase with hyphens, test files with `.test.ts` suffix\n- **Imports**: ES module style, no `.js` extension on relative imports (project uses `moduleResolution: bundler`), group imports logically\n- **Formatting**: 2-space indentation, semicolons required, single quotes preferred\n- **Testing**: Place tests under each package's `test/` directory (vitest only includes `test/**/*.test.ts`), use descriptive test names\n- **Comments**: JSDoc for public APIs, inline comments for complex logic\n\n### JSDoc `@example` Code Snippets\n\nJSDoc `@example` tags should pull type-checked code from companion `.examples.ts` files (e.g., `client.ts` → `client.examples.ts`). Use ` ```ts source=\"./file.examples.ts#regionName\" ` fences referencing `//#region regionName` blocks; region names follow `exportedName_variant` or `ClassName_methodName_variant` pattern (e.g., `applyMiddlewares_basicUsage`, `Client_connect_basicUsage`). For whole-file inclusion (any file type), omit the `#regionName`.\n\nRun `pnpm sync:snippets` to sync example content into JSDoc comments and markdown files.\n\n## Architecture Overview\n\n### Core Layers\n\nThe SDK is organized into three main layers:\n\n1. **Types Layer** (`packages/core-internal/src/types/types.ts`) - Protocol types generated from the MCP specification. All JSON-RPC message types, schemas, and protocol constants are defined here using Zod v4.\n\n2. **Protocol Layer** (`packages/core-internal/src/shared/protocol.ts`) - The abstract `Protocol` class that handles JSON-RPC message routing, request/response correlation, capability negotiation, and transport management. Both `Client` and `Server` extend this class.\n\n3. **High-Level APIs**:\n    - `Client` (`packages/client/src/client/client.ts`) - Client implementation extending Protocol with typed methods for MCP operations\n    - `Server` (`packages/server/src/server/server.ts`) - Server implementation extending Protocol with request handler registration\n    - `McpServer` (`packages/server/src/server/mcp.ts`) - High-level server API with simplified resource/tool/prompt registration\n\n### Public API Exports\n\nThe SDK separates internal code from the public API surface:\n\n- **`@modelcontextprotocol/core-internal`** (main entry, `packages/core-internal/src/index.ts`) — Internal barrel. Exports everything (including Zod schemas, Protocol class, stdio utils). Only consumed by sibling packages within the monorepo (`private: true`).\n- **`@modelcontextprotocol/core-internal/public`** (`packages/core-internal/src/exports/public/index.ts`) — Curated public API. Exports TypeScript types, error classes, constants, guards, and the `Protocol` base class (+ `mergeCapabilities`). Re-exported by client and server packages.\n- **`@modelcontextprotocol/client`** and **`@modelcontextprotocol/server`** (`packages/*/src/index.ts`) — Final public surface. Package-specific exports (named explicitly) plus re-exports from `core-internal/public`.\n- **`@modelcontextprotocol/core`** (`packages/core/src/index.ts`) — Public Zod-schema package and the canonical home of the schema source modules (`src/schemas.ts`, `src/auth.ts`, `src/constants.ts`). The root entry re-exports **only** the `*Schema` Zod constants (MCP spec + OAuth/OpenID) — the published home for raw runtime validation (`CallToolResultSchema.parse(...)`); runtime-neutral (`zod` is its only dependency). The `./internal` subpath re-exports the schema modules wholesale for the sibling packages: `core-internal` re-exports them at the old module paths, and the `client`/`server`/`server-legacy` bundles resolve `@modelcontextprotocol/core/internal` as a real external dependency instead of carrying their own schema copies (their public surfaces stay Zod-free).\n\nWhen modifying exports:\n\n- Use explicit named exports, not `export *`, in package `index.ts` files and `core-internal/public`.\n- Adding a symbol to a package `index.ts` makes it public API — do so intentionally.\n- Internal helpers should stay in the core internal barrel and not be added to `core-internal/public` or package index files.\n- The package root entry must stay runtime-neutral so browser and Cloudflare Workers bundlers can consume it. Exports whose module graph transitively touches unpolyfillable Node builtins (`node:child_process`, `node:net`, `cross-spawn`, etc.) must live at a named subpath export (e.g. `./stdio`) and be covered by a `barrelClean` test in that package.\n\n### Transport System\n\nTransports (`packages/core-internal/src/shared/transport.ts`) provide the communication layer:\n\n- **Streamable HTTP** (`packages/server/src/server/streamableHttp.ts`, `packages/client/src/client/streamableHttp.ts`) - Recommended transport for remote servers, supports SSE for streaming\n- **SSE** (`packages/server/src/server/sse.ts`, `packages/client/src/client/sse.ts`) - Legacy HTTP+SSE transport for backwards compatibility\n- **stdio** (`packages/server/src/server/stdio.ts`, `packages/client/src/client/stdio.ts`) - For local process-spawned integrations\n\n### Server-Side Features\n\n- **Tools/Resources/Prompts**: Registered via `McpServer.tool()`, `.resource()`, `.prompt()` methods\n- **OAuth/Auth**: Full OAuth 2.0 server implementation in `packages/server/src/server/auth/`\n- **Completions**: Auto-completion support via `packages/server/src/server/completable.ts`\n\n### Client-Side Features\n\n- **Auth**: OAuth client support in `packages/client/src/client/auth.ts` and `packages/client/src/client/auth-extensions.ts`\n- **Client middleware**: Request middleware in `packages/client/src/client/middleware.ts` (unrelated to the framework adapter packages below)\n- **Sampling**: Clients can handle `sampling/createMessage` requests from servers (LLM completions)\n- **Elicitation**: Clients can handle `elicitation/create` requests for user input (form or URL mode)\n- **Roots**: Clients can expose filesystem roots to servers via `roots/list`\n\n### Middleware packages (framework/runtime adapters)\n\nThe repo also ships “middleware” packages under `packages/middleware/` (e.g. `@modelcontextprotocol/express`, `@modelcontextprotocol/hono`, `@modelcontextprotocol/node`). These are thin integration layers for specific frameworks/runtimes and should not add new MCP functionality.\n\n### Experimental Features\n\nLocated in `packages/*/src/experimental/`. Currently empty.\n\n### Zod Schemas\n\nThe SDK uses `zod/v4` internally. Schema utilities live in:\n\n- `packages/core-internal/src/util/schema.ts` - AnySchema alias and helpers for inspecting Zod objects\n\n### Validation\n\nPluggable JSON Schema validation (`packages/core-internal/src/validators/`):\n\n- `ajvProvider.ts` - Default Ajv-based validator\n- `cfWorkerProvider.ts` - Cloudflare Workers-compatible alternative\n\n### Examples\n\nRunnable examples in `examples/<story>/{server.ts,client.ts}` — each story is its own\n`@mcp-examples/<story>` workspace package and a self-verifying e2e test (the client connects,\nasserts results, exits non-zero on mismatch). `pnpm run:examples` runs every story over its\nconfigured transport×era legs; the `examples (build + e2e)` CI job is part of the per-PR gate\nbasket. See `examples/README.md` for the full story matrix.\n\n- `examples/shared/` — `@mcp-examples/shared` package. Root export is args-only (`parseExampleArgs`, `check`, `siblingPath`); the demo OAuth provider and `InMemoryEventStore` live at the `@mcp-examples/shared/auth` subpath so non-auth stories don't eagerly evaluate better-auth/express/better-sqlite3. Stories import only this plumbing and inline the SDK transport setup themselves — see `examples/CONTRIBUTING.md`.\n- `scripts/examples/` — runner (`run-examples.ts`)\n- `examples/guides/` — per-page snippet companions for the `docs/` guide pages (one `<section>/<page>.examples.ts` per page); fences sync via `pnpm sync:snippets`, and the runnable ones are executed in CI by `pnpm docs:examples`\n\n## Message Flow (Bidirectional Protocol)\n\nMCP is bidirectional: both client and server can send requests. Understanding this flow is essential when implementing new request types.\n\n### Class Hierarchy\n\n```\nProtocol (abstract base)\n├── Client (packages/client/src/client/client.ts)     - can send requests TO server, handle requests FROM server\n└── Server (packages/server/src/server/server.ts)     - can send requests TO client, handle requests FROM client\n    └── McpServer (packages/server/src/server/mcp.ts) - high-level wrapper around Server\n```\n\n### Outbound Flow: Sending Requests\n\nWhen code calls `client.callTool()` or `server.createMessage()`:\n\n1. **High-level method** (e.g., `Client.callTool()`) calls `this.request()`\n2. **`Protocol.request()`**:\n    - Assigns unique message ID\n    - Checks capabilities via `assertCapabilityForMethod()` (abstract, implemented by Client/Server)\n    - Creates response handler promise\n    - Calls `transport.send()` with JSON-RPC request\n    - Waits for response handler to resolve\n3. **Transport** serializes and sends over wire (HTTP, stdio, etc.)\n4. **`Protocol._onresponse()`** resolves the promise when response arrives\n\n### Inbound Flow: Handling Requests\n\nWhen a request arrives from the remote side:\n\n1. **Transport** receives message, calls `transport.onmessage()`\n2. **`Protocol.connect()`** routes to `_onrequest()`, `_onresponse()`, or `_onnotification()`\n3. **`Protocol._onrequest()`**:\n    - Looks up handler in `_requestHandlers` map (keyed by method name)\n    - Creates `BaseContext` with `signal`, `sessionId`, `sendNotification`, `sendRequest`, etc.\n    - Calls `buildContext()` to let subclasses enrich the context (e.g., Server adds HTTP request info)\n    - Invokes handler, sends JSON-RPC response back via transport\n4. **Handler** was registered via `setRequestHandler('method', handler)`\n\n### Handler Registration\n\n```typescript\n// In Client (for server→client requests like sampling, elicitation)\nclient.setRequestHandler('sampling/createMessage', async (request, ctx) => {\n  // Handle sampling request from server\n  return { role: \"assistant\", content: {...}, model: \"...\" };\n});\n\n// In Server (for client→server requests like tools/call)\nserver.setRequestHandler('tools/call', async (request, ctx) => {\n  // Handle tool call from client\n  return { content: [...] };\n});\n```\n\n### Request Handler Context\n\nThe `ctx` parameter in handlers provides a structured context:\n\n**`BaseContext`** (common to both Server and Client), fields organized into nested groups:\n\n- `sessionId?`: Transport session identifier\n- `mcpReq`: Request-level concerns\n    - `id`: JSON-RPC message ID\n    - `method`: Request method string (e.g., 'tools/call')\n    - `_meta?`: Request metadata\n    - `signal`: AbortSignal for cancellation\n    - `send(request, schema, options?)`: Send related request (for bidirectional flows)\n    - `notify(notification)`: Send related notification back\n- `http?`: HTTP transport info (undefined for stdio)\n    - `authInfo?`: Validated auth token info\n\n**`ServerContext`** extends `BaseContext.mcpReq` and `BaseContext.http?` via type intersection:\n\n- `mcpReq` adds: `log(level, data, logger?)`, `elicitInput(params, options?)`, `requestSampling(params, options?)`\n- `http?` adds: `req?` (HTTP request info), `closeSSE?`, `closeStandaloneSSE?`\n\n**`ClientContext`** is currently identical to `BaseContext`.\n\n### Capability Checking\n\nBoth sides declare capabilities during initialization. The SDK enforces these:\n\n- **Client→Server**: `Client.assertCapabilityForMethod()` checks `_serverCapabilities`\n- **Server→Client**: `Server.assertCapabilityForMethod()` checks `_clientCapabilities`\n- **Handler registration**: `assertRequestHandlerCapability()` validates local capabilities\n\n### Adding a New Request Type\n\n1. **Define schema** in `src/types.ts` (request params, result schema)\n2. **Add capability** to `ClientCapabilities` or `ServerCapabilities` in types\n3. **Implement sender** method in Client or Server class\n4. **Add capability check** in the appropriate `assertCapabilityForMethod()`\n5. **Register handler** on the receiving side with `setRequestHandler()`\n6. **For McpServer**: Add high-level wrapper method if needed\n\n### Server-Initiated Requests (Sampling, Elicitation)\n\nServer can request actions from client (requires client capability):\n\n```typescript\n// Server sends sampling request to client\nconst result = await server.createMessage({\n  messages: [...],\n  maxTokens: 100\n});\n\n// Client must have registered handler:\nclient.setRequestHandler('sampling/createMessage', async (request, extra) => {\n  // Client-side LLM call\n  return { role: \"assistant\", content: {...} };\n});\n```\n\n## Key Patterns\n\n### Request Handler Registration (Low-Level Server)\n\n```typescript\nserver.setRequestHandler('tools/call', async (request, extra) => {\n    // extra contains sessionId, authInfo, sendNotification, etc.\n    return {\n        /* result */\n    };\n});\n```\n\n### Tool Registration (High-Level McpServer)\n\n```typescript\nmcpServer.tool('tool-name', { param: z.string() }, async ({ param }, extra) => {\n    return { content: [{ type: 'text', text: 'result' }] };\n});\n```\n\n### Transport Connection\n\n```typescript\n// Server\n// (Node.js IncomingMessage/ServerResponse wrapper; exported by @modelcontextprotocol/node)\nconst transport = new NodeStreamableHTTPServerTransport({ sessionIdGenerator: () => randomUUID() });\nawait server.connect(transport);\n\n// Client\nconst transport = new StreamableHTTPClientTransport(new URL('http://localhost:3000/mcp'));\nawait client.connect(transport);\n```\n"},"files":{"CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Build & Test Commands\n\n```sh\npnpm install         # Install all workspace dependencies\n\npnpm build:all       # Build all packages\npnpm lint:all        # Run ESLint + Prettier checks across all packages\npnpm lint:fix:all    # Auto-fix lint and formatting issues across all packages\npnpm typecheck:all   # Type-check all packages\npnpm test:all        # Run all tests (vitest) across all packages\npnpm check:all       # typecheck + lint across all packages\n\n# Run a single package script (examples)\n# Run a single package script from the repo root with pnpm filter\npnpm --filter @modelcontextprotocol/core-internal test                # vitest run (core)\npnpm --filter @modelcontextprotocol/core-internal test:watch          # vitest (watch)\npnpm --filter @modelcontextprotocol/core-internal test -- path/to/file.test.ts\npnpm --filter @modelcontextprotocol/core-internal test -- -t \"test name\"\n```\n\n## Breaking Changes\n\nWhen making breaking changes, add to the relevant subsystem section in\n`docs/migration/upgrade-to-v2.md` (or `docs/migration/support-2026-07-28.md` if the\nchange is 2026-07-28-only). Mechanical renames go in\n`packages/codemod/src/migrations/v1-to-v2/mappings/` and the codemod handles them — do\nnot reproduce mapping tables in the guide; link to the mapping file instead.\n\nInclude what changed, why, and how to migrate. Search for related sections and group related changes together rather than adding new standalone sections.\n\n## Code Style Guidelines\n\n- **TypeScript**: Strict type checking, ES modules, explicit return types\n- **Naming**: PascalCase for classes/types, camelCase for functions/variables\n- **Files**: Lowercase with hyphens, test files with `.test.ts` suffix\n- **Imports**: ES module style, no `.js` extension on relative imports (project uses `moduleResolution: bundler`), group imports logically\n- **Formatting**: 2-space indentation, semicolons required, single quotes preferred\n- **Testing**: Place tests under each package's `test/` directory (vitest only includes `test/**/*.test.ts`), use descriptive test names\n- **Comments**: JSDoc for public APIs, inline comments for complex logic\n\n### JSDoc `@example` Code Snippets\n\nJSDoc `@example` tags should pull type-checked code from companion `.examples.ts` files (e.g., `client.ts` → `client.examples.ts`). Use ` ```ts source=\"./file.examples.ts#regionName\" ` fences referencing `//#region regionName` blocks; region names follow `exportedName_variant` or `ClassName_methodName_variant` pattern (e.g., `applyMiddlewares_basicUsage`, `Client_connect_basicUsage`). For whole-file inclusion (any file type), omit the `#regionName`.\n\nRun `pnpm sync:snippets` to sync example content into JSDoc comments and markdown files.\n\n## Architecture Overview\n\n### Core Layers\n\nThe SDK is organized into three main layers:\n\n1. **Types Layer** (`packages/core-internal/src/types/types.ts`) - Protocol types generated from the MCP specification. All JSON-RPC message types, schemas, and protocol constants are defined here using Zod v4.\n\n2. **Protocol Layer** (`packages/core-internal/src/shared/protocol.ts`) - The abstract `Protocol` class that handles JSON-RPC message routing, request/response correlation, capability negotiation, and transport management. Both `Client` and `Server` extend this class.\n\n3. **High-Level APIs**:\n    - `Client` (`packages/client/src/client/client.ts`) - Client implementation extending Protocol with typed methods for MCP operations\n    - `Server` (`packages/server/src/server/server.ts`) - Server implementation extending Protocol with request handler registration\n    - `McpServer` (`packages/server/src/server/mcp.ts`) - High-level server API with simplified resource/tool/prompt registration\n\n### Public API Exports\n\nThe SDK separates internal code from the public API surface:\n\n- **`@modelcontextprotocol/core-internal`** (main entry, `packages/core-internal/src/index.ts`) — Internal barrel. Exports everything (including Zod schemas, Protocol class, stdio utils). Only consumed by sibling packages within the monorepo (`private: true`).\n- **`@modelcontextprotocol/core-internal/public`** (`packages/core-internal/src/exports/public/index.ts`) — Curated public API. Exports TypeScript types, error classes, constants, guards, and the `Protocol` base class (+ `mergeCapabilities`). Re-exported by client and server packages.\n- **`@modelcontextprotocol/client`** and **`@modelcontextprotocol/server`** (`packages/*/src/index.ts`) — Final public surface. Package-specific exports (named explicitly) plus re-exports from `core-internal/public`.\n- **`@modelcontextprotocol/core`** (`packages/core/src/index.ts`) — Public Zod-schema package and the canonical home of the schema source modules (`src/schemas.ts`, `src/auth.ts`, `src/constants.ts`). The root entry re-exports **only** the `*Schema` Zod constants (MCP spec + OAuth/OpenID) — the published home for raw runtime validation (`CallToolResultSchema.parse(...)`); runtime-neutral (`zod` is its only dependency). The `./internal` subpath re-exports the schema modules wholesale for the sibling packages: `core-internal` re-exports them at the old module paths, and the `client`/`server`/`server-legacy` bundles resolve `@modelcontextprotocol/core/internal` as a real external dependency instead of carrying their own schema copies (their public surfaces stay Zod-free).\n\nWhen modifying exports:\n\n- Use explicit named exports, not `export *`, in package `index.ts` files and `core-internal/public`.\n- Adding a symbol to a package `index.ts` makes it public API — do so intentionally.\n- Internal helpers should stay in the core internal barrel and not be added to `core-internal/public` or package index files.\n- The package root entry must stay runtime-neutral so browser and Cloudflare Workers bundlers can consume it. Exports whose module graph transitively touches unpolyfillable Node builtins (`node:child_process`, `node:net`, `cross-spawn`, etc.) must live at a named subpath export (e.g. `./stdio`) and be covered by a `barrelClean` test in that package.\n\n### Transport System\n\nTransports (`packages/core-internal/src/shared/transport.ts`) provide the communication layer:\n\n- **Streamable HTTP** (`packages/server/src/server/streamableHttp.ts`, `packages/client/src/client/streamableHttp.ts`) - Recommended transport for remote servers, supports SSE for streaming\n- **SSE** (`packages/server/src/server/sse.ts`, `packages/client/src/client/sse.ts`) - Legacy HTTP+SSE transport for backwards compatibility\n- **stdio** (`packages/server/src/server/stdio.ts`, `packages/client/src/client/stdio.ts`) - For local process-spawned integrations\n\n### Server-Side Features\n\n- **Tools/Resources/Prompts**: Registered via `McpServer.tool()`, `.resource()`, `.prompt()` methods\n- **OAuth/Auth**: Full OAuth 2.0 server implementation in `packages/server/src/server/auth/`\n- **Completions**: Auto-completion support via `packages/server/src/server/completable.ts`\n\n### Client-Side Features\n\n- **Auth**: OAuth client support in `packages/client/src/client/auth.ts` and `packages/client/src/client/auth-extensions.ts`\n- **Client middleware**: Request middleware in `packages/client/src/client/middleware.ts` (unrelated to the framework adapter packages below)\n- **Sampling**: Clients can handle `sampling/createMessage` requests from servers (LLM completions)\n- **Elicitation**: Clients can handle `elicitation/create` requests for user input (form or URL mode)\n- **Roots**: Clients can expose filesystem roots to servers via `roots/list`\n\n### Middleware packages (framework/runtime adapters)\n\nThe repo also ships “middleware” packages under `packages/middleware/` (e.g. `@modelcontextprotocol/express`, `@modelcontextprotocol/hono`, `@modelcontextprotocol/node`). These are thin integration layers for specific frameworks/runtimes and should not add new MCP functionality.\n\n### Experimental Features\n\nLocated in `packages/*/src/experimental/`. Currently empty.\n\n### Zod Schemas\n\nThe SDK uses `zod/v4` internally. Schema utilities live in:\n\n- `packages/core-internal/src/util/schema.ts` - AnySchema alias and helpers for inspecting Zod objects\n\n### Validation\n\nPluggable JSON Schema validation (`packages/core-internal/src/validators/`):\n\n- `ajvProvider.ts` - Default Ajv-based validator\n- `cfWorkerProvider.ts` - Cloudflare Workers-compatible alternative\n\n### Examples\n\nRunnable examples in `examples/<story>/{server.ts,client.ts}` — each story is its own\n`@mcp-examples/<story>` workspace package and a self-verifying e2e test (the client connects,\nasserts results, exits non-zero on mismatch). `pnpm run:examples` runs every story over its\nconfigured transport×era legs; the `examples (build + e2e)` CI job is part of the per-PR gate\nbasket. See `examples/README.md` for the full story matrix.\n\n- `examples/shared/` — `@mcp-examples/shared` package. Root export is args-only (`parseExampleArgs`, `check`, `siblingPath`); the demo OAuth provider and `InMemoryEventStore` live at the `@mcp-examples/shared/auth` subpath so non-auth stories don't eagerly evaluate better-auth/express/better-sqlite3. Stories import only this plumbing and inline the SDK transport setup themselves — see `examples/CONTRIBUTING.md`.\n- `scripts/examples/` — runner (`run-examples.ts`)\n- `examples/guides/` — per-page snippet companions for the `docs/` guide pages (one `<section>/<page>.examples.ts` per page); fences sync via `pnpm sync:snippets`, and the runnable ones are executed in CI by `pnpm docs:examples`\n\n## Message Flow (Bidirectional Protocol)\n\nMCP is bidirectional: both client and server can send requests. Understanding this flow is essential when implementing new request types.\n\n### Class Hierarchy\n\n```\nProtocol (abstract base)\n├── Client (packages/client/src/client/client.ts)     - can send requests TO server, handle requests FROM server\n└── Server (packages/server/src/server/server.ts)     - can send requests TO client, handle requests FROM client\n    └── McpServer (packages/server/src/server/mcp.ts) - high-level wrapper around Server\n```\n\n### Outbound Flow: Sending Requests\n\nWhen code calls `client.callTool()` or `server.createMessage()`:\n\n1. **High-level method** (e.g., `Client.callTool()`) calls `this.request()`\n2. **`Protocol.request()`**:\n    - Assigns unique message ID\n    - Checks capabilities via `assertCapabilityForMethod()` (abstract, implemented by Client/Server)\n    - Creates response handler promise\n    - Calls `transport.send()` with JSON-RPC request\n    - Waits for response handler to resolve\n3. **Transport** serializes and sends over wire (HTTP, stdio, etc.)\n4. **`Protocol._onresponse()`** resolves the promise when response arrives\n\n### Inbound Flow: Handling Requests\n\nWhen a request arrives from the remote side:\n\n1. **Transport** receives message, calls `transport.onmessage()`\n2. **`Protocol.connect()`** routes to `_onrequest()`, `_onresponse()`, or `_onnotification()`\n3. **`Protocol._onrequest()`**:\n    - Looks up handler in `_requestHandlers` map (keyed by method name)\n    - Creates `BaseContext` with `signal`, `sessionId`, `sendNotification`, `sendRequest`, etc.\n    - Calls `buildContext()` to let subclasses enrich the context (e.g., Server adds HTTP request info)\n    - Invokes handler, sends JSON-RPC response back via transport\n4. **Handler** was registered via `setRequestHandler('method', handler)`\n\n### Handler Registration\n\n```typescript\n// In Client (for server→client requests like sampling, elicitation)\nclient.setRequestHandler('sampling/createMessage', async (request, ctx) => {\n  // Handle sampling request from server\n  return { role: \"assistant\", content: {...}, model: \"...\" };\n});\n\n// In Server (for client→server requests like tools/call)\nserver.setRequestHandler('tools/call', async (request, ctx) => {\n  // Handle tool call from client\n  return { content: [...] };\n});\n```\n\n### Request Handler Context\n\nThe `ctx` parameter in handlers provides a structured context:\n\n**`BaseContext`** (common to both Server and Client), fields organized into nested groups:\n\n- `sessionId?`: Transport session identifier\n- `mcpReq`: Request-level concerns\n    - `id`: JSON-RPC message ID\n    - `method`: Request method string (e.g., 'tools/call')\n    - `_meta?`: Request metadata\n    - `signal`: AbortSignal for cancellation\n    - `send(request, schema, options?)`: Send related request (for bidirectional flows)\n    - `notify(notification)`: Send related notification back\n- `http?`: HTTP transport info (undefined for stdio)\n    - `authInfo?`: Validated auth token info\n\n**`ServerContext`** extends `BaseContext.mcpReq` and `BaseContext.http?` via type intersection:\n\n- `mcpReq` adds: `log(level, data, logger?)`, `elicitInput(params, options?)`, `requestSampling(params, options?)`\n- `http?` adds: `req?` (HTTP request info), `closeSSE?`, `closeStandaloneSSE?`\n\n**`ClientContext`** is currently identical to `BaseContext`.\n\n### Capability Checking\n\nBoth sides declare capabilities during initialization. The SDK enforces these:\n\n- **Client→Server**: `Client.assertCapabilityForMethod()` checks `_serverCapabilities`\n- **Server→Client**: `Server.assertCapabilityForMethod()` checks `_clientCapabilities`\n- **Handler registration**: `assertRequestHandlerCapability()` validates local capabilities\n\n### Adding a New Request Type\n\n1. **Define schema** in `src/types.ts` (request params, result schema)\n2. **Add capability** to `ClientCapabilities` or `ServerCapabilities` in types\n3. **Implement sender** method in Client or Server class\n4. **Add capability check** in the appropriate `assertCapabilityForMethod()`\n5. **Register handler** on the receiving side with `setRequestHandler()`\n6. **For McpServer**: Add high-level wrapper method if needed\n\n### Server-Initiated Requests (Sampling, Elicitation)\n\nServer can request actions from client (requires client capability):\n\n```typescript\n// Server sends sampling request to client\nconst result = await server.createMessage({\n  messages: [...],\n  maxTokens: 100\n});\n\n// Client must have registered handler:\nclient.setRequestHandler('sampling/createMessage', async (request, extra) => {\n  // Client-side LLM call\n  return { role: \"assistant\", content: {...} };\n});\n```\n\n## Key Patterns\n\n### Request Handler Registration (Low-Level Server)\n\n```typescript\nserver.setRequestHandler('tools/call', async (request, extra) => {\n    // extra contains sessionId, authInfo, sendNotification, etc.\n    return {\n        /* result */\n    };\n});\n```\n\n### Tool Registration (High-Level McpServer)\n\n```typescript\nmcpServer.tool('tool-name', { param: z.string() }, async ({ param }, extra) => {\n    return { content: [{ type: 'text', text: 'result' }] };\n});\n```\n\n### Transport Connection\n\n```typescript\n// Server\n// (Node.js IncomingMessage/ServerResponse wrapper; exported by @modelcontextprotocol/node)\nconst transport = new NodeStreamableHTTPServerTransport({ sessionIdGenerator: () => randomUUID() });\nawait server.connect(transport);\n\n// Client\nconst transport = new StreamableHTTPClientTransport(new URL('http://localhost:3000/mcp'));\nawait client.connect(transport);\n```\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Build & Test Commands\n\n```sh\npnpm install         # Install all workspace dependencies\n\npnpm build:all       # Build all packages\npnpm lint:all        # Run ESLint + Prettier checks across all packages\npnpm lint:fix:all    # Auto-fix lint and formatting issues across all packages\npnpm typecheck:all   # Type-check all packages\npnpm test:all        # Run all tests (vitest) across all packages\npnpm check:all       # typecheck + lint across all packages\n\n# Run a single package script (examples)\n# Run a single package script from the repo root with pnpm filter\npnpm --filter @modelcontextprotocol/core-internal test                # vitest run (core)\npnpm --filter @modelcontextprotocol/core-internal test:watch          # vitest (watch)\npnpm --filter @modelcontextprotocol/core-internal test -- path/to/file.test.ts\npnpm --filter @modelcontextprotocol/core-internal test -- -t \"test name\"\n```\n\n## Breaking Changes\n\nWhen making breaking changes, add to the relevant subsystem section in\n`docs/migration/upgrade-to-v2.md` (or `docs/migration/support-2026-07-28.md` if the\nchange is 2026-07-28-only). Mechanical renames go in\n`packages/codemod/src/migrations/v1-to-v2/mappings/` and the codemod handles them — do\nnot reproduce mapping tables in the guide; link to the mapping file instead.\n\nInclude what changed, why, and how to migrate. Search for related sections and group related changes together rather than adding new standalone sections.\n\n## Code Style Guidelines\n\n- **TypeScript**: Strict type checking, ES modules, explicit return types\n- **Naming**: PascalCase for classes/types, camelCase for functions/variables\n- **Files**: Lowercase with hyphens, test files with `.test.ts` suffix\n- **Imports**: ES module style, no `.js` extension on relative imports (project uses `moduleResolution: bundler`), group imports logically\n- **Formatting**: 2-space indentation, semicolons required, single quotes preferred\n- **Testing**: Place tests under each package's `test/` directory (vitest only includes `test/**/*.test.ts`), use descriptive test names\n- **Comments**: JSDoc for public APIs, inline comments for complex logic\n\n### JSDoc `@example` Code Snippets\n\nJSDoc `@example` tags should pull type-checked code from companion `.examples.ts` files (e.g., `client.ts` → `client.examples.ts`). Use ` ```ts source=\"./file.examples.ts#regionName\" ` fences referencing `//#region regionName` blocks; region names follow `exportedName_variant` or `ClassName_methodName_variant` pattern (e.g., `applyMiddlewares_basicUsage`, `Client_connect_basicUsage`). For whole-file inclusion (any file type), omit the `#regionName`.\n\nRun `pnpm sync:snippets` to sync example content into JSDoc comments and markdown files.\n\n## Architecture Overview\n\n### Core Layers\n\nThe SDK is organized into three main layers:\n\n1. **Types Layer** (`packages/core-internal/src/types/types.ts`) - Protocol types generated from the MCP specification. All JSON-RPC message types, schemas, and protocol constants are defined here using Zod v4.\n\n2. **Protocol Layer** (`packages/core-internal/src/shared/protocol.ts`) - The abstract `Protocol` class that handles JSON-RPC message routing, request/response correlation, capability negotiation, and transport management. Both `Client` and `Server` extend this class.\n\n3. **High-Level APIs**:\n    - `Client` (`packages/client/src/client/client.ts`) - Client implementation extending Protocol with typed methods for MCP operations\n    - `Server` (`packages/server/src/server/server.ts`) - Server implementation extending Protocol with request handler registration\n    - `McpServer` (`packages/server/src/server/mcp.ts`) - High-level server API with simplified resource/tool/prompt registration\n\n### Public API Exports\n\nThe SDK separates internal code from the public API surface:\n\n- **`@modelcontextprotocol/core-internal`** (main entry, `packages/core-internal/src/index.ts`) — Internal barrel. Exports everything (including Zod schemas, Protocol class, stdio utils). Only consumed by sibling packages within the monorepo (`private: true`).\n- **`@modelcontextprotocol/core-internal/public`** (`packages/core-internal/src/exports/public/index.ts`) — Curated public API. Exports TypeScript types, error classes, constants, guards, and the `Protocol` base class (+ `mergeCapabilities`). Re-exported by client and server packages.\n- **`@modelcontextprotocol/client`** and **`@modelcontextprotocol/server`** (`packages/*/src/index.ts`) — Final public surface. Package-specific exports (named explicitly) plus re-exports from `core-internal/public`.\n- **`@modelcontextprotocol/core`** (`packages/core/src/index.ts`) — Public Zod-schema package and the canonical home of the schema source modules (`src/schemas.ts`, `src/auth.ts`, `src/constants.ts`). The root entry re-exports **only** the `*Schema` Zod constants (MCP spec + OAuth/OpenID) — the published home for raw runtime validation (`CallToolResultSchema.parse(...)`); runtime-neutral (`zod` is its only dependency). The `./internal` subpath re-exports the schema modules wholesale for the sibling packages: `core-internal` re-exports them at the old module paths, and the `client`/`server`/`server-legacy` bundles resolve `@modelcontextprotocol/core/internal` as a real external dependency instead of carrying their own schema copies (their public surfaces stay Zod-free).\n\nWhen modifying exports:\n\n- Use explicit named exports, not `export *`, in package `index.ts` files and `core-internal/public`.\n- Adding a symbol to a package `index.ts` makes it public API — do so intentionally.\n- Internal helpers should stay in the core internal barrel and not be added to `core-internal/public` or package index files.\n- The package root entry must stay runtime-neutral so browser and Cloudflare Workers bundlers can consume it. Exports whose module graph transitively touches unpolyfillable Node builtins (`node:child_process`, `node:net`, `cross-spawn`, etc.) must live at a named subpath export (e.g. `./stdio`) and be covered by a `barrelClean` test in that package.\n\n### Transport System\n\nTransports (`packages/core-internal/src/shared/transport.ts`) provide the communication layer:\n\n- **Streamable HTTP** (`packages/server/src/server/streamableHttp.ts`, `packages/client/src/client/streamableHttp.ts`) - Recommended transport for remote servers, supports SSE for streaming\n- **SSE** (`packages/server/src/server/sse.ts`, `packages/client/src/client/sse.ts`) - Legacy HTTP+SSE transport for backwards compatibility\n- **stdio** (`packages/server/src/server/stdio.ts`, `packages/client/src/client/stdio.ts`) - For local process-spawned integrations\n\n### Server-Side Features\n\n- **Tools/Resources/Prompts**: Registered via `McpServer.tool()`, `.resource()`, `.prompt()` methods\n- **OAuth/Auth**: Full OAuth 2.0 server implementation in `packages/server/src/server/auth/`\n- **Completions**: Auto-completion support via `packages/server/src/server/completable.ts`\n\n### Client-Side Features\n\n- **Auth**: OAuth client support in `packages/client/src/client/auth.ts` and `packages/client/src/client/auth-extensions.ts`\n- **Client middleware**: Request middleware in `packages/client/src/client/middleware.ts` (unrelated to the framework adapter packages below)\n- **Sampling**: Clients can handle `sampling/createMessage` requests from servers (LLM completions)\n- **Elicitation**: Clients can handle `elicitation/create` requests for user input (form or URL mode)\n- **Roots**: Clients can expose filesystem roots to servers via `roots/list`\n\n### Middleware packages (framework/runtime adapters)\n\nThe repo also ships “middleware” packages under `packages/middleware/` (e.g. `@modelcontextprotocol/express`, `@modelcontextprotocol/hono`, `@modelcontextprotocol/node`). These are thin integration layers for specific frameworks/runtimes and should not add new MCP functionality.\n\n### Experimental Features\n\nLocated in `packages/*/src/experimental/`. Currently empty.\n\n### Zod Schemas\n\nThe SDK uses `zod/v4` internally. Schema utilities live in:\n\n- `packages/core-internal/src/util/schema.ts` - AnySchema alias and helpers for inspecting Zod objects\n\n### Validation\n\nPluggable JSON Schema validation (`packages/core-internal/src/validators/`):\n\n- `ajvProvider.ts` - Default Ajv-based validator\n- `cfWorkerProvider.ts` - Cloudflare Workers-compatible alternative\n\n### Examples\n\nRunnable examples in `examples/<story>/{server.ts,client.ts}` — each story is its own\n`@mcp-examples/<story>` workspace package and a self-verifying e2e test (the client connects,\nasserts results, exits non-zero on mismatch). `pnpm run:examples` runs every story over its\nconfigured transport×era legs; the `examples (build + e2e)` CI job is part of the per-PR gate\nbasket. See `examples/README.md` for the full story matrix.\n\n- `examples/shared/` — `@mcp-examples/shared` package. Root export is args-only (`parseExampleArgs`, `check`, `siblingPath`); the demo OAuth provider and `InMemoryEventStore` live at the `@mcp-examples/shared/auth` subpath so non-auth stories don't eagerly evaluate better-auth/express/better-sqlite3. Stories import only this plumbing and inline the SDK transport setup themselves — see `examples/CONTRIBUTING.md`.\n- `scripts/examples/` — runner (`run-examples.ts`)\n- `examples/guides/` — per-page snippet companions for the `docs/` guide pages (one `<section>/<page>.examples.ts` per page); fences sync via `pnpm sync:snippets`, and the runnable ones are executed in CI by `pnpm docs:examples`\n\n## Message Flow (Bidirectional Protocol)\n\nMCP is bidirectional: both client and server can send requests. Understanding this flow is essential when implementing new request types.\n\n### Class Hierarchy\n\n```\nProtocol (abstract base)\n├── Client (packages/client/src/client/client.ts)     - can send requests TO server, handle requests FROM server\n└── Server (packages/server/src/server/server.ts)     - can send requests TO client, handle requests FROM client\n    └── McpServer (packages/server/src/server/mcp.ts) - high-level wrapper around Server\n```\n\n### Outbound Flow: Sending Requests\n\nWhen code calls `client.callTool()` or `server.createMessage()`:\n\n1. **High-level method** (e.g., `Client.callTool()`) calls `this.request()`\n2. **`Protocol.request()`**:\n    - Assigns unique message ID\n    - Checks capabilities via `assertCapabilityForMethod()` (abstract, implemented by Client/Server)\n    - Creates response handler promise\n    - Calls `transport.send()` with JSON-RPC request\n    - Waits for response handler to resolve\n3. **Transport** serializes and sends over wire (HTTP, stdio, etc.)\n4. **`Protocol._onresponse()`** resolves the promise when response arrives\n\n### Inbound Flow: Handling Requests\n\nWhen a request arrives from the remote side:\n\n1. **Transport** receives message, calls `transport.onmessage()`\n2. **`Protocol.connect()`** routes to `_onrequest()`, `_onresponse()`, or `_onnotification()`\n3. **`Protocol._onrequest()`**:\n    - Looks up handler in `_requestHandlers` map (keyed by method name)\n    - Creates `BaseContext` with `signal`, `sessionId`, `sendNotification`, `sendRequest`, etc.\n    - Calls `buildContext()` to let subclasses enrich the context (e.g., Server adds HTTP request info)\n    - Invokes handler, sends JSON-RPC response back via transport\n4. **Handler** was registered via `setRequestHandler('method', handler)`\n\n### Handler Registration\n\n```typescript\n// In Client (for server→client requests like sampling, elicitation)\nclient.setRequestHandler('sampling/createMessage', async (request, ctx) => {\n  // Handle sampling request from server\n  return { role: \"assistant\", content: {...}, model: \"...\" };\n});\n\n// In Server (for client→server requests like tools/call)\nserver.setRequestHandler('tools/call', async (request, ctx) => {\n  // Handle tool call from client\n  return { content: [...] };\n});\n```\n\n### Request Handler Context\n\nThe `ctx` parameter in handlers provides a structured context:\n\n**`BaseContext`** (common to both Server and Client), fields organized into nested groups:\n\n- `sessionId?`: Transport session identifier\n- `mcpReq`: Request-level concerns\n    - `id`: JSON-RPC message ID\n    - `method`: Request method string (e.g., 'tools/call')\n    - `_meta?`: Request metadata\n    - `signal`: AbortSignal for cancellation\n    - `send(request, schema, options?)`: Send related request (for bidirectional flows)\n    - `notify(notification)`: Send related notification back\n- `http?`: HTTP transport info (undefined for stdio)\n    - `authInfo?`: Validated auth token info\n\n**`ServerContext`** extends `BaseContext.mcpReq` and `BaseContext.http?` via type intersection:\n\n- `mcpReq` adds: `log(level, data, logger?)`, `elicitInput(params, options?)`, `requestSampling(params, options?)`\n- `http?` adds: `req?` (HTTP request info), `closeSSE?`, `closeStandaloneSSE?`\n\n**`ClientContext`** is currently identical to `BaseContext`.\n\n### Capability Checking\n\nBoth sides declare capabilities during initialization. The SDK enforces these:\n\n- **Client→Server**: `Client.assertCapabilityForMethod()` checks `_serverCapabilities`\n- **Server→Client**: `Server.assertCapabilityForMethod()` checks `_clientCapabilities`\n- **Handler registration**: `assertRequestHandlerCapability()` validates local capabilities\n\n### Adding a New Request Type\n\n1. **Define schema** in `src/types.ts` (request params, result schema)\n2. **Add capability** to `ClientCapabilities` or `ServerCapabilities` in types\n3. **Implement sender** method in Client or Server class\n4. **Add capability check** in the appropriate `assertCapabilityForMethod()`\n5. **Register handler** on the receiving side with `setRequestHandler()`\n6. **For McpServer**: Add high-level wrapper method if needed\n\n### Server-Initiated Requests (Sampling, Elicitation)\n\nServer can request actions from client (requires client capability):\n\n```typescript\n// Server sends sampling request to client\nconst result = await server.createMessage({\n  messages: [...],\n  maxTokens: 100\n});\n\n// Client must have registered handler:\nclient.setRequestHandler('sampling/createMessage', async (request, extra) => {\n  // Client-side LLM call\n  return { role: \"assistant\", content: {...} };\n});\n```\n\n## Key Patterns\n\n### Request Handler Registration (Low-Level Server)\n\n```typescript\nserver.setRequestHandler('tools/call', async (request, extra) => {\n    // extra contains sessionId, authInfo, sendNotification, etc.\n    return {\n        /* result */\n    };\n});\n```\n\n### Tool Registration (High-Level McpServer)\n\n```typescript\nmcpServer.tool('tool-name', { param: z.string() }, async ({ param }, extra) => {\n    return { content: [{ type: 'text', text: 'result' }] };\n});\n```\n\n### Transport Connection\n\n```typescript\n// Server\n// (Node.js IncomingMessage/ServerResponse wrapper; exported by @modelcontextprotocol/node)\nconst transport = new NodeStreamableHTTPServerTransport({ sessionIdGenerator: () => randomUUID() });\nawait server.connect(transport);\n\n// Client\nconst transport = new StreamableHTTPClientTransport(new URL('http://localhost:3000/mcp'));\nawait client.connect(transport);\n```\n","category":"root","tokens":3784}]}