README refactor (#1197)

This commit is contained in:
Konstantin Konstantinov 2025-12-01 18:04:23 +02:00 • committed by GitHub
commit 74ab69ffa0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 486 additions and 1793 deletions

81
docs/capabilities.md Normal file
View file

@ -0,0 +1,81 @@
## Sampling
MCP servers can request LLM completions from connected clients that support the sampling capability. This lets your tools offload summarisation or generation to the client’s model.
For a runnable server that combines tools, logging and tasks, see:
- [`toolWithSampleServer.ts`](../src/examples/server/toolWithSampleServer.ts)
In practice you will:
- Declare the sampling capability on the client.
- Call `server.server.createMessage(...)` from within a tool handler.
- Return the model’s response as structured content and/or text.
Refer to the MCP spec’s sampling section for full request/response details.
## Elicitation
### Form elicitation
Form elicitation lets a tool ask the user for additional, **non‑sensitive** information via a schema‑driven form. The server sends a schema and message, and the client is responsible for collecting and returning the data.
Runnable example:
- Server: [`elicitationFormExample.ts`](../src/examples/server/elicitationFormExample.ts)
- Client‑side handling: [`simpleStreamableHttp.ts`](../src/examples/client/simpleStreamableHttp.ts)
The `simpleStreamableHttp` server also includes a `collect-user-info` tool that demonstrates how to drive elicitation from a tool and handle the response.
### URL elicitation
URL elicitation is designed for sensitive data and secure web‑based flows (e.g., collecting an API key, confirming a payment, or doing third‑party OAuth). Instead of returning form data, the server asks the client to open a URL and the rest of the flow happens in the browser.
Runnable example:
- Server: [`elicitationUrlExample.ts`](../src/examples/server/elicitationUrlExample.ts)
- Client: [`elicitationUrlExample.ts`](../src/examples/client/elicitationUrlExample.ts)
Key points:
- Use `mode: 'url'` when calling `server.server.elicitInput(...)`.
- Implement a client‑side handler for `ElicitRequestSchema` that:
- Shows the full URL and reason to the user.
- Asks for explicit consent.
- Opens the URL in the system browser.
Sensitive information **must not** be collected via form elicitation; always use URL elicitation or out‑of‑band flows for secrets.
## Task-based execution (experimental)
Task-based execution enables “call-now, fetch-later” patterns for long-running operations. Instead of returning a result immediately, a tool creates a task that can be polled or resumed later.
The APIs live under the experimental `.experimental.tasks` namespace and may change without notice.
### Server-side concepts
On the server you will:
- Provide a `TaskStore` implementation that persists task metadata and results.
- Enable the `tasks` capability when constructing the server.
- Register tools with `server.experimental.tasks.registerToolTask(...)`.
For a runnable example that uses the in-memory store shipped with the SDK, see:
- [`toolWithSampleServer.ts`](../src/examples/server/toolWithSampleServer.ts)
- `src/experimental/tasks/stores/in-memory.ts`
### Client-side usage
On the client, you use:
- `client.experimental.tasks.callToolStream(...)` to start a tool call that may create a task and emit status updates over time.
- `client.getTask(...)` and `client.getTaskResult(...)` to check status and fetch results after reconnecting.
The interactive client in:
- [`simpleStreamableHttp.ts`](../src/examples/client/simpleStreamableHttp.ts)
includes commands to demonstrate calling tools that support tasks and handling their lifecycle.
See the MCP spec’s tasks section and the example server/client above for a full walkthrough of the task status lifecycle and TTL handling.

60
docs/client.md Normal file
View file

@ -0,0 +1,60 @@
## Client overview
The SDK provides a high-level `Client` class that connects to MCP servers over different transports:
- `StdioClientTransport` – for local processes you spawn.
- `StreamableHTTPClientTransport` – for remote HTTP servers.
- `SSEClientTransport` – for legacy HTTP+SSE servers (deprecated).
Runnable client examples live under:
- [`simpleStreamableHttp.ts`](../src/examples/client/simpleStreamableHttp.ts)
- [`streamableHttpWithSseFallbackClient.ts`](../src/examples/client/streamableHttpWithSseFallbackClient.ts)
- [`ssePollingClient.ts`](../src/examples/client/ssePollingClient.ts)
- [`multipleClientsParallel.ts`](../src/examples/client/multipleClientsParallel.ts)
- [`parallelToolCallsClient.ts`](../src/examples/client/parallelToolCallsClient.ts)
## Connecting and basic operations
A typical flow:
1. Construct a `Client` with name, version and capabilities.
2. Create a transport and call `client.connect(transport)`.
3. Use high-level helpers:
- `listTools`, `callTool`
- `listPrompts`, `getPrompt`
- `listResources`, `readResource`
See [`simpleStreamableHttp.ts`](../src/examples/client/simpleStreamableHttp.ts) for an interactive CLI client that exercises these methods and shows how to handle notifications, elicitation and tasks.
## Transports and backwards compatibility
To support both modern Streamable HTTP and legacy SSE servers, use a client that:
1. Tries `StreamableHTTPClientTransport`.
2. Falls back to `SSEClientTransport` on a 4xx response.
Runnable example:
- [`streamableHttpWithSseFallbackClient.ts`](../src/examples/client/streamableHttpWithSseFallbackClient.ts)
## OAuth client authentication helpers
For OAuth-secured MCP servers, the client `auth` module exposes:
- `ClientCredentialsProvider`
- `PrivateKeyJwtProvider`
- `StaticPrivateKeyJwtProvider`
Examples:
- [`simpleOAuthClient.ts`](../src/examples/client/simpleOAuthClient.ts)
- [`simpleOAuthClientProvider.ts`](../src/examples/client/simpleOAuthClientProvider.ts)
- [`simpleClientCredentials.ts`](../src/examples/client/simpleClientCredentials.ts)
- Server-side auth demo: [`demoInMemoryOAuthProvider.ts`](../src/examples/server/demoInMemoryOAuthProvider.ts)
These examples show how to:
- Perform dynamic client registration if needed.
- Acquire access tokens.
- Attach OAuth credentials to Streamable HTTP requests.

65
docs/faq.md Normal file
View file

@ -0,0 +1,65 @@
## FAQ
<details>
<summary>Table of Contents</summary>
- [General](#general)
- [Clients](#clients)
- [Servers](#servers)
</details>
## General
### Why do I see `TS2589: Type instantiation is excessively deep and possibly infinite` after upgrading the SDK?
This TypeScript error can appear when upgrading to newer SDK versions that support Zod v4 (for example, from `@modelcontextprotocol/sdk` `1.22.0` to `1.23.0`) **and** your project ends up with multiple `zod` versions in the dependency tree.
When there are multiple copies or versions of `zod`, TypeScript may try to instantiate very complex, cross-version types and hit its recursion limits, resulting in `TS2589`. This scenario is discussed in GitHub issue
[#1180](https://github.com/modelcontextprotocol/typescript-sdk/issues/1180#event-21236550401).
To diagnose and fix this:
- **Inspect your installed `zod` versions**:
- Run `npm ls zod` or `npm explain zod`, `pnpm list zod` or `pnpm why zod`, or `yarn why zod` and check whether more than one version is installed.
- **Align on a single `zod` version**:
- Make sure all packages that depend on `zod` use a compatible version range so that your package manager can hoist a single copy.
- In monorepos, consider declaring `zod` at the workspace root and using compatible ranges in individual packages.
- **Use overrides/resolutions if necessary**:
- With npm, Yarn, or pnpm, you can use `overrides` / `resolutions` to force a single `zod` version if some transitive dependencies pull in a different one.
Once your project is using a single, compatible `zod` version, the `TS2589` error should no longer occur.
## Clients
### How do I enable Web Crypto (`globalThis.crypto`) for client authentication in older Node.js versions?
The SDK’s OAuth client authentication helpers (for example, those in `src/client/auth-extensions.ts` that use `jose`) rely on the Web Crypto API exposed as `globalThis.crypto`. This is especially important for **client credentials** and **JWT-based** authentication flows used by
MCP clients.
- **Node.js v19.0.0 and later**: `globalThis.crypto` is available by default.
- **Node.js v18.x**: `globalThis.crypto` may not be defined by default. In this repository we polyfill it for tests (see `vitest.setup.ts`), and you should do the same in your app if it is missing – or alternatively, run Node with `--experimental-global-webcrypto` as per your
Node version documentation. (See https://nodejs.org/dist/latest-v18.x/docs/api/globals.html#crypto )
If you run clients on Node.js versions where `globalThis.crypto` is missing, you can polyfill it using the built-in `node:crypto` module, similar to the SDK's own `vitest.setup.ts`:
```typescript
import { webcrypto } from 'node:crypto';
if (typeof globalThis.crypto === 'undefined') {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(globalThis as any).crypto = webcrypto as unknown as Crypto;
}
```
For production use, you can either:
- Run clients on a Node.js version where `globalThis.crypto` is available by default (recommended), or
- Apply a similar polyfill early in your client's startup code when targeting older Node.js runtimes, so that OAuth client authentication works reliably.
## Servers
### Where can I find runnable server examples?
The SDK ships several runnable server examples under `src/examples/server`. The root `README.md` contains a curated **Server examples** table that links to each scenario (stateful/stateless Streamable HTTP, JSON-only mode, SSE/backwards compatibility, elicitation, sampling,
tasks, and OAuth demos), and `src/examples/README.md` includes commands and deployment diagrams for running them.

198
docs/server.md Normal file
View file

@ -0,0 +1,198 @@
## Server overview
This SDK lets you build MCP servers in TypeScript and connect them to different transports. For most use cases you will use `McpServer` from `@modelcontextprotocol/sdk/server/mcp.js` and choose one of:
- **Streamable HTTP** (recommended for remote servers)
- **HTTP + SSE** (deprecated, for backwards compatibility only)
- **stdio** (for local, process‑spawned integrations)
For a complete, runnable example server, see:
- [`simpleStreamableHttp.ts`](../src/examples/server/simpleStreamableHttp.ts) – feature‑rich Streamable HTTP server
- [`jsonResponseStreamableHttp.ts`](../src/examples/server/jsonResponseStreamableHttp.ts) – Streamable HTTP with JSON response mode
- [`simpleStatelessStreamableHttp.ts`](../src/examples/server/simpleStatelessStreamableHttp.ts) – stateless Streamable HTTP server
- [`simpleSseServer.ts`](../src/examples/server/simpleSseServer.ts) – deprecated HTTP+SSE transport
- [`sseAndStreamableHttpCompatibleServer.ts`](../src/examples/server/sseAndStreamableHttpCompatibleServer.ts) – backwards‑compatible server for old and new clients
## Transports
### Streamable HTTP
Streamable HTTP is the modern, fully featured transport. It supports:
- Request/response over HTTP POST
- Server‑to‑client notifications over SSE (when enabled)
- Optional JSON‑only response mode with no SSE
- Session management and resumability
Key examples:
- [`simpleStreamableHttp.ts`](../src/examples/server/simpleStreamableHttp.ts) – sessions, logging, tasks, elicitation, auth hooks
- [`jsonResponseStreamableHttp.ts`](../src/examples/server/jsonResponseStreamableHttp.ts) – `enableJsonResponse: true`, no SSE
- [`standaloneSseWithGetStreamableHttp.ts`](../src/examples/server/standaloneSseWithGetStreamableHttp.ts) – notifications with Streamable HTTP GET + SSE
See the MCP spec for full transport details:
`https://modelcontextprotocol.io/specification/2025-03-26/basic/transports`
### Stateless vs stateful sessions
Streamable HTTP can run:
- **Stateless** – no session tracking, ideal for simple API‑style servers.
- **Stateful** – sessions have IDs, and you can enable resumability and advanced features.
Examples:
- Stateless Streamable HTTP: [`simpleStatelessStreamableHttp.ts`](../src/examples/server/simpleStatelessStreamableHttp.ts)
- Stateful with resumability: [`simpleStreamableHttp.ts`](../src/examples/server/simpleStreamableHttp.ts)
### Deprecated HTTP + SSE
The older HTTP+SSE transport (protocol version 2024‑11‑05) is supported only for backwards compatibility. New implementations should prefer Streamable HTTP.
Examples:
- Legacy SSE server: [`simpleSseServer.ts`](../src/examples/server/simpleSseServer.ts)
- Backwards‑compatible server (Streamable HTTP + SSE):
[`sseAndStreamableHttpCompatibleServer.ts`](../src/examples/server/sseAndStreamableHttpCompatibleServer.ts)
## Running your server
For a minimal “getting started” experience:
1. Start from [`simpleStreamableHttp.ts`](../src/examples/server/simpleStreamableHttp.ts).
2. Remove features you do not need (tasks, advanced logging, OAuth, etc.).
3. Register your own tools, resources and prompts.
For more detailed patterns (stateless vs stateful, JSON response mode, CORS, DNS rebind protection), see the examples above and the MCP spec sections on transports.
## Tools, resources, and prompts
### Tools
Tools let MCP clients ask your server to take actions. They are usually the main way that LLMs call into your application.
A typical registration with `registerTool` looks like this:
```typescript
server.registerTool(
'calculate-bmi',
{
title: 'BMI Calculator',
description: 'Calculate Body Mass Index',
inputSchema: {
weightKg: z.number(),
heightM: z.number()
},
outputSchema: { bmi: z.number() }
},
async ({ weightKg, heightM }) => {
const output = { bmi: weightKg / (heightM * heightM) };
return {
content: [{ type: 'text', text: JSON.stringify(output) }],
structuredContent: output
};
}
);
```
This snippet is illustrative only; for runnable servers that expose tools, see:
- [`simpleStreamableHttp.ts`](../src/examples/server/simpleStreamableHttp.ts)
- [`toolWithSampleServer.ts`](../src/examples/server/toolWithSampleServer.ts)
#### ResourceLink outputs
Tools can return `resource_link` content items to reference large resources without embedding them directly, allowing clients to fetch only what they need.
The README’s `list-files` example shows the pattern conceptually; for concrete usage, see the Streamable HTTP examples in `src/examples/server`.
### Resources
Resources expose data to clients, but should not perform heavy computation or side‑effects. They are ideal for configuration, documents, or other reference data.
Conceptually, you might register resources like:
```typescript
server.registerResource(
'config',
'config://app',
{
title: 'Application Config',
description: 'Application configuration data',
mimeType: 'text/plain'
},
async uri => ({
contents: [{ uri: uri.href, text: 'App configuration here' }]
})
);
```
Dynamic resources use `ResourceTemplate` and can support completions on path parameters. For full runnable examples of resources:
- [`simpleStreamableHttp.ts`](../src/examples/server/simpleStreamableHttp.ts)
### Prompts
Prompts are reusable templates that help humans (or client UIs) talk to models in a consistent way. They are declared on the server and listed through MCP.
A minimal prompt:
```typescript
server.registerPrompt(
'review-code',
{
title: 'Code Review',
description: 'Review code for best practices and potential issues',
argsSchema: { code: z.string() }
},
({ code }) => ({
messages: [
{
role: 'user',
content: {
type: 'text',
text: `Please review this code:\n\n${code}`
}
}
]
})
);
```
For prompts integrated into a full server, see:
- [`simpleStreamableHttp.ts`](../src/examples/server/simpleStreamableHttp.ts)
### Completions
Both prompts and resources can support argument completions. On the client side, you use `client.complete()` with a reference to the prompt or resource and the partially‑typed argument.
See the MCP spec sections on prompts and resources for complete details, and [`simpleStreamableHttp.ts`](../src/examples/client/simpleStreamableHttp.ts) for client‑side usage patterns.
### Display names and metadata
Tools, resources and prompts support a `title` field for human‑readable names. Older APIs can also attach `annotations.title`. To compute the correct display name on the client, use:
- `getDisplayName` from `@modelcontextprotocol/sdk/shared/metadataUtils.js`
## Multi‑node deployment patterns
The SDK supports multi‑node deployments using Streamable HTTP. The high‑level patterns are documented in [`README.md`](../src/examples/README.md):
- Stateless mode (any node can handle any request)
- Persistent storage mode (shared database for session state)
- Local state with message routing (message queue + pub/sub)
Those deployment diagrams are kept in [`README.md`](../src/examples/README.md) so the examples and documentation stay aligned.
## Backwards compatibility
To handle both modern and legacy clients:
- Run a backwards‑compatible server:
- [`sseAndStreamableHttpCompatibleServer.ts`](../src/examples/server/sseAndStreamableHttpCompatibleServer.ts)
- Use a client that falls back from Streamable HTTP to SSE:
- [`streamableHttpWithSseFallbackClient.ts`](../src/examples/client/streamableHttpWithSseFallbackClient.ts)
For the detailed protocol rules, see the “Backwards compatibility” section of the MCP spec.