Summary
The MCP server for a service I develop at my own company rejected requests whose version header held an unsupported version, and it did so with HTTP 400 before authentication. MCP is an open standard for connecting AI applications to external tools and data sources, and the name is short for Model Context Protocol. The version header is a header defined by the specification that HTTP clients attach to MCP requests, and it indicates the MCP version with a date string such as 2025-11-25. The server decided whether it supported a version by checking the list of supported versions. The list of supported versions enumerates the versions that the MCP server declares it supports, and it is written in the server’s code. Because of this rejection, the major AI client could not connect to this MCP server on 2026-09-24. The major AI client is one of the AI chat products in which users can add an MCP server as a connector.
In its first fix, the AI agent only added the observed 2025-11-25 to the list of supported versions. The major AI client is updated frequently, so in response to this fix I pointed out that rejecting a connection over a small difference in version was too strict. In its second fix, the AI agent changed the list of supported versions to two entries, 2025-11-25 and 2025-06-18. In the same fix, it made the server accept values in date form that are smaller than 2026-07-28, even when they are not in the list. With the 2026-07-28 version, the MCP specification changed to an approach that does not use the initialize request, the request a client sends first to decide the version. The AI agent left in place the handling that returns 400 for values dated 2026-07-28 or later and for values not in date form. The MCP specification has a MUST requirement, that is, an obligation that must always be met: a server that receives a version header with an unsupported version responds with 400. Based on my decision, the AI agent intentionally did not implement this requirement for versions earlier than 2026-07-28 that are not in the list. On the next day, 2026-09-25, the AI agent changed the MCP server so that it could also respond to requests that use the 2026-07-28 version.
In the first section, I explain the version header check that stopped the major AI client from connecting, and I show in a table the results of the check before the fix and after the second fix on 2026-09-24. In the next section, I explain how the server identifies legacy versions and how it handles modern versions. Legacy versions are the versions up to and including 2025-11-25, which establish a connection with the initialize request, and modern versions are the versions from 2026-07-28 onward. That section also gives the reason the MCP server was made to support both kinds of versions the next day. The section that follows compares, in a table, the two MUST requirements of the specification with how the MCP server handles them after the second fix. The section after that explains the first fix, which added one observed version, and the point I raised about it. The last section explains the robustness principle of being liberal in what you accept, and the limits that RFC 9413 placed on this principle. Building on that, Building on that, I classify the MCP server with the second fix as follows. It is neither an application of this principle’s aspect of tolerating unexpected inputs nor an extension under clear rules as described in Section 2.2 of RFC 9413, and it is an implementation that intentionally chose handling different from the handling the specification defines.
What you can take away
For those who develop MCP servers, I explain the following three things.
- When an MCP server checks the version header against a list of supported versions, a fix that only adds the one observed version to the list leads to the same 400 the next time a client raises its version. In the body, I explain why from the rules of the check before the fix.
- The MCP server with the second fix treats a header value as a legacy version if the value is in date form and smaller than 2026-07-28. In the body, I use tables to show this rule and, of the two MUST requirements of the specification, the one this MCP server meets and the one it intentionally does not meet because of my decision.
- The second fix, which accepts legacy versions not in the list, is neither an application of the aspect of tolerating unexpected inputs within the robustness principle of being liberal in what you accept, nor an extension under clear rules as described in Section 2.2 of RFC 9413. In the body, I classify the MCP server with this fix as an implementation that intentionally chose, for inputs whose handling the specification defines, handling different from the specification’s.
The body is based on the records of fixing the MCP server of my own company’s service from 2026-09-24 to 2026-09-25, and on the original texts of the MCP specification and the RFCs, which I checked on 2026-10-04.
The version header check that stopped the major AI client from connecting
I develop a service at my own company. The MCP server of that service rejected, with HTTP 400 and before authentication, any version header whose version was not in the list of supported versions. As a result, the major AI client could not connect on 2026-09-24.
MCP is an open standard for connecting AI applications to external tools and data sources, and the name is short for Model Context Protocol. The major AI client is one of the AI chat products in which users can add an MCP server as a connector. The version header is a header defined by the specification that HTTP clients attach to MCP requests. Its value is a date string such as 2025-11-25, and it indicates the MCP version. The list of supported versions enumerates the versions that the MCP server declares it supports, and it is written in the server’s code.
In versions up to and including 2025-11-25, the client first sends an initialize request and decides with the server which version they will use. Versions that establish a connection in this way are called legacy versions. This name is a term from the 2026-07-28 version of the specification.
Before 2026-09-24, the MCP server’s list of supported versions had only one entry, 2025-06-18. A note in the server’s code gave the reason for not declaring the 2025-03-26 version. That version has a requirement that implementations accept JSON-RPC batches, and the MCP server does not support batches. The MCP server accepted requests that had no version header.
On 2026-09-24, I added the MCP server in the test environment to the major AI client as a connector. The major AI client’s screen stopped while still showing that it was connecting. The screen showed an error saying, in effect, that something was not found, along with HTTP 400. In the observation that day, the major AI client put 2025-11-25 in the version header starting from the first initialize request.
On the same day, the AI agent fixed the MCP server twice. In the second fix, it changed the list of supported versions to two entries, 2025-11-25 and 2025-06-18. If a client asks for a version in the list in the initialize request, the MCP server responds with that version. If the version is not in the list, the server responds with 2025-11-25. When the MCP server rejects a request with 400, it logs the rejected version value and the User-Agent of the connecting client as a warning.
Versions from 2026-07-28 onward have no initialize request, and the client declares the version in _meta in the request body of every request. These versions are called modern versions. The following table lists the results of the check for each header value.
| Value of the version header | Before the fix | After the second fix on 2026-09-24 |
|---|---|---|
| 2025-06-18 | Accepted | Accepted |
| 2025-11-25 | Rejected with 400 | Accepted |
| Other date values smaller than 2026-07-28. An example is 2025-03-26 | Rejected with 400 | Accepted |
| Values of modern versions. Date values of 2026-07-28 or later | Rejected with 400 | Rejected with 400 |
| Values not in date form | Rejected with 400 | Rejected with 400 |
Identifying legacy versions and handling modern versions
The MCP server with the second fix treats a header value as a legacy version if the value is in YYYY-MM-DD form and smaller than 2026-07-28. Because which value is smaller is decided by string comparison, this check depends on the value being in YYYY-MM-DD form. Dates between 2025-11-25 and 2026-07-28 do not correspond to any version of the specification, but this check treats them as legacy versions.
The AI agent left in place the handling that returns 400 when the value of the version header is a modern version. An implementation that supports both legacy and modern versions is called dual-era. This name is also in the 2026-07-28 version of the specification. The reason the AI agent wrote in its description of the fix is that a dual-era client looks at the body of the 400 response and switches to a legacy version.
On 2026-09-25, I approved the work to make the MCP server dual-era. The AI agent wrote the reason for this work as follows. As of 2026-09-24, the major AI client was communicating with a legacy version. However, client updates come faster than server fixes, so it would make the MCP server dual-era before the major AI client moved to a modern version. The AI agent merged the fix for this work on 2026-09-25. The MCP server then became able to respond to requests with modern versions as well.
The specification’s obligations and the MCP server after the second fix
The MCP server with the second fix meets the obligation to respond with a different version when a client, in the initialize request, asks for a version not in the list. On the other hand, for legacy versions, it intentionally does not meet the obligation to return 400 for a version header with an unsupported version.
The Lifecycle documents of the 2025-06-18 and 2025-11-25 versions contain a MUST requirement on the version the server responds with. A server that supports the requested version responds with the same version, and a server that does not support it responds with a different version. The specification defines, as a SHOULD requirement, that is, a recommendation, that this different version be the server’s latest version.
The Transports documents of the 2025-06-18 and 2025-11-25 versions contain a MUST requirement on the header. A server that receives a version header with an invalid or unsupported version responds with 400 Bad Request. The AI agent wrote this obligation in the server’s documentation as an obligation that the MCP server does not meet.
| MUST requirement in the specification | Versions that have the requirement | MCP server with the second fix |
|---|---|---|
| A server asked in the initialize request for a version it does not support responds with a different version that it supports | 2025-06-18, 2025-11-25 | Responds with 2025-11-25 |
| A server that receives a version header with an unsupported version responds with 400 | 2025-06-18, 2025-11-25 | Intentionally does not return 400 for legacy versions not in the list |
Intentionally not implementing the obligation to return 400 is based on my decision not to reject connections over a difference in version alone. The values that the second fix newly accepts are 2025-03-26 and 2024-11-05, which are versions of the specification, and date values that do not correspond to any version of the specification. The AI agent explained the reasons for this decision as follows.
- Rejecting connections over a difference between legacy versions brings no benefit.
- If updates to the list of supported versions fall behind, the MCP server ends up rejecting clients’ connections. This harm is greater than the benefit of rejecting connections over a difference between legacy versions.
- Even if a client uses a feature that the server does not implement, the connection is kept. For example, for JSON-RPC batches, which are in the 2025-03-26 version, the MCP server only returns a standard error.
The first fix, which added one observed version
In its first fix, the AI agent only added the observed 2025-11-25 to the list of supported versions. Before the fix, the MCP server had been rejecting with 400 the value 2025-11-25 that the major AI client sent.
In response to the first fix, I pointed out that rejecting a connection over a small difference in version was too strict. This is because the major AI client is updated frequently.
The check before the fix rejected every value not in the list with 400. These facts show that with a fix that adds one observed version to the list, the same 400 occurs the next time a client raises its version.
The robustness principle and the limits set by RFC 9413
The robustness principle is the implementation principle of being liberal in what you accept and conservative in what you send. RFC 1122 lists this principle and says that it is especially important at the Internet layer.
RFC 9413 says that the robustness principle has three aspects. The three aspects are robustness to software defects, robustness to attacks, and robustness to unexpected inputs. Section 1 of RFC 9413 says that cases where the specification explicitly defines how a faulty message is handled are excluded from the aspect of robustness to unexpected inputs. RFC 9413 also says that the first two aspects are necessary guiding principles. On the other hand, it says that the interpretation of tolerantly accepting unexpected inputs can no longer be called the best approach in every situation.
Section 2.2 of RFC 9413 says that extensibility is sometimes mistaken for an application of the robustness principle. It also says that in a well-designed extensibility mechanism, the handling of new messages and parameters is decided by clear rules, so they become expected inputs.
The MCP specification has a requirement to respond with 400 to a version header with an unsupported version. Therefore, the MCP server with the second fix is an implementation that, for inputs whose handling the specification defines, handles them differently from the specification. The aspect of robustness to unexpected inputs does not include inputs whose handling the specification makes explicit. The extension under clear rules in Section 2.2 is a mechanism in which the protocol defines the rules and every implementation behaves according to those rules. These facts show that the MCP server with the second fix is neither an application of the robustness principle’s aspect of tolerating unexpected inputs nor an extension as described in Section 2.2. They also show that it is an implementation that intentionally chose handling different from the handling the specification defines.
Materials I referred to
The public materials I referred to in the body are the following six items, which cover eight documents. I checked the original text of each of them on 2026-10-04.
- Lifecycle (the 2025-06-18 version of the MCP specification) https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle
- Lifecycle (the 2025-11-25 version of the MCP specification) https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle
- Transports (the 2025-06-18 version of the MCP specification) https://modelcontextprotocol.io/specification/2025-06-18/basic/transports
- Transports (the 2025-11-25 version of the MCP specification) https://modelcontextprotocol.io/specification/2025-11-25/basic/transports
- Versioning and Compatibility (the 2026-07-28 version of the MCP specification) https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning
- Base Protocol (the 2025-03-26 version of the MCP specification) https://modelcontextprotocol.io/specification/2025-03-26/basic
- RFC 1122 Requirements for Internet Hosts -- Communication Layers https://www.rfc-editor.org/rfc/rfc1122.txt
- RFC 9413 Maintaining Robust Protocols https://www.rfc-editor.org/rfc/rfc9413.txt