Mastra Express 服务端适配器(@mastra/express)实战指南:将 AI Agent 无缝接入 Express 框架
【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra
本篇指南系统讲解 Mastra 官方 Express 服务端适配器@mastra/express的安装、初始化与深度配置。它面向希望在既有 Express 应用中托管 Mastra Agent、Workflow、Memory 与 MCP 服务的开发者,帮助你将一个普通的express()应用升级为完整的 AI 服务端:通过MastraServer自动注册一套基于 OpenAPI 的 REST/SSE 路由,并集成认证(Auth)、RBAC 权限、FGA 授权、流式响应脱敏、multipart 上传与 HTTP 日志等能力。读完本文,你将掌握MastraServer的构造参数、init()生命周期、请求参数解析链路与流式输出原理,并能直接复制文中示例投入实战。
一、@mastra/express 是什么
@mastra/express是 Mastra 为 Express 中写得很明确:"Express server adapter for Mastra, enabling you to run Mastra with the Express framework"。
与 Hono、Fastify 等适配器一样,它通过继承@mastra/server中抽象基类MastraServer<TApp, TRequest, TResponse>实现(定义见 packages/server/src/server/server-adapter/index.ts#L382),用 Express 原生的Application、Request、Response类型补齐框架特定的路由注册、中间件与流式响应逻辑。因此,使用它不需要引入额外运行时,你手中现成的 Express 中间件生态(express.json()、cors、swagger-ui-express等)可以继续原样工作。
从 server-adapters/express/package.json 可以看到其依赖关系与运行前提:
- 运行时依赖:
@mastra/server(workspace 包,承载核心服务器逻辑)、@fastify/busboy(用于 multipart/form-data 解析); - peer 依赖:
@mastra/core >= 1.50.0-0 < 2.0.0-0、express ^5.1.0、@types/express ^5.0.5,即面向 Express 5; - 运行环境:Node.js
>= 22.13.0; - 模块格式:ESM(
type: "module"),同时通过dist/index.cjs提供 CJS 入口。
二、安装
在项目根目录执行:
npm install @mastra/express安装完成后建议同步确认express、@types/express与@mastra/core满足上面列出的版本范围(Express 5 与 Node 22+),避免运行时类型不匹配。
三、最小可用示例
沿用官方 README 给出的最小用法(server-adapters/express/README.md),创建一个server.ts:
import express from 'express'; import { MastraServer } from '@mastra/express'; import { mastra } from './mastra'; // 你的 Mastra 实例(包含 agents / workflows / tools 等) const app = express(); const server = new MastraServer({ app, mastra }); await server.init(); app.listen(3000, () => { console.log('Server running on http://localhost:3000'); });三段式启动流程:
- 创建 Express
app; - 用
new MastraServer({ app, mastra })把 Mastra 实例"挂"到 Express 上; await server.init()完成全部路由与中间件注册,之后照常app.listen(port)。
init()内部按固定顺序执行(见 packages/server/src/server/server-adapter/index.ts#L840):注册上下文中间件 → 注册认证中间件 → 校验 auth 资源作用域 → 注册用户中间件 → 注册 HTTP 日志中间件 → 校验 EE 许可(RBAC/FGA 场景)→ 注册自定义 API 路由 → 注册内置路由。这也解释了为什么必须在init()之后才能接收请求。
四、MastraServer 构造参数详解
MastraServer的构造函数支持以下选项(完整定义见 packages/server/src/server/server-adapter/index.ts#L411):
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
app | Application | 必填 | Express 应用实例 |
mastra | Mastra | 必填 | Mastra 核心实例 |
prefix | string | '/api' | 所有内置路由的路径前缀,经normalizeRoutePath规范化 |
openapiPath | string | '' | OpenAPI 文档暴露路径,例如'/openapi.json' |
bodyLimitOptions | BodyLimitOptions | 无 | 请求体大小限制,{ maxSize, onError } |
tools | ToolsInput | 无 | 注册到 handler 的工具集合 |
taskStore | InMemoryTaskStore | 无 | 后台任务存储 |
customRouteAuthConfig | Map<string, boolean> | 无 | 自定义路由的认证开关(method:path→ 是否需要认证) |
streamOptions | StreamOptions | { redact: true } | 流式响应选项,默认开启敏感数据脱敏 |
customApiRoutes | ApiRoute[] | 无 | registerApiRoute/createRoute定义的自定义路由 |
mcpOptions | MCPOptions | 无 | 应用到所有 MCP HTTP/SSE 传输的选项 |
其中两个值得展开的参数:
prefix:决定内置路由挂在哪个路径下。默认/api,于是 Agent 相关接口形如POST /api/agents/:agentId/stream。若设为'/mastra',则所有内置路由整体前移。streamOptions.redact:默认为true,表示流出前会脱敏流式块中的系统提示词、工具定义、API Key 等敏感信息;调试或内部服务需要原始请求数据时可显式设为false(StreamOptions定义见 packages/server/src/server/server-adapter/index.ts#L94)。
关于 bodyLimitOptions
BodyLimitOptions定义于 packages/server/src/server/server-adapter/index.ts#L89,结构为:
interface BodyLimitOptions { maxSize: number; // 字节数上限 onError: (error: unknown) => unknown; // 超限时的自定义错误响应 }在 Express 适配器中,该限制通过注册在路由前的专用中间件实现(见 server-adapters/express/src/index.ts#L429):优先读取Content-Length头比对;当无该头(如 chunked 编码)时,会在express.json()已解析 body 之后回退为Buffer.byteLength(JSON.stringify(req.body))重新度量。超限统一返回413 Request body too large,并允许通过onError定制响应体。route.maxBodySize可以按路由覆盖全局配置。
五、init() 后自动获得的内置路由能力
init()中最终执行的registerRoutes()会注册SERVER_ROUTES——这是@mastra/server预定义的全套 REST 路由(汇总见 packages/server/src/server/server-adapter/routes/index.ts#L165),按领域划分为:Agents、Auth、Workflows、Tools、Processors、Responses、Conversations、Memory、Scores、Observability、Logs、Vectors、A2A、Workspace、MCP、Schedules、Channels 等。
以 Agent 领域为例(packages/server/src/server/server-adapter/routes/agents.ts),核心路由包括:
GET /agents与GET /agents/:agentId:列出/查询 Agent;POST /agents/:agentId/stream:SSE 流式执行 Agent(handlers/agents.ts#L1815 定义,responseType: 'stream'、streamFormat: 'sse');POST /agents/:agentId/send-message:向活跃运行发送消息或开启带 memory 的线程运行(handlers/agents.ts#L2160)。
也就是说,一旦完成init(),你的 Express 应用就自动获得了"运行 Agent、管理线程记忆、执行工作流、查询可观测数据、接入 MCP"等完整 HTTP 能力面,无需手写任何 handler。
六、请求上下文与参数解析链路(Express 实现细节)
6.1 RequestContext 中间件
Express 适配器在createContextMiddleware()中(server-adapters/express/src/index.ts#L79)负责把 HTTP 请求"翻译"成 Mastra 的RequestContext:
- POST/PUT:从
application/json请求体中的requestContext字段提取; - GET:从 query 参数
requestContext提取,先按 JSON 解析,失败则回退 base64(JSON) 解析; - 解析结果与
mastra、registeredTools、taskStore、abortSignal一起写入res.locals,供后续 handler 使用。
值得一提的是AbortController 的挂载点:代码注释明确指出应监听res.on('close')而非req.on('close')——请求对象的close事件会在请求体被express.json()消费完毕后立即触发,并不代表客户端断开;响应对象的close才对应底层连接真正关闭。仅在响应未完成写入时controller.abort(),从而把"客户端中途取消"正确传递给 Agent/工作流执行(相关测试见 express-adapter.test.ts 的 "Abort Signal" 用例组)。
6.2 参数解析(getParams)
Express 版getParams()(server-adapters/express/src/index.ts#L208)统一收集三类入参:
- 路径参数:直接取
req.params; - 查询参数:经
normalizeQueryParams规范化——支持重复参数(?tag=a&tag=b→ 数组)、orderBy[field]=createdAt括号记法重构成 JSON 字符串,便于z.preprocess(JSON.parse)校验(实现见 packages/server/src/server/server-adapter/index.ts#L327); - 请求体:对
POST/PUT/PATCH/DELETE生效。multipart/form-data走@fastify/busboy专用解析(见 index.ts#L249):文件字段转为Buffer,普通字段若可被JSON.parse则自动对象化(例如options字段);文件大小超限抛出File size limit exceeded并交由上层转成 413。
解析完成后,urlParams、queryParams、body会分别经过路由上的pathParamSchema/queryParamSchema/bodySchema做zod 运行时校验(如z.coerce.number()类型强转),校验失败返回 400 与结构化错误信息;body 解析失败(如畸形 multipart)同样返回 400(见 index.ts#L484 起的处理分支)。
七、流式响应:SSE、数据脱敏与健壮性
Agent 生成式响应普遍是流式的,Express 适配器在stream()(server-adapters/express/src/index.ts#L147)中做了三件关键事:
按格式设置响应头:
streamFormat === 'sse'时设置Content-Type: text/event-stream、Cache-Control: no-cache、Connection: keep-alive、X-Accel-Buffering: no(防止 nginx 等反向代理缓冲);普通 stream 保持text/plain,并统一以Transfer-Encoding: chunked输出。SSE 头相关行为有专门测试覆盖(express-adapter.test.ts 的 "SSE Headers" 用例组)。敏感数据脱敏:默认调用
redactStreamChunk(value)剔除流块中的系统提示、工具定义、API Key 等;streamOptions.redact: false可关闭(index.ts#L180)。测试验证默认情况下流中不出现SECRET_SYSTEM_PROMPT、secret_tool等敏感内容。序列化容错:
serializeStreamChunk对每个块做可序列化检查——若某块因包含BigInt等JSON.stringify无法处理的值,则记录错误并跳过该块,而不是中断整个 HTTP 流。这正是对 issue #17821(不可序列化块导致流静默中断)的修复(index.ts#L182 与 express-adapter.test.ts 的 "Stream Chunk Serialization" 用例)。
此外,route.sseFlushOnConnect为true时,连接建立即先写入: connected\n\n注释帧以尽早刷出响应,便于负载均衡与客户端感知连接成功。
除流式外,sendResponse()(index.ts#L301)还支持四种响应类型:
json:res.json(result);stream:上述流式处理;datastream-response:把 AI SDK 的Response对象头、状态码与 body 原样管道到 Express 响应,中途出错会取消 reader 并记录日志;mcp-http/mcp-sse:将请求委托给 MCP 服务器的 Streamable HTTP 或 SSE 传输(支持类级mcpOptions与路由级选项合并)。
八、认证、权限与授权
8.1 路由级认证
Express 适配器不在全局挂认证中间件,而是在registerRoute()内对每个路由调用checkRouteAuth()(index.ts#L459),其核心逻辑位于基类的 checkRouteAuth:
- 依据
x-mastra-client-type: studio头在 studio auth 与 server auth 之间路由(有 studio auth 时绝不停回退到 server auth,防止伪造头越权); - 支持
route.requiresAuth === false的路由级放行; - Token 提取顺序:
Authorization: Bearer ...→?apiKey=; - 认证结果若携带刷新头(如 token 刷新后的
Set-Cookie),会先写回响应再决定是否拒绝。
8.2 权限(RBAC)与 FGA
当配置了 RBAC provider 时,checkRoutePermission()会按约定式权限推导执行检查:路由未显式声明requiresPermission时,从路径与方法推导(如GET /agents→agents:read);权限数组按逻辑或判定;未配置 RBAC 时跳过权限检查(仅认证模式)。FGA(Fine-Grained Authorization)通过checkRouteFGA执行(index.ts#L581)。
需要说明的是:RBAC/FGA 属于 EE(企业版)能力,init()中的validateEELicense()会在生产环境未配置有效许可时抛错并提示设置MASTRA_EE_LICENSE环境变量;本地开发/测试环境不受影响(index.ts#L857)。
8.3 自定义路由认证中间件
@mastra/express额外导出createAuthMiddleware(server-adapters/express/src/auth-middleware.ts),用于给你自己定义的 Express 路由接入同一套 Mastra 认证:
import { createAuthMiddleware } from '@mastra/express'; app.use( '/my-private-route', createAuthMiddleware({ mastra, requiresAuth: true }), (req, res) => res.json({ secret: true }), );它从Authorization: Bearer或?apiKey提取令牌,调用@mastra/server的coreAuthMiddleware,认证失败时按result.status与result.body直接写回响应;requiresAuth: false时直接放行。
九、自定义 API 路由与 OpenAPI / Swagger
9.1 registerApiRoute 自定义路由
通过@mastra/core/server的registerApiRoute(Hono 风格)或createRoute(schema 感知风格)声明的路由,可通过customApiRoutes构造参数传入,或配置在mastra的server.apiRoutes中。Express 适配器在registerCustomApiRoutes()(index.ts#L635)中用 Express 中间件承接:请求命中受保护自定义路由时先跑认证/权限/FGA 检查,然后经handleCustomRouteRequest桥接到自定义 handler(测试见 express-adapter.test.ts 的 "Custom API Routes" 用例组)。
createRoute风格的路由自带bodySchema等 zod 校验——测试用例验证了"{ name: 42 }发送到要求name: z.string()的路由会返回 400"这一行为。
9.2 OpenAPI 与 Swagger UI
构造时传入openapiPath: '/openapi.json',init()后即可访问 OpenAPI 文档;配合swagger-ui-express可以一键获得交互式调试界面。完整写法见下方示例。
十、HTTP 请求日志
registerHttpLoggingMiddleware()(index.ts#L742)在请求finish时输出结构化日志:方法、路径、状态码、耗时(duration: "Xms");可选includeQueryParams记录 query、includeHeaders记录请求头,并对redactHeaders列表中的头(默认包含authorization、cookie)打码为[REDACTED]。
该功能由 Mastra 服务器配置server.build.apiReqLogs驱动:true表示启用默认配置;对象形式可进一步定制level、excludePaths、includeHeaders、includeQueryParams、redactHeaders(配置解析见 packages/server/src/server/server-adapter/index.ts#L465)。excludePaths采用段感知匹配(/health排除/health与/health/deep,但保留/healthcheck)。
十一、端到端完整示例(来自仓库 examples)
仓库自带的 server-adapters/express/examples/index.ts 是一个可直接运行的完整演示,整合了本适配器的全部核心能力。其关键组装逻辑如下:
import { Mastra } from '@mastra/core'; import { Agent } from '@mastra/core/agent'; import { createTool } from '@mastra/core/tools'; import { createStep, createWorkflow } from '@mastra/core/workflows'; import { LibSQLStore } from '@mastra/libsql'; import { Memory } from '@mastra/memory'; import { Observability } from '@mastra/observability'; import cors from 'cors'; import express from 'express'; import swaggerUi from 'swagger-ui-express'; import { MastraServer } from '../src/index'; // 1) 存储与记忆 const storage = new LibSQLStore({ id: 'express-storage', url: 'file:./mastra.db' }); // 2) 组装 Mastra:agents / workflows / tools / storage / observability const mastra = new Mastra({ agents: { weatherAgent, planningAgent /* ... */ }, workflows: { weatherWorkflow, travelAgentWorkflow }, tools: { weatherTool }, storage, observability: new Observability({ default: { enabled: true } }), }); // 3) 创建 Express 应用并挂载适配器 const app = express(); app.use(express.json()); app.use(cors()); const expressServerAdapter = new MastraServer({ mastra, app, openapiPath: '/openapi.json' }); await expressServerAdapter.init(); // 4) 追加 Swagger UI,指向自动生成的 OpenAPI 文档 app.use('/swagger-ui', swaggerUi.serve, swaggerUi.setup(undefined, { swaggerUrl: '/openapi.json' })); // 5) 启动 app.listen(3001, () => { console.info('Server is running on port 3001'); console.info('OpenAPI spec: http://localhost:3001/openapi.json'); console.info('Swagger UI: http://localhost:3001/swagger-ui'); });示例中还演示了带记忆的天气 Agent(Memory+lastMessages: 10)、带 suspend/resume 的人工介入工作流(humanInputStep)、以及基于createScorer的 Agent 评估打分器,展示了一个生产级 Agent 服务可以叠加的完整能力栈。
十二、测试与质量保障
@mastra/express的测试集中在 server-adapters/express/src/tests目录,是理解适配器行为边界的绝佳参考:
- express-adapter.test.ts:复用
@internal/server-adapter-test-utils的统一适配器测试套件,覆盖路由注册、SSE 响应头、流数据脱敏、不可序列化块容错、AbortSignal 生命周期、multipart 上传、body 大小限制、自定义路由认证等; - mcp-routes.test.ts:MCP 注册表路由的集成测试;
- auth-middleware.test.ts:
createAuthMiddleware行为测试; - rbac-permissions.test.ts:RBAC 权限判定测试。
测试采用真实 HTTP 服务器(随机端口 +fetch)执行请求断言,保证适配器行为与线上一致。
十三、常见问题与注意事项
- Express 版本:适配器面向 Express 5(peer 依赖
express ^5.1.0、@types/express ^5.0.5),使用 Express 4 时需先升级; - Node 版本:要求 Node
>= 22.13.0; - 不要忘记
await server.init():所有内置路由、认证与日志中间件都在这一步注册,跳过会导致路由 404; - 默认路由前缀为
/api:通过prefix可整体调整;自定义路由路径若与内置前缀冲突,init()会校验并抛出 "must not start with /api" 之类的错误(有专门测试覆盖); - SSE 流经代理:部署到 nginx 等反向代理后,务必保留
X-Accel-Buffering: no语义,避免代理缓冲导致流式延迟; - 敏感信息脱敏默认开启:调试内部服务时如需完整请求数据,可显式设置
streamOptions: { redact: false },但生产环境不建议关闭。
十四、小结
@mastra/express以极小的接入成本把 Mastra 的整套 AI 服务能力注入 Express 应用:一次init()自动注册涵盖 Agent、Workflow、Memory、MCP、可观测性等领域的 REST 路由,并提供 SSE 流式输出、敏感数据脱敏、zod 运行时校验、multipart 上传、认证/RBAC/FGA、HTTP 日志与 OpenAPI 文档。其 Express 专属实现(res.on('close')驱动的中断传播、@fastify/busboy表单解析、SSE 反代理缓冲头等)充分照顾了 Express 生态的实际运行细节。若你需要将 Mastra 托管到 Fastify、Hono、NestJS 等其他框架,仓库中的 server-adapters 目录提供了同等能力的兄弟适配器可供参考。
【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考