@mastra/mcp-docs-server 1.2.8-alpha.3 → 1.2.8-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.docs/docs/agents/structured-output.md +12 -7
- package/.docs/docs/evals/multi-turn.md +178 -0
- package/.docs/docs/evals/overview.md +1 -0
- package/.docs/docs/long-running-agents/durable-agents.md +2 -1
- package/.docs/docs/mcp/overview.md +1 -1
- package/.docs/docs/server/request-context.md +2 -0
- package/.docs/models/gateways/openrouter.md +1 -2
- package/.docs/models/index.md +1 -1
- package/.docs/models/providers/google.md +2 -2
- package/.docs/models/providers/kilo.md +1 -1
- package/.docs/models/providers/kimi-for-coding.md +8 -7
- package/.docs/models/providers/llmgateway.md +2 -8
- package/.docs/models/providers/ollama-cloud.md +25 -42
- package/.docs/models/providers/orcarouter.md +1 -1
- package/.docs/models/providers/privatemode-ai.md +10 -10
- package/.docs/reference/acp/acp-agent.md +2 -0
- package/.docs/reference/acp/create-acp-tool.md +28 -0
- package/.docs/reference/agent-controller/session.md +2 -0
- package/.docs/reference/agents/durable-agent.md +23 -0
- package/.docs/reference/agents/generate.md +1 -1
- package/.docs/reference/evals/create-scorer.md +1 -1
- package/.docs/reference/evals/run-evals.md +94 -2
- package/.docs/reference/streaming/agents/stream.md +1 -1
- package/.docs/reference/tools/mcp-client.md +96 -0
- package/CHANGELOG.md +15 -0
- package/package.json +6 -6
|
@@ -197,9 +197,9 @@ If your tools aren't being called when structured output is enabled, or you rece
|
|
|
197
197
|
|
|
198
198
|
When your model doesn't support tools and structured output together, you have three options:
|
|
199
199
|
|
|
200
|
-
1. **Use `jsonPromptInjection
|
|
201
|
-
2. **Use a separate structuring model
|
|
202
|
-
3. **Use `prepareStep
|
|
200
|
+
1. **Use `jsonPromptInjection`**: Set it to `'auto'` to select native structured output when supported and inline prompt injection otherwise, or choose an explicit injection mode
|
|
201
|
+
2. **Use a separate structuring model**: Pass a `model` to `structuredOutput` to use a second LLM for structuring
|
|
202
|
+
3. **Use `prepareStep`**: Handle tools and structured output in separate steps
|
|
203
203
|
|
|
204
204
|
Each approach is detailed in the sections below.
|
|
205
205
|
|
|
@@ -209,9 +209,7 @@ Structured output support varies across LLMs due to differences in their APIs. T
|
|
|
209
209
|
|
|
210
210
|
### `jsonPromptInjection`
|
|
211
211
|
|
|
212
|
-
By default, Mastra passes the schema to the model provider using the `response_format` API parameter.
|
|
213
|
-
|
|
214
|
-
If your model provider doesn't support `response_format`, you'll get an error from the API. When this happens, set `jsonPromptInjection: true`. This adds the schema to the system prompt instead, instructing the model to output JSON. This is less reliable than the API parameter approach.
|
|
212
|
+
By default, Mastra passes the schema to the model provider using the `response_format` API parameter. Set `jsonPromptInjection: 'auto'` to let Mastra choose the mode from its model capability data. Mastra uses native structured output for supported models and inline prompt injection for unsupported models or models without capability data.
|
|
215
213
|
|
|
216
214
|
```typescript
|
|
217
215
|
import { z } from 'zod'
|
|
@@ -224,13 +222,20 @@ const response = await testAgent.generate('Help me plan my day.', {
|
|
|
224
222
|
activities: z.array(z.string()),
|
|
225
223
|
}),
|
|
226
224
|
),
|
|
227
|
-
jsonPromptInjection:
|
|
225
|
+
jsonPromptInjection: 'auto',
|
|
228
226
|
},
|
|
229
227
|
})
|
|
230
228
|
|
|
231
229
|
console.log(response.object)
|
|
232
230
|
```
|
|
233
231
|
|
|
232
|
+
Use an explicit mode when you need to override the capability-based choice:
|
|
233
|
+
|
|
234
|
+
- `false` or omitted: Use the provider's native structured output.
|
|
235
|
+
- `'inline'`: Add the schema instructions to the latest user message.
|
|
236
|
+
- `true` or `'system'`: Add the schema instructions to the system message.
|
|
237
|
+
- `'auto'`: Use native structured output when the model supports it. Otherwise, use inline prompt injection.
|
|
238
|
+
|
|
234
239
|
> **Gemini 2.5 with tools:** Gemini 2.5 models don't support combining `response_format` (structured output) with function calling (tools) in the same API call. If your agent has tools and you're using `structuredOutput` with a Gemini 2.5 model, you must set `jsonPromptInjection: true` to avoid the error `Function calling with a response mime type: 'application/json' is unsupported`.
|
|
235
240
|
>
|
|
236
241
|
> ```typescript
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
> Discover all available pages from the documentation index: https://mastra.ai/llms.txt
|
|
2
|
+
|
|
3
|
+
# Multi-turn evals
|
|
4
|
+
|
|
5
|
+
Multi-turn evals test agent behavior across a conversation. Instead of a single `input`, you provide an `inputs` array. Each entry is sent sequentially to the agent on the same thread, and scorers see the accumulated output from all turns.
|
|
6
|
+
|
|
7
|
+
## When to use multi-turn evals
|
|
8
|
+
|
|
9
|
+
- The agent uses memory and must recall context from earlier turns
|
|
10
|
+
- The agent handles follow-up questions that depend on prior responses
|
|
11
|
+
- You need to verify tool-call sequences across a conversation
|
|
12
|
+
- The agent runs a multi-step workflow (search, confirm, execute)
|
|
13
|
+
|
|
14
|
+
## Quickstart
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { runEvals } from '@mastra/core/evals'
|
|
18
|
+
import { checks } from '@mastra/evals/checks'
|
|
19
|
+
import { weatherAgent } from '../agents'
|
|
20
|
+
|
|
21
|
+
const result = await runEvals({
|
|
22
|
+
data: [
|
|
23
|
+
{
|
|
24
|
+
inputs: [
|
|
25
|
+
'What is the weather in Brooklyn?',
|
|
26
|
+
'What about tomorrow?',
|
|
27
|
+
'Compare the two forecasts.',
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
target: weatherAgent,
|
|
32
|
+
scorers: [checks.calledTool('get_weather', { times: 2 }), checks.includes('Brooklyn')],
|
|
33
|
+
})
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Each turn runs `agent.generate()` with the same thread ID, so the agent sees the full conversation history. Scorers receive the accumulated output messages from all turns.
|
|
37
|
+
|
|
38
|
+
## Memory is required for cross-turn recall
|
|
39
|
+
|
|
40
|
+
Multi-turn recall depends on the agent having a **memory store configured**. The shared thread ID is what lets each turn see the earlier ones — but a thread only persists history when the agent has memory. If the agent has no memory configured, the turns still run sequentially and their outputs still accumulate for scoring, but the agent will not recall earlier turns (each input runs in isolation). `runEvals` logs a warning when you use `inputs` on an agent without memory.
|
|
41
|
+
|
|
42
|
+
`runEvals` manages the conversation identity for you: it generates the shared `threadId` and injects a `resourceId` (Mastra memory scopes messages by resource + thread, so both are required for recall to work). By default the resource is derived from the generated thread so each conversation is isolated. To pin a specific resource — for example to reuse an existing user's memory — pass `targetOptions.memory.resource`; `runEvals` still owns the thread, so you don't provide one:
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
await runEvals({
|
|
46
|
+
target: weatherAgent,
|
|
47
|
+
data: [{ inputs: ['What is the weather in Brooklyn?', 'What about tomorrow?'] }],
|
|
48
|
+
scorers: [checks.similarity('weather forecast')],
|
|
49
|
+
targetOptions: { memory: { resource: 'user-42' } },
|
|
50
|
+
})
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
See [Memory](https://mastra.ai/docs/memory/overview) for how to configure a memory store.
|
|
54
|
+
|
|
55
|
+
## How it works
|
|
56
|
+
|
|
57
|
+
When a data item has an `inputs` array, `runEvals`:
|
|
58
|
+
|
|
59
|
+
1. Creates a fresh thread (unique `threadId`) and resource for the conversation (a caller-provided `targetOptions.memory.resource` is preserved)
|
|
60
|
+
2. Sends each input sequentially via `agent.generate()` on that thread
|
|
61
|
+
3. Accumulates all output messages across turns
|
|
62
|
+
4. Passes the full accumulated output to scorers for evaluation
|
|
63
|
+
|
|
64
|
+
Scorers see the complete conversation output, not just the last turn.
|
|
65
|
+
|
|
66
|
+
## Scoring semantics
|
|
67
|
+
|
|
68
|
+
Two details matter when writing scorers for multi-turn items:
|
|
69
|
+
|
|
70
|
+
- **`run.output` is the accumulated output from every turn.** Output-based scorers — `checks.includes`, `checks.calledTool`, `checks.similarity`, and similar — evaluate the whole conversation. For example, `checks.calledTool('get_weather', { times: 2 })` counts calls across all turns.
|
|
71
|
+
- **`run.input` is only the first turn's input.** Scorers that compare input against output (faithfulness, answer relevancy, and other input-relative LLM scorers) only see the first user message, not the full conversation. Prefer output-based checks for multi-turn, or build scorers that read the accumulated `run.output` directly.
|
|
72
|
+
|
|
73
|
+
## Per-turn assertions with `turns`
|
|
74
|
+
|
|
75
|
+
The `inputs` form scores the **accumulated** output holistically — a single score over every turn's output. That can hide per-turn failures: an output-based check like `checks.includes('Brooklyn')` passes if _any_ turn mentions Brooklyn, even when the follow-up turn is broken.
|
|
76
|
+
|
|
77
|
+
When you need to assert that a **specific turn** behaved correctly, use `turns` instead. Each turn is an object with its own `input` and optional `gates`/`scorers` that evaluate **only that turn's** input and output:
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import { runEvals } from '@mastra/core/evals'
|
|
81
|
+
import { checks } from '@mastra/evals/checks'
|
|
82
|
+
import { weatherAgent } from '../agents'
|
|
83
|
+
|
|
84
|
+
const result = await runEvals({
|
|
85
|
+
data: [
|
|
86
|
+
{
|
|
87
|
+
turns: [
|
|
88
|
+
{
|
|
89
|
+
input: 'What is the weather in Brooklyn?',
|
|
90
|
+
gates: [checks.calledTool('get_weather')],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
// The follow-up must call the tool again — it can't be satisfied
|
|
94
|
+
// by the first turn's tool call.
|
|
95
|
+
input: 'What about tomorrow?',
|
|
96
|
+
gates: [checks.calledTool('get_weather')],
|
|
97
|
+
scorers: [{ scorer: checks.similarity('tomorrow forecast'), threshold: 0.5 }],
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
target: weatherAgent,
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
result.verdict // 'passed' | 'scored' | 'failed'
|
|
106
|
+
result.turnResults // per-turn gate/threshold/scorer outcomes
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Semantics:
|
|
110
|
+
|
|
111
|
+
- A per-turn gate or scorer sees **only that turn's** `run.input` and `run.output` — never the accumulated conversation. This fixes both blind spots of `inputs`: the wrong turn can't satisfy a check, and `run.input` is correct for each turn.
|
|
112
|
+
- Per-turn outcomes fold into the overall [verdict](https://mastra.ai/docs/evals/gates-and-verdicts): a failing turn gate makes the verdict `failed`; a missed turn threshold (with gates passing) makes it `scored`.
|
|
113
|
+
- `result.turnResults[i]` reports each turn's `gateResults`, `thresholdResults`, and `scores`, so a failure points at the exact turn. Across multiple conversations, turn results are averaged by turn index.
|
|
114
|
+
- A turn with no `gates`/`scorers` just advances the conversation.
|
|
115
|
+
- Top-level `scorers`/`gates` still run holistically over the accumulated output, so you can combine "this turn must call the tool" with "the overall answer mentions Brooklyn."
|
|
116
|
+
- When the agent has storage configured, each per-turn scorer/gate result is persisted like top-level scores, so per-turn outcomes appear in your scores store.
|
|
117
|
+
|
|
118
|
+
Use `inputs` when a single holistic score over the whole conversation is enough; use `turns` when correctness depends on individual turns. `turns` cannot be combined with `input` or `inputs` in the same data item.
|
|
119
|
+
|
|
120
|
+
## Combining with gates and thresholds
|
|
121
|
+
|
|
122
|
+
Multi-turn data items work with [gates and verdicts](https://mastra.ai/docs/evals/gates-and-verdicts). Use output-based scorers so gating reflects the full conversation:
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
import { runEvals } from '@mastra/core/evals'
|
|
126
|
+
import { checks } from '@mastra/evals/checks'
|
|
127
|
+
|
|
128
|
+
const result = await runEvals({
|
|
129
|
+
data: [
|
|
130
|
+
{
|
|
131
|
+
inputs: ['My favorite city is Brooklyn.', 'What is the weather in my favorite city?'],
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
target: weatherAgent,
|
|
135
|
+
gates: [checks.calledTool('get_weather')],
|
|
136
|
+
scorers: [{ scorer: checks.similarity('Brooklyn weather forecast'), threshold: 0.5 }],
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
result.verdict // 'passed' | 'scored' | 'failed'
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Mixing single-turn and multi-turn
|
|
143
|
+
|
|
144
|
+
A single `runEvals` call can include both single-turn and multi-turn data items:
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
const result = await runEvals({
|
|
148
|
+
data: [
|
|
149
|
+
{ input: 'What is the weather in Brooklyn?' },
|
|
150
|
+
{
|
|
151
|
+
inputs: ['My favorite city is Brooklyn.', 'What is the weather in my favorite city?'],
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
target: weatherAgent,
|
|
155
|
+
scorers: [checks.includes('Brooklyn')],
|
|
156
|
+
})
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Single-turn items use `input` as usual. Multi-turn items use `inputs` — `input` can be omitted entirely.
|
|
160
|
+
|
|
161
|
+
## Validation
|
|
162
|
+
|
|
163
|
+
`runEvals` throws a `MastraError` if `inputs` is present but empty:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
// Throws: 'inputs' must be a non-empty array
|
|
167
|
+
await runEvals({
|
|
168
|
+
data: [{ inputs: [] }],
|
|
169
|
+
target: myAgent,
|
|
170
|
+
scorers: [myScorer],
|
|
171
|
+
})
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Related
|
|
175
|
+
|
|
176
|
+
- [`runEvals()` reference](https://mastra.ai/reference/evals/run-evals): Full API for `runEvals` parameters and returns
|
|
177
|
+
- [Gates and verdicts](https://mastra.ai/docs/evals/gates-and-verdicts): Enforce hard requirements and quality thresholds
|
|
178
|
+
- [Quick Checks](https://mastra.ai/docs/evals/quick-checks): Zero-LLM composable micro-scorers
|
|
@@ -142,6 +142,7 @@ Once registered, you can score traces interactively within Studio under the **Ob
|
|
|
142
142
|
|
|
143
143
|
- Use [Quick Checks](https://mastra.ai/docs/evals/quick-checks) for fast, deterministic assertions on text and tool usage
|
|
144
144
|
- Add [gates and verdicts](https://mastra.ai/docs/evals/gates-and-verdicts) to enforce hard requirements and quality thresholds
|
|
145
|
+
- Test [multi-turn conversations](https://mastra.ai/docs/evals/multi-turn) where behavior emerges across sequential turns
|
|
145
146
|
- Learn how to create your own scorers in the [Creating Custom Scorers](https://mastra.ai/docs/evals/custom-scorers) guide
|
|
146
147
|
- Explore built-in scorers in the [Built-in Scorers](https://mastra.ai/docs/evals/built-in-scorers) section
|
|
147
148
|
- Test scorers with [Studio](https://mastra.ai/docs/studio/overview)
|
|
@@ -159,8 +159,9 @@ cleanup()
|
|
|
159
159
|
```typescript
|
|
160
160
|
import { createDurableAgent } from '@mastra/core/agent/durable'
|
|
161
161
|
import { RedisServerCache } from '@mastra/redis'
|
|
162
|
+
import Redis from 'ioredis'
|
|
162
163
|
|
|
163
|
-
const cache = new RedisServerCache({
|
|
164
|
+
const cache = new RedisServerCache({ client: new Redis('redis://localhost:6379') })
|
|
164
165
|
|
|
165
166
|
export const durableAgent = createDurableAgent({
|
|
166
167
|
agent,
|
|
@@ -64,7 +64,7 @@ export const testMcpClient = new MCPClient({
|
|
|
64
64
|
|
|
65
65
|
Visit [MCPClient](https://mastra.ai/reference/tools/mcp-client) for a full list of configuration options.
|
|
66
66
|
|
|
67
|
-
> **Authentication:** For connecting to OAuth-protected MCP servers
|
|
67
|
+
> **Authentication:** For connecting to OAuth-protected MCP servers — including completing the browser-based authorization flow with `authenticate()` — see the [OAuth Authentication](https://mastra.ai/reference/tools/mcp-client) section.
|
|
68
68
|
|
|
69
69
|
## Using `MCPClient` with an agent
|
|
70
70
|
|
|
@@ -247,6 +247,8 @@ auth: {
|
|
|
247
247
|
}
|
|
248
248
|
```
|
|
249
249
|
|
|
250
|
+
When the resource ID is derived this way, clients can omit `memory.resource` from agent generate and stream request bodies — the server-derived value is used instead (and always takes precedence over any client-provided value). If a request uses memory and neither the body nor the request context provides a resource ID, the server responds with a 400 error.
|
|
251
|
+
|
|
250
252
|
You can also set these keys manually in middleware:
|
|
251
253
|
|
|
252
254
|
```typescript
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# OpenRouter
|
|
4
4
|
|
|
5
|
-
OpenRouter aggregates models from multiple providers with enhanced features like rate limiting and failover. Access
|
|
5
|
+
OpenRouter aggregates models from multiple providers with enhanced features like rate limiting and failover. Access 341 models through Mastra's model router.
|
|
6
6
|
|
|
7
7
|
Learn more in the [OpenRouter documentation](https://openrouter.ai/models).
|
|
8
8
|
|
|
@@ -73,7 +73,6 @@ ANTHROPIC_API_KEY=ant-...
|
|
|
73
73
|
| `anthropic/claude-sonnet-4.5` |
|
|
74
74
|
| `anthropic/claude-sonnet-4.6` |
|
|
75
75
|
| `anthropic/claude-sonnet-5` |
|
|
76
|
-
| `arcee-ai/coder-large` |
|
|
77
76
|
| `arcee-ai/trinity-large-thinking` |
|
|
78
77
|
| `arcee-ai/virtuoso-large` |
|
|
79
78
|
| `baidu/ernie-4.5-vl-424b-a47b` |
|
package/.docs/models/index.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Model Providers
|
|
4
4
|
|
|
5
|
-
Mastra provides a unified interface for working with LLMs across multiple providers, giving you access to
|
|
5
|
+
Mastra provides a unified interface for working with LLMs across multiple providers, giving you access to 4844 models from 155 providers through a single API.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
@@ -49,8 +49,8 @@ for await (const chunk of stream) {
|
|
|
49
49
|
| `google/gemini-3.1-pro-preview-customtools` | 1.0M | | | | | | $2 | $12 |
|
|
50
50
|
| `google/gemini-3.5-flash` | 1.0M | | | | | | $2 | $9 |
|
|
51
51
|
| `google/gemini-embedding-001` | 2K | | | | | | $0.15 | — |
|
|
52
|
-
| `google/gemini-flash-latest` | 1.0M | | | | | | $
|
|
53
|
-
| `google/gemini-flash-lite-latest` | 1.0M | | | | | | $0.
|
|
52
|
+
| `google/gemini-flash-latest` | 1.0M | | | | | | $2 | $9 |
|
|
53
|
+
| `google/gemini-flash-lite-latest` | 1.0M | | | | | | $0.25 | $2 |
|
|
54
54
|
| `google/gemini-omni-flash-preview` | 131K | | | | | | $2 | $18 |
|
|
55
55
|
| `google/gemma-4-26b-a4b-it` | 262K | | | | | | — | — |
|
|
56
56
|
| `google/gemma-4-31b-it` | 262K | | | | | | — | — |
|
|
@@ -39,7 +39,7 @@ for await (const chunk of stream) {
|
|
|
39
39
|
| `kilo/~anthropic/claude-haiku-latest` | 200K | | | | | | $1 | $5 |
|
|
40
40
|
| `kilo/~anthropic/claude-opus-latest` | 1.0M | | | | | | $5 | $25 |
|
|
41
41
|
| `kilo/~anthropic/claude-sonnet-latest` | 1.0M | | | | | | $3 | $15 |
|
|
42
|
-
| `kilo/~google/gemini-flash-latest` | 1.0M | | | | | | $
|
|
42
|
+
| `kilo/~google/gemini-flash-latest` | 1.0M | | | | | | $2 | $9 |
|
|
43
43
|
| `kilo/~google/gemini-pro-latest` | 1.0M | | | | | | $2 | $12 |
|
|
44
44
|
| `kilo/~moonshotai/kimi-latest` | 262K | | | | | | $0.74 | $3 |
|
|
45
45
|
| `kilo/~openai/gpt-latest` | 1.1M | | | | | | $5 | $30 |
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Kimi For Coding
|
|
4
4
|
|
|
5
|
-
Access
|
|
5
|
+
Access 5 Kimi For Coding models through Mastra's model router. Authentication is handled automatically using the `KIMI_API_KEY` environment variable.
|
|
6
6
|
|
|
7
7
|
Learn more in the [Kimi For Coding documentation](https://www.kimi.com/code/docs/en/third-party-tools/other-coding-agents.html).
|
|
8
8
|
|
|
@@ -34,12 +34,13 @@ for await (const chunk of stream) {
|
|
|
34
34
|
|
|
35
35
|
## Models
|
|
36
36
|
|
|
37
|
-
| Model
|
|
38
|
-
|
|
|
39
|
-
| `kimi-for-coding/k2p5`
|
|
40
|
-
| `kimi-for-coding/k2p6`
|
|
41
|
-
| `kimi-for-coding/k2p7`
|
|
42
|
-
| `kimi-for-coding/kimi-
|
|
37
|
+
| Model | Context | Tools | Reasoning | Image | Audio | Video | Input $/1M | Output $/1M |
|
|
38
|
+
| ------------------------------------------- | ------- | ----- | --------- | ----- | ----- | ----- | ---------- | ----------- |
|
|
39
|
+
| `kimi-for-coding/k2p5` | 262K | | | | | | — | — |
|
|
40
|
+
| `kimi-for-coding/k2p6` | 262K | | | | | | — | — |
|
|
41
|
+
| `kimi-for-coding/k2p7` | 262K | | | | | | — | — |
|
|
42
|
+
| `kimi-for-coding/kimi-for-coding-highspeed` | 262K | | | | | | — | — |
|
|
43
|
+
| `kimi-for-coding/kimi-k2-thinking` | 262K | | | | | | — | — |
|
|
43
44
|
|
|
44
45
|
## Advanced configuration
|
|
45
46
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# LLM Gateway
|
|
4
4
|
|
|
5
|
-
Access
|
|
5
|
+
Access 170 LLM Gateway models through Mastra's model router. Authentication is handled automatically using the `LLMGATEWAY_API_KEY` environment variable.
|
|
6
6
|
|
|
7
7
|
Learn more in the [LLM Gateway documentation](https://llmgateway.io/docs).
|
|
8
8
|
|
|
@@ -53,7 +53,6 @@ for await (const chunk of stream) {
|
|
|
53
53
|
| `llmgateway/claude-sonnet-5` | 1.0M | | | | | | $2 | $10 |
|
|
54
54
|
| `llmgateway/codestral-2508` | 256K | | | | | | $0.30 | $0.90 |
|
|
55
55
|
| `llmgateway/custom` | 128K | | | | | | — | — |
|
|
56
|
-
| `llmgateway/deepseek-v3.1` | 128K | | | | | | $0.56 | $2 |
|
|
57
56
|
| `llmgateway/deepseek-v3.2` | 164K | | | | | | $0.26 | $0.38 |
|
|
58
57
|
| `llmgateway/deepseek-v4-flash` | 1.1M | | | | | | $0.14 | $0.28 |
|
|
59
58
|
| `llmgateway/deepseek-v4-pro` | 1.1M | | | | | | $0.43 | $0.87 |
|
|
@@ -135,7 +134,6 @@ for await (const chunk of stream) {
|
|
|
135
134
|
| `llmgateway/kimi-k2.7-code` | 262K | | | | | | $0.95 | $4 |
|
|
136
135
|
| `llmgateway/kimi-k2.7-code-highspeed` | 262K | | | | | | $2 | $8 |
|
|
137
136
|
| `llmgateway/llama-3-70b-instruct` | 8K | | | | | | $0.51 | $0.74 |
|
|
138
|
-
| `llmgateway/llama-3-8b-instruct` | 8K | | | | | | $0.04 | $0.04 |
|
|
139
137
|
| `llmgateway/llama-3.1-70b-instruct` | 128K | | | | | | $0.72 | $0.72 |
|
|
140
138
|
| `llmgateway/llama-3.1-nemotron-ultra-253b` | 128K | | | | | | $0.60 | $2 |
|
|
141
139
|
| `llmgateway/llama-3.2-11b-instruct` | 128K | | | | | | $0.07 | $0.33 |
|
|
@@ -152,7 +150,7 @@ for await (const chunk of stream) {
|
|
|
152
150
|
| `llmgateway/minimax-m2.5-highspeed` | 205K | | | | | | $0.60 | $2 |
|
|
153
151
|
| `llmgateway/minimax-m2.7` | 205K | | | | | | $0.30 | $1 |
|
|
154
152
|
| `llmgateway/minimax-m2.7-highspeed` | 205K | | | | | | $0.60 | $2 |
|
|
155
|
-
| `llmgateway/minimax-m3` |
|
|
153
|
+
| `llmgateway/minimax-m3` | 524K | | | | | | $0.30 | $1 |
|
|
156
154
|
| `llmgateway/minimax-text-01` | 1.0M | | | | | | $0.20 | $1 |
|
|
157
155
|
| `llmgateway/ministral-14b-2512` | 262K | | | | | | $0.20 | $0.20 |
|
|
158
156
|
| `llmgateway/ministral-3b-2512` | 131K | | | | | | $0.10 | $0.10 |
|
|
@@ -166,7 +164,6 @@ for await (const chunk of stream) {
|
|
|
166
164
|
| `llmgateway/o3` | 200K | | | | | | $2 | $8 |
|
|
167
165
|
| `llmgateway/o3-mini` | 200K | | | | | | $1 | $4 |
|
|
168
166
|
| `llmgateway/o4-mini` | 200K | | | | | | $1 | $4 |
|
|
169
|
-
| `llmgateway/pixtral-large-latest` | 128K | | | | | | $4 | $12 |
|
|
170
167
|
| `llmgateway/qwen-coder-plus` | 131K | | | | | | $0.50 | $1 |
|
|
171
168
|
| `llmgateway/qwen-flash` | 1.0M | | | | | | $0.05 | $0.40 |
|
|
172
169
|
| `llmgateway/qwen-max` | 33K | | | | | | $2 | $6 |
|
|
@@ -181,7 +178,6 @@ for await (const chunk of stream) {
|
|
|
181
178
|
| `llmgateway/qwen3-235b-a22b-thinking-2507` | 262K | | | | | | $0.20 | $0.60 |
|
|
182
179
|
| `llmgateway/qwen3-30b-a3b-instruct-2507` | 262K | | | | | | $0.10 | $0.30 |
|
|
183
180
|
| `llmgateway/qwen3-32b` | 33K | | | | | | $0.10 | $0.30 |
|
|
184
|
-
| `llmgateway/qwen3-4b-fp8` | 128K | | | | | | $0.03 | $0.03 |
|
|
185
181
|
| `llmgateway/qwen3-coder-30b-a3b-instruct` | 262K | | | | | | $0.07 | $0.27 |
|
|
186
182
|
| `llmgateway/qwen3-coder-480b-a35b-instruct` | 262K | | | | | | $0.30 | $1 |
|
|
187
183
|
| `llmgateway/qwen3-coder-flash` | 1.0M | | | | | | $0.30 | $2 |
|
|
@@ -193,8 +189,6 @@ for await (const chunk of stream) {
|
|
|
193
189
|
| `llmgateway/qwen3-vl-235b-a22b-instruct` | 131K | | | | | | $0.30 | $2 |
|
|
194
190
|
| `llmgateway/qwen3-vl-235b-a22b-thinking` | 131K | | | | | | $0.98 | $4 |
|
|
195
191
|
| `llmgateway/qwen3-vl-30b-a3b-instruct` | 131K | | | | | | $0.20 | $0.70 |
|
|
196
|
-
| `llmgateway/qwen3-vl-30b-a3b-thinking` | 131K | | | | | | $0.20 | $1 |
|
|
197
|
-
| `llmgateway/qwen3-vl-8b-instruct` | 131K | | | | | | $0.08 | $0.50 |
|
|
198
192
|
| `llmgateway/qwen3-vl-flash` | 262K | | | | | | $0.05 | $0.40 |
|
|
199
193
|
| `llmgateway/qwen3-vl-plus` | 262K | | | | | | $0.20 | $2 |
|
|
200
194
|
| `llmgateway/qwen3.5-9b` | 262K | | | | | | $0.10 | $0.15 |
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Ollama Cloud
|
|
4
4
|
|
|
5
|
-
Access
|
|
5
|
+
Access 18 Ollama Cloud models through Mastra's model router. Authentication is handled automatically using the `OLLAMA_API_KEY` environment variable.
|
|
6
6
|
|
|
7
7
|
Learn more in the [Ollama Cloud documentation](https://docs.ollama.com/cloud).
|
|
8
8
|
|
|
@@ -17,7 +17,7 @@ const agent = new Agent({
|
|
|
17
17
|
id: "my-agent",
|
|
18
18
|
name: "My Agent",
|
|
19
19
|
instructions: "You are a helpful assistant",
|
|
20
|
-
model: "ollama-cloud/deepseek-
|
|
20
|
+
model: "ollama-cloud/deepseek-v4-flash"
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
// Generate a response
|
|
@@ -34,43 +34,26 @@ for await (const chunk of stream) {
|
|
|
34
34
|
|
|
35
35
|
## Models
|
|
36
36
|
|
|
37
|
-
| Model
|
|
38
|
-
|
|
|
39
|
-
| `ollama-cloud/deepseek-
|
|
40
|
-
| `ollama-cloud/deepseek-
|
|
41
|
-
| `ollama-cloud/
|
|
42
|
-
| `ollama-cloud/
|
|
43
|
-
| `ollama-cloud/
|
|
44
|
-
| `ollama-cloud/
|
|
45
|
-
| `ollama-cloud/
|
|
46
|
-
| `ollama-cloud/
|
|
47
|
-
| `ollama-cloud/
|
|
48
|
-
| `ollama-cloud/
|
|
49
|
-
| `ollama-cloud/
|
|
50
|
-
| `ollama-cloud/
|
|
51
|
-
| `ollama-cloud/
|
|
52
|
-
| `ollama-cloud/
|
|
53
|
-
| `ollama-cloud/
|
|
54
|
-
| `ollama-cloud/
|
|
55
|
-
| `ollama-cloud/
|
|
56
|
-
| `ollama-cloud/
|
|
57
|
-
| `ollama-cloud/kimi-k2.6` | 262K | | | | | | — | — |
|
|
58
|
-
| `ollama-cloud/kimi-k2.7-code` | 262K | | | | | | — | — |
|
|
59
|
-
| `ollama-cloud/minimax-m2.1` | 205K | | | | | | — | — |
|
|
60
|
-
| `ollama-cloud/minimax-m2.5` | 205K | | | | | | — | — |
|
|
61
|
-
| `ollama-cloud/minimax-m2.7` | 197K | | | | | | — | — |
|
|
62
|
-
| `ollama-cloud/minimax-m3` | 512K | | | | | | — | — |
|
|
63
|
-
| `ollama-cloud/ministral-3:14b` | 262K | | | | | | — | — |
|
|
64
|
-
| `ollama-cloud/ministral-3:3b` | 262K | | | | | | — | — |
|
|
65
|
-
| `ollama-cloud/ministral-3:8b` | 262K | | | | | | — | — |
|
|
66
|
-
| `ollama-cloud/mistral-large-3:675b` | 262K | | | | | | — | — |
|
|
67
|
-
| `ollama-cloud/nemotron-3-nano:30b` | 1.0M | | | | | | — | — |
|
|
68
|
-
| `ollama-cloud/nemotron-3-super` | 262K | | | | | | — | — |
|
|
69
|
-
| `ollama-cloud/nemotron-3-ultra` | 262K | | | | | | — | — |
|
|
70
|
-
| `ollama-cloud/qwen3-coder-next` | 262K | | | | | | — | — |
|
|
71
|
-
| `ollama-cloud/qwen3-coder:480b` | 262K | | | | | | — | — |
|
|
72
|
-
| `ollama-cloud/qwen3.5:397b` | 262K | | | | | | — | — |
|
|
73
|
-
| `ollama-cloud/rnj-1:8b` | 33K | | | | | | — | — |
|
|
37
|
+
| Model | Context | Tools | Reasoning | Image | Audio | Video | Input $/1M | Output $/1M |
|
|
38
|
+
| ----------------------------------- | ------- | ----- | --------- | ----- | ----- | ----- | ---------- | ----------- |
|
|
39
|
+
| `ollama-cloud/deepseek-v4-flash` | 1.0M | | | | | | — | — |
|
|
40
|
+
| `ollama-cloud/deepseek-v4-pro` | 1.0M | | | | | | — | — |
|
|
41
|
+
| `ollama-cloud/gemma4:31b` | 262K | | | | | | — | — |
|
|
42
|
+
| `ollama-cloud/glm-5.1` | 203K | | | | | | — | — |
|
|
43
|
+
| `ollama-cloud/glm-5.2` | 976K | | | | | | — | — |
|
|
44
|
+
| `ollama-cloud/gpt-oss:120b` | 131K | | | | | | — | — |
|
|
45
|
+
| `ollama-cloud/gpt-oss:20b` | 131K | | | | | | — | — |
|
|
46
|
+
| `ollama-cloud/kimi-k2.5` | 262K | | | | | | — | — |
|
|
47
|
+
| `ollama-cloud/kimi-k2.6` | 262K | | | | | | — | — |
|
|
48
|
+
| `ollama-cloud/kimi-k2.7-code` | 262K | | | | | | — | — |
|
|
49
|
+
| `ollama-cloud/minimax-m2.5` | 205K | | | | | | — | — |
|
|
50
|
+
| `ollama-cloud/minimax-m2.7` | 197K | | | | | | — | — |
|
|
51
|
+
| `ollama-cloud/minimax-m3` | 512K | | | | | | — | — |
|
|
52
|
+
| `ollama-cloud/mistral-large-3:675b` | 262K | | | | | | — | — |
|
|
53
|
+
| `ollama-cloud/nemotron-3-nano:30b` | 1.0M | | | | | | — | — |
|
|
54
|
+
| `ollama-cloud/nemotron-3-super` | 262K | | | | | | — | — |
|
|
55
|
+
| `ollama-cloud/nemotron-3-ultra` | 262K | | | | | | — | — |
|
|
56
|
+
| `ollama-cloud/qwen3.5:397b` | 262K | | | | | | — | — |
|
|
74
57
|
|
|
75
58
|
## Advanced configuration
|
|
76
59
|
|
|
@@ -82,7 +65,7 @@ const agent = new Agent({
|
|
|
82
65
|
name: "custom-agent",
|
|
83
66
|
model: {
|
|
84
67
|
url: "https://ollama.com/v1",
|
|
85
|
-
id: "ollama-cloud/deepseek-
|
|
68
|
+
id: "ollama-cloud/deepseek-v4-flash",
|
|
86
69
|
apiKey: process.env.OLLAMA_API_KEY,
|
|
87
70
|
headers: {
|
|
88
71
|
"X-Custom-Header": "value"
|
|
@@ -100,8 +83,8 @@ const agent = new Agent({
|
|
|
100
83
|
model: ({ requestContext }) => {
|
|
101
84
|
const useAdvanced = requestContext.task === "complex";
|
|
102
85
|
return useAdvanced
|
|
103
|
-
? "ollama-cloud/
|
|
104
|
-
: "ollama-cloud/deepseek-
|
|
86
|
+
? "ollama-cloud/qwen3.5:397b"
|
|
87
|
+
: "ollama-cloud/deepseek-v4-flash";
|
|
105
88
|
}
|
|
106
89
|
});
|
|
107
90
|
```
|
|
@@ -57,7 +57,7 @@ for await (const chunk of stream) {
|
|
|
57
57
|
| `orcarouter/google/gemini-3.1-flash-lite-preview` | 1.0M | | | | | | $0.25 | $2 |
|
|
58
58
|
| `orcarouter/google/gemini-3.1-pro-preview` | 1.0M | | | | | | $4 | $18 |
|
|
59
59
|
| `orcarouter/google/gemini-3.1-pro-preview-customtools` | 1.0M | | | | | | $4 | $18 |
|
|
60
|
-
| `orcarouter/google/gemini-flash-latest` | 1.0M | | | | | | $
|
|
60
|
+
| `orcarouter/google/gemini-flash-latest` | 1.0M | | | | | | $2 | $9 |
|
|
61
61
|
| `orcarouter/google/gemini-flash-lite-latest` | 1.0M | | | | | | $0.25 | $2 |
|
|
62
62
|
| `orcarouter/google/gemma-4-26b-a4b-it` | 262K | | | | | | $0.06 | $0.33 |
|
|
63
63
|
| `orcarouter/google/gemma-4-31b-it` | 262K | | | | | | $0.13 | $0.38 |
|
|
@@ -17,7 +17,7 @@ const agent = new Agent({
|
|
|
17
17
|
id: "my-agent",
|
|
18
18
|
name: "My Agent",
|
|
19
19
|
instructions: "You are a helpful assistant",
|
|
20
|
-
model: "privatemode-ai/
|
|
20
|
+
model: "privatemode-ai/gpt-oss-120b"
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
// Generate a response
|
|
@@ -34,13 +34,13 @@ for await (const chunk of stream) {
|
|
|
34
34
|
|
|
35
35
|
## Models
|
|
36
36
|
|
|
37
|
-
| Model
|
|
38
|
-
|
|
|
39
|
-
| `privatemode-ai/
|
|
40
|
-
| `privatemode-ai/
|
|
41
|
-
| `privatemode-ai/qwen3-
|
|
42
|
-
| `privatemode-ai/
|
|
43
|
-
| `privatemode-ai/whisper-large-v3`
|
|
37
|
+
| Model | Context | Tools | Reasoning | Image | Audio | Video | Input $/1M | Output $/1M |
|
|
38
|
+
| ----------------------------------- | ------- | ----- | --------- | ----- | ----- | ----- | ---------- | ----------- |
|
|
39
|
+
| `privatemode-ai/gpt-oss-120b` | 128K | | | | | | — | — |
|
|
40
|
+
| `privatemode-ai/kimi-k2.6` | 262K | | | | | | — | — |
|
|
41
|
+
| `privatemode-ai/qwen3-embedding-4b` | 32K | | | | | | — | — |
|
|
42
|
+
| `privatemode-ai/voxtral-mini-3b` | 32K | | | | | | — | — |
|
|
43
|
+
| `privatemode-ai/whisper-large-v3` | — | | | | | | — | — |
|
|
44
44
|
|
|
45
45
|
## Advanced configuration
|
|
46
46
|
|
|
@@ -52,7 +52,7 @@ const agent = new Agent({
|
|
|
52
52
|
name: "custom-agent",
|
|
53
53
|
model: {
|
|
54
54
|
url: "http://localhost:8080/v1",
|
|
55
|
-
id: "privatemode-ai/
|
|
55
|
+
id: "privatemode-ai/gpt-oss-120b",
|
|
56
56
|
apiKey: process.env.PRIVATEMODE_API_KEY,
|
|
57
57
|
headers: {
|
|
58
58
|
"X-Custom-Header": "value"
|
|
@@ -71,7 +71,7 @@ const agent = new Agent({
|
|
|
71
71
|
const useAdvanced = requestContext.task === "complex";
|
|
72
72
|
return useAdvanced
|
|
73
73
|
? "privatemode-ai/whisper-large-v3"
|
|
74
|
-
: "privatemode-ai/
|
|
74
|
+
: "privatemode-ai/gpt-oss-120b";
|
|
75
75
|
}
|
|
76
76
|
});
|
|
77
77
|
```
|
|
@@ -76,6 +76,8 @@ export const claudeCodeAgent = new AcpAgent({
|
|
|
76
76
|
|
|
77
77
|
**onPermissionRequest** (`(request: RequestPermissionRequest) => Promise<RequestPermissionResponse>`): Callback invoked when the ACP agent requests permission. Defaults to selecting the first permission option, or cancelling when no option is available.
|
|
78
78
|
|
|
79
|
+
**createClient** (`(defaultClient: Client) => Client`): Customize the ACP client used to answer agent requests. Receives the default client so it can be wrapped or extended, for example with extMethod and extNotification handlers. See Extension methods.
|
|
80
|
+
|
|
79
81
|
**workspace** (`Workspace`): Workspace used for ACP file read and write requests. Defaults to a Workspace backed by LocalFilesystem at cwd or process.cwd().
|
|
80
82
|
|
|
81
83
|
**model** (`ModelId`): Model ID to select after ACP session creation using the ACP session/set\_model method.
|
|
@@ -57,6 +57,8 @@ export const codeSupervisor = new Agent({
|
|
|
57
57
|
|
|
58
58
|
**onPermissionRequest** (`(request: RequestPermissionRequest) => Promise<RequestPermissionResponse>`): Callback invoked when the ACP agent requests permission. Defaults to selecting the first permission option, or cancelling when no option is available.
|
|
59
59
|
|
|
60
|
+
**createClient** (`(defaultClient: Client) => Client`): Customize the ACP client used to answer agent requests. Receives the default client so it can be wrapped or extended, for example with extMethod and extNotification handlers.
|
|
61
|
+
|
|
60
62
|
**workspace** (`Workspace`): Workspace option from the shared ACP connection options. During tool execution, createACPTool() passes the current Mastra workspace from the execution context when one is available; otherwise the ACP connection falls back to a local filesystem workspace. Use AcpAgent when you need to provide an explicit workspace instance.
|
|
61
63
|
|
|
62
64
|
**model** (`ModelId`): Model ID to select after ACP session creation using the ACP session/set\_model method.
|
|
@@ -124,6 +126,32 @@ export const codeAgentTool = createACPTool({
|
|
|
124
126
|
|
|
125
127
|
Use this callback to enforce local policy, inspect the permission title, or route the decision to your own approval flow.
|
|
126
128
|
|
|
129
|
+
## Extension methods
|
|
130
|
+
|
|
131
|
+
Some ACP agents call custom extension methods on the client, outside the standard ACP request set. The default client rejects unknown methods with a "Method not found" error, which can abort the agent's turn.
|
|
132
|
+
|
|
133
|
+
Pass `createClient` to extend or replace the default client. The callback receives the default client and returns the client used for the connection:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { createACPTool } from '@mastra/acp'
|
|
137
|
+
|
|
138
|
+
export const codeAgentTool = createACPTool({
|
|
139
|
+
id: 'code-agent',
|
|
140
|
+
description: 'Use an ACP-compatible coding agent',
|
|
141
|
+
command: 'acp-agent',
|
|
142
|
+
args: ['--stdio'],
|
|
143
|
+
createClient: defaultClient =>
|
|
144
|
+
Object.assign(defaultClient, {
|
|
145
|
+
async extMethod(method: string, params: Record<string, unknown>) {
|
|
146
|
+
return {}
|
|
147
|
+
},
|
|
148
|
+
async extNotification(method: string, params: Record<string, unknown>) {},
|
|
149
|
+
}),
|
|
150
|
+
})
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Return a fully custom `Client` implementation when you need to change the standard handlers as well. The `Client` type is re-exported from `@mastra/acp`.
|
|
154
|
+
|
|
127
155
|
## Related
|
|
128
156
|
|
|
129
157
|
- [Agent Client Protocol docs](https://mastra.ai/docs/agents/acp)
|
|
@@ -211,6 +211,8 @@ Retrieve messages for a specific thread.
|
|
|
211
211
|
const messages = await agentController.session.thread.listMessages({ threadId: 'thread-abc123' })
|
|
212
212
|
```
|
|
213
213
|
|
|
214
|
+
The message-reading methods `listActiveMessages`, `listMessages`, and `firstUserMessage` return `MastraDBMessage` objects, while `firstUserMessages` returns a `Map<string, MastraDBMessage>` keyed by thread ID. Each message has a `role`, an `id`, a `createdAt`, and a `content` object with `content.format` and a `content.parts` array. Read text, reasoning, tool calls, and attachments from `content.parts`. Signals such as system reminders and notifications are returned as separate messages with `role: 'signal'`.
|
|
215
|
+
|
|
214
216
|
### `session.thread.firstUserMessage({ threadId })`
|
|
215
217
|
|
|
216
218
|
Retrieve the first user message for a thread, or `null` if none.
|
|
@@ -37,6 +37,29 @@ const text = await output.text
|
|
|
37
37
|
cleanup()
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
### Using the `durable` config flag
|
|
41
|
+
|
|
42
|
+
Set `durable: true` on `AgentConfig` and the agent is automatically wrapped with `createDurableAgent` when it is attached to a `Mastra` instance. Use an object to forward advanced options such as `cache`, `pubsub`, `maxSteps`, or `cleanupTimeoutMs`.
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { Mastra } from '@mastra/core'
|
|
46
|
+
import { Agent } from '@mastra/core/agent'
|
|
47
|
+
|
|
48
|
+
const myAgent = new Agent({
|
|
49
|
+
id: 'my-agent',
|
|
50
|
+
name: 'My Agent',
|
|
51
|
+
instructions: 'You are a helpful assistant',
|
|
52
|
+
model: 'openai/gpt-5.5',
|
|
53
|
+
durable: true, // or: { maxSteps: 10, cleanupTimeoutMs: 60_000 }
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
export const mastra = new Mastra({
|
|
57
|
+
agents: { myAgent },
|
|
58
|
+
})
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`mastra.getAgent('myAgent')` returns the wrapped `DurableAgent`. Standalone agents (constructed but never registered on a `Mastra` instance) do not become durable; the wrapping is applied at registration.
|
|
62
|
+
|
|
40
63
|
## `createDurableAgent(options)`
|
|
41
64
|
|
|
42
65
|
Wraps an `Agent` with durable execution and resumable streams. This is the recommended way to create a `DurableAgent`.
|
|
@@ -106,7 +106,7 @@ const result = await agent.generate('message for agent')
|
|
|
106
106
|
|
|
107
107
|
**options.structuredOutput.instructions** (`string`): Additional instructions for the structured output model.
|
|
108
108
|
|
|
109
|
-
**options.structuredOutput.jsonPromptInjection** (`boolean`):
|
|
109
|
+
**options.structuredOutput.jsonPromptInjection** (`boolean | 'system' | 'inline' | 'auto'`): Controls how the JSON schema reaches the model. Set to 'auto' to use native structured output when supported and inline prompt injection otherwise.
|
|
110
110
|
|
|
111
111
|
**options.structuredOutput.logger** (`IMastraLogger`): Optional logger instance for structured logging during output generation.
|
|
112
112
|
|
|
@@ -51,7 +51,7 @@ const scorer = createScorer({
|
|
|
51
51
|
|
|
52
52
|
**judge.instructions** (`string`): System prompt/instructions for the LLM.
|
|
53
53
|
|
|
54
|
-
**judge.jsonPromptInjection** (`boolean
|
|
54
|
+
**judge.jsonPromptInjection** (`boolean | 'system' | 'inline' | 'auto'`): Controls how the judge's structured output schema reaches the model. Defaults to 'auto', which uses native structured output when supported and inline prompt injection otherwise. Explicit values override automatic routing.
|
|
55
55
|
|
|
56
56
|
**judge.inputProcessors** (`Processor[]`): Input processors applied to the internal judge agent before its messages reach the model (e.g. redaction, validation).
|
|
57
57
|
|
|
@@ -31,6 +31,28 @@ console.log(`Average scores:`, result.scores)
|
|
|
31
31
|
console.log(`Processed ${result.summary.totalItems} items`)
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
### Multi-turn evaluation
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { runEvals } from '@mastra/core/evals'
|
|
38
|
+
import { checks } from '@mastra/evals/checks'
|
|
39
|
+
import { weatherAgent } from './agents/weather-agent'
|
|
40
|
+
|
|
41
|
+
const result = await runEvals({
|
|
42
|
+
target: weatherAgent,
|
|
43
|
+
data: [
|
|
44
|
+
{
|
|
45
|
+
inputs: [
|
|
46
|
+
'What is the weather in Brooklyn?',
|
|
47
|
+
'What about tomorrow?',
|
|
48
|
+
'Compare the two forecasts.',
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
scorers: [checks.calledTool('get_weather', { times: 2 }), checks.includes('Brooklyn')],
|
|
53
|
+
})
|
|
54
|
+
```
|
|
55
|
+
|
|
34
56
|
### With gates and thresholds
|
|
35
57
|
|
|
36
58
|
```typescript
|
|
@@ -60,7 +82,7 @@ result.thresholdResults // [{ id, passed, averageScore, threshold }]
|
|
|
60
82
|
|
|
61
83
|
**gates** (`MastraScorer[]`): Scorers that must score 1.0 for the run to pass. If any gate averages below 1.0 across data items, the verdict is failed. Gates run before regular scorers on each data item. When provided, scorers may be omitted.
|
|
62
84
|
|
|
63
|
-
**targetOptions** (`AgentExecutionOptions | WorkflowRunOptions`): Options forwarded to the target during execution. For agents: options passed to agent.generate() (e.g. maxSteps, modelSettings, instructions). For workflows: options passed to run.start() (e.g. perStep, outputOptions, initialState).
|
|
85
|
+
**targetOptions** (`AgentExecutionOptions | WorkflowRunOptions`): Options forwarded to the target during execution. For agents: options passed to agent.generate() (e.g. maxSteps, modelSettings, instructions). For workflows: options passed to run.start() (e.g. perStep, outputOptions, initialState). For multi-turn agent runs (inputs/turns), runEvals generates and injects the shared thread and a resource, so memory.thread is optional; provide memory.resource to reuse a specific resource.
|
|
64
86
|
|
|
65
87
|
**concurrency** (`number`): Number of test cases to run concurrently. (Default: `1`)
|
|
66
88
|
|
|
@@ -68,7 +90,11 @@ result.thresholdResults // [{ id, passed, averageScore, threshold }]
|
|
|
68
90
|
|
|
69
91
|
## Data item structure
|
|
70
92
|
|
|
71
|
-
**input** (`string | string[] | CoreMessage[] | any`): Input data for the target. For agents: messages or strings. For workflows: workflow input data.
|
|
93
|
+
**input** (`string | string[] | CoreMessage[] | any`): Input data for the target. For agents: messages or strings. For workflows: workflow input data. Optional when inputs is provided.
|
|
94
|
+
|
|
95
|
+
**inputs** (`(string | string[] | CoreMessage[] | any)[]`): Multi-turn inputs. Each entry is one turn (same shape as input) sent sequentially to the agent on the same thread. Scorers see the accumulated output from all turns. Only supported for Agent targets. When provided, input can be omitted. Mutually exclusive with turns.
|
|
96
|
+
|
|
97
|
+
**turns** (`EvalTurn[]`): Multi-turn conversation with per-turn assertions. Each turn is an object { input, gates?, scorers? } sent sequentially on the same thread; its gates/scorers evaluate only that turn's input and output. Per-turn outcomes are reported in turnResults and folded into the overall verdict. Only supported for Agent targets. Mutually exclusive with input and inputs.
|
|
72
98
|
|
|
73
99
|
**groundTruth** (`any`): Expected or reference output for comparison during scoring.
|
|
74
100
|
|
|
@@ -112,6 +138,18 @@ For workflows, use `WorkflowScorerConfig` to specify scorers at different levels
|
|
|
112
138
|
|
|
113
139
|
**thresholdResults** (`ThresholdResult[]`): Per-threshold-scorer results averaged across all data items. Each entry has id, passed, averageScore, and threshold.
|
|
114
140
|
|
|
141
|
+
**turnResults** (`TurnResult[]`): Present when any data item uses turns. Each entry has index (zero-based turn), optional gateResults, thresholdResults, and scores (bare-scorer averages keyed by scorer id), aggregated by turn index across data items.
|
|
142
|
+
|
|
143
|
+
## EvalTurn
|
|
144
|
+
|
|
145
|
+
A single turn in a `turns` array. Its `gates`/`scorers` evaluate only that turn's input and output:
|
|
146
|
+
|
|
147
|
+
**input** (`string | string[] | CoreMessage[] | any`): The input sent to the agent for this turn.
|
|
148
|
+
|
|
149
|
+
**gates** (`MastraScorer[]`): Gates that must score 1.0 for this turn. A failing turn gate makes the overall verdict failed.
|
|
150
|
+
|
|
151
|
+
**scorers** (`ScorerEntry[]`): Scorers (optionally with thresholds) evaluated against this turn only. A missed per-turn threshold (with gates passing) makes the verdict scored.
|
|
152
|
+
|
|
115
153
|
## ScorerEntry
|
|
116
154
|
|
|
117
155
|
A scorer entry in the `scorers` array can be either a bare scorer or a scorer with a threshold:
|
|
@@ -314,8 +352,62 @@ const result = await runEvals({
|
|
|
314
352
|
})
|
|
315
353
|
```
|
|
316
354
|
|
|
355
|
+
### Multi-turn conversation evaluation
|
|
356
|
+
|
|
357
|
+
Use `inputs` to send sequential turns on a shared thread. Scorers see the accumulated output from all turns:
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
const result = await runEvals({
|
|
361
|
+
target: chatAgent,
|
|
362
|
+
data: [
|
|
363
|
+
{
|
|
364
|
+
inputs: ['My favorite city is Brooklyn.', 'What is the weather in my favorite city?'],
|
|
365
|
+
},
|
|
366
|
+
],
|
|
367
|
+
gates: [checks.calledTool('get_weather')],
|
|
368
|
+
scorers: [{ scorer: checks.similarity('Brooklyn weather forecast'), threshold: 0.5 }],
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
// result.verdict: 'passed' | 'scored' | 'failed'
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Each turn runs `agent.generate()` with the same `threadId`, so the agent sees the full conversation history. `runEvals` also injects a `resourceId` (Mastra memory scopes messages by resource + thread), defaulting it to the generated thread; pass `targetOptions.memory.resource` to pin a specific one. Cross-turn recall requires the agent to have a memory store configured; otherwise turns run in isolation. Mix single-turn (`input`) and multi-turn (`inputs`) items in the same `data` array. When using `inputs`, `input` can be omitted.
|
|
375
|
+
|
|
376
|
+
Scoring uses the accumulated output from all turns as `run.output`, but only the first turn as `run.input`. Prefer output-based scorers (`checks.includes`, `checks.calledTool`, `checks.similarity`) for multi-turn; input-relative scorers (e.g. faithfulness) only see the first turn's input. Trajectory scorers that read from the trace (`AgentScorerConfig.trajectory`) resolve against the last turn's span; tool-call checks that read `run.output` (like `checks.calledTool`) still see every turn.
|
|
377
|
+
|
|
378
|
+
### Per-turn assertions
|
|
379
|
+
|
|
380
|
+
Use `turns` to attach `gates`/`scorers` to individual turns. Each per-turn assertion sees only that turn's input and output, so a later-turn regression can't be hidden by an earlier turn:
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
const result = await runEvals({
|
|
384
|
+
target: chatAgent,
|
|
385
|
+
data: [
|
|
386
|
+
{
|
|
387
|
+
turns: [
|
|
388
|
+
{
|
|
389
|
+
input: 'What is the weather in Brooklyn?',
|
|
390
|
+
gates: [checks.calledTool('get_weather')],
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
input: 'What about tomorrow?',
|
|
394
|
+
gates: [checks.calledTool('get_weather')], // must call again this turn
|
|
395
|
+
scorers: [{ scorer: checks.similarity('tomorrow forecast'), threshold: 0.5 }],
|
|
396
|
+
},
|
|
397
|
+
],
|
|
398
|
+
},
|
|
399
|
+
],
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
result.verdict // folds in per-turn gate/threshold outcomes
|
|
403
|
+
result.turnResults // [{ index, gateResults, thresholdResults, scores }]
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Per-turn gates/scorers evaluate only that turn (`run.input`/`run.output` are that turn's). A failing turn gate makes the verdict `failed`; a missed turn threshold (gates passing) makes it `scored`. Top-level `scorers`/`gates` still score the accumulated conversation holistically. `turns` is Agent-only and cannot be combined with `input` or `inputs`.
|
|
407
|
+
|
|
317
408
|
## Related
|
|
318
409
|
|
|
410
|
+
- [Multi-turn evals](https://mastra.ai/docs/evals/multi-turn): Conceptual guide to multi-turn evaluation
|
|
319
411
|
- [Gates and Verdicts](https://mastra.ai/docs/evals/gates-and-verdicts): Conceptual guide to severity semantics
|
|
320
412
|
- [Quick Checks](https://mastra.ai/reference/evals/checks): Zero-LLM composable micro-scorers
|
|
321
413
|
- [createScorer()](https://mastra.ai/reference/evals/create-scorer): Create custom scorers for experiments
|
|
@@ -100,7 +100,7 @@ const stream = await agent.stream('message for agent')
|
|
|
100
100
|
|
|
101
101
|
**options.structuredOutput.instructions** (`string`): Additional instructions for the structured output model.
|
|
102
102
|
|
|
103
|
-
**options.structuredOutput.jsonPromptInjection** (`boolean`):
|
|
103
|
+
**options.structuredOutput.jsonPromptInjection** (`boolean | 'system' | 'inline' | 'auto'`): Controls how the JSON schema reaches the model. Set to 'auto' to use native structured output when supported and inline prompt injection otherwise.
|
|
104
104
|
|
|
105
105
|
**options.structuredOutput.providerOptions** (`ProviderOptions`): Provider-specific options passed to the internal structuring agent. Use this to control model behavior like reasoning effort for thinking models (e.g., { openai: { reasoningEffort: 'low' } }).
|
|
106
106
|
|
|
@@ -207,6 +207,34 @@ const instructionsByServer = mcp.getServerInstructions()
|
|
|
207
207
|
console.log(instructionsByServer.db)
|
|
208
208
|
```
|
|
209
209
|
|
|
210
|
+
### `authenticate()`
|
|
211
|
+
|
|
212
|
+
Runs the interactive OAuth authorization-code flow for a server configured with an `MCPOAuthClientProvider` whose redirect URL points at a loopback address. Starts a local callback server, delivers the authorization URL through the provider's `onRedirectToAuthorization` callback, waits for the browser to return the authorization code, exchanges it for tokens, and reconnects. See [Interactive browser authentication](#interactive-browser-authentication).
|
|
213
|
+
|
|
214
|
+
The optional `timeoutMs` bounds how long the flow waits for the browser to return the authorization code before rejecting, and defaults to 5 minutes.
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
async authenticate(serverName: string, options?: { timeoutMs?: number }): Promise<void>
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### `getServerAuthState()`
|
|
221
|
+
|
|
222
|
+
Returns the OAuth authorization state of a configured server: `'needs-auth'` after a connection attempt was rejected with an authorization error, `'authorized'` once the server accepted the provider's credentials, or `undefined` for servers without an `authProvider` or that haven't attempted a connection yet.
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
getServerAuthState(serverName: string): 'needs-auth' | 'authorized' | undefined
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### `cancelAuthentication()`
|
|
229
|
+
|
|
230
|
+
Cancels an in-progress `authenticate()` flow for a server, so an abandoned browser authorization does not leave the client waiting indefinitely. It aborts the flow (including its setup phase, before the callback server binds), closes the local callback server if one is listening, and the pending `authenticate()` call rejects. Returns `true` if a flow was cancelled, or `false` when no flow was in progress.
|
|
231
|
+
|
|
232
|
+
The resulting `getServerAuthState()` depends on how far the flow had progressed: a flow cancelled after the server rejected the connection with `401` stays at `'needs-auth'` and can be retried immediately, while a flow cancelled during the setup phase — before any connection was attempted — leaves the state unchanged (typically `undefined`).
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
async cancelAuthentication(serverName: string): Promise<boolean>
|
|
236
|
+
```
|
|
237
|
+
|
|
210
238
|
### `disconnect()`
|
|
211
239
|
|
|
212
240
|
Disconnects from all MCP servers and cleans up resources.
|
|
@@ -821,6 +849,74 @@ const client = new MCPClient({
|
|
|
821
849
|
})
|
|
822
850
|
```
|
|
823
851
|
|
|
852
|
+
Give each server its own `MCPOAuthClientProvider` instance. A provider holds per-server session and credential state during authorization, so sharing one instance across multiple servers lets their flows overwrite each other. When configuring several protected servers, construct a separate provider for each.
|
|
853
|
+
|
|
854
|
+
### Interactive browser authentication
|
|
855
|
+
|
|
856
|
+
When a server rejects a connection because authorization is required, the client records a `'needs-auth'` state instead of failing outright. Calling `authenticate()` then completes the flow end to end: it starts a one-shot callback server on the provider's loopback redirect URL (falling back to the next sequential ports when it is in use), lets the SDK run discovery and dynamic client registration, delivers the authorization URL through `onRedirectToAuthorization` — open it in the user's browser — and finishes the token exchange once the browser returns the authorization code:
|
|
857
|
+
|
|
858
|
+
```typescript
|
|
859
|
+
import { MCPClient, MCPOAuthClientProvider } from '@mastra/mcp'
|
|
860
|
+
|
|
861
|
+
const oauthProvider = new MCPOAuthClientProvider({
|
|
862
|
+
redirectUrl: 'http://127.0.0.1:5533/oauth/callback',
|
|
863
|
+
clientMetadata: {
|
|
864
|
+
redirect_uris: ['http://127.0.0.1:5533/oauth/callback'],
|
|
865
|
+
client_name: 'My MCP Client',
|
|
866
|
+
grant_types: ['authorization_code', 'refresh_token'],
|
|
867
|
+
response_types: ['code'],
|
|
868
|
+
},
|
|
869
|
+
onRedirectToAuthorization: url => {
|
|
870
|
+
// Open the user's browser at the consent page
|
|
871
|
+
console.log(`Please visit: ${url}`)
|
|
872
|
+
},
|
|
873
|
+
})
|
|
874
|
+
|
|
875
|
+
const mcp = new MCPClient({
|
|
876
|
+
servers: {
|
|
877
|
+
protectedServer: {
|
|
878
|
+
url: new URL('https://mcp.example.com/mcp'),
|
|
879
|
+
authProvider: oauthProvider,
|
|
880
|
+
},
|
|
881
|
+
},
|
|
882
|
+
})
|
|
883
|
+
|
|
884
|
+
try {
|
|
885
|
+
await mcp.listTools()
|
|
886
|
+
} catch {
|
|
887
|
+
if (mcp.getServerAuthState('protectedServer') === 'needs-auth') {
|
|
888
|
+
await mcp.authenticate('protectedServer')
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
```
|
|
892
|
+
|
|
893
|
+
Concurrent `authenticate()` calls for the same server join the pending flow; different servers authenticate independently. With valid stored tokens the call simply reconnects without opening a browser.
|
|
894
|
+
|
|
895
|
+
Hosts that drive the flow themselves can capture the authorization code with the exported `createOAuthCallbackServer` helper, which binds a one-shot loopback server, validates the OAuth `state` parameter, and resolves with the code. It creates a plain HTTP server, so it is only for local loopback redirects. Web applications that use an HTTPS redirect URL must host their own callback endpoint and drive the provider directly rather than using this helper:
|
|
896
|
+
|
|
897
|
+
```typescript
|
|
898
|
+
import { createOAuthCallbackServer, getCallbackUrlCandidates } from '@mastra/mcp'
|
|
899
|
+
|
|
900
|
+
// getCallbackUrlCandidates() lists every URL the helper may bind, so register
|
|
901
|
+
// all of them as redirect_uris during client registration to cover port fallback.
|
|
902
|
+
const redirectUris = getCallbackUrlCandidates('http://127.0.0.1:5533/oauth/callback').map(url =>
|
|
903
|
+
url.toString(),
|
|
904
|
+
)
|
|
905
|
+
|
|
906
|
+
const server = await createOAuthCallbackServer({
|
|
907
|
+
redirectUrl: 'http://127.0.0.1:5533/oauth/callback',
|
|
908
|
+
state: expectedState,
|
|
909
|
+
})
|
|
910
|
+
|
|
911
|
+
// server.url reflects the port actually bound — use it as the redirect_uri.
|
|
912
|
+
try {
|
|
913
|
+
const { code } = await server.waitForCode()
|
|
914
|
+
// Exchange the code here.
|
|
915
|
+
} finally {
|
|
916
|
+
await server.close()
|
|
917
|
+
}
|
|
918
|
+
```
|
|
919
|
+
|
|
824
920
|
### Quick Token Provider
|
|
825
921
|
|
|
826
922
|
For testing or when you already have a valid access token:
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @mastra/mcp-docs-server
|
|
2
2
|
|
|
3
|
+
## 1.2.8-alpha.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [[`1426af2`](https://github.com/mastra-ai/mastra/commit/1426af24975879c000d13ac75673f630fcc970c1), [`975295d`](https://github.com/mastra-ai/mastra/commit/975295d418552f0d46a59edfef4c3ee555f9930a), [`85e4fb5`](https://github.com/mastra-ai/mastra/commit/85e4fb50087a81c74df3a762f53b56373db0b912), [`ef03c0c`](https://github.com/mastra-ai/mastra/commit/ef03c0cfc62367a458e4cc56462e2148b35681c5), [`4fb4d88`](https://github.com/mastra-ai/mastra/commit/4fb4d881bc107acee13890ad4d78661016c510ed), [`4eba27a`](https://github.com/mastra-ai/mastra/commit/4eba27adcf60f991df0e62f94b3e75b4e67f3b4b), [`c701be3`](https://github.com/mastra-ai/mastra/commit/c701be32d7d9aa94a66da8c6cc38dcac6856f464)]:
|
|
8
|
+
- @mastra/core@1.52.0-alpha.3
|
|
9
|
+
|
|
10
|
+
## 1.2.8-alpha.4
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies [[`8b20926`](https://github.com/mastra-ai/mastra/commit/8b20926cd59e2ba3d66458e062fa0e6e2ada3e68), [`74faf8b`](https://github.com/mastra-ai/mastra/commit/74faf8bd9c1018f2492653c06b1e25fc8300e9e6), [`1fadac4`](https://github.com/mastra-ai/mastra/commit/1fadac44537caeefe81f9f775ae2f2f3d94e9069), [`970c032`](https://github.com/mastra-ai/mastra/commit/970c032502751ee5dd4d0b603331d9838cb538fc), [`792ec9a`](https://github.com/mastra-ai/mastra/commit/792ec9a0869bab8274cf5e0ed2840738737a1607), [`712b864`](https://github.com/mastra-ai/mastra/commit/712b864aa1ed12b14c54390ec17b69de163c37f7), [`8f7a5de`](https://github.com/mastra-ai/mastra/commit/8f7a5dedc246cdc938bb65516703cf9b27b03756), [`c0bec73`](https://github.com/mastra-ai/mastra/commit/c0bec732c93d1a22ae5e51ed66cf8cacca8bd6a6)]:
|
|
15
|
+
- @mastra/core@1.52.0-alpha.2
|
|
16
|
+
- @mastra/mcp@1.15.0-alpha.0
|
|
17
|
+
|
|
3
18
|
## 1.2.8-alpha.3
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/mcp-docs-server",
|
|
3
|
-
"version": "1.2.8-alpha.
|
|
3
|
+
"version": "1.2.8-alpha.7",
|
|
4
4
|
"description": "MCP server for accessing Mastra.ai documentation, changelogs, and news.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"jsdom": "^26.1.0",
|
|
29
29
|
"local-pkg": "^1.1.2",
|
|
30
30
|
"zod": "^4.4.3",
|
|
31
|
-
"@mastra/core": "1.
|
|
32
|
-
"@mastra/mcp": "^1.
|
|
31
|
+
"@mastra/core": "1.52.0-alpha.3",
|
|
32
|
+
"@mastra/mcp": "^1.15.0-alpha.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@hono/node-server": "^1.19.
|
|
35
|
+
"@hono/node-server": "^1.19.14",
|
|
36
36
|
"@types/jsdom": "^21.1.7",
|
|
37
37
|
"@types/node": "22.20.1",
|
|
38
38
|
"@vitest/coverage-v8": "4.1.10",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"tsx": "^4.22.4",
|
|
46
46
|
"typescript": "^6.0.3",
|
|
47
47
|
"vitest": "4.1.10",
|
|
48
|
-
"@internal/lint": "0.0.114",
|
|
49
48
|
"@internal/types-builder": "0.0.89",
|
|
50
|
-
"@
|
|
49
|
+
"@internal/lint": "0.0.114",
|
|
50
|
+
"@mastra/core": "1.52.0-alpha.3"
|
|
51
51
|
},
|
|
52
52
|
"homepage": "https://mastra.ai",
|
|
53
53
|
"repository": {
|