Dissolve capabilities.md into server.md and client.md (#1532)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
dc896e198b
commit
284a4135f2
1 changed files with 336 additions and 161 deletions
235
docs/server.md
235
docs/server.md
|
|
@ -2,7 +2,7 @@
|
|||
title: Server
|
||||
---
|
||||
|
||||
## Server overview
|
||||
# Server overview
|
||||
|
||||
This guide covers SDK usage for building MCP servers in TypeScript. For protocol-level details and message formats, see the [MCP specification](https://modelcontextprotocol.io/specification/latest/).
|
||||
|
||||
|
|
@ -92,30 +92,6 @@ const transport = new StdioServerTransport();
|
|||
await server.connect(transport);
|
||||
```
|
||||
|
||||
## DNS rebinding protection
|
||||
|
||||
MCP servers running on localhost are vulnerable to DNS rebinding attacks. Use `createMcpExpressApp()` from `@modelcontextprotocol/express` to create an Express app with DNS rebinding protection enabled by default:
|
||||
|
||||
```ts source="../examples/server/src/serverGuide.examples.ts#dnsRebinding_basic"
|
||||
// Default: DNS rebinding protection auto-enabled (host is 127.0.0.1)
|
||||
const app = createMcpExpressApp();
|
||||
|
||||
// DNS rebinding protection also auto-enabled for localhost
|
||||
const appLocal = createMcpExpressApp({ host: 'localhost' });
|
||||
|
||||
// No automatic protection when binding to all interfaces
|
||||
const appOpen = createMcpExpressApp({ host: '0.0.0.0' });
|
||||
```
|
||||
|
||||
When binding to `0.0.0.0` / `::`, provide an allow-list of hosts:
|
||||
|
||||
```ts source="../examples/server/src/serverGuide.examples.ts#dnsRebinding_allowedHosts"
|
||||
const app = createMcpExpressApp({
|
||||
host: '0.0.0.0',
|
||||
allowedHosts: ['localhost', '127.0.0.1', 'myhost.local']
|
||||
});
|
||||
```
|
||||
|
||||
## Tools, resources, and prompts
|
||||
|
||||
### Tools
|
||||
|
|
@ -185,37 +161,12 @@ server.registerTool(
|
|||
> [!NOTE]
|
||||
> For a full runnable example with `ResourceLink` outputs, see [`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts).
|
||||
|
||||
#### Logging
|
||||
#### Tool annotations
|
||||
|
||||
Use `ctx.mcpReq.log(level, data)` (from {@linkcode @modelcontextprotocol/server!index.ServerContext | ServerContext}) inside a tool handler to send structured log messages to the client. The server must declare the `logging` capability:
|
||||
|
||||
```ts source="../examples/server/src/serverGuide.examples.ts#logging_capability"
|
||||
const server = new McpServer({ name: 'my-server', version: '1.0.0' }, { capabilities: { logging: {} } });
|
||||
```
|
||||
|
||||
Then log from any tool callback:
|
||||
|
||||
```ts source="../examples/server/src/serverGuide.examples.ts#registerTool_logging"
|
||||
server.registerTool(
|
||||
'fetch-data',
|
||||
{
|
||||
description: 'Fetch data from an API',
|
||||
inputSchema: z.object({ url: z.string() })
|
||||
},
|
||||
async ({ url }, ctx): Promise<CallToolResult> => {
|
||||
await ctx.mcpReq.log('info', `Fetching ${url}`);
|
||||
const res = await fetch(url);
|
||||
await ctx.mcpReq.log('debug', `Response status: ${res.status}`);
|
||||
const text = await res.text();
|
||||
return { content: [{ type: 'text', text }] };
|
||||
}
|
||||
);
|
||||
```
|
||||
Tools can include annotations that hint at their behavior — for example, whether a tool is read‑only, destructive, or idempotent. Annotations help clients present tools appropriately without changing their execution semantics.
|
||||
|
||||
> [!NOTE]
|
||||
> For logging in a full server, see [`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts) and [`jsonResponseStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/jsonResponseStreamableHttp.ts).
|
||||
>
|
||||
> For protocol details, see [Logging](https://modelcontextprotocol.io/specification/latest/server/utilities/logging) in the MCP specification.
|
||||
> For tool annotations in a full server, see [`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts).
|
||||
|
||||
### Resources
|
||||
|
||||
|
|
@ -337,11 +288,181 @@ server.registerPrompt(
|
|||
);
|
||||
```
|
||||
|
||||
For client-side completion usage, see the [Client guide](client.md).
|
||||
### Logging
|
||||
|
||||
Unlike tools, resources, and prompts, logging is not a registered primitive — it is a handler-level API available inside any callback. Use `ctx.mcpReq.log(level, data)` (from {@linkcode @modelcontextprotocol/server!index.ServerContext | ServerContext}) to send structured log messages to the client. The server must declare the `logging` capability:
|
||||
|
||||
```ts source="../examples/server/src/serverGuide.examples.ts#logging_capability"
|
||||
const server = new McpServer({ name: 'my-server', version: '1.0.0' }, { capabilities: { logging: {} } });
|
||||
```
|
||||
|
||||
Then log from any handler callback:
|
||||
|
||||
```ts source="../examples/server/src/serverGuide.examples.ts#registerTool_logging"
|
||||
server.registerTool(
|
||||
'fetch-data',
|
||||
{
|
||||
description: 'Fetch data from an API',
|
||||
inputSchema: z.object({ url: z.string() })
|
||||
},
|
||||
async ({ url }, ctx): Promise<CallToolResult> => {
|
||||
await ctx.mcpReq.log('info', `Fetching ${url}`);
|
||||
const res = await fetch(url);
|
||||
await ctx.mcpReq.log('debug', `Response status: ${res.status}`);
|
||||
const text = await res.text();
|
||||
return { content: [{ type: 'text', text }] };
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> For logging in a full server, see [`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts) and [`jsonResponseStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/jsonResponseStreamableHttp.ts).
|
||||
>
|
||||
> For protocol details, see [Logging](https://modelcontextprotocol.io/specification/latest/server/utilities/logging) in the MCP specification.
|
||||
|
||||
## Server‑initiated requests
|
||||
|
||||
MCP is bidirectional — servers can also send requests *to* the client during tool execution, as long as the client declares matching capabilities.
|
||||
|
||||
### Sampling
|
||||
|
||||
Use `ctx.mcpReq.requestSampling(params)` (from {@linkcode @modelcontextprotocol/server!index.ServerContext | ServerContext}) inside a tool handler to request an LLM completion from the connected client:
|
||||
|
||||
```ts source="../examples/server/src/serverGuide.examples.ts#registerTool_sampling"
|
||||
server.registerTool(
|
||||
'summarize',
|
||||
{
|
||||
description: 'Summarize text using the client LLM',
|
||||
inputSchema: z.object({ text: z.string() })
|
||||
},
|
||||
async ({ text }, ctx): Promise<CallToolResult> => {
|
||||
const response = await ctx.mcpReq.requestSampling({
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
content: {
|
||||
type: 'text',
|
||||
text: `Please summarize:\n\n${text}`
|
||||
}
|
||||
}
|
||||
],
|
||||
maxTokens: 500
|
||||
});
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Model (${response.model}): ${JSON.stringify(response.content)}`
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> For a full runnable example, see [`toolWithSampleServer.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/toolWithSampleServer.ts).
|
||||
>
|
||||
> For protocol details, see [Sampling](https://modelcontextprotocol.io/specification/latest/client/sampling) in the MCP specification.
|
||||
|
||||
### Elicitation
|
||||
|
||||
Use `ctx.mcpReq.elicitInput(params)` (from {@linkcode @modelcontextprotocol/server!index.ServerContext | ServerContext}) inside a tool handler to request user input. Elicitation supports two modes:
|
||||
|
||||
- **Form** (`mode: 'form'`) — collects **non‑sensitive** data via a schema‑driven form.
|
||||
- **URL** (`mode: 'url'`) — for sensitive data or secure web‑based flows (API keys, payments, OAuth). The client opens a URL in the browser.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Sensitive information **must not** be collected via form elicitation; always use URL elicitation or out‑of‑band flows for secrets.
|
||||
|
||||
```ts source="../examples/server/src/serverGuide.examples.ts#registerTool_elicitation"
|
||||
server.registerTool(
|
||||
'collect-feedback',
|
||||
{
|
||||
description: 'Collect user feedback via a form',
|
||||
inputSchema: z.object({})
|
||||
},
|
||||
async (_args, ctx): Promise<CallToolResult> => {
|
||||
const result = await ctx.mcpReq.elicitInput({
|
||||
mode: 'form',
|
||||
message: 'Please share your feedback:',
|
||||
requestedSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
rating: {
|
||||
type: 'number',
|
||||
title: 'Rating (1\u20135)',
|
||||
minimum: 1,
|
||||
maximum: 5
|
||||
},
|
||||
comment: { type: 'string', title: 'Comment' }
|
||||
},
|
||||
required: ['rating']
|
||||
}
|
||||
});
|
||||
if (result.action === 'accept') {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Thanks! ${JSON.stringify(result.content)}`
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
return { content: [{ type: 'text', text: 'Feedback declined.' }] };
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> For runnable examples, see [`elicitationFormExample.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/elicitationFormExample.ts) (form mode) and [`elicitationUrlExample.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/elicitationUrlExample.ts) (URL mode).
|
||||
>
|
||||
> For protocol details, see [Elicitation](https://modelcontextprotocol.io/specification/latest/client/elicitation) in the MCP specification.
|
||||
|
||||
## Tasks (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. To use tasks:
|
||||
|
||||
- Provide a {@linkcode @modelcontextprotocol/server!index.TaskStore | TaskStore} implementation that persists task metadata and results (see {@linkcode @modelcontextprotocol/server!index.InMemoryTaskStore | InMemoryTaskStore} for reference).
|
||||
- Enable the `tasks` capability when constructing the server.
|
||||
- Register tools with {@linkcode @modelcontextprotocol/server!experimental/tasks/mcpServer.ExperimentalMcpServerTasks#registerToolTask | server.experimental.tasks.registerToolTask(...)}.
|
||||
|
||||
> [!NOTE]
|
||||
> For a full runnable example, see [`simpleTaskInteractive.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleTaskInteractive.ts).
|
||||
|
||||
> [!WARNING]
|
||||
> The tasks API is experimental and may change without notice.
|
||||
|
||||
## Deployment
|
||||
|
||||
### DNS rebinding protection
|
||||
|
||||
MCP servers running on localhost are vulnerable to DNS rebinding attacks. Use `createMcpExpressApp()` from `@modelcontextprotocol/express` to create an Express app with DNS rebinding protection enabled by default:
|
||||
|
||||
```ts source="../examples/server/src/serverGuide.examples.ts#dnsRebinding_basic"
|
||||
// Default: DNS rebinding protection auto-enabled (host is 127.0.0.1)
|
||||
const app = createMcpExpressApp();
|
||||
|
||||
// DNS rebinding protection also auto-enabled for localhost
|
||||
const appLocal = createMcpExpressApp({ host: 'localhost' });
|
||||
|
||||
// No automatic protection when binding to all interfaces
|
||||
const appOpen = createMcpExpressApp({ host: '0.0.0.0' });
|
||||
```
|
||||
|
||||
When binding to `0.0.0.0` / `::`, provide an allow-list of hosts:
|
||||
|
||||
```ts source="../examples/server/src/serverGuide.examples.ts#dnsRebinding_allowedHosts"
|
||||
const app = createMcpExpressApp({
|
||||
host: '0.0.0.0',
|
||||
allowedHosts: ['localhost', '127.0.0.1', 'myhost.local']
|
||||
});
|
||||
```
|
||||
|
||||
## More server features
|
||||
|
||||
The sections above cover the essentials. The SDK supports several additional capabilities — each is demonstrated in the runnable examples and covered in more detail in the linked references.
|
||||
The sections above cover the essentials. The table below links to additional capabilities demonstrated in the runnable examples.
|
||||
|
||||
| Feature | Description | Reference |
|
||||
|---------|-------------|-----------|
|
||||
|
|
@ -349,8 +470,4 @@ The sections above cover the essentials. The SDK supports several additional cap
|
|||
| Session management | Per-session transport routing, initialization, and cleanup | [`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts) |
|
||||
| Resumability | Replay missed SSE events via an event store | [`inMemoryEventStore.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/inMemoryEventStore.ts) |
|
||||
| CORS | Expose MCP headers (`mcp-session-id`, etc.) for browser clients | [`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts) |
|
||||
| Tool annotations | Hint whether tools are read-only, destructive, etc. | [`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts) |
|
||||
| Elicitation | Request user input (forms or URLs) during tool execution | [Capabilities guide](capabilities.md#elicitation), [`elicitationFormExample.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/elicitationFormExample.ts) |
|
||||
| Sampling | Request LLM completions from the connected client | [Capabilities guide](capabilities.md#sampling), [`toolWithSampleServer.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/toolWithSampleServer.ts) |
|
||||
| Tasks (experimental) | Long-running operations with polling and resumption | [Capabilities guide](capabilities.md#task-based-execution-experimental), [`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts) |
|
||||
| Multi‑node deployment | Stateless, persistent‑storage, and distributed routing patterns | [`examples/server/README.md`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/README.md#multi-node-deployment-patterns) |
|
||||
|
|
|
|||
Loading…
Reference in a new issue