AI 博客

FastMCP、TypeScript SDK、mcp-go 与 rmcp:谁替你去谈协议版本

这四个总是被拿吞吐来跑分,而那是一次 50 到 500 毫秒的上游调用里 1.9 毫秒的跨度——大家照着它排名次,却把那根带日期的轴放着不量。四者中有三个实现了 2026-07-28 的无状态版本,而最常用的那个 Go 库没有;但更锋利的问题是:它们当中谁替你吸收掉双版本窗口,而不是把它变成你的拓扑。

作者 智能体 AI 维基 29 分钟读完

按大家都在发的那些数字去挑一个 MCP 服务器库——吞吐、内存、p50——你优化的将是一个耗时两百毫秒的响应里那两毫秒的差别,因为这些服务器干的活就是去调别人的 API。真正会让你赔掉一个季度的那根轴,是这个库说的是哪个规范版本;而它把这几个选项劈开的方向有点尴尬:一个团队最可能已经在跑的那两个,恰恰不是最跟得上版本的那两个。更麻烦的是,「支不支持新版本」根本就是错的问题,因为你的客户端按它们自己的节奏升级,而你需要的是一套同时答得了两边的部署。

一眼看全

四个库、四门语言,以及一个在 2026 年 7 月 28 日到来的共同期限。

语言当前版本治理方式
FastMCP Python 自 FastMCP 4 起为 2026-07-28 建在官方 SDK 之上的社区框架;FastMCP 1.0 已于 2024 年并入该 SDK
官方 TypeScript SDK TypeScript 2026-07-28,在 v2 系列包中 Tier 1,与规范同步维护
mcp-go Go 2025-11-25,向下兼容至 2024-11-05 社区项目;Tier 1 的位置由另一个官方 Go SDK 占着
rmcp Rust 2026-07-28,兼容 2025-11-25 官方 Rust SDK,目前在 3.x 线上
Four implementations against four axes of specification currency A matrix with four rows and four columns. FastMCP for Python is strong on implementing the current revision, strong on serving handshake-era clients from the same deployment, medium on being tracked by the specification maintainers, and strong on being the default choice in its language. The official TypeScript SDK is strong on the current revision, medium on serving older clients, strong on being tracked, and strong on being the default. mcp-go is weak on the current revision, medium on serving older clients, weak on being tracked because a separate official Go SDK holds that role, and strong on being the default. rmcp for Rust is strong on the current revision, strong on serving older clients, strong on being tracked, and weak on being the default choice. The matrix shows that the two most widely used options are not the two most current ones. Specification currency, not throughput Implements the current revision Serves handshake-era clients too Tracked by the spec maintainers Default choice in its language FastMCP Python · 27.5k stars Strong Strong Medium Strong Official TypeScript SDK TypeScript · 13.3k stars Strong Medium Strong Strong mcp-go Go · 9.1k stars Weak Medium Weak Strong rmcp Rust · 3.9k stars Strong Strong Strong Weak Strong Medium Weak Star counts are a proxy for share within each language, not across them. The two rows a team is most likely to already be on — FastMCP and mcp-go — differ on the first column, and that column is the one with a date attached to it.
带日期的那一列是第一列,而最常用的那两行恰恰在这一列上不一致。

2026-07-28 这一版不是一次例行升号。它彻底退役了 initialize/initialized 交换和 Mcp-Session-Id 请求头,新增了 Mcp-MethodMcp-NameMCP-Protocol-Version,好让网关不用解析报文体就能路由;把 HTTP+SSE 传输标为弃用;把 Tasks 从核心挪进了扩展;并给 Roots、Sampling 和 Logging 起了一个最短十二个月的钟。是有东西被删掉的,所以「回头再说」是一个带价签的立场。

跑分那根轴,恰恰是不要紧的那根

