MCP Just Went Stateless: Audit the Integrations Behind Your AI Tools
By Greg Nowak. Last updated 2026-08-03.
The stable MCP specification published on 28 July 2026 changes the working assumptions behind many MCP integrations. Clients and servers now establish compatibility differently. State, notifications, long-running tasks, caching and authorization credentials all follow revised rules.
The awkward part is that an integration may still look healthy. A basic tool call can succeed while retries, subscriptions or OAuth flows continue to rely on behaviour that has been removed or deprecated. For organisations running several MCP servers, multiple SDKs or a mix of internal and customer-facing environments, that is a real operational gap.
Updating a package is only one part of the job. You need to know which protocol version every component speaks, which capabilities it expects and what happens when old and new implementations meet.
Stateless changes the integration contract
The new base protocol uses self-contained requests with capability negotiation on every call. Protocol-level sessions are gone, along with the Mcp-Session-Id header and the initialize handshake. Each request carries the protocol version and client capabilities in _meta. Clients should identify themselves there too, while servers should provide their identity in result metadata.
Servers must implement server/discover, which advertises their identity, supported protocol versions and capabilities. Discovery makes compatibility easier to inspect, but it does not make a mixed-version estate safe by default. Older clients and servers may still expect the previous handshake or response conventions.
Some compatibility behaviour is defined. For example, an earlier response without resultType can be treated as complete. That helps at a specific boundary; it is not proof that every feature in the pairing will behave correctly. Each supported client-server combination still needs testing.
There is another distinction worth making: stateless is not the same as state-free. When a server needs continuity between calls, it can issue an explicit handle that the client sends back as a normal tool argument. State therefore becomes part of the application contract. Its ownership, lifetime, authorization and isolation can all be inspected. Code built around an implicit connection session needs an architectural review, not a simple header replacement.
Notifications, tasks and caching need their own tests
Change notifications now run through subscriptions/listen, using a long-lived POST-response stream. This replaces the previous HTTP GET endpoint and the resource subscribe and unsubscribe methods. Streamable HTTP no longer provides SSE resumability or message redelivery. If the response stream breaks, the in-flight request is lost. The client must send a fresh request with a new request ID.
That matters most when a tool has side effects. A retry must not quietly repeat a payment, record update or other transaction simply because the client could not tell whether the first attempt completed.
Tasks have moved out of the core protocol and into the official io.modelcontextprotocol/tasks extension. The revised lifecycle uses tasks/get for polling and tasks/update when the client needs to supply more information. Multi-round-trip requests have changed as well: the server returns an input_required result, then the client retries the original request with the requested input.
Caching is also explicit now. Relevant list and resource results include ttlMs and a cacheScope value of public or private. Deterministic tool ordering is recommended because it helps client caching and prompt-cache reuse. These details affect freshness, privacy and performance. They should be verified in the compatibility suite instead of being left to an intermediary's default settings.
| Area | Question the audit must answer | Useful evidence |
|---|---|---|
| Inventory | Which hosts, clients, servers, SDKs and environments are actually in use, and who owns them? | A versioned register of dependencies and endpoints |
| Negotiation | Do per-request metadata, discovery and unsupported-version responses work for every supported pairing? | A client-server compatibility matrix |
| State and transport | Does any component still depend on session IDs, the old handshake or SSE replay? | Disconnect, retry and handle-lifecycle tests |
| Tasks and input | Are extension negotiation, polling, updates and input_required retries handled correctly? |
Lifecycle and failure-path test results |
| Subscriptions and cache | Are notifications routed correctly, TTLs enforced and private caches isolated? | Freshness and cross-user isolation tests |
| Authorization | Are issuers validated and credentials kept bound to the correct authorization server? | OAuth flow traces with secrets removed |
| Observability | Can one request be followed across the host, client, server and downstream tools? | Correlated traces and redacted logs |
| Deprecations | Where are Roots, Sampling, Logging, HTTP+SSE or dynamic registration still used? | A replacement plan with a named owner |
Authorization must be checked end to end
The authorization changes look modest in the specification, but they affect how credentials are stored and trusted. If an authorization response contains iss, the client must compare it with the recorded issuer before exchanging the code. Persisted client credentials must be keyed by issuer and cannot be reused with another authorization server. A change of authorization server requires registration again.
Dynamic Client Registration is deprecated in favour of Client ID Metadata Documents, although it remains available for backward compatibility.
A useful audit follows a credential through discovery, registration, authorization, storage, refresh and revocation. A successful OAuth login is not enough. Check whether credentials can cross an issuer boundary, whether redirects match the declared application type and whether tokens appear in logs or traces.
The trust boundary extends beyond the authorization endpoint. NSA guidance identifies serialization risks, context sharing, implicit trust, dynamic tool invocation and agent misuse among the issues facing MCP-based automation. OWASP's secure-server guidance calls for strong authentication and authorization, strict validation, session isolation and hardened deployment.
Protocol sessions may have disappeared, but isolation has not become optional. Application state, explicit handles, private cached data and delegated user permissions still need clear boundaries.
Audit behaviour, not package names
Begin with the estate as it is actually deployed. For each integration, record the host application, MCP client, server, SDK and version. Include the transport, authentication method, authorization server, supported protocol versions, enabled capabilities and extensions, downstream tools, data classification and operational owner.
A dependency scan will help, but it will not find everything. Custom adapters, hosted servers and older production binaries often sit outside the neat package inventory.
Turn that register into a compatibility matrix. Test every supported client-server pairing against the tagged 2026-07-28 schemas and implementation artifacts. Cover the happy path, but spend time on unsupported versions, missing capabilities, malformed metadata and older response formats too. Break streams deliberately. Send duplicate retries. Exercise explicit state handles and confirm their expiry and isolation.
For tools with side effects, make retry safety an acceptance criterion. The client needs a defined response when the connection fails at the worst possible moment.
Then work through the revised lifecycles. Confirm that subscriptions deliver only the requested notification types and that request-scoped progress stays on the correct response stream. Test ordinary results, input_required results, task polling, mid-flight updates, cancellation and expiry. Apply cache TTLs and prove that private results cannot move between users or tenants.
Add traceability before changing production traffic
The specification describes OpenTelemetry propagation through traceparent, tracestate and baggage metadata. Use it to follow a request from the host through the MCP client and server to the downstream service.
Those traces need redaction rules from the outset. The goal is to tell a negotiation failure from an authorization error, a tool failure or a broken response stream without unnecessarily recording credentials, sensitive prompts or returned data.
Adding this visibility before migration makes the rollout easier to diagnose. Adding it after a failure leaves the team comparing partial logs from several systems while production behaviour remains unclear.
Move in controlled slices
Rank integrations by reach, privilege and recoverability. A read-only internal service is a sensible proving ground. An agent that can alter customer or financial records is not.
Give each migration slice a tested rollback route. An old protocol path does not qualify merely because it still exists; its transport and authorization behaviour must be understood and verified as well.
Acceptance criteria should be concrete. Supported versions are discovered correctly. Session assumptions have been removed. Explicit handles are isolated. Task and input flows finish cleanly. Retries do not duplicate side effects. Cache scopes are honoured. Credentials stay bound to their issuer. Deprecated features have named replacements. Traces explain failures without exposing secrets.
This is closer to an API migration programme than a routine library update. Greg at GrN.dk can help map the MCP estate, shape the compatibility and security tests, review OAuth boundaries, introduce useful tracing and organise the rollout around measurable gates. The aim is a migration the team can explain and operate, not simply a version number it can report.
Related on GrN.dk
- Copilot Has Repo-Level Metrics Now. What Should Teams Measure?
- Not Every AI Job Needs an Instant Answer: Batch the Backlog
- One Timeout, Two Orders: Make AI Actions Safe to Retry
Need help with this kind of work?
Plan your MCP integration audit Get in touch with Greg.