You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: clarify automatic vs manual sendToolListChanged usage
Address review feedback: registerTool, tool.remove(), tool.enable(),
and tool.disable() already fire the notification automatically. Reserve
sendToolListChanged() for external state changes the SDK cannot observe
(e.g. feature flags). Also fix spec link to use /latest/ pattern.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instructions describe how to use the server and its features — cross-tool relationships, workflow patterns, and constraints (see [Instructions](https://modelcontextprotocol.io/specification/latest/basic/lifecycle#instructions) in the MCP specification). Clients may add them to the system prompt. Instructions should not duplicate information already in tool descriptions.
66
+
Instructions describe how to use the server and its features — cross-tool relationships, workflow patterns, and constraints (see [Instructions](https://modelcontextprotocol.io/specification/latest/basic/lifecycle#instructions) in the MCP specification). Clients may add them to
67
+
the system prompt. Instructions should not duplicate information already in tool descriptions.
'Always call list_tables before running queries. Use validate_schema before migrate_schema for safe migrations. Results are limited to 1000 rows.'
73
+
instructions: 'Always call list_tables before running queries. Use validate_schema before migrate_schema for safe migrations. Results are limited to 1000 rows.'
74
74
}
75
75
);
76
76
```
@@ -103,12 +103,13 @@ server.registerTool(
103
103
);
104
104
```
105
105
106
-
> [!NOTE]
107
-
> When defining a named type for `structuredContent`, use a `type` alias rather than an `interface`. Named interfaces lack implicit index signatures in TypeScript, so they aren't assignable to `{ [key: string]: unknown }`:
106
+
> [!NOTE] When defining a named type for `structuredContent`, use a `type` alias rather than an `interface`. Named interfaces lack implicit index signatures in TypeScript, so they aren't assignable to `{ [key: string]: unknown }`:
108
107
>
109
108
> ```ts
110
-
>typeBmiResult= { bmi:number }; // assignable
111
-
>interfaceBmiResult { bmi:number } // type error
109
+
>typeBmiResult= { bmi:number }; // assignable
110
+
>interfaceBmiResult {
111
+
> bmi:number;
112
+
> } // type error
112
113
>```
113
114
>
114
115
> Alternatively, spread the value: `structuredContent: { ...result }`.
@@ -203,26 +204,33 @@ If a handler throws instead of returning `isError`, the SDK catches the exceptio
203
204
204
205
### List changed notifications
205
206
206
-
When the set of available tools changes at runtime, the server should notify connected clients so they can refresh their tool list (see [List Changed Notification](https://spec.modelcontextprotocol.io/specification/2025-06-18/server/tools/#list-changed-notification) in the MCP specification).
207
+
When the set of available tools changes at runtime, the server should notify connected clients so they can refresh their tool list (see [List Changed Notification](https://modelcontextprotocol.io/specification/latest/server/tools/#list-changed-notification) in the MCP
208
+
specification).
207
209
208
-
{@linkcode@modelcontextprotocol/server!server/mcp.McpServer#registerTool | registerTool} sends this notification automatically when called after the client is already connected. To notify manually — for example, after removing a tool or toggling tool availability — call {@linkcode@modelcontextprotocol/server!server/mcp.McpServer#sendToolListChanged | sendToolListChanged}:
210
+
The SDK sends this notification automatically whenever you call {@linkcode@modelcontextprotocol/server!server/mcp.McpServer#registerTool | registerTool}, `tool.remove()`, `tool.enable()`, or `tool.disable()` while a client is connected — no extra code needed.
211
+
212
+
For changes the SDK cannot observe — for example, an external feature flag that alters which tools are available — call {@linkcode@modelcontextprotocol/server!server/mcp.McpServer#sendToolListChanged | sendToolListChanged} manually:
// Manual: notify clients explicitly (e.g. after removing a tool)
222
+
// Manual: notify clients when tool availability changes through external
223
+
// means the SDK cannot observe (e.g. a feature flag or config reload).
217
224
server.sendToolListChanged();
218
225
```
219
226
220
-
> [!NOTE]
221
-
> On the client side, use the {@linkcode@modelcontextprotocol/client!client/client.ClientOptions | listChanged} option to automatically re-fetch tool lists when this notification arrives — see [Automatic list-change tracking](./client.md#automatic-list-change-tracking)in the client guide.
227
+
> [!NOTE] On the client side, use the {@linkcode@modelcontextprotocol/client!client/client.ClientOptions | listChanged} option to automatically re-fetch tool lists when this notification arrives — see [Automatic list-change tracking](./client.md#automatic-list-change-tracking)
228
+
> in the client guide.
222
229
223
230
## Resources
224
231
225
-
Resources expose read-only data — files, database schemas, configuration — that the host application can retrieve and attach as context for the model (see [Resources](https://modelcontextprotocol.io/docs/learn/server-concepts#resources) in the MCP overview). Unlike [tools](#tools), which the LLM invokes on its own, resources are application-controlled: the host decides which resources to fetch and how to present them.
232
+
Resources expose read-only data — files, database schemas, configuration — that the host application can retrieve and attach as context for the model (see [Resources](https://modelcontextprotocol.io/docs/learn/server-concepts#resources) in the MCP overview). Unlike
233
+
[tools](#tools), which the LLM invokes on its own, resources are application-controlled: the host decides which resources to fetch and how to present them.
226
234
227
235
A static resource at a fixed URI:
228
236
@@ -272,7 +280,8 @@ server.registerResource(
272
280
273
281
## Prompts
274
282
275
-
Prompts are reusable templates that help structure interactions with models (see [Prompts](https://modelcontextprotocol.io/docs/learn/server-concepts#prompts) in the MCP overview). Use a prompt when you want to offer a canned interaction pattern that users invoke explicitly; use a [tool](#tools) when the LLM should decide when to call it.
283
+
Prompts are reusable templates that help structure interactions with models (see [Prompts](https://modelcontextprotocol.io/docs/learn/server-concepts#prompts) in the MCP overview). Use a prompt when you want to offer a canned interaction pattern that users invoke explicitly; use
284
+
a [tool](#tools) when the LLM should decide when to call it.
MCP is bidirectional — servers can send requests *to* the client during tool execution, as long as the client declares matching capabilities (see [Architecture](https://modelcontextprotocol.io/docs/learn/architecture) in the MCP overview).
408
+
MCP is bidirectional — servers can send requests _to_ the client during tool execution, as long as the client declares matching capabilities (see [Architecture](https://modelcontextprotocol.io/docs/learn/architecture) in the MCP overview).
402
409
403
410
### Sampling
404
411
405
-
Sampling lets a tool handler request an LLM completion from the connected client — the handler describes a prompt and the client returns the model's response (see [Sampling](https://modelcontextprotocol.io/docs/learn/client-concepts#sampling) in the MCP overview). Use sampling when a tool needs the model to generate or transform text mid-execution.
412
+
Sampling lets a tool handler request an LLM completion from the connected client — the handler describes a prompt and the client returns the model's response (see [Sampling](https://modelcontextprotocol.io/docs/learn/client-concepts#sampling) in the MCP overview). Use sampling
413
+
when a tool needs the model to generate or transform text mid-execution.
406
414
407
415
Call `ctx.mcpReq.requestSampling(params)` (from {@linkcode@modelcontextprotocol/server!index.ServerContext | ServerContext}) inside a tool handler:
408
416
@@ -447,8 +455,7 @@ Elicitation lets a tool handler request direct input from the user — form fiel
447
455
-**Form** (`mode: 'form'`) — collects non-sensitive data via a schema-driven form.
448
456
-**URL** (`mode: 'url'`) — opens a browser URL for sensitive data or secure flows (API keys, payments, OAuth).
449
457
450
-
> [!IMPORTANT]
451
-
> Sensitive information must not be collected via form elicitation; always use URL elicitation or out-of-band flows for secrets.
458
+
> [!IMPORTANT] Sensitive information must not be collected via form elicitation; always use URL elicitation or out-of-band flows for secrets.
452
459
453
460
Call `ctx.mcpReq.elicitInput(params)` (from {@linkcode@modelcontextprotocol/server!index.ServerContext | ServerContext}) inside a tool handler:
454
461
@@ -492,11 +499,13 @@ server.registerTool(
492
499
);
493
500
```
494
501
495
-
For runnable examples, see [`elicitationFormExample.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/elicitationFormExample.ts) (form) and [`elicitationUrlExample.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/elicitationUrlExample.ts) (URL).
502
+
For runnable examples, see [`elicitationFormExample.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/elicitationFormExample.ts) (form) and
Roots let a tool handler discover the client's workspace directories — for example, to scope a file search or identify project boundaries (see [Roots](https://modelcontextprotocol.io/docs/learn/client-concepts#roots) in the MCP overview). Call {@linkcode@modelcontextprotocol/server!server/server.Server#listRoots | server.server.listRoots()} (requires the client to declare the `roots` capability):
507
+
Roots let a tool handler discover the client's workspace directories — for example, to scope a file search or identify project boundaries (see [Roots](https://modelcontextprotocol.io/docs/learn/client-concepts#roots) in the MCP overview). Call {@linkcode
508
+
@modelcontextprotocol/server!server/server.Server#listRoots | server.server.listRoots()} (requires the client to declare the `roots` capability):
> The tasks API is experimental and may change without notice.
527
+
> [!WARNING] The tasks API is experimental and may change without notice.
520
528
521
-
Task-based execution enables "call-now, fetch-later" patterns for long-running operations (see [Tasks](https://modelcontextprotocol.io/specification/latest/basic/utilities/tasks) in the MCP specification). Instead of returning a result immediately, a tool creates a task that can be polled or resumed later. To use tasks:
529
+
Task-based execution enables "call-now, fetch-later" patterns for long-running operations (see [Tasks](https://modelcontextprotocol.io/specification/latest/basic/utilities/tasks) in the MCP specification). Instead of returning a result immediately, a tool creates a task that can
530
+
be polled or resumed later. To use tasks:
522
531
523
532
- Provide a {@linkcode@modelcontextprotocol/server!index.TaskStore | TaskStore} implementation that persists task metadata and results (see {@linkcode@modelcontextprotocol/server!index.InMemoryTaskStore | InMemoryTaskStore} for reference).
524
533
- Enable the `tasks` capability when constructing the server.
@@ -563,9 +572,11 @@ For a complete multi-session server with shutdown handling, see [`simpleStreamab
563
572
564
573
### DNS rebinding protection
565
574
566
-
Under normal circumstances, cross-origin browser restrictions limit what a malicious website can do to your localhost server. [DNS rebinding attacks](https://en.wikipedia.org/wiki/DNS_rebinding) get around those restrictions entirely by making the requests appear as same-origin, since the attacking domain resolves to localhost. Validating the host header on the server side protects against this scenario. **All localhost MCP servers should use DNS rebinding protection.**
575
+
Under normal circumstances, cross-origin browser restrictions limit what a malicious website can do to your localhost server. [DNS rebinding attacks](https://en.wikipedia.org/wiki/DNS_rebinding) get around those restrictions entirely by making the requests appear as same-origin,
576
+
since the attacking domain resolves to localhost. Validating the host header on the server side protects against this scenario. **All localhost MCP servers should use DNS rebinding protection.**
567
577
568
-
The recommended approach is to use {@linkcode@modelcontextprotocol/express!express.createMcpExpressApp | createMcpExpressApp()} (from `@modelcontextprotocol/express`) or {@linkcode@modelcontextprotocol/hono!hono.createMcpHonoApp | createMcpHonoApp()} (from `@modelcontextprotocol/hono`), which enable Host header validation by default:
578
+
The recommended approach is to use {@linkcode@modelcontextprotocol/express!express.createMcpExpressApp | createMcpExpressApp()} (from `@modelcontextprotocol/express`) or {@linkcode@modelcontextprotocol/hono!hono.createMcpHonoApp | createMcpHonoApp()} (from
579
+
`@modelcontextprotocol/hono`), which enable Host header validation by default:
`createMcpHonoApp()` from `@modelcontextprotocol/hono` provides the same protection for Hono-based servers and Web Standard runtimes (Cloudflare Workers, Deno, Bun).
591
602
592
-
If you use `NodeStreamableHTTPServerTransport` directly with your own HTTP framework, you must implement Host header validation yourself. See the [`hostHeaderValidation`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/packages/middleware/express/src/express.ts) middleware source for reference.
603
+
If you use `NodeStreamableHTTPServerTransport` directly with your own HTTP framework, you must implement Host header validation yourself. See the [`hostHeaderValidation`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/packages/middleware/express/src/express.ts)
604
+
middleware source for reference.
593
605
594
606
## See also
595
607
@@ -601,10 +613,10 @@ If you use `NodeStreamableHTTPServerTransport` directly with your own HTTP frame
601
613
602
614
### Additional examples
603
615
604
-
| Feature | Description | Example |
605
-
|---------|-------------|---------|
606
-
| Web Standard transport | Deploy on Cloudflare Workers, Deno, or Bun |[`honoWebStandardStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/honoWebStandardStreamableHttp.ts)|
607
-
| Session management | Per-session transport routing, initialization, and cleanup |[`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts)|
608
-
| Resumability | Replay missed SSE events via an event store |[`inMemoryEventStore.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/inMemoryEventStore.ts)|
609
-
| CORS | Expose MCP headers for browser clients |[`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts)|
| Web Standard transport | Deploy on Cloudflare Workers, Deno, or Bun |[`honoWebStandardStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/honoWebStandardStreamableHttp.ts)|
619
+
| Session management | Per-session transport routing, initialization, and cleanup |[`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts)|
620
+
| Resumability | Replay missed SSE events via an event store |[`inMemoryEventStore.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/inMemoryEventStore.ts)|
621
+
| CORS | Expose MCP headers for browser clients |[`simpleStreamableHttp.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/server/src/simpleStreamableHttp.ts)|
0 commit comments