Blog, by , , 9 min read

MCP deprecated roots, sampling and logging: what to do

MCP 2026-07-28 deprecates Roots, Sampling, Logging and dynamic client registration (removable from July 2027) and HTTP+SSE. What replaces each one.

9min read
On this page
  1. What deprecated means, by policy
  2. The five features
  3. Roots: send the path with the call
  4. Sampling: call the model yourself
  5. Logging: stderr and OpenTelemetry
  6. Dynamic Client Registration: host a metadata document
  7. HTTP+SSE: the oldest item on the list
  8. What to change this quarter
  9. Frequently asked questions

Short answer: the 2026-07-28 revision of the Model Context Protocol put five features on a removal track: the Roots and Sampling client features, the Logging utility, OAuth Dynamic Client Registration, and the old HTTP+SSE transport. None of the five is removed yet, though 2026-07-28 did remove logging/setLevel and the roots change notification and moved every server-initiated request onto a new pattern, so a server written against 2025-11-25 does not work unchanged. Under the new feature lifecycle policy a deprecated feature must stay in the spec for at least twelve months, so the first four become eligible for removal in the first revision released on or after 28 July 2027; HTTP+SSE, deprecated since 2025, is already past its window. The official SDKs must mark deprecated features as such and should warn when they are used. What changes now is what you should build: pass paths as tool arguments instead of asking for roots, call your model provider directly instead of sampling through the client, log to stderr or OpenTelemetry, register OAuth clients with a Client ID Metadata Document, and serve Streamable HTTP. The details, as of 25 October 2026, follow.

Some background: MCP revisions are dated, and 2026-07-28 is the current one. Its changelog is mostly about making the protocol stateless: no initialize handshake, no Mcp-Session-Id, a server/discover method, and a new way for servers to ask the client for input mid-request. Remote MCP server not connecting? Test it by hand covers the transport side. This post is about the "Deprecated" section of that changelog, which is the first one written under a formal policy, and about the deprecated features registry that the policy created so that "an implementer does not have to reconstruct that picture from deprecation entries spread across revision changelogs".

What deprecated means, by policy

The lifecycle policy (SEP-2596) defines three states. Active is the normal one. Deprecated means "the feature remains in the specification but is scheduled for removal", with a documented migration path; "new implementations should not adopt the feature" and existing ones "should migrate before the earliest removal date". Removed means it is gone from the draft and will be absent from the next revision.

The window is the part to plan against. A deprecation SEP must set a minimum deprecation window of "at least twelve" months, measured from the release of the revision that first marks the feature deprecated. The feature "becomes eligible for removal in the first specification revision released as Current on or after the window elapses", and removal is a maintainer decision which "may happen later": features "may remain Deprecated, without removal, for much longer than the minimum deprecation window". The only shortcut is an expedited removal for an active security risk with a published advisory or documented exploitation, and even then at least ninety days must pass.

Two obligations fall on the Tier 1 (official) SDKs once a revision with a deprecation ships: they "must mark the corresponding API surface deprecated using the language's native mechanism" in their next release, and "should emit a runtime warning when a deprecated feature is exercised". Removal from the spec, on the other hand, "does not oblige an SDK to drop the feature from releases". So the practical signals you will see are compiler and linter warnings first, runtime warnings second, and, for the four 2026-07-28 deprecations, a hard break only after July 2027, if the maintainers decide on it. HTTP+SSE is the exception, below.

The five features

Feature Deprecated in Migration path Earliest removal
Roots 2026-07-28 Pass directories or files via tool parameters, resource URIs, or server configuration First revision on or after 2027-07-28
Sampling 2026-07-28 Integrate directly with LLM provider APIs First revision on or after 2027-07-28
Logging 2026-07-28 Log to stderr for stdio; use OpenTelemetry for observability First revision on or after 2027-07-28
Dynamic Client Registration 2026-07-28 Client ID Metadata Documents First revision on or after 2027-07-28
HTTP+SSE transport 2025-03-26 Streamable HTTP Three months after SEP-2596 reaches Final

The table is condensed from the registry as published on 25 October 2026; the registry also records what deprecated each feature: SEP-2577 for the first three, PR #2858 for dynamic client registration, SEP-2596 for HTTP+SSE. One smaller entry rides along, the includeContext values "thisServer" and "allServers" on sampling requests, deprecated with 2025-11-25 and removed no later than Sampling itself. The registry's "Removed" section is empty: "No features have been removed under this policy yet."

Roots: send the path with the call

Roots let a client tell a server which directories it may operate in. The deprecation SEP (SEP-2577) gives the reason as "vague semantics, overlaps with tool parameters and server configuration", with low adoption relative to the complexity. The migration is the obvious one: a tool that works on a file takes the file's path or a resource URI as an argument, and a server that should be confined to a directory gets that directory from its configuration, not from a protocol message. If your server auto-approved filesystem access on the strength of a root, note that the SEP discussion raised exactly that question and did not answer it; the safe reading is that the client's consent model, not the server's root list, is where that permission lives now.

The roots/list request and result shapes are unchanged; what 2026-07-28 removed is the notifications/roots/list_changed notification, and the request itself now travels inside the Multi Round-Trip pattern described below rather than as a server-initiated message. A server can still ask for roots that way; new servers should not.

Sampling: call the model yourself

