Skip to content

Commit 81f1756

Browse files
Reorder docs/server.md sections for a clearer overview narrative
Move DNS rebinding protection and multi-node deployment patterns into a new `## Deployment` umbrella near the end — they were splitting the flow between Transports and core primitives. Promote Logging from a `####` under Tools to a `###` peer of Tools/Resources/Prompts, since `ctx.mcpReq.log()` is available in any handler, not just tools. Add a brief `#### Tool annotations` subsection under Tools (previously only in the catch-all table). Remove the Tool annotations row from the `More server features` table and drop the cross-link to client.md from the Completions section. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e9a6a34 commit 81f1756

1 file changed

Lines changed: 60 additions & 54 deletions

File tree

docs/server.md

Lines changed: 60 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -92,30 +92,6 @@ const transport = new StdioServerTransport();
9292
await server.connect(transport);
9393
```
9494

95-
## DNS rebinding protection
96-
97-
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:
98-
99-
```ts source="../examples/server/src/serverGuide.examples.ts#dnsRebinding_basic"
100-
// Default: DNS rebinding protection auto-enabled (host is 127.0.0.1)
101-
const app = createMcpExpressApp();
102-
103-
// DNS rebinding protection also auto-enabled for localhost
104-
const appLocal = createMcpExpressApp({ host: 'localhost' });
105-
106-
// No automatic protection when binding to all interfaces
107-
const appOpen = createMcpExpressApp({ host: '0.0.0.0' });
108-
```
109-
110-
When binding to `0.0.0.0` / `::`, provide an allow-list of hosts:
111-
112-
```ts source="../examples/server/src/serverGuide.examples.ts#dnsRebinding_allowedHosts"
113-
const app = createMcpExpressApp({
114-
host: '0.0.0.0',
115-
allowedHosts: ['localhost', '127.0.0.1', 'myhost.local']
116-
});
117-
```
118-
11995
## Tools, resources, and prompts
12096

12197
### Tools
@@ -185,37 +161,12 @@ server.registerTool(
185161
> [!NOTE]
186162
> For a full runnable example with `ResourceLink` outputs, see [`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts).
187163
188-
#### Logging
189-
190-
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:
191-
192-
```ts source="../examples/server/src/serverGuide.examples.ts#logging_capability"
193-
const server = new McpServer({ name: 'my-server', version: '1.0.0' }, { capabilities: { logging: {} } });
194-
```
164+
#### Tool annotations
195165

196-
Then log from any tool callback:
197-
198-
```ts source="../examples/server/src/serverGuide.examples.ts#registerTool_logging"
199-
server.registerTool(
200-
'fetch-data',
201-
{
202-
description: 'Fetch data from an API',
203-
inputSchema: z.object({ url: z.string() })
204-
},
205-
async ({ url }, ctx): Promise<CallToolResult> => {
206-
await ctx.mcpReq.log('info', `Fetching ${url}`);
207-
const res = await fetch(url);
208-
await ctx.mcpReq.log('debug', `Response status: ${res.status}`);
209-
const text = await res.text();
210-
return { content: [{ type: 'text', text }] };
211-
}
212-
);
213-
```
166+
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.
214167

215168
> [!NOTE]
216-
> 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).
217-
>
218-
> For protocol details, see [Logging](https://modelcontextprotocol.io/specification/latest/server/utilities/logging) in the MCP specification.
169+
> For tool annotations in a full server, see [`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts).
219170
220171
### Resources
221172

@@ -337,7 +288,37 @@ server.registerPrompt(
337288
);
338289
```
339290

340-
For client-side completion usage, see the [Client guide](client.md).
291+
### Logging
292+
293+
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:
294+
295+
```ts source="../examples/server/src/serverGuide.examples.ts#logging_capability"
296+
const server = new McpServer({ name: 'my-server', version: '1.0.0' }, { capabilities: { logging: {} } });
297+
```
298+
299+
Then log from any handler callback:
300+
301+
```ts source="../examples/server/src/serverGuide.examples.ts#registerTool_logging"
302+
server.registerTool(
303+
'fetch-data',
304+
{
305+
description: 'Fetch data from an API',
306+
inputSchema: z.object({ url: z.string() })
307+
},
308+
async ({ url }, ctx): Promise<CallToolResult> => {
309+
await ctx.mcpReq.log('info', `Fetching ${url}`);
310+
const res = await fetch(url);
311+
await ctx.mcpReq.log('debug', `Response status: ${res.status}`);
312+
const text = await res.text();
313+
return { content: [{ type: 'text', text }] };
314+
}
315+
);
316+
```
317+
318+
> [!NOTE]
319+
> 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).
320+
>
321+
> For protocol details, see [Logging](https://modelcontextprotocol.io/specification/latest/server/utilities/logging) in the MCP specification.
341322
342323
## Server‑initiated requests
343324

@@ -453,6 +434,32 @@ Task-based execution enables "call-now, fetch-later" patterns for long-running o
453434
> [!WARNING]
454435
> The tasks API is experimental and may change without notice.
455436
437+
## Deployment
438+
439+
### DNS rebinding protection
440+
441+
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:
442+
443+
```ts source="../examples/server/src/serverGuide.examples.ts#dnsRebinding_basic"
444+
// Default: DNS rebinding protection auto-enabled (host is 127.0.0.1)
445+
const app = createMcpExpressApp();
446+
447+
// DNS rebinding protection also auto-enabled for localhost
448+
const appLocal = createMcpExpressApp({ host: 'localhost' });
449+
450+
// No automatic protection when binding to all interfaces
451+
const appOpen = createMcpExpressApp({ host: '0.0.0.0' });
452+
```
453+
454+
When binding to `0.0.0.0` / `::`, provide an allow-list of hosts:
455+
456+
```ts source="../examples/server/src/serverGuide.examples.ts#dnsRebinding_allowedHosts"
457+
const app = createMcpExpressApp({
458+
host: '0.0.0.0',
459+
allowedHosts: ['localhost', '127.0.0.1', 'myhost.local']
460+
});
461+
```
462+
456463
## More server features
457464

458465
The sections above cover the essentials. The table below links to additional capabilities demonstrated in the runnable examples.
@@ -463,5 +470,4 @@ The sections above cover the essentials. The table below links to additional cap
463470
| Session management | Per-session transport routing, initialization, and cleanup | [`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts) |
464471
| Resumability | Replay missed SSE events via an event store | [`inMemoryEventStore.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/inMemoryEventStore.ts) |
465472
| 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) |
466-
| 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) |
467473
| 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) |

0 commit comments

Comments
 (0)