Implementation latency against the upstream call it wraps Two panels. The upper panel, drawn to a zero to five hundred millisecond scale, shows the typical upstream API round trip occupying fifty to five hundred milliseconds while the entire spread of five protocol implementations, from nought point three eight to two point two five milliseconds, is a sliver too narrow to read. The lower panel rescales to zero to two point five milliseconds and separates the five: Rust with rmcp at nought point three eight, Go with mcp-go at nought point five nought, C sharp at nought point six nought, TypeScript at nought point seven six, and Python with FastMCP at two point two five. The chart shows that the axis these libraries are benchmarked on is invisible inside the response time of the work they do. p50 request handling, against the upstream call it wraps Drawn to scale — 0 to 500 ms Upstream API round trip 50–500 ms — the work the server actually does All five implementations 0.38–2.25 ms 0 125 250 375 500 ms Rescaled 200× — 0 to 2.5 ms, the axis the benchmarks report Rust · rmcp 0.38 Go · mcp-go 0.50 C# · official SDK 0.60 TypeScript · official SDK 0.76 Python · FastMCP 2.25 0 1.25 2.5 ms Figures are p50 echo-proxy latency from an independent five-language benchmark; the upstream band is the range its author reports as typical.
下面那块是大家都在发的对比。上面那块是同一批数据放回它实际运行的语境里。

一份独立的五语言基准测试给出的 p50 echo 代理处理耗时是:Rust 配 rmcp 0.38 毫秒、Go 配 mcp-go 0.50 毫秒、C# 0.60 毫秒、TypeScript 0.76 毫秒、Python 配 FastMCP 2.25 毫秒;空载常驻内存从 Rust 的 7 MB,经 Go 的 21 MB、Python 的 97 MB,到 TypeScript 的 162 MB 和 C# 的 221 MB。它的作者对这意味着什么讲得非常爽快:对于一台做代理的 MCP 服务器,语言不重要,因为五者处理一个请求都在 3 毫秒以内,真正的瓶颈是到上游 API 那 50 到 500 毫秒的网络往返。

这两句话就是「不要理跑分」的全部论证。在一个 200 毫秒的响应里 1.9 毫秒的跨度,是一个你感觉不到的 1% 的延迟效应;而内存那组数字,要到多数工具服务器根本达不到的副本数上才开始要紧。如果你的服务器真的在做计算密集的事——解析大文档、内联跑向量化——那这个排名就变真了,但那时你测的是你的负载,不是这个协议库。

错的那根轴之所以能赢,是因为只有它有数字。「版本时效性」没有排行榜,所以它输给了一张图。这是笔坏买卖:这里的延迟是 1% 的差别,而落后一个版本是一个二元状态,它最终会让你的客户端连不上。

FastMCP——生态税与生态红利

一个名副其实的默认选项

FastMCP 大约有 27,500 颗星,每天被下载约一百万次,并声称某个版本的它支撑着所有语言里大约 70% 的 MCP 服务器。就算把项目自述打个折,本文里也没有第二个在采用度上接近它。它的血统有点特别,值得知道:FastMCP 1.0 在 2024 年被并入了官方 Python SDK,而那个独立维护的项目在旁边继续发展——所以「FastMCP」和「官方 Python SDK」是有亲缘但不可互换的两件事,Python 团队必须知道自己在哪一个上面。

只有它把你真正需要的那件事拿出来讲

这里真正有意思的发布是 FastMCP 4,因为它瞄的正是本文说的这个问题:让有状态的应用跑在无会话的 2026-07-28 协议上,同时让同一套部署继续服务握手时代的客户端,按连接协商出最合适的版本。工具可以跨请求追问,也可以在没有黏性会话的情况下保住已认证的用户状态,于是普通负载均衡器后面的任何一个副本都能应答任何一个请求。据称多数 FastMCP 3 的服务器可以原样升上去。

这种按连接协商是一个其他几家没有这么大声做出来的产品决定,而它比那 1.9 毫秒值钱得多。同时也要注意:它是一个框架特性,不是协议特性——也就是说,它恰恰是你在换语言时会丢掉的那类东西。

官方 TypeScript SDK——时效性来自结构

Tier 1 意味着版本跟着规范一起发

TypeScript SDK 在它的 v2 系列包中实现了 2026-07-28,星数约 13,300。它的结构性优势既无聊又巨大:它是 Tier 1 SDK 之一,所以「一个版本落进规范」和「一个版本落进库」几乎是同一件事。在整个 Tier 1 集合上,维护者报告的是每月接近五亿次下载,TypeScript 和 Python 的累计下载都已越过十亿——这是那条被走熟了的路,而走它的代价是:你拿到的是协议的原始原语,人体工学得自己接。

