Skip to content

Protocol 2026-07-28

MCP-TUI asks for protocol 2026-07-28 by default. That revision removes sessions and lets a server no longer call the client in the middle of a request, so several things look different from 2025-11-25. This page lists what MCP-TUI does differently and where you see it.

Terminal window
# Default: ask for 2026-07-28, let the server negotiate down
mcp-tui --url http://localhost:8080/mcp tool list
# Pin an older revision
mcp-tui --url http://localhost:8080/mcp --protocol-version 2025-11-25 tool list

--protocol-version accepts 2026-07-28, 2025-11-25, 2025-06-18, 2025-03-26 and 2024-11-05, in CLI and TUI mode. Any other value fails before a server is started. The server can still negotiate a lower version.

On 2026-07-28 the SDK connects with server/discover instead of initialize. It may retry at a version the server offered, and falls back to initialize at 2025-11-25 when discovery fails otherwise. The debug log records each attempt and ends with one Protocol version negotiated line (requested, negotiated, handshake, fallback), so a server that quietly dropped you to the older protocol is visible. server prints the negotiated version.

The HTTP+SSE transport (--transport sse) negotiates at most 2025-11-25. Use http for 2026-07-28.

Pin 2025-11-25 when a server’s tools still call the client directly (sampling, elicitation, roots) and fail under 2026-07-28.

2026-07-28 has no sessions (SEP-2575):

  • The session ID shows as stateless (2026-07-28) in the connect log, the health report and the event trace.
  • ping no longer exists, so the connection health check is skipped. It would otherwise read the refused ping as a dead connection and reconnect.
  • tools, prompts and resources list_changed notifications arrive only on a subscriptions/listen stream. MCP-TUI opens it at connect and waits up to 5 seconds for the server’s acknowledgement; a server that never acknowledges is logged, not fatal.
  • Resource subscriptions (resource watch, s in the TUI) use a per-URI subscriptions/listen stream instead of resources/subscribe, and wait for the server to acknowledge the URI. A server that does not declare resources.subscribe is refused up front.

A server can no longer send sampling/createMessage, elicitation/create or roots/list while it handles a request. Instead, tools/call, prompts/get and resources/read answer with input requests; the client answers them and retries the call (SEP-2322).

MCP-TUI runs this loop itself so it can show every round. It answers input requests with the same handlers as the older direct calls: the TUI’s sampling and elicitation screens and roots editor, or the CLI’s --sampling-stub, --elicit-stub and --root flags. It gives up after 10 rounds, or after 3 rounds in which the server shed load.

Where the rounds show:

  • CLI — tool call, prompt execute and resource get end with an Input rounds (SEP-2322) section in text output and carry rounds in JSON.
  • TUI — the tool result, prompt viewer and resource viewer list the rounds under the result.
  • Debug log — one line per round and per answered input (key, kind, and the answer’s shape, never its content). The MCP Protocol tab shows each retry as its own request.

A call the server answers on the first try shows nothing extra.

URL-mode elicitation behaves differently too: 2026-07-28 removed notifications/elicitation/complete, so the outcome arrives in the server’s answer to the retried call. The debug log says so after the URL is shown.

Progress is request-scoped: a server reports on a request only through notifications/progress naming the progressToken that request carried, and on 2026-07-28 those notifications travel with the request’s response. MCP-TUI puts a token on every tools/call, prompts/get and resources/read it sends, on every protocol version, and routes each notification to the call that holds the token.

Each multi round-trip round gets a fresh token. The rounds are independent requests with their own ids, each one completes, and progress must increase under one token, which a server counting per request would break if the rounds shared it. All of a call’s tokens report to the same call, and are released when the call returns.

Where progress shows:

  • CLI — tool call, prompt execute and resource get redraw one stderr line with the latest progress, only on a terminal in text mode (see the CLI reference).
  • TUI — the tool screen draws a progress bar under the spinner (the value and message when the server gives no total); a prompt or resource that is still loading shows its progress in the status line.
  • Notifications — every progress notification still lands in the Notifications tab, --watch-notifications and the debug log, including ones for a token no call holds any more.

Tasks differ by form. Under 2025-11-25 the token of the call that created a task stays valid for the task’s lifetime, so tool call --task --wait and the TUI’s task mode keep showing its progress until the task ends. The 2026-07-28 tasks extension does not support progress on tasks: the token covers only the tools/call itself.

List results carry ttlMs and cacheScope (SEP-2549), and the SDK answers repeat lists from its own cache until the ttl runs out. In the TUI the rule under the tabs shows how the active tab’s list was served, e.g. cached · ttl 30s · private; the debug log records the same per list method. Refreshing with r does not bypass the cache: only a list_changed notification or reconnecting fetches a fresh list.

resources/read results are cached the same way, per URI. The resource viewer and resource get show how each read was served (Cache: cached · ttl 1m0s · private; cache in JSON). A notifications/resources/updated for the URI drops it from the cache, so the next read goes to the server; subscribe to the resource to get those.

Over HTTP the SDK sends Mcp-Method, Mcp-Name and Mcp-Param-* on requests (SEP-2243). --mcp-method-headers does nothing on this revision and MCP-TUI logs that at connect. --debug lists the Mcp-* headers each request carried, and the TUI’s HTTP Debug tab shows them.

The SDK removes any tool whose x-mcp-header annotations break SEP-2243 from tools/list (on every protocol version). tool list and the TUI tools tab name each dropped tool and why.

logging/setLevel no longer exists. With --server-log-level <level>, MCP-TUI puts the level in every request’s _meta (io.modelcontextprotocol/logLevel); on older versions it sends logging/setLevel once after connecting. Without the flag, servers send no log notifications.

Each result’s _meta can name the server that produced it (io.modelcontextprotocol/serverInfo). Behind a gateway that can differ from the server that answered server/discover. The CLI ends such results with Served by: <name> <version> (server in JSON), and the TUI viewers show the same line.

2026-07-28 deprecates logging, sampling and roots (SEP-2577). They still work through the deprecation window, and MCP-TUI labels them: the --server-log-level, --sampling-*, --root and --roots-file help text, the TUI’s sampling overlay, roots editor and server log notifications. The sampling overlay also flags includeContext values thisServer and allServers (SEP-2596).

notifications/roots/list_changed is removed. On 2026-07-28 MCP-TUI does not advertise or send it; editing roots changes what later input requests are answered with.

New error codes are named in the error text: -32020 HEADER_MISMATCH, -32021 MISSING_REQUIRED_CLIENT_CAPABILITIES, -32022 UNSUPPORTED_VERSION. Resource-not-found is -32602 on resources/read (SEP-2164). See the CLI reference.

Tasks use the io.modelcontextprotocol/tasks extension on 2026-07-28 instead of the 2025-11-25 experimental form. See Tasks.

These arrived with the same work but do not depend on the protocol version:

  • --traceparent puts a W3C traceparent in every request’s _meta (SEP-414) so the server’s spans join your trace.
  • Tool input schemas are read through $ref/$defs and anyOf [T, null] (SEP-2106 allows any JSON Schema 2020-12 keyword), in tool call argument conversion and in the TUI form. A remote $ref is never fetched; the call fails instead.