深入解析 @modelcontextprotocol/fastify:用 Fastify 承载 MCP 服务器的官方适配器
2026/9/15 15:28:52 网站建设 项目流程

深入解析 @modelcontextprotocol/fastify:用 Fastify 承载 MCP 服务器的官方适配器

【免费下载链接】typescript-sdkThe official TypeScript SDK for Model Context Protocol servers and clients项目地址: https://gitcode.com/GitHub_Trending/ty/typescript-sdk

导读

@modelcontextprotocol/fastify是官方 TypeScript SDK(typescript-sdk)中面向 Fastify 框架的 MCP 服务器适配层,用于将 @modelcontextprotocol/server 的能力以 Fastify 应用的形式对外提供。阅读本文后,你将掌握:如何用createMcpFastifyApp()一键创建带安全默认值的 MCP Fastify 应用、如何挂载 Streamable HTTP 端点、如何通过 Host 与 Origin 头部校验防御 DNS rebinding 攻击,以及该包在 SDK v2 演进中引入的 ESM/CJS 双构建与 2026-07-28 规范支持等关键变更。

包定位:薄集成层而非 MCP 实现

从 README.md 的定位描述与 package.json 的依赖声明可以看出,该包自身不实现任何 MCP 协议逻辑

  • dependencies为空,核心能力来自两个peerDependencies@modelcontextprotocol/serverfastify
  • 它只做两件事:创建带 MCP 合理默认值的 Fastify 应用为 localhost 服务器提供 DNS rebinding 防护
  • 与 Express 适配器、Hono 适配器 遵循完全相同的适配模式,按变更记录(2.0.0-alpha.1)所述,该包即是在参考二者后新增的 Fastify 版本。

包的公开导出非常精简,全部来自 src/index.ts:

export * from './fastify'; export * from './middleware/hostHeaderValidation'; export * from './middleware/originValidation';

实际对外 API 共 6 个:createMcpFastifyApphostHeaderValidationlocalhostHostValidationoriginValidationlocalhostOriginValidation

安装与前置条件

npm install @modelcontextprotocol/server @modelcontextprotocol/fastify fastify # 若需要基于 Node.js (IncomingMessage/ServerResponse) 的 MCP Streamable HTTP: npm install @modelcontextprotocol/node

安装前提(以当前仓库为准):包要求 Node.js>=20(见 package.json 的engines字段),模块系统为"type": "module",同时通过exportsimport/require双条件支持 ESM 与 CommonJS 两种消费方式(详见下文“构建与发布”)。

createMcpFastifyApp:带安全默认值的应用工厂

核心入口是 src/fastify.ts 中的createMcpFastifyApp(options?)。它的设计哲学是“默认安全”:只要绑定在 localhost 类地址上,就自动挂载 DNS rebinding 防护钩子。

选项参数说明

选项类型默认值行为
hoststring'127.0.0.1'绑定主机名。为'127.0.0.1''localhost''::1'时自动启用 DNS rebinding 保护
allowedHostsstring[]显式提供 Host 校验白名单(端口无关,仅主机名)。IPv6 需带方括号(如'[::1]')。常用于绑定'0.0.0.0'/'::'但仍想限制合法主机名时
allowedOriginsstring[]显式提供 Origin 校验白名单(端口无关,仅主机名,约定与allowedHosts一致)。省略时对 localhost 类绑定自动启用 Origin 校验

安全默认值的武装逻辑

从 src/fastify.ts 的实现可以归纳出以下决策阶梯:

  1. Host 校验
    • 若显式传入allowedHosts,则用hostHeaderValidation(allowedHosts)挂载onRequest钩子;
    • 否则若host属于['127.0.0.1', 'localhost', '::1'],自动挂载localhostHostValidation()
    • 否则若host'0.0.0.0''::'(绑定所有网卡),打印一条警告日志,提示应使用allowedHosts限制主机或改用认证保护服务器。
  2. Origin 校验2.0.0-alpha.4起):
    • 若显式传入allowedOrigins,挂载originValidation(allowedOrigins)
    • 否则对 localhost 类绑定自动挂载localhostOriginValidation()——没有Origin头的请求放行(非浏览器 MCP 客户端不受影响),带Origin但主机名不在白名单或无法解析(包括不透明的nullorigin)的请求以403拒绝。

典型用法示例