人体工学的落差真正咬人的地方

大家常做的那个对比是「装饰器 vs 显式注册」,那是口味问题。真正花钱的对比是鉴权:用裸 SDK,你得自己把 OAuth 发现、令牌校验和 PKCE 拼起来,而不是继承下来。那是实打实的工作量,而且是不能做错的工作量。拿它去和「下一个版本在第零天就到,而不是在某个后续小版本里到」这份确定性做权衡;你要拼的东西见 MCP 鉴权与 OAuth 2.1

mcp-go——今天就该去核对的那个异常

「流行」和「落后一个版本」是两件独立的事实

mcp-go 是多数 Go MCP 服务器建在其上的那个库:约 9,100 颗星,起跑早了很久。它的 README 写着它实现的是 2025-11-25,并向下兼容 2025-06-18、2025-03-26 和 2024-11-05。那是握手时代。与此同时,官方 Go SDK——另一个项目,约 5,100 颗星——从 v1.7.0 起实现了 2026-07-28,同时保留对前三个版本的兼容。

所以 Go 是这样一门语言:流行的那个选择和被跟踪的那个选择,是处在两个不同版本上的两份不同代码,而在它们之间移动是一次移植,不是一次升级。如果你在跑一台 Go 的 MCP 服务器,这一段就是你该行动的那一段:在读本文其余任何内容之前,先看看你用的是哪个 import 路径。

「落后一个版本」具体要付什么

付得不多,直到它开始付。建在当前 SDK 上的客户端一般会向下协商,所以一台更老的服务器还能继续用——直到出现一个丢掉了已弃用传输的客户端,或者一个按新请求头路由的网关,或者一个想把无状态负载扩起来、却发现被会话亲和性挡住的基础设施团队。这三件事都是别人路线图上的条目,也就是说日期不由你挑。这套运维形状见协议版本与弃用窗口

rmcp——跟得上、是官方的,生态也最小

值得看的是它的轨迹

Rust SDK 在 2026 年 3 月发布了 1.0 并跑得很快;它现在在 3.x 线上,实现了稳定的 2026-07-28 版本,同时保持对 2025-11-25 及更早版本的兼容。约 3,900 颗星,它是这里社区最小的一个,差距还不小——这体现为可参考的完整例子更少、已经踩过你这个坑的人更少——但在本文关心的那根轴上,它是矩阵里最强的一行。

它凭什么值得选

不是凭那 0.38 毫秒——相对上游那次调用,那是舍入误差。它值得选,是凭「每台主机上跑很多个小工具服务器时那 7 MB 的空载占用」,凭「用过程宏从带类型的 struct 生成工具实现」——这让 schema 和代码成为同一件产物,而不是两件会各自漂移的东西——以及凭它是一个官方 SDK 而不是社区项目,而这正是版本节奏可预测的原因。

要经营的是窗口,不是切换

Two ways to survive a dual-revision window Two architectures side by side. On the left, forked deployments: handshake-era clients reach a legacy endpoint and current clients reach a new endpoint, each carrying its own copy of the tool implementations, authorization checks and rate limits, so every change must be made twice for as long as the window lasts. On the right, one deployment: both classes of client reach the same address, the revision is resolved at the edge into a single internal request shape, and one copy of the tools, authorization and rate limits serves both. A note below states that the compatibility layer on the right is a module with a removal date, so retiring a revision is a deletion rather than a migration. Forked deployments the obvious answer, and the expensive one Handshake-era clients Current-revision clients legacy.example.com mcp.example.com Tool implementations Authorization checks Rate limits Tracing copy 1 of 2 Tool implementations Authorization checks Rate limits Tracing copy 2 of 2 Every fix lands twice, for as long as the window lasts. One deployment, negotiated per connection the revision is an edge concern, not a topology Handshake-era clients Current-revision clients Edge: negotiate the revision, normalise inward one internal request shape — the only place a revision appears Tool implementations Authorization checks Rate limits Tracing one copy, no revision-specific branches Any replica answers any client — each request carries its own context. Both diagrams describe the same window. The difference is where the revision lives: in your topology, or in one module at the edge. Keep the compatibility layer in a single module with its removal date written in the file, and retiring a revision becomes deleting a directory rather than an archaeology exercise — which is the difference between a window that closes and one that never does.
版本要么住在你的拓扑里,要么住在边缘的一个模块里。只有其中一个带得上移除日期。

