Mastra Cursor SDK Agent 集成指南:用@mastra/cursor把 Cursor 编码 Agent 接入 Mastra
【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra
@mastra/cursor是 Mastra 为 Cursor Agent SDK 提供的官方适配包(位于仓库agent-sdks/cursor/),它以CursorSDKAgent这一 Mastra Agent 包装器为核心,让开发者既保留 Cursor 编码 Agent 运行时与仓库工具能力,又能通过 Mastra 统一的generate()/stream()接口驱动它。读完本文,你将掌握该包的安装方式、三种 Agent 构造形态、完整的调用 API(含恢复执行与流式输出)、可观测性数据的落地方式,以及如何按仓库约定进行构建与测试。
一、这个包解决什么问题
Mastra 是一个面向 AI 应用与 Agent 的 TypeScript 框架,其Agent基类提供了generate()、stream()等统一能力。Cursor 则提供了自己的 TypeScript Agent SDK(@cursor/sdk),内置了适合编码场景的 Agent 运行时与仓库(repository)工具。
两者各有所长,@mastra/cursor充当桥梁:
- 对外:以 Mastra 兼容的方式暴露
CursorSDKAgent(继承自@mastra/core的Agent基类),可作为普通 Agent 注册进Mastra实例,供mastra.getAgent()、Playground、服务端路由等生态复用; - 对内:直接驱动
@cursor/sdk的Agent,保留其编码 Agent 运行时与仓库工具能力; - 同步把 Cursor 运行产生的用量(usage)与遥测(telemetry)数据转成 Mastra 标准格式,接入统一的可观测性体系。
关于该包的定位,agent-sdks/cursor/README.md 写得很明确:当你希望使用 Cursor 的编码 Agent 运行时与仓库工具,同时让 Agent 通过 Mastra 兼容的generate()与stream()方法暴露时,就使用@mastra/cursor。
二、安装与环境准备
npm install @mastra/cursor npm install @cursor/sdk@cursor/sdk是 peerDependency,必须由使用方显式安装。从 agent-sdks/cursor/package.json 可以看到该包的关键约束:
| 项目 | 值 | 说明 |
|---|---|---|
| 当前版本 | 0.3.1 | 见 agent-sdks/cursor/CHANGELOG.md |
| Node.js | >=22.13.0 | 运行时下限要求 |
| 模块格式 | ESM + CJS 双格式 | dist/index.js与dist/index.cjs分别供 import / require |
| peerDependencies | @cursor/sdk ^1.0.13、@mastra/core >=1.34.0-0 <2.0.0-0 | 核心依赖需由应用自行提供 |
| 许可 | Apache-2.0 | — |
使用前需要设置CURSOR_API_KEY环境变量(也可以在sdkOptions.apiKey中显式传入)。若未在配置中提供apiKey,包装器会自动回退读取process.env.CURSOR_API_KEY——这一回退逻辑在 agent-sdks/cursor/src/index.ts 的toCursorCreateOptions()中实现,并有对应测试用例覆盖(见下文第五节)。
三、快速上手:最小可运行示例
以下示例直接取自 agent-sdks/cursor/README.md,它演示了创建一个 Cursor SDK Agent、注册进Mastra实例的完整流程:
import { CursorSDKAgent } from '@mastra/cursor'; import { Mastra } from '@mastra/core/mastra'; export const cursorAgent = new CursorSDKAgent({ id: 'cursor-sdk-agent', name: 'Cursor SDK Agent', description: 'Use Cursor Agent SDK through Mastra.', sdkOptions: { apiKey: process.env.CURSOR_API_KEY, model: { id: process.env.CURSOR_MODEL_ID! }, local: { cwd: process.cwd(), }, }, }); export const mastra = new Mastra({ agents: { cursorAgent }, });要点解读:
id是包装器注册到 Mastra 时使用的 Agent 标识;name默认为id;description会在 Mastra 列出或选择 Agent 时展示(见CursorSDKAgentBaseOptions的类型注释);sdkOptions原样透传给@cursor/sdk的Agent.create(),model指定底层模型,local.cwd指定 Cursor 编码 Agent 操作的本地工作目录;- 包装器内部会创建一个 noop 模型(
createNoopModel)占位,provider为@cursor/sdk,模型 ID 取你配置的模型 ID;当未配置模型时回退为常量cursor-agent-sdk。
四、三种 Agent 构造形态
从源码的类型定义(agent-sdks/cursor/src/index.ts 中的CursorAgentOptions)看,CursorSDKAgent支持三种互斥的构造方式,按agent与sdkOptions的组合区分:
1. 传入已创建好的 Cursor SDK Agent(agent: SDKAgent | Promise<SDKAgent>)
适合你自己管理 SDK Agent 生命周期、复用一个已有实例的场景:
const sdkAgent = await createCursorSdkAgent(); // 由你自行创建 const agent = new CursorSDKAgent({ id: 'cursor-sdk-agent', description: 'Use Cursor Agent SDK through Mastra.', agent: sdkAgent, // 注意:此时不能再传 sdkOptions });2. 传入 Agent 工厂函数(agent: CursorAgentFactory)
包装器会用合并后的sdkOptions(含默认注入的process.env.CURSOR_API_KEY)调用工厂,工厂可在此之上追加自己的配置:
const agent = new CursorSDKAgent({ id: 'cursor-sdk-agent', description: 'Cursor', agent: options => CursorSdk.create({ ...options, model: { id: 'my-model' } }), sdkOptions: { mcpServers: { filesystem: { command: 'node', args: ['server.js'] }, }, }, });3. 仅传sdkOptions(agent省略)
包装器在首次调用时内部执行CursorAgent.create(sdkOptions)惰性创建,创建失败会自动重置,下一次调用会重试(对应测试"retries inline Cursor SDK agent creation after a failure"验证了该行为):
const agent = new CursorSDKAgent({ id: 'cursor-agent', description: 'Cursor', sdkOptions: { model: { id: 'my-model' }, local: { cwd: process.cwd() }, }, });无论哪种形态,解析出的 SDK Agent 都会被缓存(#createdAgent),避免重复创建。
五、核心调用 API:generate / stream / resume
CursorSDKAgent直接继承@mastra/core的Agent,因此提供与标准 Mastra Agent 一致的调用面,同时针对 Cursor 做了底层适配:
generate():一次性获取完整结果
const result = await cursorAgent.generate('为 /repo 下的代码写一个单元测试', { runId: 'my-run-001', // 可选,用于链路追踪 maxSteps: 5, // 可选,最大推理步骤 instructions: '尽量保持原有代码风格', // 可选,追加指令 requestContext, // 可选,透传请求上下文 onFinish, // 可选,完成回调 }); // result.text 为最终文本 // result.usage 为标准 LanguageModelUsage(含 inputTokens / outputTokens / totalTokens 等) // result.providerMetadata.cursor 内含 Cursor 特有的运行信息实现上(generateWithAgent),generate()会把消息列表经promptToText转成纯文本 prompt,通过sdkAgent.send()发起运行,再run.wait()等待结果;若运行以error或cancelled状态结束则抛出异常,最终包装成 Mastra 的FullOutput返回。
stream():流式输出
const stream = await cursorAgent.stream('逐步重构这个函数', { runId: 'stream-001' }); for await (const chunk of stream.fullStream) { // chunk.type 依次为 start → step-start → response-metadata → text-start → text-delta → … → text-end → step-finish → finish } const text = await stream.text; // 聚合后的完整文本 const usage = await stream.usage; // 汇总用量流式实现(runCursorAsMastraStream)优先使用 Cursor 的run.stream()逐条产出增量文本(text-delta);当底层运行不支持流式时,回退为run.wait()一次性取回结果再以单个text-delta发出。最终通过wrapStream与 agent / model span 绑定,保证遥测完整。
resumeGenerate() / resumeStream():恢复已存在的运行
0.2.0 版本起(见 agent-sdks/cursor/CHANGELOG.md),SDK Agent 支持通过 Mastra 的resumeGenerate/resumeStream实现 provider 原生恢复。CursorSDKAgentResumeData包含三个字段:
| 字段 | 说明 |
|---|---|
message | 必填,继续执行时发送的消息 |
agentId | 可选,指定要恢复的 Cursor SDK Agent ID;省略时复用包装的 SDK Agent |
sdkOptions | 可选,仅在提供agentId时使用,用于恢复时覆盖部分创建参数 |
// 复用当前包装的 SDK Agent 继续执行 const result = await cursorAgent.resumeGenerate({ message: '继续完成剩余的修改' }); // 按 agentId 恢复另一个 Cursor SDK Agent 实例 const stream = await cursorAgent.resumeStream({ message: '继续完成剩余的修改', agentId: 'agent-abc', sdkOptions: { model: { id: 'other-model' } }, });resumeData缺少message或agentId类型非法时,validateCursorResumeData会抛出明确错误。
限制:不支持结构化输出
Cursor TypeScript SDK 未暴露 schema 约束的输出 API,因此当调用传入structuredOutput: { schema }时,CursorSDKAgent会在发起调用前直接抛出错误:
CursorSDKAgent does not support structuredOutput because the Cursor TypeScript SDK does not expose a schema-constrained output API.对应测试"does not force structured output when the Cursor SDK has no native schema output API"验证了该行为(同时确认send不会被调用)。作为对比,Claude 与 OpenAI 的 SDK Agent 支持 provider 原生结构化输出,这是各 SDK 能力差异所致,并非包装器缺陷。
六、可观测性:用量汇总与遥测 Span
@mastra/cursor并不仅仅是把调用转发出去,它还把 Cursor 侧的数据规范化为 Mastra 标准格式,全部实现在 agent-sdks/cursor/src/utils.ts 与 agent-sdks/cursor/src/index.ts 中。
1. Token 用量聚合
Cursor SDK 通过InteractionUpdate推送交互事件,其中turn-ended事件携带当轮的 token 用量。包装器实现了一个CursorUsageCollector:在send()的onDelta回调中持续记录inputTokens、outputTokens、cacheReadTokens、cacheWriteTokens,并在运行结束时把多轮用量求和,最终转成 Mastra 的LanguageModelUsage(cachedInputTokens对应 cacheRead,cacheCreationInputTokens对应 cacheWrite)。测试"sums usage across Cursor turn-ended updates"验证了跨多轮事件的累加正确性。
2. 可观测性 Span 树
通过createSDKAgentTelemetry(见 agent-sdks/cursor/src/utils.ts),每次运行都会建立 span 树:
- AGENT_RUN span:以
agent run: '<agentId>'命名,属性携带 prompt、instructions、maxSteps,元数据标注sdkAgent: true、sdkProvider: '@cursor/sdk'、sdkMethod: 'generate' | 'stream'; - MODEL_GENERATION span:以
llm: '<modelId>'命名,记录模型、provider、是否流式,结束时写入 finishReason、responseId、responseModel 与用量; - TOOL_CALL / MCP_TOOL_CALL span:监听 Cursor 的
tool-call-started、partial-tool-call、tool-call-completed事件。MCP 工具会以mcp_tool: '<toolName>' on '<serverName>'命名并单独成 span,非 MCP 工具以tool: '<toolName>'命名;工具调用失败(isError)时对应 span 会被标记为 error。
observability.test.ts 用 mock span 验证了完整链路:generate 后 model span 记录输出文本、finishReason、responseId、usage;MCP 工具调用会创建MCP_TOOL_CALLspan 并在成功时以输出内容结束。
3. Provider 元数据
每次运行的providerMetadata.cursor会携带 Cursor 特有信息,测试用例中的期望结构如下:
{ cursor: { agentId: 'cursor-sdk-agent', // 底层 SDK Agent 的 ID runId: 'generate-run', // Cursor 运行 ID requestedModel: '__GATEWAY_OPENAI_MODEL__', durationMs: 25, // 运行耗时(毫秒) mcpServerNames: ['filesystem'], // 已配置的 MCP 服务器名 usage: { /* 聚合后的 token 用量 */ }, status: 'finished', }, }这些数据会随 span 一起导出,便于在追踪系统中还原 Cursor 侧的运行细节。
七、构建、测试与开发约定
该包的开发工作流记录在 agent-sdks/cursor/AGENTS.md,核心约定如下。
1. 从仓库根目录构建
pnpm --filter ./agent-sdks/cursor build:libbuild:lib对应package.json中的脚本tsdown --silent --config tsdown.config.ts。根据 tsdown.config.ts,构建会同时产出 ESM 与 CJS 两种格式,声明@cursor/sdk永不打包(neverBundle),并在构建成功后用@internal/types-builder生成类型声明(dts: false表示类型由生成器单独产出)。
2. 从仓库根目录测试
pnpm --filter ./agent-sdks/cursor testtest脚本为vitest run --passWithNoTests,vitest.config.ts 将测试范围限定在src/**/*.test.ts。测试覆盖了 index.test.ts(Agent 契约兼容性、三种构造形态、环境变量回退、工厂组合、失败重试、generate/stream/resume 行为、结构化输出拒绝)与 observability.test.ts(span 记录与 MCP 工具遥测)。
3. 架构约定
AGENTS.md 中特别强调了一条封装原则:
Keep vendor-specific SDK-agent helpers private to this package unless a helper is clearly useful as stable core API.
即:与具体厂商 SDK 相关的辅助逻辑(如本包的 usage 收集器、telemetry 工厂、消息转文本等)应保持在该包内部私有,除非某个辅助函数明确适合作为稳定的核心 API,否则不要外泄到@mastra/core。这也是该包将promptToText、createSDKAgentTelemetry、createMastraOutput等大量辅助函数集中在utils.ts的原因——保持核心包与厂商适配逻辑的边界清晰。
另外需要注意:agent字段未传、仅靠sdkOptions时,Agent 是惰性创建的;而一旦某个包装器实例被多个请求共享,内部缓存的 SDK Agent 会复用同一实例,这在多租户或高并发场景下需要自行评估生命周期管理策略。
八、小结
@mastra/cursor以极小的封装面完成了两件关键事情:把 Cursor 编码 Agent 的运行时与仓库工具完整保留,同时让 Mastra 生态(generate/stream/resume、统一用量、span 遥测、Playground 与路由)无缝接管调用与观测。无论你是想用 Mastra 编排一个具备真实仓库操作能力的编码 Agent,还是想把 Cursor 的编码 Agent 纳入统一的观测体系,这个包都是最直接的切入点。动手前,记得先设置好CURSOR_API_KEY,并确认 Node.js 版本不低于 22.13.0。
【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考