import { createMcpFastifyApp } from '@modelcontextprotocol/fastify'; // 默认:绑定 127.0.0.1,自动启用 Host + Origin 校验 const app = createMcpFastifyApp(); // 自定义 host:绑定 0.0.0.0 时不自动启用 DNS rebinding 保护 const appOpen = createMcpFastifyApp({ host: '0.0.0.0' }); // 绑定 localhost 时保护仍然生效 const appLocal = createMcpFastifyApp({ host: 'localhost' }); // 非 localhost 绑定 + 显式白名单 const app = createMcpFastifyApp({ host: '0.0.0.0', allowedHosts: ['myapp.local', 'localhost'], });

注意:createMcpFastifyApp内部直接调用Fastify()创建实例,Fastify 默认就会解析 JSON 请求体,因此 MCP Streamable HTTP 端点无需额外 body 解析中间件(见 src/fastify.ts 的注释)。

Streamable HTTP 端点挂载

将 MCP 服务器挂到 Fastify 路由上的完整示例(来自 README.md):

import { createMcpFastifyApp } from '@modelcontextprotocol/fastify'; import { NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/node'; import { McpServer } from '@modelcontextprotocol/server'; const app = createMcpFastifyApp(); const mcpServer = new McpServer({ name: 'my-server', version: '1.0.0' }); app.post('/mcp', async (request, reply) => { // 无状态示例:每个请求新建 transport。 // 有状态模式(sessions)下应保留并复用 transport 实例。 const transport = new NodeStreamableHTTPServerTransport({ sessionIdGenerator: undefined }); await mcpServer.connect(transport); // 客户端关闭连接(如 SSE 流式传输期间)时清理 transport reply.raw.on('close', () => { transport.close(); }); await transport.handleRequest(request.raw, reply.raw, request.body); });

实战注意事项(README 明确给出):

  • 无状态模式下若每个请求都新建McpServer,也应在close处理器中调用mcpServer.close()
  • 若希望以405 Method Not Allowed拒绝非 POST 请求,可为 GET/DELETE 添加返回 JSON-RPC 错误响应的路由;
  • 更完整的 Fastify 托管方案可参考 serving/fastify.md 与可运行的 examples/fastify 示例。

Host 头部校验:DNS rebinding 防护

原理与动机

DNS rebinding 攻击通过操控 DNS 让一个域名解析到127.0.0.1,使恶意网页能够绕过同源策略访问本机服务。对没有认证、没有 HTTPS 的 localhost/开发服务器而言,这是需要重点防御的攻击面——这正是 src/middleware/hostHeaderValidation.ts 中注释强调的适用场景。

两个 Hook

import { hostHeaderValidation, localhostHostValidation } from '@modelcontextprotocol/fastify'; // 自定义白名单(端口无关;IPv6 带方括号) app.addHook('onRequest', hostHeaderValidation(['localhost', '127.0.0.1', '[::1]'])); // 便捷钩子:只允许 localhost / 127.0.0.1 / [::1] app.addHook('onRequest', localhostHostValidation());

实现上(见 src/middleware/hostHeaderValidation.ts),钩子将request.headers.host交给服务器包导出的validateHostHeader(来自@modelcontextprotocol/server,导出见 packages/server/src/index.ts),校验失败时以403返回 JSON-RPC 格式错误:

{ "jsonrpc": "2.0", "error": { "code": -32000, "message": "<校验失败原因>" }, "id": null }

localhostHostValidation()则直接复用服务器包提供的localhostAllowedHostnames()作为白名单。

测试用例印证

test/fastify.test.ts 覆盖了完整行为矩阵:

  • 仅允许localhost时,host: 'evil.com:3000'的请求返回403,响应体为 JSON-RPC 错误且code === -32_000
  • host: 'localhost:3000'正常放行(200);
  • 多白名单场景下127.0.0.1:8080myapp.local均放行;
  • localhostHostValidation()分别允许localhost:3000127.0.0.1[::1]:3000,拒绝evil.com:3000

Origin 头部校验:面向浏览器的跨站防护

2.0.0-alpha.4引入的 Origin 校验(PR #2286)是 Host 校验的补充:浏览器在跨域请求中会携带Origin头,校验它可以进一步防御 DNS rebinding 与跨站请求伪造(CSRF)。

核心实现位于 src/middleware/originValidation.ts,同样提供两个钩子:

import { originValidation, localhostOriginValidation } from '@modelcontextprotocol/fastify'; // 自定义 origin 白名单(无 scheme、无端口;IPv6 带方括号) app.addHook('onRequest', originValidation(['localhost', '127.0.0.1', '[::1]'])); // 便捷钩子:仅允许 localhost / 127.0.0.1 / [::1] 的 origin app.addHook('onRequest', localhostOriginValidation());

行为约定(与 src/fastify.ts 注释及 CHANGELOG 一致):

  • Origin头 → 放行:非浏览器的 MCP 客户端(如 CLI、SDK 直连)通常不发送该头,不受影响;
  • Origin存在但主机名不在白名单、或无法解析(含不透明的nullorigin)→ 403 拒绝
  • 校验同样委托给服务器包提供的validateOriginHeaderlocalhostAllowedOrigins(导出见 packages/server/src/index.ts),底层是框架无关的辅助函数validateOriginHeader/originValidationResponse

这套 Origin 校验并非 Fastify 独有——同一 PR 同时为 Express、Hono 适配器增加了对应中间件与allowedOrigins选项,并为node:http裸服务器适配器(@modelcontextprotocol/node)补齐了hostHeaderValidation/originValidation请求守卫。

构建与发布:ESM 与 CommonJS 双构建

2.0.0-beta.2起(PR #2405),所有包改为同时发布 ESM 与 CommonJS 两种产物

  • 通过 tsdown 的format: ['esm', 'cjs']同时产出.mjs/.d.mts.cjs/.d.cts(见 tsdown.config.ts);
  • exportsmap 增加require条件,使require('@modelcontextprotocol/fastify')在 CommonJS 消费方也能正常工作;
  • 输出扩展名在各包间统一规范化,公开导入路径不变。

从 package.json 可以看到完整的条件导出结构:

"exports": { ".": { "import": { "types": "./dist/index.d.mts", "default": "./dist/index.mjs" }, "require": { "types": "./dist/index.d.cts", "default": "./dist/index.cjs" } } }, "main": "./dist/index.cjs", "types": "./dist/index.d.mts"

此外2.0.0-alpha.3(PR #1898)为包增加了顶层types字段(client/server 上另有typesVersions),使采用旧式moduleResolution: "node"的消费方也能解析类型声明;exportsmap 对nodenext/bundler解析仍是权威来源。2.0.0-alpha.2则修复了 tsdown 的 exports 解析问题。

版本演进时间线:从 alpha 到 2.0.0

结合 CHANGELOG.md,该包的演进脉络如下:

版本关键变更
2.0.0-alpha.1首次引入 Fastify 中间件适配器(PR #1536),遵循 Express/Hono 适配器模式
2.0.0-alpha.2修复 tsdown exports 解析(PR #1840)
2.0.0-alpha.3增加顶层types字段与typesVersions,兼容旧式moduleResolution: "node"(PR #1898)
2.0.0-alpha.4新增 Origin 头部校验:originValidation/localhostOriginValidation中间件与allowedOrigins选项(PR #2286)
2.0.0-beta.2ESM 与 CommonJS 双构建(PR #2405)
2.0.0-beta.1/2.0.0首个支持MCP 2026-07-28 规范修订的 SDK v2 正式版(PR #2402)

各版本均与@modelcontextprotocol/server对应版本同步发布(CHANGELOG 中每个版本都带有对该依赖的Updated dependencies条目)。

向 v2 与 2026-07-28 规范迁移

2.0.0是 SDK v2 的首个正式版本,核心是支持 MCP 2026-07-28 规范修订。CHANGELOG 明确指引读者参考两份迁移文档:

  • docs/migration/upgrade-to-v2.md:从 v1 升级到 v2 的完整指南;
  • docs/migration/support-2026-07-28.md:采用 2026-07-28 规范修订的指南。

对于使用本适配器的开发者,升级到 v2 后 API 表面保持稳定(createMcpFastifyApp与各校验钩子签名不变),新增的allowedOrigins选项与默认启用的 Origin 校验属于行为层面的增强:只要绑定在 localhost 类地址,应用就会自动获得 Host + Origin 双重防护,而对非浏览器客户端(不发送Origin头)透明无感。

小结

@modelcontextprotocol/fastify用极薄的 API 表面(一个工厂函数加四个校验钩子)为 Fastify 用户补齐了 MCP 服务器托管的三件关键能力:合理的默认绑定与防护Streamable HTTP 端点挂载、以及面向 localhost/开发场景的 Host + Origin 双重校验。其实现完全依赖@modelcontextprotocol/server的框架无关校验辅助函数,保持了一致的适配模式与安全语义;配合 v2 的 ESM/CJS 双构建,可以无缝接入 ESM 或 CommonJS 的 Fastify 项目。

【免费下载链接】typescript-sdkThe official TypeScript SDK for Model Context Protocol servers and clients项目地址: https://gitcode.com/GitHub_Trending/ty/typescript-sdk

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询