{"slug": "introducing-mcp-7-28-for-ai-application-developers-what-goes-away-and-what-might", "title": "Introducing MCP 7-28 for AI Application Developers: What Goes Away, and What Might Break", "summary": "The MCP 7-28 specification revision, expected July 28, 2026, deprecates Roots, Sampling, and protocol-level Logging while moving to a stateless, sessionless architecture with explicit state handles. The update strengthens HTTP authorization, standardizes tool contracts on JSON Schema 2020-12, and requires most lookup-style MCP servers to make modest updates, but servers relying on sessions, filesystem Roots, browser state, or remote HTTP deployments need broader migration planning.", "body_md": "*Junghwan Park ( 9bow) is an AAIF Ambassador, a PyTorch Ambassador, and the lead maintainer of the PyTorch Korea User Group (PyTorchKR). A Korean version of this post is available here.*\n\nTL;DR: MCP 7-28 is less about new features than simplifying and hardening the protocol for production use. The release deprecates Roots, Sampling, and protocol-level Logging, moves MCP to a stateless, sessionless architecture that replaces implicit session state with explicit state handles, strengthens HTTP authorization, and standardizes tool contracts on JSON Schema 2020-12. Most lookup-style MCP servers will require only modest updates, while servers that depend on sessions, filesystem Roots, browser state, long-running workflows, or remote HTTP deployments should plan for a broader architectural review and migration.\n\n*Disclaimer: ‘MCP 7-28’ is a working name for the MCP specification changes expected to be published around July 28, 2026. The SEPs (Specification Enhancement Proposals) cited in this post ( SEP-2577, SEP-2575, SEP-2567, SEP-1613, SEP-2106, and others) have already reached Final status, but the official specification revision that incorporates them has not yet been finalized as of this writing. It is currently published as a Release Candidate (locked May 21, 2026; see the official RC announcement); 2025-11-25 remains the latest finalized revision, and 2026-07-28 is scheduled to ship as final on July 28, 2026. Dates, exact wording, and any “planned/incorporated/finalized” phrasing in this post should therefore be re-verified against the official MCP specification, release notes, and SDK changelogs once the revision actually ships.*\n\n## Introduction to MCP and Why It Matters\n\nThe [PyTorch Korea User Group (PyTorchKR)](https://pytorch.kr/) covers not only training and inference with PyTorch, but also everything it takes to put those models to work in real services outside the lab. Curating and sharing the latest news, open-source projects, and notable papers and research trends on the [PyTorchKR community forum](https://discuss.pytorch.kr/) comes from the same motivation. Training a model well and making that model genuinely useful inside a product are no longer things we can think about separately.\n\nModels are increasingly used together with agents and external tools, and MCP (Model Context Protocol) is one of the standardized touchpoints in that connection layer. For a large language model (LLM) to be useful in the real world, the model alone is not enough. It needs channels to the real world: reading files, querying databases, searching the documents a user cares about, calling external APIs. MCP is an open protocol that standardizes exactly that channel: instead of building a bespoke integration for every tool, you connect models to external tools, data, and execution environments through one shared contract. This is why tools like Claude Desktop, Cursor, and VS Code all follow the same MCP client specification.\n\n### How MCP (Model Context Protocol) Works\n\n```\ngraph TB\n    subgraph \"MCP Host (AI application)\"\n        Client1[\"MCP Client 1\"]\n        Client2[\"MCP Client 2\"]\n        Client3[\"MCP Client 3\"]\n        Client4[\"MCP Client 4\"]\n    end\n\n    ServerA[\"MCP Server A\n(local; e.g., filesystem)\"]\n    ServerB[\"MCP Server B\n(local; e.g., database)\"]\n    ServerC[\"MCP Server C\n(remote; e.g., Sentry)\"]\n\n    Client1 ---|\"dedicated\nconnection\"| ServerA\n    Client2 ---|\"dedicated\nconnection\"| ServerB\n    Client3 ---|\"dedicated\nconnection\"| ServerC\n    Client4 ---|\"dedicated\nconnection\"| ServerC\n```\n\nMCP is easiest to understand in terms of three participants: the host, the server, and the client. The LLM application the user directly interacts with, such as Claude Desktop or Cursor, is the host; the connector inside the host that maintains a 1:1 connection with a single server is the client; and the side that actually provides tools and data is the server. These three participants exchange requests and responses as [JSON-RPC 2.0](https://www.jsonrpc.org/specification) messages. As of this writing, the latest MCP specification is the [November 25, 2025 revision](https://modelcontextprotocol.io/specification/2025-11-25).\n\nAn MCP server exposes what it can do to the client. It advertises three kinds of building blocks:\n\n- Tools: functions the model invokes to perform real actions (e.g., search, file reads, external API calls).\n- Resources: data provided to the model as context (e.g., files, documents, records).\n- Prompts: reusable prompt templates.\n\nServers and clients generally connect over one of two transports: (1) For MCP servers run locally, the host launches the server as a subprocess and exchanges messages over standard input and output (stdin/stdout), using the stdio transport.\n\n```\nsequenceDiagram\n    participant Client\n    participant SP as Server Process\n\n    Client->>+SP: Launch subprocess\n    loop Message Exchange\n        Client->>SP: Write to stdin\n        SP->>Client: Write to stdout\n        SP--)Client: Optional logs on stderr\n    end\n    Client->>SP: Close stdin, terminate subprocess\n    deactivate SP\n```\n\n(2) For MCP servers running remotely, messages are exchanged over the HTTP-based [Streamable HTTP](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http) transport. Under the [currently published spec (2025-11-25)](https://modelcontextprotocol.io/specification/2025-11-25), the client and server exchange versions and capabilities in an initialization (initialize) step at the start of the connection, then continue subsequent requests and responses on top of the established session.\n\n```\nsequenceDiagram\n    participant Client\n    participant Server\n\n    note over Client, Server: initialization\n\n    Client->>+Server: POST InitializeRequest\n    Server->>-Client: InitializeResponse\nMCP-Session-Id: 1868a90c...\n\n    Client->>+Server: POST InitializedNotification\nMCP-Session-Id: 1868a90c...\n    Server->>-Client: 202 Accepted\n\n    note over Client, Server: client requests\n    Client->>+Server: POST ... request ...\nMCP-Session-Id: 1868a90c...\n\n    alt single HTTP response\n      Server->>Client: ... response ...\n    else server opens SSE stream\n      loop while connection remains open\n          Server-)Client: ... SSE messages from server ...\n      end\n      Server-)Client: SSE event: ... response ...\n    end\n    deactivate Server\n\n    note over Client, Server: client notifications/responses\n    Client->>+Server: POST ... notification/response ...\nMCP-Session-Id: 1868a90c...\n    Server->>-Client: 202 Accepted\n\n    note over Client, Server: server requests\n    Client->>+Server: GET\nMCP-Session-Id: 1868a90c...\n    loop while connection remains open\n        Server-)Client: ... SSE messages from server ...\n    end\n    deactivate Server\n```\n\nMuch of what changes in ‘MCP 7-28’, the subject of this post, is precisely about revisiting the assumptions baked into how these connections are established (handshake) and maintained (session). If you want more background on MCP concepts and architecture, the PyTorchKR community’s [Deep Research: Model Context Protocol (MCP) study material](https://discuss.pytorch.kr/t/deep-research-model-context-protocol-mcp/6594) is a good starting point.\n\n### Introducing the Next MCP Standard: MCP 7-28\n\n‘MCP 7-28’ is the working name for the next MCP specification revision, expected to land around July 28, 2026. Rather than adding new features, this release is closer to a migration-focused one. The core idea is to keep MCP’s Core Protocol smaller and clearer while cleaning up state management, authorization, schemas, and the lifecycle of several existing features. So the first thing to look at in this revision is ‘what goes away, and what might break’.\n\nAnyone who has built and operated MCP servers in production runs into questions like these:\n\n- Which tools can the model see?\n- Against which schema are tool-call arguments validated?\n- Where is state stored between one tool call and the next?\n- Who decides access to external resources like files, browsers, databases, and document search?\n- How does an MCP server exposed over HTTP validate tokens, scopes, and audiences?\n- Should observability live in protocol-level logging, or in application logs and traces?\n\nThe major changes in MCP 7-28 map directly onto these questions, and they fall into two broad groups:\n\n- What goes away (Deprecation): Roots, Sampling, and Logging are marked deprecated in the core protocol (\n[SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2577-deprecate-roots-sampling-and-logging.md)). These features do not disappear immediately, but new development should stop relying on them. - What might break (Breaking Change): the protocol moves stateless-first (\n[SEP-2575](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2575-stateless-mcp.md)), the protocol-level session is removed in favor of surfacing state as explicit handles ([SEP-2567](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2567-sessionless-mcp.md)), and the authorization baseline for the HTTP transport is hardened. On top of that, tool schemas are aligned with JSON Schema 2020-12, resetting the baseline for tool contracts ([SEP-1613](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/1613-establish-json-schema-2020-12-as-default-dialect-f.md),[SEP-2106](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2106-json-schema-2020-12.md)).\n\nThis post focuses less on the upgrade steps for any particular SDK, and more on what to audit when you operate MCP servers as the tooling infrastructure of an LLM application. For the rest of the post, we walk through each change in the same order: ① what the feature originally was → ② what changes and how → ③ how it lands in your code and configuration → ④ what you gain as a result. We first sort out the concepts, then close with real MCP server case studies and a migration checklist. Operational topics such as routing headers, list caching, trace propagation, and the Tasks extension are out of scope here and will be covered separately in a [follow-up series](https://discuss.pytorch.kr/).\n\nMCP 7-28 changes covered in this post, at a glance\n\n| Checklist item | Direction of change | Question to ask |\n| Roots | Deprecated | Do you rely on roots/list for workspace/filesystem access boundaries? |\n| Sampling | Deprecated | Does your MCP server ask the client/host to generate LLM completions? |\n| Logging | Deprecated | Do you depend on MCP protocol logging for operational logs and observability? |\n| Stateless/sessionless | Protocol-level session state removed; state becomes explicit handles | Can each request be understood without a prior handshake/session? Is state referenced by explicit IDs? |\n| HTTP authorization | Hardened security baseline for the HTTP transport | Do you validate bearer tokens, resource indicators, scopes, and audiences? |\n| JSON Schema 2020-12 | Tool contract baseline cleaned up | Do inputSchema, outputSchema, and structuredContent conform to the new baseline? |\n\n## What Goes Away (Deprecation): Roots, Sampling, Logging\n\n[SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2577-deprecate-roots-sampling-and-logging.md) designates Roots, Sampling, and Logging as deprecated in the core protocol. Deprecation does not mean immediate removal. [SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2577-deprecate-roots-sampling-and-logging.md) explains that during the deprecation period, wire-level behavior does not change, and neither the types nor capability negotiation are removed. So the accurate reading is not ‘this breaks today’ but ‘stop using these in new MCP implementations’.\n\n### Roots\n\nWhat it originally was: Roots lets a client tell a server which local directories and file boundaries it may access. For servers that touch the local filesystem, like the [filesystem MCP server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem), access boundaries matter, and a server could query the client-provided boundaries via roots/list.\n\nWhat changes and how: [SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2577-deprecate-roots-sampling-and-logging.md) views Roots not as an actual access-control mechanism but as informational guidance. From that viewpoint, the MCP protocol does not confine the server to those paths, so assuming ‘this path is inside the client-sent Roots, therefore it is safe’ blurs the security boundary. The proposal instead recommends conveying access scope through more explicit means: tool parameters, resource URIs, server configuration, or environment variables.\n\nHow it lands in code/configuration: from a migration standpoint, check the following:\n\n- Does the MCP server accept its allowed paths as launch arguments?\n- Can an allowlist be set via a configuration file or environment variables?\n- Is access scope made explicit in tool parameters or resource URIs?\n- Is filesystem policy enforced at the host, gateway, or sandbox layer?\n- Does the server only behave correctly when roots/list results change?\n\nWhat you gain: you move away from the structure where, within each session, the server dynamically trusts whatever Roots the client advertised. Access policy becomes decidable from the request and the server configuration alone. As a result, the security boundary stops being a protocol-level hint and becomes a policy the MCP server itself enforces.\n\n### Sampling\n\nWhat it originally was: Sampling lets an MCP server request an LLM completion from the client or host. With it, a server could use the model connected to the client even without its own LLM integration or API key.\n\nWhat changes and how: Sampling is powerful, but it blurs the boundary of responsibility. It becomes ambiguous whether the server is a simple tool provider or an orchestrator directing model invocations. Responsibility for choosing which model to call, handling the user-approval UI, managing cost and policy, and defending against prompt injection inside the tool loop can end up in a gray zone between server and client. For these reasons, [SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2577-deprecate-roots-sampling-and-logging.md) deprecates Sampling and suggests alternatives such as calling an LLM provider API directly when a server genuinely needs completions.\n\nHow it lands in code/configuration: the direction for reducing a server’s dependence on the model looks like this:\n\n- The MCP server returns the necessary context, candidate prompts, and structured results.\n- Model invocation happens in the MCP host, the agent runtime, or the application layer.\n- Long-running workflow orchestration is managed by a separate agent runtime or job queue.\n- If the server truly needs its own LLM, it integrates a provider API directly and surfaces that fact in its tool contract and operational policy.\n\nWhat you gain: the default role of an MCP server shifts from ‘go invoke the model’ toward ‘reliably provide the tools and data the model reasons over’. Responsibility boundaries become clear, and risk surfaces like prompt injection and data exfiltration become easier to manage.\n\n### Logging\n\nWhat it originally was: Logging lets an MCP server deliver structured logs to the MCP client via protocol messages (notifications/message), with the client able to adjust logging verbosity.\n\nWhat changes and how: deprecating Logging does not mean ‘stop logging’. It means: do not entrust operational observability to Logging, a protocol feature. [SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2577-deprecate-roots-sampling-and-logging.md) itself [recommends](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2577-deprecate-roots-sampling-and-logging.md#logging) leaning on mature, existing logging/observability infrastructure such as standard error (stderr) or [OpenTelemetry](https://github.com/open-telemetry).\n\nHow it lands in code/configuration: in production, apply setups like the following:\n\n- Locally run MCP servers use a standard logger and standard error (stderr).\n- Remote, HTTP-based MCP servers keep request logs, audit logs, and trace IDs.\n- Tool calls, retrieval, external API calls, and model calls are tied together as OpenTelemetry traces.\n- Responsibilities of protocol messages and application logs are kept separate.\n\nWhat you gain: in an AI application, a single user request mixes retrieval, tool calls, model calls, and external API calls. An end-to-end trace is far more useful than protocol logging alone.\n\nHow reference MCP servers from the [official MCP repository](https://github.com/modelcontextprotocol/servers), such as [filesystem](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) and [memory](https://github.com/modelcontextprotocol/servers/tree/main/src/memory), are affected is covered later in this post.\n\n## What Might Break (Breaking Change): Stateless/Sessionless, HTTP Authorization, JSON Schema 2020-12\n\n### Stateless/Sessionless\n\nWhat the structure originally was: the [current MCP standard](https://modelcontextprotocol.io/specification/2025-11-25) depends in places on the initialize handshake and connection/session state. The client and server exchange versions and capabilities at the start of a connection; once the server issues a session ID (MCP-Session-Id), every subsequent request must carry it in a header. Managing state on top of a pinned session like this was fine for a single local process, but became an obstacle at scale.\n\nWhat changes and how: first, [SEP-2575](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2575-stateless-mcp.md) proposes a stateless-first direction. If an HTTP-based remote MCP server sits behind a load balancer or runs across multiple nodes, a given client session gets pinned to the in-memory state of whichever server it first connected to, forcing sticky sessions, session stores, resumption, and failover. To fix this, [SEP-2575](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2575-stateless-mcp.md) proposes:\n\n- Requests should be as self-contained as possible.\n- The protocol version and client capabilities travel as per-request metadata on every request.\n- An MCP server can advertise its supported versions and capabilities via server/discover.\n- Server designs that can only process the current request by remembering a previous one should be avoided.\n\nOn top of this, [SEP-2567](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2567-sessionless-mcp.md) pushes further toward a sessionless direction: it removes the protocol-level session concept entirely, and where application state is needed, it is passed around as explicit state handles in tool results and arguments.\n\nHow it lands in code/configuration: to see what stateless/sessionless means in practice, imagine an MCP server that serves search results. State like a search session is treated as an explicit handle:\n\n```\n# Create a new search, returning a state handle for it (e.g., srch_7f3a)\n1. create_search(query=\"MCP Roots deprecation\")\n   -> { \"search_handle\": \"srch_7f3a\" }\n\n# Request the next page of results, passing the earlier handle (srch_7f3a)\n2. get_search_page(search_handle=\"srch_7f3a\", page=2)\n   -> { \"items\": [...] }\n\n# When done, pass the handle (srch_7f3a) to close the search\n3. close_search(search_handle=\"srch_7f3a\")\n   -> { \"closed\": true }\n```\n\nEven under the stateless/sessionless assumption, state can still live on the server. What changes is that the state is no longer bound to a prior session; it is expressed as an explicit value, search_handle. [SEP-2567](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2567-sessionless-mcp.md) describes this not as a new protocol primitive but as a tool-design pattern. Each handle is just a string inside a tool result, passed back as an argument on later calls. For good handle design, refer to the SEP’s [guidance for servers](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2567-sessionless-mcp.md#guidance-for-servers): use opaque values, validate (handle, auth_context) on every call, and make expiry/cleanup policies explicit.\n\nWhat you gain: client requests can be routed to any server node. Horizontal scale-out becomes easy, state no longer vanishes with a failed node, and caching of list results such as tools/list becomes straightforward. This change has significant impact on MCP servers that must manage state across requests, including browser automation, shopping carts, payment flows, long-running jobs, and DB transactions. But lookup-style MCP servers that take search criteria on every call and return results are unlikely to conflict with it.\n\nThe precise meaning of the stateless core, handle design for search sessions / long-running jobs / browser contexts, session independence of tools/list, and the Tasks Extension of [SEP-2663](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md) will be covered in a follow-up post.\n\n### HTTP Authorization\n\nWhat the structure originally was: for local MCP servers, an MCP host like Claude Desktop or Cursor launches the server directly as a subprocess. In that setting, it is hard for the MCP protocol to determine who is using the server and how far they may reach. The trust boundary is already ‘whoever is using the MCP host’, so MCP had little need for its own authentication or authorization layer. In other words, when MCP servers were used to wire tools inside an LLM application, it was easy to treat authorization as something to bolt on later.\n\nWhat changes and how: the [MCP authorization draft](https://modelcontextprotocol.io/specification/draft/basic/authorization) defines the authorization flow for HTTP-based transports. Authorization remains optional in MCP implementations, but if an HTTP-based transport supports authorization, following this specification is recommended. For local stdio transports, the draft advises using local credential delivery, such as environment variables, instead of this flow. Running legalize-mcp locally inside Claude Desktop or Cursor and exposing an HTTP-based remote MCP server to the internet involve different threat models.\n\n```\nsequenceDiagram\n    participant B as User-Agent (Browser)\n    participant C as Client\n    participant M as MCP Server (Resource Server)\n    participant A as Authorization Server\n\n    C->>M: MCP request without token\n    M->>C: HTTP 401 Unauthorized with WWW-Authenticate header\n    Note over C: Extract resource_metadata URL from WWW-Authenticate\n\n    C->>M: Request Protected Resource Metadata\n    M->>C: Return metadata\n\n    Note over C: Parse metadata and extract authorization server(s)\nClient determines AS to use\n\n    C->>A: GET Authorization server metadata endpoint\n    Note over C,A: Try OAuth 2.0 and OpenID Connect\ndiscovery endpoints in priority order\n    A-->>C: Authorization server metadata\n\n    alt Client ID Metadata Documents\n        Note over C: Client uses HTTPS URL as client_id\n        Note over A: Server detects URL-formatted client_id\n        A->>C: Fetch metadata from client_id URL\n        C-->>A: JSON metadata document\n        Note over A: Validate metadata and redirect_uris\n    else Dynamic client registration\n        C->>A: POST /register\n        A->>C: Client Credentials\n    else Pre-registered client\n        Note over C: Use existing client_id\n    end\n\n    Note over C: Generate PKCE parameters\nInclude resource parameter\nApply scope selection strategy\nRecord expected issuer\n    C->>B: Open browser with authorization URL + code_challenge + resource\n    B->>A: Authorization request with resource parameter\n    Note over A: User authorizes\n    A->>B: Redirect to callback with authorization code + iss\n    B->>C: Authorization code callback\n    Note over C: Validate iss against recorded issuer (RFC 9207)\n    C->>A: Token request + code_verifier + resource\n    A->>C: Access token (+ refresh token)\n    C->>M: MCP request with access token\n    M-->>C: MCP response\n    Note over C,M: MCP communication continues with valid token\n```\n\nHow it lands in code/configuration: for HTTP-based remote MCP servers, verify the following:\n\n- Does every HTTP request carry an Authorization: Bearer <access-token> header?\n- Are access tokens kept out of the query string?\n- Do you provide OAuth 2.0 Protected Resource Metadata and authorization server discovery?\n- Does the resource parameter name the MCP server as the target resource?\n- Does the MCP server validate the token audience?\n- Are scopes granular per operation, with an additional authorization challenge (WWW-Authenticate) returned for insufficient scopes?\n- Can the client recover from 401s, 403s, invalid or expired tokens, and insufficient_scope errors?\n\nWhat you gain: the moment an MCP server is exposed as an external HTTP endpoint, its tool contract and auth contract get designed together. The model can then determine, along the same request path, which tools it can see on the remote server, which scopes the user has granted, and whether it is authorized to touch a particular handle or resource.\n\nThe HTTP authorization flow itself, including OAuth 2.1, Protected Resource Metadata, token audience validation, scope challenges, and more, is covered in greater detail in upcoming posts.\n\n### JSON Schema 2020-12, Which Defines the Contract\n\nWhat the structure originally was: in an MCP server, a tool is not just a function. To the client and the LLM, the tool’s name, description, inputSchema, outputSchema, and structuredContent together form a contract. But until now, the definition was fairly loose about which JSON Schema dialect these contracts use, and how a tool with no arguments should express its schema.\n\nWhat changes and how: first, [SEP-1613](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/1613-establish-json-schema-2020-12-as-default-dialect-f.md) proposes establishing [JSON Schema 2020-12](https://json-schema.org/draft/2020-12/json-schema-core) as the default dialect for JSON schemas embedded in MCP messages. That is: absent an explicit $schema, JSON Schema 2020-12 is assumed; inputSchema must not be null; and even a tool with no parameters must carry a valid schema. [SEP-2106](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2106-json-schema-2020-12.md) then relaxes the constraints further:\n\n- inputSchema keeps type: “object” (tool arguments are an object), but now also allows JSON Schema 2020-12 keywords including oneOf, anyOf, allOf, if/then/else, and $ref/$defs.\n- outputSchema additionally supports full JSON Schema 2020-12 schemas, since tool output can be any JSON value, including arrays and scalars as well as objects.\n- structuredContent is likewise no longer restricted to objects and may be any JSON value that conforms to outputSchema.\n\nHow it lands in code/configuration: if you build MCP servers in Python on FastMCP, Pydantic, or dataclasses, check:\n\n- Are the inputSchemas your SDK generates valid against JSON Schema 2020-12?\n- Does a zero-argument tool end up with a null inputSchema?\n- Can lookup-by-ID-or-name tools use composition keywords like oneOf?\n- Are you wrapping a list API’s natural array response in an artificial wrapper object?\n- Do structuredContent and outputSchema match what the tool actually returns?\n- If internal tools must specify $schema explicitly, are those values consistent?\n\nWhat you gain: when the contract an MCP server exposes is unambiguous, the model miscalls tools less, clients fail validation less, and outputs can be post-processed safely. Even a lookup-style server with no session state suffers degraded tool usability if its schemas disagree with the client, so this change deserves an audit from every kind of MCP server.\n\nWhy tools/list is the real contract, the distinction between optional and nullable, when to use oneOf vs. anyOf, and aligning outputSchema with structuredContent are covered in upcoming posts.\n\n## Impact, Through Case Studies\n\nSo far we have surveyed the changes in the MCP 7-28 revision through its SEPs (Specification Enhancement Proposals). Now let’s see, through two brief case studies, how MCP servers should respond. The key point: not all MCP servers are affected equally. A server offering lookup-style tools may see relatively little impact, while filesystem servers, browser automation servers, and HTTP-based remote servers may need a review starting at the design level.\n\n### Case 1: A Lookup-Style MCP Server, Legalize-KR\n\n[Legalize-KR](https://github.com/legalize-kr/) is an open-source project that makes South Korea’s [statutes](https://github.com/legalize-kr/legalize-kr), [court precedents](https://github.com/legalize-kr/precedent-kr), [local ordinances](https://github.com/legalize-kr/ordinance-kr), and [administrative rules](https://github.com/legalize-kr/admrule-kr) data repositories available as [CLI tools and an MCP server](https://github.com/legalize-kr/cli-tools), plus agent skills. The MCP section of the Legalize-KR usage docs explains how MCP clients like Claude Desktop, Cursor, and VS Code call Legalize-KR data as tools. The agent interprets the natural-language question, and a local stdio MCP server performs the actual statute/precedent lookups. Judging by the [MCP tool descriptions published on its homepage](https://legalize.kr/usage.html#mcp), the Legalize-KR MCP server is lookup-style:\n\n- Supported tools\n- Statutes: laws_list, laws_get, laws_article\n- Precedents: precedents_list, precedents_get\n- Ordinances: ordinances_list, ordinances_get\n- Administrative rules: admrules_list, admrules_get\n- Unified search: search\n\n- Example configuration\n\n```\n{\n   \"mcpServers\": {\n      \"legalize-kr\": {\n         \"command\": \"uvx\",\n         \"args\": [\"--from\", \"legalize-cli[mcp]\", \"legalize-mcp\"]\n      }\n   }\n}\n```\n\nBased on the public docs and code, the Legalize-KR MCP server holds no long-lived protocol session state; on each tool call it simply takes the required arguments, looks up statute or precedent data, and returns the result. Simplified, the structure looks like this:\n\n```\n# Illustrative sketch, not the actual implementation.\nmcp = FastMCP(\"legalize-kr\")\n@mcp.tool()\ndef laws_article(\nlaw_name: str,\narticle_no: str,\ndate: str | None = None,\n) -> str:\nresult = fetch_law_article(\nlaw_name=law_name,\narticle_no=article_no,\ndate=date,\n)\nreturn json.dumps(result, ensure_ascii=False)\n```\n\nThe key point is that inputs like law_name, article_no, and date arrive explicitly in the tool call, and the server can produce its result from those inputs alone. Lookup-style servers like this are likely to be relatively lightly affected by the changes above.\n\n| Major MCP 7-28 change | Expected impact from Legalize-KR’s perspective |\n| Roots deprecation | Based on Legalize-KR’s public MCP usage docs, it does not appear to be a core dependency. |\n| Sampling deprecation | Low impact unless the server asks the client for LLM completions. |\n| Logging deprecation | Low impact unless protocol-level logging is on the critical operational path. |\n| Stateless/sessionless direction | A good fit for lookup-style tool calls, though SDK and protocol-version updates still need verification. |\n| HTTP authorization | Little impact for local stdio use; separate review needed if exposed over remote HTTP. |\n| JSON Schema 2020-12 | Verify that SDK-generated inputSchema/outputSchema match the new baseline. |\n\nAs the table shows, migrating to MCP 7-28 should be scoped not by ‘my whole MCP server’ but by ‘which MCP features am I actually using’.\n\n### Case 2: The Reference Implementations in the Official modelcontextprotocol/servers Repository\n\nThe [official modelcontextprotocol/servers repository](https://github.com/modelcontextprotocol/servers), which provides MCP server examples, also deserves careful reading. It contains a small set of reference servers maintained by the MCP steering group. Keep in mind that these servers are not production-ready solutions but educational reference implementations demonstrating MCP features and SDK usage.\n\nWith that in mind, the per-feature impact for the reference MCP servers looks like this:\n\n| Reference server | What to look at | MCP 7-28 angle |\n| filesystem | File-access boundary example | After the Roots deprecation, more explicit boundaries, including allowlists, launch arguments, and resource URIs, matter more. |\n| everything | Test server for feature-surface coverage | Useful for exercising combinations of prompts, resources, and tools. |\n| memory | Persistent application state example | Requires distinguishing ‘has state’ from ‘implicitly bound to a protocol session’. |\n| sequential-thinking | Cross-call context example | A place to examine how cross-call context surfaces in tool arguments and results. |\n| git | Repository tooling example | Check where local file and Git operation permissions are constrained. |\n\nLooking more closely at filesystem and memory at the implementation level reveals considerations quite different from the lookup-style case above.\n\n#### filesystem: A Server That Leans on Roots for Access Boundaries\n\nThe [filesystem server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) comprehensively provides file read/write plus directory create/list/move, search, and metadata tools (read_text_file, write_file, edit_file, list_directory, search_files, get_file_info, list_allowed_directories, and so on). All file operations are confined to ‘allowed directories’.\n\nAmong the MCP 7-28 changes, we saw one that affects how those allowed directories get set. The [filesystem server README](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem/README.md) documents two ways to specify them:\n\n- Command-line arguments: pass allowed paths directly at server startup, for example mcp-server-filesystem /path/to/allowed/dir1 /path/to/allowed/dir2, or configure:\n\n```\n{\n  \"mcpServers\": {\n    \"filesystem\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol/server-filesystem\", \"/path/to/allowed/dir1\", \"/path/to/allowed/dir2\"]\n    }\n  }\n}\n```\n\n- MCP Roots (the recommended method): if the MCP client advertises Roots, the server fully replaces its allowed directories with them, and notifications/roots/list_changed updates them at runtime without a server restart (though if the server starts with no command-line arguments and the client does not support Roots, initialization fails).\n\nOf these two, the recommended approach, using Roots, collides head-on with MCP 7-28: the documentation’s recommended way of conveying access boundaries relies on the very Roots feature that [SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2577-deprecate-roots-sampling-and-logging.md) proposes to deprecate.\n\nOne distinction matters here, though. The actual enforcement is not the Roots feature itself; the server enforces path validation that blocks access outside the allowed directories. Roots is merely the mechanism for dynamically delivering and updating the allowed-directory list. So what the deprecation destabilizes is not file access control itself, but the specific path of ‘runtime dynamic updates via Roots’. The remedy is to expose access scope through command-line arguments and configuration files, and (as discussed earlier) explicit tool parameters or resource URIs. Since wire-level behavior is preserved for a while after deprecation, nothing breaks immediately. For newly designed MCP servers, it is safer not to treat ‘the Roots the client passed during the session’ as the primary basis for your boundary.\n\n#### memory: A Server That Has State but Is Not Bound to Sessions\n\nThe [memory server](https://github.com/modelcontextprotocol/servers/tree/main/src/memory) persistently stores a knowledge graph of entities, relations, and observations in a local JSONL file (the MEMORY_FILE_PATH environment variable, default memory.jsonl). This lets a model remember and recall information across conversations. Its tools are create_entities, create_relations, add_observations, delete_entities, delete_observations, delete_relations, read_graph, search_nodes, and open_nodes, and it also exposes the whole graph as a memory://knowledge-graph resource. A single entity in the graph looks roughly like this:\n\n`{ \"name\": \"John_Smith\", \"entityType\": \"person\", \"observations\": [\"Speaks fluent Spanish\"] }`\n\nmemory is unmistakably a stateful server. But its state lives not in the current MCP session; it lives in the knowledge graph persisted to a file. The identifier that points at state is not a session ID but an explicit key, name, and the whole graph is addressable via a resource URI. This is exactly why the earlier impact table lists memory as the example for separating ‘has state’ from ‘implicitly bound to a protocol session’. The flow of creating a name via create_entities and later passing that name back into open_nodes or search_nodes is close to the explicit state handle pattern described earlier (with the difference that the handle is chosen by the user or the model rather than being an opaque server-issued ID).\n\nSo for an MCP server like memory, the MCP 7-28 review should focus less on the deprecated features and more on operations and scaling:\n\n- Horizontal scaling: the default store is a single JSONL file: process-local storage. Satisfying MCP 7-28’s ‘any request can go to any instance’ requires storage shared across instances.\n- Isolation and authorization: today there is a single graph, with no multi-user or tenant isolation. Exposing it as a remote MCP server requires splitting the graph into per-user files or namespaces, and validating not just the handle value (name) but authorization as well, (name, auth_context), on each request.\n- Resource subscriptions and caching: mutation tools emit notifications/resources/updated for memory://knowledge-graph. If clients depend on these notifications, verify that list/resource caching and invalidation flows stay consistent.\n\nThe reference servers in the [official modelcontextprotocol/servers repository](https://github.com/modelcontextprotocol/servers) are a starting point for building MCP servers. For production, security boundaries, authentication/authorization, observability, and deployment architecture must be redesigned and reimplemented against each service’s own threat model.\n\n## Where Does My MCP Server Fit?\n\nAs the case studies show, migration priorities for the MCP 7-28 changes depend on the type of server. Classifying your server with the flow below makes it easier to set priorities:\n\n``` php\nflowchart TD\n\nA[\"Inventory your MCP servers\"] --> B[\"Check usage of deprecated features\"]\n\nB --> C[\"Roots, Sampling, Logging\"]\n\nA --> D[\"Check how state is managed\"]\n\nD --> E[\"Stateless core and explicit handles\"]\n\nA --> F[\"Check tool schemas\"]\n\nF --> G[\"JSON Schema 2020-12\"]\n\nA --> H[\"Check transport and auth\"]\n\nH --> I[\"stdio or HTTP authorization\"]\n\nC --> J[\"Set migration priorities\"]\n\nE --> J\n\nG --> J\n\nI --> J\n```\n\nAlternatively, you can gauge the impact of the MCP 7-28 changes by what your server does. The following server types are likely to see relatively little impact:\n\n- Tool-centric servers focused on lookups\n- Servers where every tool call receives all required inputs as parameters\n- Servers that do not depend on protocol session state\n- Servers that do not use Roots, Sampling, or Logging as core features\n- Servers used only in local stdio environments\n- Servers whose authentication is limited to local environment variables or client configuration\n\nBy contrast, the following MCP server types may be significantly affected and deserve a careful review:\n\n- Servers that dynamically change their filesystem workspace via the Roots feature\n- Servers that call the client/host’s sampling/createMessage\n- Servers that use MCP protocol-level logging as their operational logs\n- Servers that bind browser contexts, shopping carts, payments, DB transactions, or long-running jobs to sessions\n- Servers whose tools/list, resources/list, or prompts/list results differ per session\n- Servers exposed externally over HTTP with weak token audience, scope, or discovery handling\n\nIf you fall into these categories, treat MCP 7-28 not as a simple compatibility update but as an opportunity for a design review.\n\n## Migration Checklist\n\nYou will want to re-verify against the final MCP 7-28 specification and SDK release notes, but as of this writing you can audit in this order:\n\n- Inventory the MCP features your server uses:\n- Check usage of Tools, Resources, Prompts, Roots, Sampling, Logging, Tasks, Elicitation, and any custom extensions.\n\n- Check usage of and dependence on deprecated features:\n- If you do not use Roots, Sampling, or Logging, impact may be limited.\n- If you use or depend on one or more, schedule replacement designs or removal.\n\n- Find session state:\n- Check whether per-client state is held and used in server memory.\n- If state management is genuinely needed, see whether it can be surfaced as explicit handles instead of sessions.\n\n- Check whether list endpoints vary by session:\n- If tools/list, resources/list, or prompts/list results change with connection or session state, a redesign may be needed.\n\n- Review your state-handle design:\n- Audit opaque handles, expiry, cleanup, authorization checks, error messages, and recovery tools.\n\n- Audit authentication on HTTP transports:\n- Check bearer tokens, resource indicators, Protected Resource Metadata, authorization server discovery, scope challenges, and audience validation.\n\n- Dump and validate your tool schemas:\n- Verify inputSchema, outputSchema, and structuredContent against\n[JSON Schema 2020-12](https://json-schema.org/draft/2020-12/json-schema-core).\n\n- Verify inputSchema, outputSchema, and structuredContent against\n- Consult the official reference servers:\n- Use reference servers like filesystem, everything, memory, sequential-thinking, and git as per-feature impact samples.\n\n- Prepare smoke tests:\n- Keep a minimal test set covering representative tool calls, schema listing, auth success/failure, handle expiry, and error messages.\n\n## Closing\n\nWhat matters most when reading the MCP 7-28 changes is not ‘what new features arrived’ but ‘which features does my MCP server actually use’. A lookup-style tool server like the Legalize-KR example is likely to fit the stateless/sessionless direction well. Conversely, MCP servers that depend on Roots, Sampling, Logging, session-scoped state management, or HTTP authorization should review their design and operations together.\n\n## Further Reading\n\n[The 2026-07-28 MCP Specification Release Candidate (official MCP blog)](https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/)[SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2577-deprecate-roots-sampling-and-logging.md):[Deprecate Roots, Sampling, and Logging](https://modelcontextprotocol.io/seps/2577-deprecate-roots-sampling-and-logging)[SEP-2575](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2575-stateless-mcp.md):[Make MCP Stateless](https://modelcontextprotocol.io/seps/2575-stateless-mcp)[SEP-2567](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2567-sessionless-mcp.md):[Sessionless MCP via Explicit State Handles](https://modelcontextprotocol.io/seps/2567-sessionless-mcp)[SEP-1613](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/1613-establish-json-schema-2020-12-as-default-dialect-f.md):[Establish JSON Schema 2020-12 as Default Dialect for MCP](https://modelcontextprotocol.io/seps/1613-establish-json-schema-2020-12-as-default-dialect-f)[SEP-2106](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2106-json-schema-2020-12.md):[Tools inputSchema & outputSchema Conform to JSON Schema 2020-12](https://modelcontextprotocol.io/seps/2106-json-schema-2020-12)[Legalize-KR MCP usage](https://legalize.kr/usage.html#mcp)[Official MCP reference servers repository](https://github.com/modelcontextprotocol/servers)", "url": "https://wpnews.pro/news/introducing-mcp-7-28-for-ai-application-developers-what-goes-away-and-what-might", "canonical_source": "https://aaif.io/blog/introducing-mcp-7-28-for-ai-application-developers-what-goes-away-and-what-might-break/", "published_at": "2026-07-16 18:25:09+00:00", "updated_at": "2026-07-16 18:39:00.652854+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "ai-agents", "ai-tools", "developer-tools"], "entities": ["MCP", "PyTorch Korea User Group", "Claude Desktop", "Cursor", "VS Code", "Junghwan Park"], "alternates": {"html": "https://wpnews.pro/news/introducing-mcp-7-28-for-ai-application-developers-what-goes-away-and-what-might", "markdown": "https://wpnews.pro/news/introducing-mcp-7-28-for-ai-application-developers-what-goes-away-and-what-might.md", "text": "https://wpnews.pro/news/introducing-mcp-7-28-for-ai-application-developers-what-goes-away-and-what-might.txt", "jsonld": "https://wpnews.pro/news/introducing-mcp-7-28-for-ai-application-developers-what-goes-away-and-what-might.jsonld"}}