[KongchangAI]
· 2 min read· 1,296 words

MCP Official Servers v2.0.0 Released: Full Compatibility with the New Protocol

MCP Official Servers v2.0.0 Released: Full Compatibility with the New Protocol

MCP official servers v2.0.0 released with dual-protocol compatibility and a full refactor of both the TS and Python stacks.

The official MCP servers repository released v2.0.0, a sweeping refactor across TypeScript and Python that makes all official servers support both the 2026-07-28 modern protocol and the 2025-11-25 legacy protocol while keeping old clients working. On the TS side, four npm packages reach 2.0.0, migrate to TS SDK v2, raise the Node minimum to 24, and add a concurrency state machine for roots refresh races in server-filesystem. On the Python side, three servers move to the high-level MCPServer wrapper, tighten dependencies to mcp>=2.3,<3, return JSON-RPC -32602 for unknown tools, unify tool error text, and expand prompts/resources capability declarations. The release also documents a known issue where the git server treats the string "null" as no value, with a workaround, and hardens CI and release processes.

MCP Official Servers v2.0.0 Released

The official Model Context Protocol (MCP) servers repository has released v2.0.0, a sweeping refactor spanning both the TypeScript and Python stacks. The core goal is to make all official servers simultaneously support the "modern era spec" while remaining compatible with legacy clients. For developers building agent toolchains on the MCP ecosystem, this upgrade deserves a careful read of the changelog.

Two Protocols in Parallel: Compatibility Strategy for Modern and Legacy Eras

The most critical architectural change in this release is that all servers now serve two protocol eras at once: the 2026-07-28 era and the 2025-11-25 era. According to the repository release notes, the servers follow the modern spec while still "responding as expected to legacy-era clients." This dual-track design means there's no need to worry about downstream client incompatibility in the short term, but it also requires the server side to handle capability declarations, error codes, structured returns, and other details with more granular branching.

On the TypeScript side, all four npm packages are bumped to 2.0.0: server-everything, server-filesystem, server-memory, and server-sequential-thinking. On the Python side, mcp-server-fetch, mcp-server-git, and mcp-server-time use CalVer versioning, uniformly marked as 2026.10.19.

MCP protocol versions and "era" semantics: MCP (Model Context Protocol) uses date-based version numbers (such as 2026-07-28). Each spec revision may introduce changes to capability sets, error models, or transport layers, so the version number actually identifies a set of protocol contracts rather than a software package version. The so-called "modern protocol era" and "legacy era" are shorthand in the official repository for two sets of contracts: the server must select the corresponding capability declarations and return formats based on the protocol version declared by the client during the initialization handshake. This design of negotiating versions per session allows the server to serve both new and old clients from a single codebase, at the cost of branching logic that must strictly align with the spec—any deviation in error codes or structured returns could cause clients in one era to fail parsing.

TypeScript Servers: Node Baseline Raised and Roots Fixes

The mainline change for TS servers is migration to the TypeScript SDK v2 (done in bulk via codemod) and raising the minimum Node version requirement to 24. CI now runs in parallel on Node 22, 24, and 26, indicating that while the team aggressively raised the floor, they are still observing behavior across a wider version range.

Several fixes in server-filesystem deserve individual attention: access is revoked when no valid root directories remain after a roots update; only the response to the most recent roots refresh request is accepted; and tool calls are held in a waiting state while any roots refresh is pending. Together, these three fixes effectively add a concurrency state machine to the filesystem server, preventing race conditions during roots changes that could lead to unauthorized access or mismatched calls.

server-sequential-thinking fixed a small rendering issue: alignment padding between the thinking box header row and the border.

Roots and the concurrency state machine: In MCP, roots are the "operable scope" declared by the client to the server (for example, a list of directories that may be accessed), and the server uses them to limit the scope of filesystem tools. Roots can be dynamically refreshed by the client at runtime, and refreshes are asynchronous requests—after the server sends roots/list, multiple tool calls may be waiting simultaneously. Without controls, late-arriving old responses, having no valid roots during a refresh, or interleaved multiple refreshes could cause the server to determine permissions using a stale or empty root set, resulting in unauthorized access or false denials. The three fixes in v2.0.0 essentially maintain a versioned/sequenced state on the server side: only accepting the latest request's response, suspending tool calls during refreshes, and revoking access if no valid roots remain after a refresh—turning the roots lifecycle into serializable state transitions.

