skip to content

What do modern, legacy and dual-era mean in MCP, and which combinations interoperate?

level: middleimportance: must knowfreq 58%

answer

  1. two lifecycle models, one deployed fleet
  2. modern is per-request, legacy is handshake
  3. the server owns the era
  4. old peers cannot be upgraded in flight
  5. only one configuration bridges both

basics

~20 s

Modern means the per-request metadata model of MCP 2026-07-28 and later; legacy means the initialize handshake of 2025-11-25 and earlier; dual-era supports both. Era is a property of the server, and only a dual-era server serves clients of both eras.

solid answer

~50 s

The terminology describes which lifecycle model an implementation speaks. **Modern** is revision 2026-07-28 and later, where every request carries its own protocol version and capabilities and there is no handshake. **Legacy** is 2025-11-25 and earlier, where a connection began with an `initialize` request and `notifications/initialized` and then ran under the negotiated result. **Dual-era** means supporting both. Crucially, era is a property of the **server**, not of an individual request — a server either accepts handshake-era traffic or it does not. The matrix is unforgiving: a modern client against a legacy-only server fails, and a legacy client against a modern-only server also fails, because there is no fall-forward — an old client cannot be talked into the new model. Only a dual-era server interoperates with both. That is why a client that must work across today's mixed fleet has to determine the server's era before it can rely on anything.

go deeper

for a junior

Learn the three words and their boundaries: modern is 2026-07-28 and later with per-request metadata, legacy is 2025-11-25 and earlier with the initialize handshake, dual-era is both. Say that only dual-era serves everyone.

for a middle

Draw the matrix and justify both failing cells, especially that there is no fall-forward from a modern server to a legacy client. Be explicit that era belongs to the server, not to a request.

for a senior

Bring the deployment angle: a partly upgraded fleet fails intermittently per node, dual-era servers must keep the stateless path strictly stateless, and era detection results should be cached per server rather than re-derived per call.

for a principal

Own the decision of whether to carry dual-era support at all, what it costs in duplicated lifecycle code and test matrix, and how you sequence a fleet-wide rollout so clients never see node-dependent behaviour.

## Where the vocabulary comes from Revision 2026-07-28 made a change that cannot be papered over: it removed the `initialize` request and the `notifications/initialized` notification, removed protocol-level sessions, and declared MCP a stateless protocol in which "every request is self-contained and carries its own protocol version and capabilities". Everything before that revision worked the opposite way — you opened a connection, exchanged a handshake, and the negotiated result governed the traffic that followed. Because both designs are deployed at the same time, the ecosystem needs words for them: - **Modern** — implements the per-request metadata model. Revision 2026-07-28 and later. - **Legacy** — implements the `initialize` handshake model. Revision 2025-11-25 and earlier. - **Dual-era** — implements both, and can serve either kind of peer. ## Era belongs to the server The single most important framing point is that era is a property of the **server**, not of a request and not of a connection. A request declares a protocol version, but that declaration does not change what the server is: a legacy-only server does not become modern because a modern request arrived. It has one lifecycle model implemented in its code — or, if it is dual-era, two — and the client's job is to find out which before it builds any expectations. This matters for how you reason about a fleet. "Half our requests are modern" is a statement about traffic; "half our servers are legacy" is a statement about capability, and only the second one predicts what will fail. ## The compatibility matrix | Client | Legacy server | Modern server | Dual-era server | |---|---|---|---| | **Legacy** | works | fails | works | | **Modern** | fails | works | works | | **Dual-era** | works | works | works | Two cells deserve explanation. **Modern client, legacy server: fails.** The client sends a self-contained request with per-request metadata. The legacy server expects a handshake first and does not implement the modern discovery entry point at all, so the call does not land. The client can recover only by itself speaking the old model — that is, by being dual-era. **Legacy client, modern server: fails, and there is no fall-forward.** This is the asymmetry candidates miss. A modern server cannot rescue an old client, because the old client will open with `initialize`, a method the modern server no longer implements, and it has no code path for declaring version and capabilities per request. Compatibility cannot be pushed onto a peer that was compiled before the mechanism existed. The only fix is on the server side — be dual-era — or upgrade the client. So dual-era support is the only thing that actually bridges the gap, and in practice it is the servers that carry it, because servers are the side you can redeploy and clients are the side that lives in someone else's installed application. ## What dual-era costs A dual-era server is not a flag; it is two lifecycle implementations behind one surface. It must accept a handshake and hold the negotiated result for that connection *and* accept self-contained requests where nothing may be inferred from prior traffic. The stateless rule — servers must not rely on prior requests over the same connection to establish context — has to hold strictly on the modern path even while the legacy path does exactly the opposite. Test matrices double, and the temptation to let modern requests quietly reuse handshake state is a real correctness bug, because a load balancer may route the next request elsewhere. ## Practical guidance - Determine the server's era once, cache it per server, and drive everything from that decision. - Never infer a peer's era from a single successful call. One call succeeding tells you that call was acceptable; only a rejection with a supported-version list, or a discovery response, tells you the set. - When you write a new server today, write it modern-first and treat any legacy support as an adapter in front of it, so the stateless core is the thing that stays. - Deployment reality check: because a request declares its version but a server owns its era, a partially upgraded fleet produces intermittent, node-dependent failures for identical requests. Roll era support fleet-wide before you advertise it. ## Interview framing Give the three definitions with their revision boundaries, state that era is a server property, then draw the matrix and call out that there is no fall-forward. The candidates who have actually shipped against MCP in 2026 volunteer the last point without prompting, because it is the one that dictates who has to do the work: the server operator, not the client author.

  • Why can a modern server not simply fall forward and serve a legacy client?
    Because the legacy client only knows how to open with `initialize`, a method removed in revision 2026-07-28, and it has no code path for declaring version and capabilities on each request. Compatibility can only be added by the side that has code to change, so the server must implement the old handshake as well — dual-era — or the client must be upgraded.
  • Is era a property of a request, a connection, or the server?
    The server. A request declares a protocol version, but that declaration does not alter what the server implements. A legacy-only server stays legacy no matter what arrives, and since 2026-07-28 an open connection is explicitly not a session, so there is nothing connection-scoped for an era to attach to either.
  • What is the main correctness hazard inside a dual-era server?
    Letting the modern path lean on state established by the legacy path. Since 2026-07-28 servers must not rely on prior requests over the same connection to establish context, and any node may serve any request, so a modern request that quietly reuses handshake-negotiated capabilities works in test on one process and fails behind a load balancer.
  • Which side usually carries dual-era support in practice, and why?
    Servers. A server is the component its operator can redeploy on demand, while clients are embedded in host applications that users upgrade on their own schedule. Putting the bridge in the server lets the fleet move without waiting for every installed client, which is exactly the constraint the mixed 2026 fleet imposes.

saying these in an interview costs you the question

  • Says a modern server can automatically fall forward and serve legacy clients
  • Treats era as a property of an individual request rather than of the server
  • Thinks declaring an older protocol version turns a modern server into a legacy one
  • Assumes one successful call proves the peer supports the whole revision
  • Believes clients can bridge the gap without implementing the handshake model themselves

context