Sampling let a server ask the client's model to complete a prompt, so that a server could use an LLM without holding API keys. SEP-2577 calls it complex to implement, citing human-in-the-loop handling, model selection and security, with low client adoption, and the registry's migration path is to "integrate directly with LLM provider APIs". That is a real change for the few servers that relied on it: they now need their own model access and their own key management. A maintainer in the SEP thread (kurtisvg) said deprecation doesn't forbid the feature's return and suggested an improved sampling could come back as an experimental extension if there is demand; nothing of the kind exists in the registry today.

There is a second reason sampling got harder in 2026-07-28, even before the deprecation. The revision replaced all server-initiated requests with Multi Round-Trip Requests: a server that needs something from the client, a root list, a sampled completion or an elicitation answer, returns a result with resultType: "input_required" and an inputRequests map, and the client retries the original tools/call, resources/read or prompts/get with inputResponses and an opaque requestState the server gave it. The spec marks the old pattern as "no longer supported" and the change as breaking. For a sampling-dependent tool that means every model call is a round trip through the client, with no server-side state needed between them. Elicitation, which is not deprecated, uses the same mechanism and is the right tool when what you need from the user is an answer rather than a completion.

Logging: stderr and OpenTelemetry

The logging/setLevel request and the notifications/message stream let a server send log lines to the client. The SEP's one-line rationale is that logging "overlaps with stderr and OpenTelemetry", and the registry's migration path is "log to stderr for stdio transports; use OpenTelemetry for observability". 2026-07-28 already removed logging/setLevel: the changelog says the level "is now set per-request via io.modelcontextprotocol/logLevel in _meta; servers MUST NOT emit notifications/message for requests that did not include this field". The same revision documents how to carry traceparent, tracestate and baggage in _meta, which is the OpenTelemetry route. For a remote server the pragmatic answer is the one you would give any HTTP service: structured logs on the server, traces with the propagated context, and nothing the client has to subscribe to.

Dynamic Client Registration: host a metadata document

RFC 7591 dynamic registration let an MCP client create an OAuth client on the fly at an authorization server it had never seen. The 2026-07-28 changelog deprecates it "in favor of Client ID Metadata Documents", keeping it "for backwards compatibility with authorization servers that do not support Client ID Metadata Documents". The replacement makes the client's own HTTPS URL its client_id; the authorization server fetches the JSON at that URL and validates the redirect URIs in it. The client registration page says clients and authorization servers "SHOULD support" the new mechanism and lists dynamic registration as the fallback when client_id_metadata_document_supported is absent from the authorization server's metadata. Remote MCP server returns 401? How MCP OAuth works walks through the whole flow, including the new requirement that clients sending a dynamic registration set application_type so OpenID Connect servers don't reject localhost redirect URIs.

HTTP+SSE: the oldest item on the list

The two-endpoint transport from the 2024-11-05 revision, a GET that opens a server-sent-events stream and a POST for messages, was already marked deprecated with 2025-03-26, when Streamable HTTP replaced it. SEP-2596 reclassified it under the new policy, and it is the one entry whose removal is not tied to a twelve-month window but to "three months after SEP-2596 reaches Final", because its window has long since run. SEP-2596 was merged as Final on 18 May 2026, so those three months have already elapsed: HTTP+SSE is the one item on this list that is already eligible for removal, and the next revision may drop it if the Core Maintainers decide so. The connectivity post shows how to recognise a server that still answers only this way.

What to change this quarter

For a server: remove roots/list calls and take paths as arguments; replace sampling with a direct provider client, or with elicitation if the input you need is the user's; drop the logging capability and write to stderr or a tracer; serve Streamable HTTP, and if you are still on the GET-plus-POST transport, do that first. Then run your server through the ToolVet MCP scanner, which connects over Streamable HTTP, reads the tool list and grades the tool definitions for manipulation patterns; it does not speak HTTP+SSE, so a server on the old transport gets no grade.

For a client: keep handling all five, since the policy keeps four of them for at least a year and does not oblige an SDK to drop a feature when the spec does; surface the SDK's deprecation warnings to your users rather than suppressing them; and add Client ID Metadata Document support, because the spec says authorization servers SHOULD support it while dynamic registration is only a MAY kept for backwards compatibility.

Frequently asked questions

Will MCP servers that use sampling or roots stop working?

Not in 2026-07-28, and not before the first revision released on or after 28 July 2027, which is the earliest removal date in the registry. The policy requires at least twelve months in the Deprecated state, and Tier 1 SDKs must mark the features deprecated; removal from the spec does not oblige an SDK to drop them. Removal after that date is a maintainer decision and may come later.

What replaces MCP sampling?

The registry's migration path is to integrate directly with the LLM provider's API, so the server holds its own model access. For the cases where a server needs an answer from the user rather than a completion, elicitation remains active and now runs through the Multi Round-Trip Requests pattern.

Is MCP logging removed in 2026-07-28?

The feature is deprecated, not removed, but logging/setLevel is gone: the log level now travels per request in _meta under io.modelcontextprotocol/logLevel, and servers must not send notifications/message for requests without it. The recommended replacement is stderr for stdio servers and OpenTelemetry for observability, which is the route for remote servers.

Is dynamic client registration still supported in MCP?

Yes, as a fallback. It is deprecated in favour of Client ID Metadata Documents and remains for authorization servers that don't support them. Clients should use pre-registered credentials first, then a metadata document if the authorization server advertises support, then dynamic registration, then ask the user.

The registry, changelog and policy text quoted above are as published on 25 October 2026. How we check and score explains how ToolVet tests remote MCP servers.