Follow Discord
Sweep 09 Oct 2026 · 17:27Z Build v2.1.296 517 read Stable v2.1.287 Latest v2.1.296 Next v2.1.296 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · mcp

Protocol eras changeddocs/2026-07-28/tools/inspector/protocol-eras

Nearest release: v2.1.295, published 5 hours after upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Upstream edited this page at 8 Oct 2026 12:58 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 8 Oct 2026 13:07 UTC.

Upstream edited
Recorded here
Lines+46added
Lines−28removed
From line 6 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits3to this page, all time

## Cancellation

The whole hunk

from line 6, old and new numbered
/
lines
from line 6
66 
77## The `Protocol Era` setting
88 
9Each server carries a `protocolEra` of `legacy`, `auto`, or `modern`. In the web client it lives in **Server Settings**; in a catalog or config file it is the `protocolEra` field; in the CLI and TUI it comes from that same file.
9Each server carries a `protocolEra` of `legacy`, `auto`, or `modern`. In the web client it lives in **Server Settings**; in a catalog or config file it is the `protocolEra` field; the CLI and TUI read it from that same file, and their `--protocol-era <legacy|auto|modern>` flag overrides it for a single run.
1010 
1111| Era | What the Inspector does at connect |
1212| - | - |
from line 23
2323 configured.
2424</Note>
2525 
26Era selection works the same way in all three clients.
26Once connected, the negotiated era is shown as a badge on the **Protocol** tab's Messages header and in **Connection Info**. On a modern connection, `server/discover` also supplies `capabilities` (including `extensions`), `instructions`, and the list of `supportedVersions`. The server's name and version arrive in the result `_meta` under `io.modelcontextprotocol/serverInfo`.
2727 
28Once connected, the negotiated era is reported in the connection header and in **Connection Info**. On a modern connection, `server/discover` also supplies `capabilities` (including `extensions`), `instructions`, and the list of `supportedVersions`. The server's name and version arrive in the result `_meta` under `io.modelcontextprotocol/serverInfo`.
29 
3028<Frame caption="Server Settings: the Protocol Era selector, with all three choices.">
3129 <img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/settings-protocol-era.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=34566c45f97c8af0e2c0d9ee0493b572" width="3840" height="2160" data-path="images/inspector/settings-protocol-era.png" />
3230</Frame>
from line 31
3331 
3432## Reproducing each era locally
3533 
36Every section below ends with a **Reproduce with ...** pointer to a JSON config for one of the **composable test servers** shipped in the Inspector repository. Clone the repo, build the test servers, then point the Inspector at the config the section names.
34Every section below ends with a **Reproduce with ...** pointer to a JSON config for one of the **composable test servers** shipped in the Inspector repository. Clone the repo and build the test servers:
3735 
3836```bash theme={null}
3937git clone https://github.com/modelcontextprotocol/inspector
4038cd inspector && npm install && npm run build
41cd clients/web && npm run test-servers:build
39cd clients/web && npm run test-servers:build && cd ../..
4240```
4341 
42Then, from the repo root, start a server from the config a section names:
43 
44```bash theme={null}
45node test-servers/build/server-composable.js --config test-servers/configs/<name>.json
46```
47 
48The server prints its URL on stderr. If the config's port is already in use, it binds the next free port, so use the printed URL rather than assuming the port. Add that URL as a server in the Inspector, with the Protocol Era the section names.
49 
4450***
4551 
4652## Logging
from line 93
8793 </Tab>
8894 
8995 <Tab title="Modern">
90 The same **Subscribe** button instead sends **`subscriptions/listen`**, with a filter carrying `resourceSubscriptions` plus the `resourcesListChanged` opt-in. The subscription is confirmed when the server sends `notifications/subscriptions/acknowledged`.
96 The same **Subscribe** button instead sends **`subscriptions/listen`**, with a filter carrying `resourceSubscriptions` plus whichever `*ListChanged` opt-ins apply (such as `resourcesListChanged`). The subscription is confirmed when the server sends `notifications/subscriptions/acknowledged`.
9197 
92 Because the subscription is now a long-lived stream rather than a session flag, the Subscriptions section grows a **stream-status badge** in its header that moves from `Connecting...` to `Listening`. If the stream drops, the Inspector reconnects by re-sending `subscriptions/listen`.
98 Because the subscription is now a long-lived stream rather than a session flag, the Subscriptions section grows a **stream-status badge** in its header that moves from `Connecting...` to `Listening`. If the stream drops, the badge shows `Reconnecting...` while the Inspector re-sends `subscriptions/listen`. It shows `Stream ended` once the stream closes for good. It shows `Not acknowledged` when the server answers the listen with a plain result and never sends the acknowledgement; the Inspector does not retry in that case.
9399 
94 Reproduce with `test-servers/configs/subscriptions-modern-http.json`.
100 Reproduce with `test-servers/configs/subscriptions-modern-http.json`. To see the `Not acknowledged` state, use `test-servers/configs/subscriptions-never-acknowledged-http.json`. That server acknowledges your first subscription, then refuses every later listen, so subscribing to a second resource trips the badge.
95101 </Tab>
96102</Tabs>
97103 
from line 119
113119 </Tab>
114120 
115121 <Tab title="Modern">
116 Tasks are an **extension** (`io.modelcontextprotocol/tasks`, [SEP-2663](/seps/2663-tasks-extension)), so the tab is gated on the *negotiated extension* rather than on `capabilities.tasks`.
122 Tasks are an **extension** (`io.modelcontextprotocol/tasks`, [SEP-2663](/seps/2663-tasks-extension)), so the tab is gated on the server *advertising that extension* rather than on `capabilities.tasks`.
117123 
118124 Run a tool as a task and `tools/call` returns a `CreateTaskResult` (`resultType: "task"`, visible in the Protocol and Network tabs). The Inspector polls **`tasks/get`** only; there is no `tasks/list`, so **Refresh** re-polls the handles the client already knows about. A completed task **inlines its result**, with no blocking `tasks/result` call.
119125 
from line 154
148154| `mrtr_sample` | An embedded sampling request, routed to the Sampling panel. |
149155| `mrtr_roots` | An embedded `roots/list`, answered silently from configured roots (no modal). |
150156| `mrtr_edge` | An `inputRequests`-only round, then a `requestState`-only round. |
157| `mrtr_empty` | One elicitation round, then completes with an empty result (no `content`, no `structuredContent`). |
151158| `mrtr_loop` | Never completes, so the client stops at its `MRTR_MAX_ROUNDS` limit. |
152159 
153160<Note>
154 The legacy `collect_elicitation` pattern (a server calling
155 `server.elicitInput`) **errors** on a 2026-07-28 connection, because
161 The legacy pattern of a server calling `server.elicitInput` (the test servers'
162 `collect_elicitation` preset) **errors** on a 2026-07-28 connection, because
156163 server-to-client requests aren't allowed there. MRTR is its modern
157164 replacement.
158165</Note>
from line 168
161168 <img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/mrtr-pending-request.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=99f8acb7f845a12aed42bcea4d310fee" width="3840" height="2160" data-path="images/inspector/mrtr-pending-request.png" />
162169</Frame>
163170 
171<Frame caption="The monitoring sidebar's Protocol tab after mrtr_confirm completes. Both tools/call rounds sit inside one MRTR conversation, Round 1 tagged input_required and Round 2 complete, while unrelated traffic stays outside it.">
172 <img src="https://mintcdn.com/mcp/pUebPdrb6PY5_mfH/images/inspector/mrtr-protocol-conversation.png?fit=max&auto=format&n=pUebPdrb6PY5_mfH&q=85&s=b083d8127a7a67028fcd9702b25aeac1" width="3840" height="2160" data-path="images/inspector/mrtr-protocol-conversation.png" />
173</Frame>
174 
164175***
165176 
166177## Tools: mirrored headers and excluded tools
from line 185
174185 
175186Reproduce with `test-servers/configs/xmcpheader-modern-http.json`.
176187 
177<Warning>
178 **`Mcp-Param-*` mirroring is skipped by the SDK in the browser.** Calling a
179 mirrored tool from the *web* client omits the header, so a strict server
180 answers `-32020` (`HeaderMismatch`, see the [error
181 taxonomy](#network-and-protocol-headers-and-the-error-taxonomy) below). The
182 same tool called from the **CLI** or **TUI**, which both run on Node, mirrors
183 correctly. The header is dropped by an environment check inside the SDK,
184 outside the Inspector's control.
185</Warning>
188<Note>
189 On a modern connection the Inspector mirrors `x-mcp-header` arguments into
190 `Mcp-Param-*` headers itself, in all three clients. In the **web** client the
191 headers are added by the Inspector's Node backend, which issues the upstream
192 request, so they reach the server even though the browser never sends them.
193</Note>
186194 
187<Frame caption="get_weather shows its mirrored city -> Mcp-Param-City header, while invalid_header_tool is struck through under the Excluded (SEP-2243) divider.">
188 <img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/tools-sep2243.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=98b020f6612b3a76b78b1a8d6159c2c0" width="3840" height="2160" data-path="images/inspector/tools-sep2243.png" />
195<Frame caption="get_weather shows its mirrored city -> Mcp-Param-City header, and the Network sidebar confirms the call carried mcp-param-city: Boston. invalid_header_tool is struck through under the Excluded (SEP-2243) divider.">
196 <img src="https://mintcdn.com/mcp/pUebPdrb6PY5_mfH/images/inspector/tools-sep2243.png?fit=max&auto=format&n=pUebPdrb6PY5_mfH&q=85&s=0e011c3012332c0a74d0f57fc84a5cf2" width="3840" height="2160" data-path="images/inspector/tools-sep2243.png" />
189197</Frame>
190198 
191199### `-32602` error panels
192200 
193Under the modern era a `tools/call` that rejects with `-32602` renders as a distinct **error panel**:
201A `tools/call` that rejects with `-32602` renders as a distinct **error panel**, on either era:
194202 
195203* **Unknown Tool**: when the message names a tool the server does not list. Reproduce by calling any name absent from the server's `tools/list`.
196204* **Invalid Parameters**: any other `-32602`. Reproduce with the `trigger_invalid_params` tool in the config above.
197205 
198Both eras reject with `-32602`; only the Inspector's presentation changes. On a legacy connection you get one generic JSON-RPC failure and have to read the message to tell which case you hit.
206The two share one error code, so the Inspector reads the message to tell them apart. Any other error code renders as a generic failure.
199207 
200208***
201209 
from line 233
225233 
226234***
227235 
236## Cancellation
237 
238On a legacy connection, cancelling an in-flight tool call sends `notifications/cancelled`. On a modern Streamable HTTP connection the Inspector instead closes that request's own SSE response stream, which is the 2026-07-28 cancellation signal. Over stdio, cancellation is still `notifications/cancelled`.
239 
240Reproduce with `test-servers/configs/cancellation-modern-http.json`: run `slow_task`, click **Cancel** after a few seconds, and the server's terminal prints how far the task got before it stopped.
241 
242***
243 
228244## Sessions
229245 
230246A legacy Streamable HTTP connection may carry a server-assigned session id (`Mcp-Session-Id`), which the client tears down with an HTTP `DELETE`. A modern connection is **sessionless and per-request**: with no session id the client SDK sends no `DELETE` to the server, so disconnect is purely local.
247 
248A legacy connection also opens a standalone `GET` notification stream after `initialize`, to carry notifications that do not belong to any request. The legacy-only **Suppress Notification Stream** option in **Server Settings** skips that stream, so you can inspect a server that cannot serve a second concurrent request. Modern connections never open the stream, so the option does not apply to them.
231249 
232250This has a practical consequence for your own test servers. A stateless modern handler constructed per request cannot hold state between calls, which is why `test-servers/configs/subscriptions-modern-http.json`, unlike its legacy counterpart, omits an `update_resource` tool: the mutation would run against a throwaway server instance and be invisible to the next read.
233251 
Feedback