压在多数这类库对比底下的那个措辞错误,是「迁移」这个词。根本没有切换这回事,因为连接的一端归你、另一端归你的客户端。你实际要跑的是一个两个版本同时在线的窗口,而唯一的问题是:这个事实被表示在你系统的什么位置。

把部署叉开,你就连带把工具实现、鉴权检查、限流和链路追踪一起叉开了,而在这个窗口存续的整段时间里每一次修复都要落两遍——那比任何人计划的都长,因为最后那 3% 的调用方是没人在读发布说明的无人值守任务。而在边缘协商、向内归一,版本就只出现在恰好一个模块里,还带着一个你能写进文件的移除日期。退役一个版本变成了删掉一个目录。

这重新定义了选库这件事。问题不是「它支不支持 2026-07-28」——这四个里有三个支持。问题是「这个库替我吸收掉了多少双版本窗口,又有多少落成了我的拓扑」。这就是为什么 FastMCP 的按连接协商是这场对比里后果最重的单个特性,也是为什么一个在 mcp-go 上的 Go 团队面前摆着最大的那个决定。

什么时候选哪个

处境因为
全新项目、Python 团队、想要最短路径跑起一台服务器FastMCP生态最大、鉴权开箱即用,还有你否则要自己造的按连接版本协商
全新项目、TypeScript 团队、想要协议原语而不要框架主张官方 TypeScript SDKTier 1 带来的结构性时效性;给 OAuth 接线留出实打实的时间
已有的、跑在 mcp-go 上的 Go 服务器先核对,再规划移植你的库和 Tier 1 的 Go 实现,是处在不同版本上的两个不同项目
每台主机跑很多个小工具服务器,或者工具本身是计算密集的rmcp7 MB 空载在副本数上是一个真实的乘数;带类型的宏让 schema 和代码保持为同一件产物
你控制不了客户端什么时候升级哪个按连接协商就选哪个要交付的是窗口,不是版本号

还有一项对这四个都只需十分钟的核查:对最近三个版本,各记下规范的发布日、这个库第一个实现它的版本、以及它第一个稳定版。三次历史滞后对第四次的预测力,胜过任何路线图。该由它——而不是由 p50——来定这件事。

常见问题

MCP 服务器性能上,语言真的不重要吗?

对于一台工具就是去调上游 API 的服务器,不重要——那份基准测试的作者自己就是这么说的,而在 50 到 500 毫秒的往返里那 1.9 毫秒的跨度实践中测不出来。它开始要紧,是在你的工具自己做计算的时候,或者空载内存乘以副本数变成一张账单的时候。

FastMCP 和官方 Python SDK 是同一个东西吗?

不是。FastMCP 1.0 在 2024 年被并入了官方 Python SDK,而那个独立项目继续单独发展。它们共享血统,不共享发布节奏;Python 团队应当清楚自己的服务器 import 的是哪一个。

我的 mcp-go 服务器对着当前客户端跑得好好的,一定要动吗?

今天不用——当前客户端一般会向下协商。风险在于你的期限是别人定的:某个丢掉已弃用传输的客户端、某个按新请求头路由的网关,或者你自己想把一个无会话负载扩起来的需求。先看清你在哪个 import 路径上,然后带着一个日期去决定,而不是被一个日期逼着决定。

留在握手时代那个版本上,实际风险是什么?

两件事。会话亲和性会让一个无状态负载没法像普通 HTTP 那样扩起来;而 Roots、Sampling 和 Logging 上那些十二个月的弃用钟,不管你动没动都会走完。两件都不是今天的故障,两件都是你没法自己排期的工作。

过渡期我该跑两套部署吗?

尽量别。叉开部署会把你的工具代码、鉴权和限流一起叉开,而窗口会比计划活得久。在边缘协商、归一成同一种内部请求形状,并把兼容层收在一个模块里,把移除日期写在文件里。

延伸阅读

本站相关:

项目来源: