The two sides of this change are more than 400 edits apart, too far apart to line up, so this is the differ's own diff of it and the words inside a line are not marked.
from line 15
1515* **MCP Development Tools**: Tools for developing MCP servers and clients, including the [MCP Inspector](https://github.com/modelcontextprotocol/inspector)
1616* [MCP Reference Server Implementations](https://github.com/modelcontextprotocol/servers): Reference implementations of MCP servers.
1717
18<Note>
19 MCP focuses solely on the protocol for context exchange—it does not dictate
20 how AI applications use LLMs or manage the provided context.
21</Note>
18> [!NOTE]
19>
20> MCP focuses solely on the protocol for context exchange—it does not dictate
21> how AI applications use LLMs or manage the provided context.
2222
2323## Concepts of MCP
2424
from line 104
104104
105105#### Statelessness and discovery
106106
107MCP is a <Tooltip tip="Every request contains all the information needed to process it, so servers infer nothing from previous requests">stateless protocol</Tooltip>. Every request carries the protocol version and the <Tooltip tip="Features and operations that a client or server supports, such as tools, resources, or prompts">capabilities</Tooltip> relevant to that request in its `_meta` field, so the server can process each request on its own. Clients should also identify themselves in the same field unless configured not to. Servers advertise their supported versions and capabilities through the mandatory [`server/discover`](/specification/draft/server/discover) request, which clients may send before any other request. Detailed information can be found in the [specification](/specification/draft/basic/index#statelessness), and the [example](#example) showcases the per-request metadata and the discovery sequence.
107MCP is a stateless protocol (Every request contains all the information needed to process it, so servers infer nothing from previous requests). Every request carries the protocol version and the capabilities (Features and operations that a client or server supports, such as tools, resources, or prompts) relevant to that request in its `_meta` field, so the server can process each request on its own. Clients should also identify themselves in the same field unless configured not to. Servers advertise their supported versions and capabilities through the mandatory [`server/discover`](/specification/draft/server/discover) request, which clients may send before any other request. Detailed information can be found in the [specification](/specification/draft/basic/index#statelessness), and the [example](#example) showcases the per-request metadata and the discovery sequence.
108108
109109#### Primitives
110110
from line 148
148148
149149This section provides a step-by-step walkthrough of an MCP client-server interaction, focusing on the data layer protocol. We'll demonstrate discovery, tool operations, and notifications using JSON-RPC 2.0 messages.
150150
151<Steps>
152 <Step title="Discovery">
153 As described in the [statelessness and discovery](#statelessness-and-discovery) section, every MCP request carries the protocol version and client capabilities in its `_meta` field, and clients should also include their identity there. A client that wants to learn what a server supports before issuing other requests sends a `server/discover` request, which every server must implement. The discovery response is typically cacheable, meaning it can be re-used so the discovery flow does not need to be performed for every request.
154
155 <CodeGroup>
156 ```json Discover Request theme={null}
151**1. Discovery**
152
153As described in the [statelessness and discovery](#statelessness-and-discovery) section, every MCP request carries the protocol version and client capabilities in its `_meta` field, and clients should also include their identity there. A client that wants to learn what a server supports before issuing other requests sends a `server/discover` request, which every server must implement. The discovery response is typically cacheable, meaning it can be re-used so the discovery flow does not need to be performed for every request.
154
155```json Discover Request theme={null}
156{
157 "jsonrpc": "2.0",
158 "id": 1,
159 "method": "server/discover",
160 "params": {
161 "_meta": {
162 "io.modelcontextprotocol/protocolVersion": "2026-07-28",
163 "io.modelcontextprotocol/clientInfo": {
164 "name": "example-client",
165 "version": "1.0.0"
166 },
167 "io.modelcontextprotocol/clientCapabilities": {
168 "elicitation": {}
169 }
170 }
171 }
172}
173```
174
175```json Discover Response theme={null}
176{
177 "jsonrpc": "2.0",
178 "id": 1,
179 "result": {
180 "resultType": "complete",
181 "supportedVersions": ["2026-07-28"],
182 "capabilities": {
183 "tools": {
184 "listChanged": true
185 },
186 "resources": {}
187 },
188 "_meta": {
189 "io.modelcontextprotocol/serverInfo": {
190 "name": "example-server",
191 "version": "1.0.0"
192 }
193 },
194 "ttlMs": 3600000,
195 "cacheScope": "public"
196 }
197}
198```
199
200#### Understanding the Discovery Exchange
201
202The `_meta` fields and the discovery response together serve several purposes:
203
2041. **Protocol Version Selection**: The `io.modelcontextprotocol/protocolVersion` field declares the version the client is speaking on this request, and `supportedVersions` in the response lists the versions the server accepts. If a server does not support the requested version, it rejects the request with an `UnsupportedProtocolVersionError` listing the versions it does support, and the client retries with a mutually supported version.
205
2062. **Capability Discovery**: The client declares its capabilities in `io.modelcontextprotocol/clientCapabilities` on every request, and the server returns its own `capabilities` object from `server/discover`. This tells each party which [primitives](#primitives) the other can handle (tools, resources, prompts) and whether change [notifications](#notifications) are available, so unsupported operations are never attempted.
207
2083. **Identity Exchange**: The `io.modelcontextprotocol/clientInfo` field in the request's `_meta` and the `io.modelcontextprotocol/serverInfo` field in the result's `_meta` provide identification and versioning information for debugging and compatibility purposes.
209
210In this example, the exchange demonstrates how MCP capabilities are declared:
211
212**Client Capabilities**:
213
214* `"elicitation": {}` - The client declares it can gather additional input from the user when the server requests it
215
216**Server Capabilities**:
217
218* `"tools": {"listChanged": true}` - The server supports the tools primitive and can honor a `toolsListChanged` filter in [`subscriptions/listen`](/specification/draft/basic/patterns/subscriptions). Clients that request this filter receive `notifications/tools/list_changed` when the tool list changes.
219* `"resources": {}` - The server also supports the resources primitive (can handle `resources/list` and `resources/read` methods)
220
221Calling `server/discover` is optional. Because every request carries the same `_meta` fields, a client is free to send any request directly and handle a version error if one comes back. Discovery is a convenient way to fetch the server's identity, capabilities, and supported versions in a single request.
222
223#### How This Works in AI Applications
224
225The AI application's MCP client manager connects to configured servers and stores their discovered capabilities for later use. The application uses this information to determine which servers can provide specific types of functionality (tools, resources, prompts) and whether they support real-time updates. In the Python SDK, discovery happens while the client connects. The results are then available on the client object.
226
227```python Pseudo-code for AI application discovery theme={null}
228# Pseudo Code
229async with Client(stdio_client(server_config)) as client:
230 if client.server_capabilities.tools:
231 app.register_mcp_server(client, supports_tools=True)
232 app.set_server_ready(client)
233```
234
235**2. Tool Discovery (Primitives)**
236
237The client can discover available tools by sending a `tools/list` request. This request is fundamental to MCP's tool discovery mechanism: it allows clients to understand what tools are available on the server before attempting to use them.
238
239```json Tools List Request theme={null}
240{
241 "jsonrpc": "2.0",
242 "id": 2,
243 "method": "tools/list",
244 "params": {
245 "_meta": {
246 "io.modelcontextprotocol/protocolVersion": "2026-07-28",
247 "io.modelcontextprotocol/clientInfo": {
248 "name": "example-client",
249 "version": "1.0.0"
250 },
251 "io.modelcontextprotocol/clientCapabilities": {
252 "elicitation": {}
253 }
254 }
255 }
256}
257```
258
259```json Tools List Response theme={null}
260{
261 "jsonrpc": "2.0",
262 "id": 2,
263 "result": {
264 "resultType": "complete",
265 "tools": [
157266 {
158 "jsonrpc": "2.0",
159 "id": 1,
160 "method": "server/discover",
161 "params": {
162 "_meta": {
163 "io.modelcontextprotocol/protocolVersion": "2026-07-28",
164 "io.modelcontextprotocol/clientInfo": {
165 "name": "example-client",
166 "version": "1.0.0"
167 },
168 "io.modelcontextprotocol/clientCapabilities": {
169 "elicitation": {}
170 }
171 }
172 }
173 }
174 ```
175
176 ```json Discover Response theme={null}
177 {
178 "jsonrpc": "2.0",
179 "id": 1,
180 "result": {
181 "resultType": "complete",
182 "supportedVersions": ["2026-07-28"],
183 "capabilities": {
184 "tools": {
185 "listChanged": true
186 },
187 "resources": {}
188 },
189 "_meta": {
190 "io.modelcontextprotocol/serverInfo": {
191 "name": "example-server",
192 "version": "1.0.0"
267 "name": "calculator_arithmetic",
268 "title": "Calculator",
269 "description": "Perform mathematical calculations including basic arithmetic, trigonometric functions, and algebraic operations",
270 "inputSchema": {
271 "type": "object",
272 "properties": {
273 "expression": {
274 "type": "string",
275 "description": "Mathematical expression to evaluate (e.g., '2 + 3 * 4', 'sin(30)', 'sqrt(16)')"
193276 }
194277 },
195 "ttlMs": 3600000,
196 "cacheScope": "public"
278 "required": ["expression"]
197279 }
198 }
199 ```
200 </CodeGroup>
201
202 #### Understanding the Discovery Exchange
203
204 The `_meta` fields and the discovery response together serve several purposes:
205
206 1. **Protocol Version Selection**: The `io.modelcontextprotocol/protocolVersion` field declares the version the client is speaking on this request, and `supportedVersions` in the response lists the versions the server accepts. If a server does not support the requested version, it rejects the request with an `UnsupportedProtocolVersionError` listing the versions it does support, and the client retries with a mutually supported version.
207
208 2. **Capability Discovery**: The client declares its capabilities in `io.modelcontextprotocol/clientCapabilities` on every request, and the server returns its own `capabilities` object from `server/discover`. This tells each party which [primitives](#primitives) the other can handle (tools, resources, prompts) and whether change [notifications](#notifications) are available, so unsupported operations are never attempted.
209
210 3. **Identity Exchange**: The `io.modelcontextprotocol/clientInfo` field in the request's `_meta` and the `io.modelcontextprotocol/serverInfo` field in the result's `_meta` provide identification and versioning information for debugging and compatibility purposes.
211
212 In this example, the exchange demonstrates how MCP capabilities are declared:
213
214 **Client Capabilities**:
215
216 * `"elicitation": {}` - The client declares it can gather additional input from the user when the server requests it
217
218 **Server Capabilities**:
219
220 * `"tools": {"listChanged": true}` - The server supports the tools primitive and can honor a `toolsListChanged` filter in [`subscriptions/listen`](/specification/draft/basic/patterns/subscriptions). Clients that request this filter receive `notifications/tools/list_changed` when the tool list changes.
221 * `"resources": {}` - The server also supports the resources primitive (can handle `resources/list` and `resources/read` methods)
222
223 Calling `server/discover` is optional. Because every request carries the same `_meta` fields, a client is free to send any request directly and handle a version error if one comes back. Discovery is a convenient way to fetch the server's identity, capabilities, and supported versions in a single request.
224
225 #### How This Works in AI Applications
226
227 The AI application's MCP client manager connects to configured servers and stores their discovered capabilities for later use. The application uses this information to determine which servers can provide specific types of functionality (tools, resources, prompts) and whether they support real-time updates. In the Python SDK, discovery happens while the client connects. The results are then available on the client object.
228
229 ```python Pseudo-code for AI application discovery theme={null}
230 # Pseudo Code
231 async with Client(stdio_client(server_config)) as client:
232 if client.server_capabilities.tools:
233 app.register_mcp_server(client, supports_tools=True)
234 app.set_server_ready(client)
235 ```
236 </Step>
237
238 <Step title="Tool Discovery (Primitives)">
239 The client can discover available tools by sending a `tools/list` request. This request is fundamental to MCP's tool discovery mechanism: it allows clients to understand what tools are available on the server before attempting to use them.
240
241 <CodeGroup>
242 ```json Tools List Request theme={null}
280 },
243281 {
244 "jsonrpc": "2.0",
245 "id": 2,
246 "method": "tools/list",
247 "params": {
248 "_meta": {
249 "io.modelcontextprotocol/protocolVersion": "2026-07-28",
250 "io.modelcontextprotocol/clientInfo": {
251 "name": "example-client",
252 "version": "1.0.0"
282 "name": "weather_current",
283 "title": "Weather Information",
284 "description": "Get current weather information for any location worldwide",
285 "inputSchema": {
286 "type": "object",
287 "properties": {
288 "location": {
289 "type": "string",
290 "description": "City name, address, or coordinates (latitude,longitude)"
253291 },
254 "io.modelcontextprotocol/clientCapabilities": {
255 "elicitation": {}
292 "units": {
293 "type": "string",
294 "enum": ["metric", "imperial", "kelvin"],
295 "description": "Temperature units to use in response",
296 "default": "metric"
256297 }
257 }
298 },
299 "required": ["location"]
258300 }
259301 }
260 ```
261
262 ```json Tools List Response theme={null}
302 ],
303 "ttlMs": 300000,
304 "cacheScope": "public"
305 }
306}
307```
308
309#### Understanding the Tool Discovery Request
310
311The `tools/list` request requires no parameters beyond the standard `_meta` fields that accompany every MCP request. It also accepts an optional `cursor` parameter for [pagination](/specification/draft/server/utilities/pagination), which the example above omits.
312
313#### Understanding the Tool Discovery Response
314
315The response contains a `tools` array that provides comprehensive metadata about each available tool. This array-based structure allows servers to expose multiple tools simultaneously while maintaining clear boundaries between different functionalities.
316
317Each tool object in the response includes several key fields:
318
319* **`name`**: A unique identifier for the tool within the server's namespace. This serves as the primary key for tool execution and should follow a clear naming pattern (e.g., `calculator_arithmetic` rather than just `calculate`)
320* **`title`**: A human-readable display name for the tool that clients can show to users
321* **`description`**: Detailed explanation of what the tool does and when to use it
322* **`inputSchema`**: A JSON Schema that defines the expected input parameters, enabling type validation and providing clear documentation about required and optional parameters
323
324The result is marked `"resultType": "complete"` and carries two caching fields. `ttlMs` is a freshness hint in milliseconds, so this tool list can be cached for five minutes. `cacheScope` indicates who may reuse the response. The specification's [caching utility](/specification/draft/server/utilities/caching) defines the full rules.
325
326#### How This Works in AI Applications
327
328The AI application fetches available tools from all connected MCP servers and combines them into a unified tool registry that the language model can access. This allows the LLM to understand what actions it can perform and automatically generates the appropriate tool calls during conversations.
329
330```python Pseudo-code for AI application tool discovery theme={null}
331# Pseudo-code using MCP Python SDK patterns
332available_tools = []
333for client in app.mcp_clients():
334 tools_response = await client.list_tools()
335 available_tools.extend(tools_response.tools)
336conversation.register_available_tools(available_tools)
337```
338
339Clients that federate many servers can use [progressive tool discovery](/docs/draft/develop/clients/client-best-practices#progressive-tool-discovery) rather than loading every tool upfront.
340
341**3. Tool Execution (Primitives)**
342
343The client can now execute a tool using the `tools/call` method. This demonstrates how MCP primitives are used in practice: after discovering available tools, the client can invoke them with appropriate arguments.
344
345#### Understanding the Tool Execution Request
346
347The `tools/call` request follows a structured format that ensures type safety and clear communication between client and server. Note that we're using the proper tool name from the discovery response (`weather_current`) rather than a simplified name:
348
349```json Tool Call Request theme={null}
350{
351 "jsonrpc": "2.0",
352 "id": 3,
353 "method": "tools/call",
354 "params": {
355 "name": "weather_current",
356 "arguments": {
357 "location": "San Francisco",
358 "units": "imperial"
359 },
360 "_meta": {
361 "io.modelcontextprotocol/protocolVersion": "2026-07-28",
362 "io.modelcontextprotocol/clientInfo": {
363 "name": "example-client",
364 "version": "1.0.0"
365 },
366 "io.modelcontextprotocol/clientCapabilities": {
367 "elicitation": {}
368 }
369 }
370 }
371}
372```
373
374```json Tool Call Response theme={null}
375{
376 "jsonrpc": "2.0",
377 "id": 3,
378 "result": {
379 "resultType": "complete",
380 "content": [
263381 {
264 "jsonrpc": "2.0",
265 "id": 2,
266 "result": {
267 "resultType": "complete",
268 "tools": [
269 {
270 "name": "calculator_arithmetic",
271 "title": "Calculator",
272 "description": "Perform mathematical calculations including basic arithmetic, trigonometric functions, and algebraic operations",
273 "inputSchema": {
274 "type": "object",
275 "properties": {
276 "expression": {
277 "type": "string",
278 "description": "Mathematical expression to evaluate (e.g., '2 + 3 * 4', 'sin(30)', 'sqrt(16)')"
279 }
280 },
281 "required": ["expression"]
282 }
283 },
284 {
285 "name": "weather_current",
286 "title": "Weather Information",
287 "description": "Get current weather information for any location worldwide",
288 "inputSchema": {
289 "type": "object",
290 "properties": {
291 "location": {
292 "type": "string",
293 "description": "City name, address, or coordinates (latitude,longitude)"
294 },
295 "units": {
296 "type": "string",
297 "enum": ["metric", "imperial", "kelvin"],
298 "description": "Temperature units to use in response",
299 "default": "metric"
300 }
301 },
302 "required": ["location"]
303 }
304 }
305 ],
306 "ttlMs": 300000,
307 "cacheScope": "public"
308 }
309 }
310 ```
311 </CodeGroup>
312
313 #### Understanding the Tool Discovery Request
314
315 The `tools/list` request requires no parameters beyond the standard `_meta` fields that accompany every MCP request. It also accepts an optional `cursor` parameter for [pagination](/specification/draft/server/utilities/pagination), which the example above omits.
316
317 #### Understanding the Tool Discovery Response
318
319 The response contains a `tools` array that provides comprehensive metadata about each available tool. This array-based structure allows servers to expose multiple tools simultaneously while maintaining clear boundaries between different functionalities.
320
321 Each tool object in the response includes several key fields:
322
323 * **`name`**: A unique identifier for the tool within the server's namespace. This serves as the primary key for tool execution and should follow a clear naming pattern (e.g., `calculator_arithmetic` rather than just `calculate`)
324 * **`title`**: A human-readable display name for the tool that clients can show to users
325 * **`description`**: Detailed explanation of what the tool does and when to use it
326 * **`inputSchema`**: A JSON Schema that defines the expected input parameters, enabling type validation and providing clear documentation about required and optional parameters
327
328 The result is marked `"resultType": "complete"` and carries two caching fields. `ttlMs` is a freshness hint in milliseconds, so this tool list can be cached for five minutes. `cacheScope` indicates who may reuse the response. The specification's [caching utility](/specification/draft/server/utilities/caching) defines the full rules.
329
330 #### How This Works in AI Applications
331
332 The AI application fetches available tools from all connected MCP servers and combines them into a unified tool registry that the language model can access. This allows the LLM to understand what actions it can perform and automatically generates the appropriate tool calls during conversations.
333
334 ```python Pseudo-code for AI application tool discovery theme={null}
335 # Pseudo-code using MCP Python SDK patterns
336 available_tools = []
337 for client in app.mcp_clients():
338 tools_response = await client.list_tools()
339 available_tools.extend(tools_response.tools)
340 conversation.register_available_tools(available_tools)
341 ```
342
343 Clients that federate many servers can use [progressive tool discovery](/docs/draft/develop/clients/client-best-practices#progressive-tool-discovery) rather than loading every tool upfront.
344 </Step>
345
346 <Step title="Tool Execution (Primitives)">
347 The client can now execute a tool using the `tools/call` method. This demonstrates how MCP primitives are used in practice: after discovering available tools, the client can invoke them with appropriate arguments.
348
349 #### Understanding the Tool Execution Request
350
351 The `tools/call` request follows a structured format that ensures type safety and clear communication between client and server. Note that we're using the proper tool name from the discovery response (`weather_current`) rather than a simplified name:
352
353 <CodeGroup>
354 ```json Tool Call Request theme={null}
355 {
356 "jsonrpc": "2.0",
357 "id": 3,
358 "method": "tools/call",
359 "params": {
360 "name": "weather_current",
361 "arguments": {
362 "location": "San Francisco",
363 "units": "imperial"
364 },
365 "_meta": {
366 "io.modelcontextprotocol/protocolVersion": "2026-07-28",
367 "io.modelcontextprotocol/clientInfo": {
368 "name": "example-client",
369 "version": "1.0.0"
370 },
371 "io.modelcontextprotocol/clientCapabilities": {
372 "elicitation": {}
373 }
374 }
375 }
376 }
377 ```
378
379 ```json Tool Call Response theme={null}
380 {
381 "jsonrpc": "2.0",
382 "id": 3,
383 "result": {
384 "resultType": "complete",
385 "content": [
386 {
387 "type": "text",
388 "text": "Current weather in San Francisco: 68°F, partly cloudy with light winds from the west at 8 mph. Humidity: 65%"
389 }
390 ]
391 }
392 }
393 ```
394 </CodeGroup>
395
396 #### Key Elements of Tool Execution
397
398 The request structure includes several important components:
399
400 1. **`name`**: Must match exactly the tool name from the discovery response (`weather_current`). This ensures the server can correctly identify which tool to execute.
401
402 2. **`arguments`**: Contains the input parameters as defined by the tool's `inputSchema`. In this example:
403 * `location`: "San Francisco" (required parameter)
404 * `units`: "imperial" (optional parameter, defaults to "metric" if not specified)
405
406 3. **`_meta`**: Carries the standard per-request fields: the protocol version and client capabilities that every MCP request must include, plus the client's identity, which clients should include unless configured not to.
407
408 4. **JSON-RPC Structure**: Uses standard JSON-RPC 2.0 format with unique `id` for request-response correlation.
409
410 #### Understanding the Tool Execution Response
411
412 The response demonstrates MCP's flexible content system:
413
414 1. **`content` Array**: Tool responses return an array of content objects, allowing for rich, multi-format responses (text, images, resources, etc.)
415
416 2. **Content Types**: Each content object has a `type` field. In this example, `"type": "text"` indicates plain text content, but MCP supports various content types for different use cases.
417
418 3. **Structured Output**: The response provides actionable information that the AI application can use as context for language model interactions.
419
420 This execution pattern allows AI applications to dynamically invoke server functionality and receive structured responses that can be integrated into conversations with language models.
421
422 #### How This Works in AI Applications
423
424 When the language model decides to use a tool during a conversation, the AI application intercepts the tool call, routes it to the appropriate MCP server, executes it, and returns the results back to the LLM as part of the conversation flow. This enables the LLM to access real-time data and perform actions in the external world.
425
426 ```python theme={null}
427 # Pseudo-code for AI application tool execution
428 async def handle_tool_call(conversation, tool_name, arguments):
429 client = app.find_mcp_client_for_tool(tool_name)
430 result = await client.call_tool(tool_name, arguments)
431 conversation.add_tool_result(result.content)
432 ```
433 </Step>
434
435 <Step title="Real-time Updates (Notifications)">
436 MCP supports real-time notifications that enable servers to inform clients about changes without being polled for them. This demonstrates the notification system, a key feature that keeps clients synchronized and responsive.
437
438 #### Subscribing to Changes
439
440 Change notifications are opt-in. To receive them, the client opens a long-lived notification stream by sending a [`subscriptions/listen`](/specification/draft/basic/patterns/subscriptions) request with a `notifications` filter naming the event types it wants. Here the client asks for tool list changes:
441
442 ```json Listen Request theme={null}
443 {
444 "jsonrpc": "2.0",
445 "id": 4,
446 "method": "subscriptions/listen",
447 "params": {
448 "_meta": {
449 "io.modelcontextprotocol/protocolVersion": "2026-07-28",
450 "io.modelcontextprotocol/clientInfo": {
451 "name": "example-client",
452 "version": "1.0.0"
453 },
454 "io.modelcontextprotocol/clientCapabilities": {
455 "elicitation": {}
456 }
457 },
458 "notifications": {
459 "toolsListChanged": true
460 }
461 }
462 }
463 ```
464
465 Every client request carries the `io.modelcontextprotocol/protocolVersion` and `io.modelcontextprotocol/clientCapabilities` fields in `_meta`, and normally `io.modelcontextprotocol/clientInfo` as well, so the server can identify the client without relying on connection state.
466
467 The server acknowledges the subscription with `notifications/subscriptions/acknowledged`, which is the first message carrying that subscription's ID in `_meta` (the server sends no other notification for that subscription before it). Its `notifications` field reflects the subset of the requested filter the server agreed to honor, with unsupported notification types omitted:
468
469 ```json Acknowledgment theme={null}
470 {
471 "jsonrpc": "2.0",
472 "method": "notifications/subscriptions/acknowledged",
473 "params": {
474 "_meta": {
475 "io.modelcontextprotocol/subscriptionId": 4
476 },
477 "notifications": {
478 "toolsListChanged": true
479 }
480 }
481 }
482 ```
483
484 #### Understanding Tool List Change Notifications
485
486 After the acknowledgment, when the server's available tools change (for example, when new functionality becomes available, existing tools are modified, or tools become temporarily unavailable), the server delivers a notification on that stream:
487
488 ```json Notification theme={null}
489 {
490 "jsonrpc": "2.0",
491 "method": "notifications/tools/list_changed",
492 "params": {
493 "_meta": {
494 "io.modelcontextprotocol/subscriptionId": 4
495 }
496 }
497 }
498 ```
499
500 #### Key Features of MCP Notifications
501
502 1. **No Response Required**: Notice there's no `id` field in the notification. This follows JSON-RPC 2.0 notification semantics where no response is expected or sent.
503
504 2. **Opt-In Based**: This notification is only sent to clients that requested `"toolsListChanged": true` in their `subscriptions/listen` filter, and it is only available from servers that declared `"listChanged": true` in their tools capability (as shown in Step 1).
505
506 3. **Subscription-ID Tagging**: Every notification on the stream carries `io.modelcontextprotocol/subscriptionId` in `_meta`. The value is the JSON-RPC ID of the `subscriptions/listen` request that opened the stream (`4` in this example), so clients can correlate each notification with the subscription that produced it.
507
508 4. **Event-Driven**: The server decides when to send notifications based on internal state changes, making MCP connections dynamic and responsive.
509
510 5. **Best Effort**: There are no guarantees that every notification will be sent or received, particularly across transport reconnects. Clients should also rely on polling to preserve freshness of results.
511
512 #### Client Response to Notifications
513
514 Upon receiving this notification, the client typically reacts by requesting the updated tool list. This creates a refresh cycle that keeps the client's understanding of available tools current:
515
516 ```json Request theme={null}
517 {
518 "jsonrpc": "2.0",
519 "id": 5,
520 "method": "tools/list",
521 "params": {
522 "_meta": {
523 "io.modelcontextprotocol/protocolVersion": "2026-07-28",
524 "io.modelcontextprotocol/clientInfo": {
525 "name": "example-client",
526 "version": "1.0.0"
527 },
528 "io.modelcontextprotocol/clientCapabilities": {
529 "elicitation": {}
530 }
531 }
532 }
533 }
534 ```
535
536 #### Why Notifications Matter
537
538 This notification system is crucial for several reasons:
539
540 1. **Dynamic Environments**: Tools may come and go based on server state, external dependencies, or user permissions
541 2. **Efficiency**: Clients don't need to poll for changes; they're notified when updates occur
542 3. **Consistency**: Ensures clients always have accurate information about available server capabilities
543 4. **Real-time Collaboration**: Enables responsive AI applications that can adapt to changing contexts
544
545 This notification pattern extends beyond tools to other MCP primitives, enabling comprehensive real-time synchronization between clients and servers.
546
547 #### How This Works in AI Applications
548
549 The AI application keeps a notification stream open for the changes it cares about. When one arrives, it immediately refreshes its tool registry and updates the LLM's available capabilities. This ensures that ongoing conversations always have access to the most current set of tools, and the LLM can dynamically adapt to new functionality as it becomes available.
550
551 ```python theme={null}
552 # Pseudo-code for AI application notification handling
553 async def follow_tool_changes(client):
554 async with client.listen(tools_list_changed=True) as sub:
555 async for _event in sub:
556 tools_response = await client.list_tools()
557 app.update_available_tools(client, tools_response.tools)
558 if app.conversation.is_active():
559 app.conversation.notify_llm_of_new_capabilities()
560 ```
561 </Step>
562</Steps>
382 "type": "text",
383 "text": "Current weather in San Francisco: 68°F, partly cloudy with light winds from the west at 8 mph. Humidity: 65%"
384 }
385 ]
386 }
387}
388```
389
390#### Key Elements of Tool Execution
391
392The request structure includes several important components:
393
3941. **`name`**: Must match exactly the tool name from the discovery response (`weather_current`). This ensures the server can correctly identify which tool to execute.
395
3962. **`arguments`**: Contains the input parameters as defined by the tool's `inputSchema`. In this example:
397 * `location`: "San Francisco" (required parameter)
398 * `units`: "imperial" (optional parameter, defaults to "metric" if not specified)
399
4003. **`_meta`**: Carries the standard per-request fields: the protocol version and client capabilities that every MCP request must include, plus the client's identity, which clients should include unless configured not to.
401
4024. **JSON-RPC Structure**: Uses standard JSON-RPC 2.0 format with unique `id` for request-response correlation.
403
404#### Understanding the Tool Execution Response
405
406The response demonstrates MCP's flexible content system:
407
4081. **`content` Array**: Tool responses return an array of content objects, allowing for rich, multi-format responses (text, images, resources, etc.)
409
4102. **Content Types**: Each content object has a `type` field. In this example, `"type": "text"` indicates plain text content, but MCP supports various content types for different use cases.
411
4123. **Structured Output**: The response provides actionable information that the AI application can use as context for language model interactions.
413
414This execution pattern allows AI applications to dynamically invoke server functionality and receive structured responses that can be integrated into conversations with language models.
415
416#### How This Works in AI Applications
417
418When the language model decides to use a tool during a conversation, the AI application intercepts the tool call, routes it to the appropriate MCP server, executes it, and returns the results back to the LLM as part of the conversation flow. This enables the LLM to access real-time data and perform actions in the external world.
419
420```python theme={null}
421# Pseudo-code for AI application tool execution
422async def handle_tool_call(conversation, tool_name, arguments):
423 client = app.find_mcp_client_for_tool(tool_name)
424 result = await client.call_tool(tool_name, arguments)
425 conversation.add_tool_result(result.content)
426```
427
428**4. Real-time Updates (Notifications)**
429
430MCP supports real-time notifications that enable servers to inform clients about changes without being polled for them. This demonstrates the notification system, a key feature that keeps clients synchronized and responsive.
431
432#### Subscribing to Changes
433
434Change notifications are opt-in. To receive them, the client opens a long-lived notification stream by sending a [`subscriptions/listen`](/specification/draft/basic/patterns/subscriptions) request with a `notifications` filter naming the event types it wants. Here the client asks for tool list changes:
435
436```json Listen Request theme={null}
437{
438 "jsonrpc": "2.0",
439 "id": 4,
440 "method": "subscriptions/listen",
441 "params": {
442 "_meta": {
443 "io.modelcontextprotocol/protocolVersion": "2026-07-28",
444 "io.modelcontextprotocol/clientInfo": {
445 "name": "example-client",
446 "version": "1.0.0"
447 },
448 "io.modelcontextprotocol/clientCapabilities": {
449 "elicitation": {}
450 }
451 },
452 "notifications": {
453 "toolsListChanged": true
454 }
455 }
456}
457```
458
459Every client request carries the `io.modelcontextprotocol/protocolVersion` and `io.modelcontextprotocol/clientCapabilities` fields in `_meta`, and normally `io.modelcontextprotocol/clientInfo` as well, so the server can identify the client without relying on connection state.
460
461The server acknowledges the subscription with `notifications/subscriptions/acknowledged`, which is the first message carrying that subscription's ID in `_meta` (the server sends no other notification for that subscription before it). Its `notifications` field reflects the subset of the requested filter the server agreed to honor, with unsupported notification types omitted:
462
463```json Acknowledgment theme={null}
464{
465 "jsonrpc": "2.0",
466 "method": "notifications/subscriptions/acknowledged",
467 "params": {
468 "_meta": {
469 "io.modelcontextprotocol/subscriptionId": 4
470 },
471 "notifications": {
472 "toolsListChanged": true
473 }
474 }
475}
476```
477
478#### Understanding Tool List Change Notifications
479
480After the acknowledgment, when the server's available tools change (for example, when new functionality becomes available, existing tools are modified, or tools become temporarily unavailable), the server delivers a notification on that stream:
481
482```json Notification theme={null}
483{
484 "jsonrpc": "2.0",
485 "method": "notifications/tools/list_changed",
486 "params": {
487 "_meta": {
488 "io.modelcontextprotocol/subscriptionId": 4
489 }
490 }
491}
492```
493
494#### Key Features of MCP Notifications
495
4961. **No Response Required**: Notice there's no `id` field in the notification. This follows JSON-RPC 2.0 notification semantics where no response is expected or sent.
497
4982. **Opt-In Based**: This notification is only sent to clients that requested `"toolsListChanged": true` in their `subscriptions/listen` filter, and it is only available from servers that declared `"listChanged": true` in their tools capability (as shown in Step 1).
499
5003. **Subscription-ID Tagging**: Every notification on the stream carries `io.modelcontextprotocol/subscriptionId` in `_meta`. The value is the JSON-RPC ID of the `subscriptions/listen` request that opened the stream (`4` in this example), so clients can correlate each notification with the subscription that produced it.
501
5024. **Event-Driven**: The server decides when to send notifications based on internal state changes, making MCP connections dynamic and responsive.
503
5045. **Best Effort**: There are no guarantees that every notification will be sent or received, particularly across transport reconnects. Clients should also rely on polling to preserve freshness of results.
505
506#### Client Response to Notifications
507
508Upon receiving this notification, the client typically reacts by requesting the updated tool list. This creates a refresh cycle that keeps the client's understanding of available tools current:
509
510```json Request theme={null}
511{
512 "jsonrpc": "2.0",
513 "id": 5,
514 "method": "tools/list",
515 "params": {
516 "_meta": {
517 "io.modelcontextprotocol/protocolVersion": "2026-07-28",
518 "io.modelcontextprotocol/clientInfo": {
519 "name": "example-client",
520 "version": "1.0.0"
521 },
522 "io.modelcontextprotocol/clientCapabilities": {
523 "elicitation": {}
524 }
525 }
526 }
527}
528```
529
530#### Why Notifications Matter
531
532This notification system is crucial for several reasons:
533
5341. **Dynamic Environments**: Tools may come and go based on server state, external dependencies, or user permissions
5352. **Efficiency**: Clients don't need to poll for changes; they're notified when updates occur
5363. **Consistency**: Ensures clients always have accurate information about available server capabilities
5374. **Real-time Collaboration**: Enables responsive AI applications that can adapt to changing contexts
538
539This notification pattern extends beyond tools to other MCP primitives, enabling comprehensive real-time synchronization between clients and servers.
540
541#### How This Works in AI Applications
542
543The AI application keeps a notification stream open for the changes it cares about. When one arrives, it immediately refreshes its tool registry and updates the LLM's available capabilities. This ensures that ongoing conversations always have access to the most current set of tools, and the LLM can dynamically adapt to new functionality as it becomes available.
544
545```python theme={null}
546# Pseudo-code for AI application notification handling
547async def follow_tool_changes(client):
548 async with client.listen(tools_list_changed=True) as sub:
549 async for _event in sub:
550 tools_response = await client.list_tools()
551 app.update_available_tools(client, tools_response.tools)
552 if app.conversation.is_active():
553 app.conversation.notify_llm_of_new_capabilities()
554```
563555
No line in this hunk matches that.