Python Servers: Migration to the High-Level MCPServer Wrapper

The three Python servers have no independent CHANGELOG; the release notes directly list the behavior changes visible to clients. They are now built on top of the MCP Python SDK's high-level MCPServer, with the dependency range tightened to mcp>=2.3,<3.

There are three key behavior-level changes:

  • The error code for unknown tools has changed. Previously an isError result was returned; now, per the spec, a JSON-RPC -32602 error is returned (Unknown tool: <name>), and this applies to both protocol eras. Clients that branch on the old error shape need to adjust.
  • Tool error text format is unified as Error executing tool <name>: <message>, and parameter validation errors now use pydantic's wording while still returning isError results.
  • Capability declarations expanded: every server now declares prompts and resources capabilities (listChanged: false), with fetch's fetch prompt being the only entry in these lists.

Additionally, the time server's get_current_time and convert_time declare an outputSchema and return structuredContent, with text content unchanged; the description in fetch's prompts/get results now always uses the description from when the prompt was registered.

The difference between JSON-RPC error codes and isError: MCP is based on JSON-RPC 2.0, so there are two levels of error expression. Protocol-level errors are returned via the JSON-RPC error object, containing a numeric error code (such as -32602 for Invalid params) and a message; tool-level errors are expressed via isError: true in the tool call result, representing "call succeeded but business failed." The former typically means the request itself is invalid (for example, the tool name doesn't exist), while the latter means the tool executed but returned error content. Changing unknown tools from isError to -32602 restores "tool not found" to protocol-level semantics; the benefit is that clients can handle it uniformly at the RPC layer, while the downside is that old clients branching on the result body will miss it.

outputSchema and structuredContent: MCP tools can declare an output schema, allowing the server to return human-readable text alongside a structured JSON that conforms to the outputSchema (i.e., structuredContent). This lets agents reliably extract fields without parsing natural language text, and lets clients perform output validation. After declaring outputSchema, the server must ensure the structured content matches the schema, while text content can be retained for compatibility with old text-only clients. The time server's two tools exemplify this pattern: the return structure is unchanged, the text is unchanged, but a machine-parseable structured payload has been added.

Known Issue: The Literal "null" Trap

The release notes explicitly document a known issue (#5176): in mcp-server-git, passing the string "null" as base_branch to git_create_branch, or as contains/not_contains to git_branch, is treated as no value. The impact is limited to branches literally named null, and the root cause is in the Python SDK (python-sdk#3055). The official workaround is: in filtering scenarios, pass refs/heads/null or the commit SHA instead; when you need to create a new branch from the null branch, first run git_checkout and then call git_create_branch without base_branch.

Repository Engineering: Hardening CI and Release Processes

Beyond the server code itself, this release comes with a batch of repository-level governance changes: protection rules added to main, requiring that PRs merged into main must already exist in v2/main; a ruleset recorded for v2/main (PRs only, force-push and deletion prohibited); read-only GITHUB_TOKEN permissions declared in python.yml and typescript.yml; automated version PRs now also trigger TS and Python CI; and a fix for backslash escaping before quotes in the win-shell-args script. Together, these details form a release discipline geared toward long-term maintenance rather than a one-off cleanup.

Upgrade Recommendations

If you use official MCP servers, confirm two things before upgrading: first, whether your clients depend on the old behavior of returning isError for unknown tools; second, whether your runtime satisfies the Node 24+ or mcp>=2.3,<3 dependency constraints. If your workflow involves a git branch named null, remember to apply the official workaround.

#MCP#Model Context Protocol#MCP servers#v2.0.0#TypeScript SDK#Python SDK#JSON-RPC#roots#outputSchema
Share:

Related articles