跳到主内容
@wquguru
精选88MCP TypeScript SDK(GitHub Releases)AI 编程与模型

@modelcontextprotocol/[email protected]:MCP Server

@modelcontextprotocol/[email protected]

原文
发到 X
推荐理由

核心 MCP SDK 改变了并发模型,沿用旧代码(复用 Server 实例)会导致线上服务第二个请求直接报错。请检查你的 Express/Fastify/Hono 集成代码,确保每个请求都新建 Server 实例。

Patch Changes

补丁更改

  • #2929 40f8f4e Thanks @claude! - requireBearerAuth and verifyBearerToken take a new optional expectedResource, which makes them accept only tokens issued for this resource (the token's audience). Set it to the value your authorization server puts into tokens meant for this server, usually the server's URL. When it is set, a token is accepted only if the verifier reports that value in AuthInfo.resource; the two are compared as strings, ignoring a fragment and one trailing slash. A token reported for another value, or for none, is answered 401 invalid_token with the usual WWW-Authenticate challenge. When it is not set, nothing changes. To use it, pass expectedResource and have verifyAccessToken fill AuthInfo.resource, for example from the aud claim. The option is declared on a new exported type, VerifyBearerTokenOptions, which extends BearerAuthOptions; BearerAuthOptions itself is unchanged. The Express requireBearerAuth passes the option through. With Express, @modelcontextprotocol/express has to be upgraded to this release as well: 2.0.1 does not pass the option on, so nothing is compared. Its options type does not have the option, so TypeScript reports an expectedResource written in a call to the 2.0.1 requireBearerAuth as an error.
  • #2918 84804c2 Thanks @claude! - A Server or McpServer now serves one connection at a time, and a Streamable HTTP server transport without sessions (sessionIdGenerator: undefined) serves one request. An app that uses one server object, or one stateless transport, for every HTTP request fails on the second request after this upgrade. Build the server and the transport per request instead.
  • What keeps working without a change:
  • createMcpHandler(buildServer) and serveStdio(buildServer), where buildServer returns a new server on every call.
  • A handler that builds a new server and a new stateless transport for each request.
  • One server and one transport per session (a transport with a sessionIdGenerator).
  • Connecting a server again after close().
  • Client.
  • What fails now, how it shows, and what to change:
  • One server object with a new stateless transport per request (const server = new McpServer(...) outside the handler, await server.connect(transport) inside it): the second HTTP request the process receives fails, and so does every later one. connect() rejects with an SdkError of code ALREADY_CONNECTED. If the handler closes the transport when the response ends, requests that arrive one after the other still work and a request that overlaps another one fails. Change: move new McpServer(...) and its registrations into the handler.
  • One stateless transport for every request (a transport built once with sessionIdGenerator: undefined): the second HTTP request fails. WebStandardStreamableHTTPServerTransport.handleRequest() rejects with Stateless transport cannot be reused across requests. Create a new transport per request., and NodeStreamableHTTPServerTransport.handleRequest() answers 500. Change: build the server and the transport inside the handler and connect them there.
  • createMcpHandler(() => server) with a server built once: a request that arrives after the previous response has been read to its end still works. A request that arrives while another one is being served is answered 500 with the JSON-RPC error -32603 (Internal server error); the reason is reported only through the onerror option. Change: pass a function that builds the server, as in createMcpHandler(buildServer).
  • One server object for every session: the initialize request of the second session fails with ALREADY_CONNECTED. Change: build a server per session.
  • What the caller sees when connect() or handleRequest() rejects depends on the host. Express 5, Fastify and Hono answer 500. A plain node:http listener without its own error handling gets an unhandled rejection, which ends the process.
  • The README examples of @modelcontextprotocol/express, @modelcontextprotocol/fastify, @modelcontextprotocol/hono and @modelcontextprotocol/node, and the handler examples in the JSDoc of WebStandardStreamableHTTPServerTransport and NodeStreamableHTTPServerTransport, now build a server and a transport per request.
  • #2908 633dd3e Thanks @claude! - The license field of the package manifests is now Apache-2.0; the LICENSE file shipped in each package carries the full terms, including the MIT text for earlier contributions. No code change.
  • Updated dependencies [40f8f4e, 6d8dbc6, 5238fba, 2fc49ea, 4d94e7b, 84804c2, e55f9ac, 633dd3e, 2237555]:
  • @modelcontextprotocol/[email protected]
  • #2929 40f8f4e 感谢 @claude!- requireBearerAuth 和 verifyBearerToken 现在接受一个新的可选参数 expectedResource,这使得它们仅接受为此资源(令牌的受众)颁发的令牌。将其设置为你授权服务器放入为此服务器准备的令牌中的值,通常是服务器的 URL。当设置了该参数时,只有当验证者在 AuthInfo.resource 中报告该值时才会接受令牌;两者作为字符串进行比较,忽略片段和一个尾随斜杠。如果令牌报告了其他值或未报告任何值,则返回 401 invalid_token 并附带常规的 WWW-Authenticate 挑战。当未设置该参数时,没有任何变化。要使用它,请传递 expectedResource 并让 verifyAccessToken 填充 AuthInfo.resource,例如从 aud 声明中获取。该选项在一个新的导出类型 VerifyBearerTokenOptions 上声明,它扩展了 BearerAuthOptions;BearerAuthOptions 本身保持不变。Express 的 requireBearerAuth 会透传该选项。对于 Express,@modelcontextprotocol/express 也必须升级到此版本:2.0.1 不会透传该选项,因此不会进行任何比较。其选项类型没有该选项,因此 TypeScript 会将写入对 2.0.1 的 requireBearerAuth 调用中的 expectedResource 报告为错误。
  • #2918 84804c2 感谢 @claude!- Server 或 McpServer 现在一次只服务一个连接,而没有会话(sessionIdGenerator: undefined)的 Streamable HTTP 服务器传输一次只服务一个请求。每个 HTTP 请求使用一个服务器对象或一个无状态传输的应用程序在此升级后的第二个请求时会失败。改为按请求构建服务器和传输。
  • 无需更改即可继续工作的内容:
  • createMcpHandler(buildServer) 和 serveStdio(buildServer),其中 buildServer 每次调用都返回一个新服务器。
  • 为每个请求构建新服务器和新无状态传输的处理程序。
  • 每个会话一个服务器和一个传输(带有 sessionIdGenerator 的传输)。
  • 在 close() 之后重新连接服务器。
  • 客户端。
  • 现在哪些会失败、如何表现以及如何更改:
  • 每个请求使用一个新的无状态传输,对应一个服务器对象(const server = new McpServer(...) 定义在处理器外部,await server.connect(transport) 在处理器内部):进程收到的第二个 HTTP 请求会失败,后续所有请求也会失败。connect() 抛出代码为 ALREADY_CONNECTED 的 SdkError。如果处理器在响应结束时关闭传输,连续到达的请求仍能正常工作,但与其他请求重叠的请求会失败。变更:将 new McpServer(...) 及其注册逻辑移入处理器中。
  • 每个请求使用一个无状态传输(通过 sessionIdGenerator: undefined 构建一次传输):第二个 HTTP 请求会失败。WebStandardStreamableHTTPServerTransport.handleRequest() 抛出错误 "Stateless transport cannot be reused across requests. Create a new transport per request.",而 NodeStreamableHTTPServerTransport.handleRequest() 返回 500。变更:在处理器中构建服务器和传输,并在其中连接它们。
  • 使用仅构建一次的服务器调用 createMcpHandler(() => server):在上一响应完全读取后到达的请求仍可正常工作。而在处理另一个请求期间到达的请求会收到 500 响应及 JSON-RPC 错误 -32603(Internal server error);原因仅通过 onerror 选项报告。变更:传入一个用于构建服务器的函数,如 createMcpHandler(buildServer)。
  • 每个会话使用一个服务器对象:第二个会话的 initialize 请求因 ALREADY_CONNECTED 而失败。变更:为每个会话构建一个服务器。
  • 当 connect() 或 handleRequest() 抛出拒绝时,调用者看到的结果取决于主机环境。Express 5、Fastify 和 Hono 返回 500。没有自定义错误处理的普通 node:http 监听器会遭遇未处理的拒绝(unhandled rejection),从而导致进程终止。
  • @modelcontextprotocol/express、@modelcontextprotocol/fastify、@modelcontextprotocol/hono 和 @modelcontextprotocol/node 的 README 示例,以及 WebStandardStreamableHTTPServerTransport 和 NodeStreamableHTTPServerTransport JSDoc 中的处理器示例,现在改为每个请求构建一个服务器和一个传输。
  • #2908 633dd3e 感谢 @claude!- 包清单中的 license 字段现设为 Apache-2.0;每个包附带的 LICENSE 文件包含完整条款,包括早期贡献的 MIT 文本。无代码变更。
  • 更新依赖项 [40f8f4e, 6d8dbc6, 5238fba, 2fc49ea, 4d94e7b, 84804c2, e55f9ac, 633dd3e, 2237555]:
  • @modelcontextprotocol/[email protected]

更进一步:量化金融体系

看懂新闻只是起点——沿量化金融路径,把它变成能交付的工程能力

进入量化体系 →

相似阅读

关联信息,但可能不是同一事件