Pick an MCP server library on the numbers everyone publishes — throughput, memory, p50 — and you will optimise a difference of two milliseconds inside a response that takes two hundred, because the work these servers do is calling somebody else's API. The axis that will actually cost you a quarter is which specification revision the library speaks, and it splits the field in an awkward direction: the two options a team is most likely to already be running are not the two most current ones. Worse, "supports the new revision" is the wrong question, because your clients upgrade on their own schedule and you need one deployment that answers both.
At a glance
Four libraries, four languages, and one shared deadline that arrived on 28 July 2026.
| Library | Language | Current revision | Governance |
|---|---|---|---|
| FastMCP | Python | 2026-07-28, from FastMCP 4 | Community framework above the official SDK; FastMCP 1.0 was folded into that SDK in 2024 |
| Official TypeScript SDK | TypeScript | 2026-07-28, in the v2 packages | Tier 1, maintained alongside the specification |
| mcp-go | Go | 2025-11-25, with compatibility back to 2024-11-05 | Community; the separate official Go SDK holds the Tier 1 slot |
| rmcp | Rust | 2026-07-28, compatible with 2025-11-25 | Official Rust SDK, now on its 3.x line |
The 2026-07-28 revision is not a routine bump. It retired the initialize/initialized exchange and the Mcp-Session-Id header outright, added Mcp-Method, Mcp-Name and MCP-Protocol-Version so gateways can route without parsing bodies, deprecated the HTTP+SSE transport, moved Tasks out of the core into an extension, and started a minimum twelve-month clock on Roots, Sampling and Logging. Things were removed, which is why "we will get to it" is a position with a cost attached.
The benchmark axis is the one that does not matter
An independent five-language benchmark puts p50 echo-proxy handling at 0.38 ms for Rust with rmcp, 0.50 ms for Go with mcp-go, 0.60 ms for C#, 0.76 ms for TypeScript and 2.25 ms for Python with FastMCP; idle resident memory runs from 7 MB for Rust through 21 MB for Go and 97 MB for Python to 162 MB for TypeScript and 221 MB for C#. Its author is refreshingly direct about what this means: for a proxying MCP server, language does not matter, because all five handle a request in under 3 ms and the real bottleneck is the 50–500 ms network round trip to the upstream API.
Those two sentences are the whole argument for ignoring the benchmark. A 1.9 ms spread inside a 200 ms response is a 1% effect on latency you cannot feel, and the memory numbers only start mattering at a replica count most tool servers never reach. If your server does something genuinely compute-bound — parsing large documents, running embeddings inline — the ranking becomes real, but then you are benchmarking your workload, not the protocol library.
The reason the wrong axis wins is that it is the only one with numbers. Revision currency has no leaderboard, so it loses to a chart. That is a bad trade, because latency here is a 1% difference and being a revision behind is a binary that eventually stops your clients connecting.
FastMCP — the ecosystem tax and the ecosystem benefit
The default that is genuinely the default
FastMCP sits at around 27,500 stars, is downloaded roughly a million times a day, and claims that some version of it powers about 70% of MCP servers across all languages. Even discounting a project's own framing, nothing else in this comparison is close on adoption. Its lineage is unusual and worth knowing: FastMCP 1.0 was absorbed into the official Python SDK in 2024, and the actively maintained standalone project continued alongside it — so "FastMCP" and "the official Python SDK" are related but not interchangeable, and a Python team has to know which one it is on.
It is the only one that advertises the thing you actually need
FastMCP 4 is the interesting release here, because it is aimed squarely at the problem this article is about: making stateful applications work on the sessionless 2026-07-28 protocol while one deployment continues to serve handshake-era clients, negotiating the best revision per connection. Tools can ask follow-up questions across requests and hold authenticated user state without sticky sessions, so any replica behind an ordinary load balancer can answer any request. Most FastMCP 3 servers are said to upgrade untouched.
That per-connection negotiation is a product decision the others have not made as loudly, and it is worth more than 1.9 ms. It is also, notably, a framework feature rather than a protocol feature — which means it is exactly the kind of thing you lose in a language migration.
The official TypeScript SDK — currency by construction
Tier 1 means the revision ships with the spec
The TypeScript SDK implements 2026-07-28 in its v2 packages and sits at roughly 13,300 stars. Its structural advantage is boring and large: it is one of the Tier 1 SDKs, so a revision landing in the specification and a revision landing in the library are close to the same event. Across the Tier 1 set the maintainers report close to half a billion downloads a month, with TypeScript and Python both past a billion total — this is the well-trodden path, and the cost of being on it is that you get the protocol's raw primitives and wire the ergonomics yourself.
Where the ergonomics gap actually bites
The comparison people make is decorators versus explicit registration, which is taste. The comparison that costs money is auth: with a raw SDK you assemble OAuth discovery, token validation and PKCE rather than inheriting them. That is a real amount of work, and it is work you must not get wrong. Weigh it against the certainty that the next revision arrives on day zero rather than in some later minor release; see MCP auth and OAuth 2.1 for what you are assembling.
mcp-go — the anomaly worth checking today
Popular and a revision behind, and those are separate facts
mcp-go is the library most Go MCP servers were built on: roughly 9,100 stars and a long head start. Its README states that it implements 2025-11-25, with backward compatibility to 2025-06-18, 2025-03-26 and 2024-11-05. That is the handshake era. Meanwhile the official Go SDK — a different project, around 5,100 stars — implements 2026-07-28 from v1.7.0 onward while retaining compatibility with the three previous revisions.
So Go is the language where the popular choice and the tracked choice are two different codebases at two different revisions, and moving between them is a port rather than an upgrade. If you run a Go MCP server, this is the paragraph to act on: check which import path you are on before you read anything else here.
What "a revision behind" costs, concretely
Not much, until it does. Clients built on current SDKs generally negotiate down, so an older server keeps working — right up to a client that drops the deprecated transport, or a gateway that routes on the new headers, or an infrastructure team that wants to scale a stateless workload and finds session affinity in the way. Each of those is somebody else's roadmap item, which means the date is not yours to pick. That is the operational shape covered in protocol revisions and deprecation windows.
rmcp — current, official, and the smallest ecosystem
The trajectory is the story
The Rust SDK reached 1.0 in March 2026 and moved fast; it is now on a 3.x line, implements the stable 2026-07-28 revision, and remains compatible with 2025-11-25 and earlier. At roughly 3,900 stars it is the smallest community here by some distance, which shows up as fewer worked examples and fewer people who have already hit your problem — but on the axis this article cares about it is the strongest row in the matrix.
Where it earns its place
Not on the 0.38 ms, which is a rounding error against the upstream call. It earns its place on the 7 MB idle footprint when you are running many small tool servers per host, on procedural macros that generate tool implementations from typed structs — which makes the schema and the code one artefact rather than two that drift — and on being an official SDK rather than a community one, which is what makes the revision cadence predictable.
The window, not the cutover
The framing error underneath most of these library comparisons is the word "migration". There is no cutover, because you own one end of the connection and your clients own the other. What you actually run is a window in which both revisions are live, and the only question is where in your system that fact is represented.
Fork the deployment and you fork your tool implementations, authorisation checks, rate limits and tracing along with it, and every fix lands twice for as long as the window lasts — which is longer than anyone plans, because the last 3% of callers are unattended jobs with no owner reading release notes. Negotiate at the edge and normalise inward, and the revision appears in exactly one module, with a removal date you can write in the file. Retiring a revision becomes deleting a directory.
This reframes the library choice. The question is not "does it support 2026-07-28" — three of these four do. It is "how much of my dual-revision window does this library absorb, and how much becomes my topology". That is why FastMCP's per-connection negotiation is the most consequential single feature in the comparison, and why a Go team on mcp-go has the largest decision in front of it.
When to pick which
| Situation | Pick | Because |
|---|---|---|
| Greenfield, Python shop, want the shortest path to a working server | FastMCP | Largest ecosystem, batteries-included auth, and per-connection revision negotiation you would otherwise build |
| Greenfield, TypeScript shop, want protocol primitives and no framework opinion | Official TypeScript SDK | Tier 1 currency by construction; budget real time for the OAuth wiring |
| Existing Go server on mcp-go | Audit first, then plan the port | Your library and the Tier 1 Go implementation are different projects at different revisions |
| Many small tool servers per host, or a compute-bound tool | rmcp | 7 MB idle is a real multiplier at replica count; typed macros keep schema and code as one artefact |
| You cannot control when your clients upgrade | Whichever negotiates per connection | The window is the deliverable, not the revision |
And a check that takes ten minutes for any of them: for each of the last three revisions, record the specification's publication date, the library's first release implementing it, and its first stable release. Three historical lags predict the fourth better than any roadmap. That number, not the p50, is the one that should decide this.
FAQ
Does language really not matter for MCP server performance?
For a server whose tools call an upstream API, no — the benchmark's own author says so, and a 1.9 ms spread inside a 50–500 ms round trip is unmeasurable in practice. It starts mattering when your tools do the compute themselves, or when idle memory multiplied by replica count becomes a bill.
Is FastMCP the same thing as the official Python SDK?
No. FastMCP 1.0 was folded into the official Python SDK in 2024, and the standalone project kept developing separately. They share ancestry, not a release train, and a Python team should know which one its server imports.
My mcp-go server works fine against current clients. Do I have to move?
Not today — current clients generally negotiate down. The exposure is that your deadline is set by other people: a client dropping the deprecated transport, a gateway routing on the new headers, or your own need to scale a session-free workload. Check which import path you are on, then decide with a date rather than under one.
What is the actual risk of staying on the handshake-era revision?
Two things. Session affinity keeps a stateless workload from scaling like ordinary HTTP, and the twelve-month deprecation clocks on Roots, Sampling and Logging expire whether or not you have moved. Neither is an outage today; both are work you do not get to schedule.
Should I run two deployments during the transition?
Prefer not to. Forking the deployment forks your tool code, authorisation and rate limits with it, and the window outlasts the plan. Negotiate at the edge, normalise to one internal request shape, and keep the compatibility layer in a single module with its removal date written in the file.
Further reading
On this wiki:
- Protocol Revisions & Deprecation Windows — the operational discipline this comparison implies, including the revision-distribution metric nobody records.
- MCP Streamable HTTP — what the transport actually does, and what statelessness changed about it.
- MCP Ops in Production — running servers once they have real callers.
- MCP Auth and OAuth 2.1 — the wiring you inherit with a framework and assemble with a raw SDK.
- Building MCP Servers in Practice — the layer above the library choice.