MCP Went Stateless. Your AI App Still Needs a State Ownership Contract
A founder launch gate for MCP 2026-07-28: decide where tasks, approvals, identity, business records, caches, and recovery state must live.
The Model Context Protocol (MCP) released its largest revision so far on July 28, 2026. The new protocol is stateless by default: the required initialization handshake and protocol session disappear, each request carries the information needed to interpret it, clients can discover server capabilities explicitly, and long-running or multi-step work moves to explicit mechanisms such as Tasks and Multi Round-Trip Requests.
That sounds like infrastructure news. For an AI app builder, it is really a product-state decision. “Stateless MCP” does not mean your research agent forgets its job, your onboarding assistant can lose an approval, or a support workflow may recreate a refund after a retry. It means the protocol will no longer hide those responsibilities inside a connection. Your team must decide which durable facts belong to the product, who may read or change them, how an interrupted job resumes, and what evidence proves that the same business action was not executed twice.
This guide is for nontechnical founders and small product teams using connectors, no-code builders, hosted agents, or custom MCP integrations. It provides a plain-language state map, a reusable state ownership contract, a customer-support scenario, a dual-protocol migration matrix, six launch tests, failure modes, and a 48-hour checklist.
The central judgment is simple: do not approve an MCP 2026 migration because a connector reconnects successfully. Approve it when every important state has an owner, lifetime, authority rule, recovery path, and verification receipt.
What changed in MCP 2026-07-28—and what did not
The official MCP release overview describes a stateless core, explicit discovery, Tasks as an extension, Multi Round-Trip Requests (MRTR), MCP Apps, authorization hardening, cache semantics, and a formal deprecation policy. The final revision is now available in the official 2026-07-28 specification and the signed repository releases.
The most consequential lifecycle change is the removal of the mandatory initialize / initialized handshake. Under the accepted SEP-2575 stateless design, protocol version, client identity information, and client capabilities travel with each request. A client may call server/discover to learn what a server supports. A normal request should be understandable without the server remembering an invisible conversation with that client.
Several old behaviors also change. Resuming a dropped SSE stream is removed; durable work should use a task primitive. Free-floating server-to-client calls are replaced by MRTR within the scope of a client request. Some previously core features move to extensions or are deprecated. Cacheable results carry explicit time-to-live and scope hints. Authentication and authorization must be evaluated independently for requests rather than assumed from a protocol session.
What did not change is equally important:
- Your customer, order, ticket, project, and entitlement records still need durable storage.
- A long-running job may still need to wait, resume, expire, or be cancelled.
- An approval must still be bound to a specific action and parameters.
- A retry can still duplicate a side effect unless the product prevents it.
- A user can still lose trust if the interface shows stale or contradictory state.
- Different SDKs and vendors may adopt the revision at different speeds.
Translate the new terms into product decisions
You do not need to read JSON-RPC schemas to make the right launch decision, but the vocabulary matters.
Protocol state is information the connector previously inferred from an established MCP session, such as negotiated version and capabilities. The new revision puts that information into each request or explicit discovery. Business state is the truth your product is responsible for: a ticket is open, a refund is proposed, a campaign is approved, or an invoice was paid. It belongs in a system of record, not in an MCP connection. Task state describes a unit of work over time: queued, working, waiting for input, completed, failed, cancelled, or expired. A task handle is a reference to that state; it is not the state itself. Interaction state is the short-lived context needed to ask a question or obtain an approval during a request. The accepted MRTR proposal lets a server request input from the client within the scope of the original call without depending on sticky routing. Cache state is a reusable copy of discovered capabilities, tools, resources, or other results. It needs an explicit lifetime and audience. A cache that outlives a permission change can turn yesterday’s valid answer into today’s access-control error. Idempotency means retrying the same intended business action does not create a second charge, message, record, or deployment. It is a product guarantee, not a networking detail.These categories must not collapse into one generic “agent memory.” Each has a different authority, lifetime, storage location, and failure consequence.
The founder’s core rule: state references are not state ownership
The stateless design follows a useful principle: prefer a self-contained request; when that is impractical, pass a reference to state. For a founder, the dangerous shortcut is to see a task ID, conversation ID, or approval ID and assume the underlying responsibility is solved.
A reference answers “where can this be found?” It does not answer:
- Who created the record?
- Which user and tenant own it?
- What exact action and parameters does it authorize?
- Who may read, update, cancel, or delete it?
- How long does it remain valid?
- What happens after a permission change?
- Can a retry create another effect?
- What evidence proves completion?
task_84F2. If the product cannot show which customer request created it, which account it may modify, when it expires, whether approval is still valid, and whether the downstream effect occurred, the handle is merely an opaque string.
This is why “we store the task ID” is not an acceptance criterion. The acceptance criterion is that the product can reconstruct the authorized job and its result after the original process, connection, browser tab, or server instance no longer exists.
Inventory six classes of state before changing any connector
Start with an inventory of one real workflow, not every integration in the company. Use the smallest workflow that crosses a meaningful boundary such as sending a message, creating a record, updating a customer account, or charging money.
| State class | Example | Correct owner | Typical lifetime | Never rely on |
|---|---|---|---|---|
| Business truth | Refund status, CRM stage, subscription plan | Product system of record | Business retention period | Connector session |
| Job progress | Research job at step 3 of 6 | Durable task store or provider with an exportable contract | Until terminal state plus audit period | Browser tab or worker memory |
| Authorization | User approved a $45 refund to order 918 | Product approval record bound to actor, action, target, amount, and expiry | Minutes or hours | A generic “approved” chat message |
| Interaction | Agent needs the missing order number | Scoped request or task input request | Until answered, cancelled, or expired | A free-floating follow-up with no parent |
| Capability cache | Server supports tool X with schema version Y | Client or gateway cache with explicit scope and TTL | Seconds to hours | An indefinite global cache |
| Execution receipt | Payment provider accepted idempotency key K | Product audit/evidence store | Support and compliance period | A model-written success sentence |
For each row, identify the current source. Many teams discover that job progress lives in a queue, approval lives in chat history, identity lives in an access token, and completion exists only in a generated response. That fragmentation is the migration risk.
Do not begin by asking whether your builder “supports MCP 2026.” Ask whether it exposes enough product controls to assign these owners. If a hosted platform abstracts the protocol, request its behavior for task durability, approval binding, retries, cache invalidation, identity, audit export, and legacy fallback.
Complete a state ownership contract
The reusable artifact for this release is a state ownership contract. Complete one contract for each consequential workflow, not one vague contract for the whole product.
| Field | Founder decision | Required evidence |
|---|---|---|
| Outcome | The business result the user requested | Plain-language job statement |
| System of record | Where the authoritative result lives | Record type and owner |
| State reference | Task, job, order, or approval identifier | Stable ID linked to user and tenant |
| Allowed transitions | Valid movement between queued, working, waiting, approved, completed, failed, cancelled, expired | State diagram or transition table |
| Authority | Who may create, view, approve, retry, cancel, or resume | Role and permission matrix |
| Parameter binding | Exact target, amount, destination, scope, and version approved | Immutable approval snapshot or hash |
| Lifetime | Expiry, retention, and deletion rules | Timestamps and cleanup behavior |
| Retry rule | Whether and how the action may be attempted again | Idempotency key and retry count |
| Recovery | What happens after disconnect, restart, provider failure, or lost client | Resume, reconcile, or safe restart path |
| Completion proof | Independent evidence that the business effect occurred | Provider ID, read-after-write check, or signed event |
| User visibility | What the user sees while waiting and after recovery | UI states and plain-language messages |
| Compatibility | Supported MCP eras and fallback behavior | Tested client-server matrix |
A completed contract might say:
The product may propose one refund for one order. The commerce platform owns refund truth. Our product stores a job linked to user, tenant, order, amount, reason, approval snapshot, and idempotency key. Approval expires after 30 minutes and cannot be reused if the amount or destination changes. After a disconnect, the worker reads the commerce platform before retrying. Completion requires a provider refund ID plus a read-back showing the order’s refunded amount.
That paragraph is more valuable than “MCP is stateless compatible” because it defines the product promise.
Walk through a support-agent scenario
Imagine a small SaaS team has built a support assistant. It reads a ticket, checks the billing system, proposes a refund, asks an operator to approve it, executes the refund, and replies to the customer.
At 10:04, the agent receives ticket 681: “I was charged twice.” It finds two charges but cannot determine which order the customer intended. It asks the operator for the order number. The operator replies, reviews a proposal for $45, and approves. The connector sends the refund request. Immediately after the provider accepts it, the response stream drops.
A session-dependent design may fail in three ways:
- The replacement worker cannot recover the earlier question and answer.
- The UI presents the approval again because it cannot connect the approval to the original parameters.
- The agent retries the refund because it never received the success response.
- Ticket 681 and the billing records remain in their systems of record.
- The support job stores its current step and the parent request for the missing order number.
- The operator’s approval is bound to order 918, amount $45, refund destination, policy version, and expiry.
- The commerce call uses an idempotency key derived from the approved job.
- Recovery first queries the commerce provider for that key or reads the order state.
- The customer reply is sent only after independent confirmation, and its own send action uses a separate idempotency key.
- The UI shows “verifying provider result,” not “failed” or “refunding again.”
Choose MRTR, Tasks, or a normal request deliberately
The new revision separates interaction patterns that older implementations often blurred together.
Use a normal request when the result should be fast, no human input is expected, and interruption can safely produce a fresh attempt. A read-only lookup with a short deadline is a good candidate.
Use MRTR when a server needs input from the client while handling the original request—for example, asking the user to choose an account, confirming a missing field, requesting roots, or obtaining a bounded approval. MRTR keeps the follow-up associated with its parent request. That association prevents a response intended for one job from drifting into another.
Use a Task when the work must continue or remain queryable beyond a single live response. The official Tasks extension documentation describes asynchronous work that returns a task handle and can be polled, updated, cancelled, or supplied with more input. The release notes also warn that the new Tasks lifecycle is not wire-compatible with the earlier experimental task design.
Do not choose Tasks merely because a job is “agentic.” A two-second tool call does not need a durable lifecycle. Do not use MRTR as a hidden approval database. Do not force a long-running import into an open connection and call reconnection “recovery.”
The product question is: what must survive the loss of the current request? If the answer includes progress, approval, evidence, or user expectations, make that state durable and addressable.
Treat discovery and caching as permission-sensitive product behavior
server/discover separates capability discovery from a mandatory initialization handshake. That improves flexibility, but it creates a product question: when may your app reuse discovered information?
The TypeScript SDK’s 2026-07-28 migration guide documents explicit ttlMs and cacheScope fields for cacheable results, with conservative defaults when no real policy is advertised. The terms are technical, but the founder decision is familiar:
- TTL: How long may this answer be reused before checking again?
- Scope: Is the answer public, tenant-specific, user-specific, or request-specific?
- Invalidation: What event makes it wrong immediately?
- Failure behavior: If refresh fails, may the app use stale data, hide the function, or stop?
Require cache keys to include every dimension that changes the answer, such as server, protocol version, tenant, user or role, authorization scope, extension set, and schema version. Set a short default until you have evidence for a longer TTL. Never let cached capability data substitute for authorization at execution time.
Recheck identity and authorization on every consequential request
Removing a protocol session does not remove identity. It removes one place where implementations may have assumed identity was already settled.
SEP-2575 states that every request must be independently authenticated and authorized. The broader release also hardens OAuth behavior, including issuer validation and credential binding. The product interpretation is: a valid connector credential is not enough. The request must still be allowed for this user, tenant, resource, action, and moment.
For each consequential call, verify:
- Actor: Which user, service, or delegated agent initiated it?
- Tenant: Which workspace owns the target and the job?
- Resource: Which record, account, project, or tool is affected?
- Action: Is this actor allowed to read, propose, approve, execute, cancel, or retry?
- Parameters: Does the authorization cover this exact amount, destination, scope, and version?
- Freshness: Has the role, consent, token, policy, or resource state changed since the job began?
A useful rule is that discovery may reveal that a capability exists; authorization decides whether it may be used now.
Plan for a dual-protocol period
The final specification date does not make every client, SDK, hosted builder, and connector ready at once. The official Go SDK v1.7.0 release supports the 2026-07-28 protocol and describes legacy negotiation. The TypeScript v2 migration material describes explicit modern, legacy, and automatic modes. Other SDK and vendor timelines differ.
Use a migration matrix instead of a single “MCP supported” badge:
| Client | Server | Expected path | Product decision |
|---|---|---|---|
| Modern | Modern | server/discover, per-request metadata, new lifecycle | Canary after full state tests |
| Modern | Legacy | Explicit fallback to legacy initialization, if supported | Allow only when fallback is visible and tested |
| Legacy | Modern with compatibility | Legacy path on a compatible endpoint | Keep temporarily with retirement date |
| Legacy | Modern-only | Predictable unsupported-version error | Block rollout; do not silently drop capabilities |
| Unknown hosted builder | Third-party server | Vendor-defined | Hold consequential actions until behavior is documented |
Pin exact SDK versions in your launch receipt. “Latest” is not reproducible. Record whether fallback happened, which protocol revision was actually used, and whether the effective capability set changed.
Do not test only the happy pair. A migration commonly fails at the seam: a modern client talks to a legacy server, an older desktop app reaches a modern-only endpoint, or an automatic fallback silently removes Tasks or a required extension while the UI still offers the feature.
Run six launch tests with visible evidence
Use synthetic accounts and reversible actions. A reconnect screenshot is not enough.
Test 1: kill the connection after the effect
Perform a reversible write, then interrupt the response after the downstream system accepts it. Resume the job. Pass only if the product reconciles the existing result and does not repeat the action.
Test 2: change approval parameters
Approve a $10 action, then change the target or amount before execution. Pass only if the old approval becomes invalid and the user sees the changed parameters before approving again.
Test 3: change permissions mid-task
Start a job, revoke the user’s role or connector scope, then resume. Pass only if execution rechecks authority and stops safely. A cached capability list must not override the new permission.
Test 4: cross tenant and user boundaries
Run the same connector for two workspaces with different tools and policies. Pass only if task handles, discovery results, caches, logs, and approval records never cross boundaries.
Test 5: exercise every compatibility pair
Test the modern-modern path, every supported fallback, and an unsupported pair. Pass only if the UI and logs identify the effective protocol and capability set, and unsupported features fail closed.
Test 6: expire and cancel waiting work
Leave a task waiting for input beyond its approved lifetime, then answer or resume it. Pass only if expired authority cannot be revived. Cancel another task and verify no delayed worker later completes the action.
For every test, retain the input, effective identity, protocol version, state transitions, approval snapshot, idempotency key, external result, reconciliation read, UI result, and final disposition. That bundle is the launch receipt.
Avoid the most common misreadings
“Stateless means no database.” It means the protocol request should not depend on hidden connection state. Business truth and durable work still need an owner. “A task handle makes the job durable.” Only if the referenced state survives failure, has a defined lifetime, remains bound to identity and authority, and can be reconciled. “The user approved the agent.” Approval must cover one understandable action with visible parameters. General trust in an assistant is not authorization for every future tool call. “Automatic fallback preserves the product.” It may preserve a connection while removing Tasks, extensions, or other expected behavior. Test the effective capability set. “A fresh discovery result authorizes execution.” Discovery describes capabilities. Authorization must still evaluate the current actor, tenant, resource, action, and parameters. “The provider said success, so the job is complete.” A generated message is not a business receipt. Confirm the downstream effect through a provider identifier, read-after-write check, or authoritative event.Know where this launch gate applies
Use the full contract for workflows that write data, contact people, spend money, publish content, change access, move files, alter production systems, or wait for human input. It is also useful when a job can outlive a browser session or when more than one tenant uses the same connector.
Use a smaller contract for short, read-only, low-risk calls. You still need identity, scope, timeout, and failure behavior, but you may not need a durable task lifecycle.
This guide is not an SDK implementation tutorial, a conformance test suite, or proof that every MCP 2026 implementation is production-ready. It does not tell you which database or queue to buy. It cannot replace legal review for regulated records, a security review for credential handling, or provider-specific documentation.
If your platform does not expose protocol version, task state, authorization boundaries, retry behavior, or logs, do not invent certainty. Mark those fields unknown and limit the connector to read-only or reversible work until the vendor supplies evidence.
Use the next 48 hours to make one workflow safe
- Choose one consequential MCP workflow that is already live or planned.
- Write its requested business outcome in one sentence.
- Inventory the six state classes and identify the current owner of each.
- Complete the state ownership contract, especially authority, parameter binding, retry, recovery, and completion proof.
- Ask the builder or integration vendor which protocol revisions and fallback modes are actually used.
- Pin versions and document the modern, legacy, and unsupported combinations.
- Add an idempotency key to every repeatable side effect.
- Separate capability discovery from execution-time authorization.
- Run the six launch tests with synthetic data and retain the evidence bundle.
- Ship a small canary only if every important state survives process and connection loss without crossing identity, tenant, or approval boundaries.
References
- Model Context Protocol, The 2026-07-28 MCP Specification Release Candidate
- Model Context Protocol, 2026-07-28 specification
- Model Context Protocol, Specification releases
- Model Context Protocol, SEP-2575: Make MCP Stateless
- Model Context Protocol, SEP-2322: Multi Round-Trip Requests
- MCP TypeScript SDK, Supporting protocol revision 2026-07-28
- MCP Go SDK, Releases
- MCP C# SDK, Tasks
- MCP C# SDK, Stateless and stateful mode
- MCP C# SDK, Multi Round-Trip Requests
- OWASP, AI Agent Security Cheat Sheet