@mastra/mcp-docs-server 1.1.39-alpha.8 → 1.1.39
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/acp.md +238 -0
- package/.docs/docs/agents/agent-approval.md +2 -0
- package/.docs/docs/agents/background-tasks.md +9 -6
- package/.docs/docs/agents/response-caching.md +2 -0
- package/.docs/docs/agents/signals.md +29 -3
- package/.docs/docs/evals/evals-with-memory.md +146 -0
- package/.docs/docs/evals/running-in-ci.md +1 -0
- package/.docs/docs/memory/multi-user-threads.md +206 -0
- package/.docs/docs/memory/observational-memory.md +53 -17
- package/.docs/docs/memory/overview.md +1 -0
- package/.docs/docs/memory/working-memory.md +1 -1
- package/.docs/models/gateways/netlify.md +2 -1
- package/.docs/models/gateways/openrouter.md +2 -1
- package/.docs/models/index.md +1 -1
- package/.docs/models/providers/deepinfra.md +2 -2
- package/.docs/models/providers/fireworks-ai.md +23 -22
- package/.docs/models/providers/google.md +29 -46
- package/.docs/models/providers/llmgateway.md +186 -191
- package/.docs/models/providers/opencode.md +1 -1
- package/.docs/models/providers/orcarouter.md +2 -2
- package/.docs/models/providers/poe.md +2 -1
- package/.docs/models/providers/routing-run.md +27 -40
- package/.docs/models/providers/the-grid-ai.md +15 -9
- package/.docs/models/providers/xai.md +2 -1
- package/.docs/reference/agents/agent.md +13 -5
- package/.docs/reference/agents/channels.md +4 -2
- package/.docs/reference/client-js/agents.md +1 -1
- package/.docs/reference/configuration.md +1 -1
- package/.docs/reference/memory/observational-memory.md +5 -3
- package/.docs/reference/server/register-api-route.md +1 -1
- package/.docs/reference/storage/convex.md +74 -12
- package/.docs/reference/tools/mcp-client.md +27 -2
- package/.docs/reference/vectors/convex.md +129 -7
- package/CHANGELOG.md +66 -0
- package/package.json +6 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# routing.run
|
|
2
2
|
|
|
3
|
-
Access
|
|
3
|
+
Access 24 routing.run models through Mastra's model router. Authentication is handled automatically using the `ROUTING_RUN_API_KEY` environment variable.
|
|
4
4
|
|
|
5
5
|
Learn more in the [routing.run documentation](https://docs.routing.run).
|
|
6
6
|
|
|
@@ -32,45 +32,32 @@ for await (const chunk of stream) {
|
|
|
32
32
|
|
|
33
33
|
## Models
|
|
34
34
|
|
|
35
|
-
| Model
|
|
36
|
-
|
|
|
37
|
-
| `routing-run/route/deepseek-v3.2`
|
|
38
|
-
| `routing-run/route/deepseek-v4-flash`
|
|
39
|
-
| `routing-run/route/deepseek-v4-flash-
|
|
40
|
-
| `routing-run/route/deepseek-v4-pro`
|
|
41
|
-
| `routing-run/route/deepseek-v4-pro-
|
|
42
|
-
| `routing-run/route/gemma-4-31b-it`
|
|
43
|
-
| `routing-run/route/glm-
|
|
44
|
-
| `routing-run/route/glm-
|
|
45
|
-
| `routing-run/route/
|
|
46
|
-
| `routing-run/route/
|
|
47
|
-
| `routing-run/route/
|
|
48
|
-
| `routing-run/route/
|
|
49
|
-
| `routing-run/route/
|
|
50
|
-
| `routing-run/route/
|
|
51
|
-
| `routing-run/route/
|
|
52
|
-
| `routing-run/route/
|
|
53
|
-
| `routing-run/route/
|
|
54
|
-
| `routing-run/route/
|
|
55
|
-
| `routing-run/route/
|
|
56
|
-
| `routing-run/route/
|
|
57
|
-
| `routing-run/route/
|
|
58
|
-
| `routing-run/route/
|
|
59
|
-
| `routing-run/route/
|
|
60
|
-
| `routing-run/route/
|
|
61
|
-
| `routing-run/route/minimax-m2.7` | 100K | | | | | | $0.33 | $1 |
|
|
62
|
-
| `routing-run/route/minimax-m2.7-highspeed` | 100K | | | | | | $0.33 | $1 |
|
|
63
|
-
| `routing-run/route/mistral-large-3` | 128K | | | | | | $0.50 | $2 |
|
|
64
|
-
| `routing-run/route/mistral-medium-2505` | 128K | | | | | | $0.40 | $2 |
|
|
65
|
-
| `routing-run/route/mistral-small-2503` | 128K | | | | | | $0.15 | $0.60 |
|
|
66
|
-
| `routing-run/route/qwen3.5-397b-a17b` | 262K | | | | | | $1 | $3 |
|
|
67
|
-
| `routing-run/route/qwen3.5-9b` | 262K | | | | | | $0.20 | $0.60 |
|
|
68
|
-
| `routing-run/route/qwen3.5-9b-chat` | 262K | | | | | | $0.20 | $0.60 |
|
|
69
|
-
| `routing-run/route/qwen3.6-27b` | 262K | | | | | | $1 | $3 |
|
|
70
|
-
| `routing-run/route/step-3.5-flash` | 262K | | | | | | $0.10 | $0.29 |
|
|
71
|
-
| `routing-run/route/step-3.5-flash-2603` | 262K | | | | | | $0.10 | $0.30 |
|
|
72
|
-
| `routing-run/route/step-3.5-flash-full` | 262K | | | | | | $0.10 | $0.29 |
|
|
73
|
-
| `routing-run/route/stepfun-3.5-flash` | 262K | | | | | | $0.10 | $0.29 |
|
|
35
|
+
| Model | Context | Tools | Reasoning | Image | Audio | Video | Input $/1M | Output $/1M |
|
|
36
|
+
| ------------------------------------------ | ------- | ----- | --------- | ----- | ----- | ----- | ---------- | ----------- |
|
|
37
|
+
| `routing-run/route/deepseek-v3.2` | 164K | | | | | | $0.49 | $0.74 |
|
|
38
|
+
| `routing-run/route/deepseek-v4-flash` | 1.0M | | | | | | $0.49 | $0.74 |
|
|
39
|
+
| `routing-run/route/deepseek-v4-flash-6bit` | 1.0M | | | | | | $0.49 | $0.74 |
|
|
40
|
+
| `routing-run/route/deepseek-v4-pro` | 1.0M | | | | | | $0.49 | $0.74 |
|
|
41
|
+
| `routing-run/route/deepseek-v4-pro-6bit` | 1.0M | | | | | | $0.49 | $0.74 |
|
|
42
|
+
| `routing-run/route/gemma-4-31b-it` | 131K | | | | | | $0.10 | $0.30 |
|
|
43
|
+
| `routing-run/route/glm-5.1` | 203K | | | | | | $1 | $3 |
|
|
44
|
+
| `routing-run/route/glm-5.1-6bit` | 203K | | | | | | $1 | $3 |
|
|
45
|
+
| `routing-run/route/kimi-k2.5` | 131K | | | | | | $0.46 | $2 |
|
|
46
|
+
| `routing-run/route/kimi-k2.6` | 262K | | | | | | $0.46 | $2 |
|
|
47
|
+
| `routing-run/route/kimi-k2.6-6bit` | 262K | | | | | | $0.46 | $2 |
|
|
48
|
+
| `routing-run/route/mimo-v2.5-pro` | 1.0M | | | | | | $0.45 | $1 |
|
|
49
|
+
| `routing-run/route/mimo-v2.5-pro-6bit` | 1.0M | | | | | | $0.45 | $1 |
|
|
50
|
+
| `routing-run/route/minimax-m2.5` | 100K | | | | | | $0.19 | $1 |
|
|
51
|
+
| `routing-run/route/minimax-m2.5-highspeed` | 100K | | | | | | $0.19 | $1 |
|
|
52
|
+
| `routing-run/route/minimax-m2.7` | 100K | | | | | | $0.33 | $1 |
|
|
53
|
+
| `routing-run/route/minimax-m2.7-highspeed` | 100K | | | | | | $0.33 | $1 |
|
|
54
|
+
| `routing-run/route/mistral-large-3` | 128K | | | | | | $0.50 | $2 |
|
|
55
|
+
| `routing-run/route/mistral-medium-2505` | 128K | | | | | | $0.40 | $2 |
|
|
56
|
+
| `routing-run/route/mistral-small-2503` | 128K | | | | | | $0.15 | $0.60 |
|
|
57
|
+
| `routing-run/route/qwen3.6-27b` | 262K | | | | | | $1 | $3 |
|
|
58
|
+
| `routing-run/route/step-3.5-flash` | 262K | | | | | | $0.10 | $0.29 |
|
|
59
|
+
| `routing-run/route/step-3.5-flash-2603` | 262K | | | | | | $0.10 | $0.30 |
|
|
60
|
+
| `routing-run/route/stepfun-3.5-flash` | 262K | | | | | | $0.10 | $0.29 |
|
|
74
61
|
|
|
75
62
|
## Advanced configuration
|
|
76
63
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# The Grid AI
|
|
2
2
|
|
|
3
|
-
Access
|
|
3
|
+
Access 9 The Grid AI models through Mastra's model router. Authentication is handled automatically using the `THEGRIDAI_API_KEY` environment variable.
|
|
4
4
|
|
|
5
5
|
Learn more in the [The Grid AI documentation](https://thegrid.ai/docs).
|
|
6
6
|
|
|
@@ -15,7 +15,7 @@ const agent = new Agent({
|
|
|
15
15
|
id: "my-agent",
|
|
16
16
|
name: "My Agent",
|
|
17
17
|
instructions: "You are a helpful assistant",
|
|
18
|
-
model: "the-grid-ai/
|
|
18
|
+
model: "the-grid-ai/agent-max"
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
// Generate a response
|
|
@@ -32,11 +32,17 @@ for await (const chunk of stream) {
|
|
|
32
32
|
|
|
33
33
|
## Models
|
|
34
34
|
|
|
35
|
-
| Model
|
|
36
|
-
|
|
|
37
|
-
| `the-grid-ai/
|
|
38
|
-
| `the-grid-ai/
|
|
39
|
-
| `the-grid-ai/
|
|
35
|
+
| Model | Context | Tools | Reasoning | Image | Audio | Video | Input $/1M | Output $/1M |
|
|
36
|
+
| ---------------------------- | ------- | ----- | --------- | ----- | ----- | ----- | ---------- | ----------- |
|
|
37
|
+
| `the-grid-ai/agent-max` | 1.0M | | | | | | — | — |
|
|
38
|
+
| `the-grid-ai/agent-prime` | 128K | | | | | | — | — |
|
|
39
|
+
| `the-grid-ai/agent-standard` | 128K | | | | | | — | — |
|
|
40
|
+
| `the-grid-ai/code-max` | 1.0M | | | | | | — | — |
|
|
41
|
+
| `the-grid-ai/code-prime` | 128K | | | | | | — | — |
|
|
42
|
+
| `the-grid-ai/code-standard` | 128K | | | | | | — | — |
|
|
43
|
+
| `the-grid-ai/text-max` | 1.0M | | | | | | — | — |
|
|
44
|
+
| `the-grid-ai/text-prime` | 128K | | | | | | — | — |
|
|
45
|
+
| `the-grid-ai/text-standard` | 128K | | | | | | — | — |
|
|
40
46
|
|
|
41
47
|
## Advanced configuration
|
|
42
48
|
|
|
@@ -48,7 +54,7 @@ const agent = new Agent({
|
|
|
48
54
|
name: "custom-agent",
|
|
49
55
|
model: {
|
|
50
56
|
url: "https://api.thegrid.ai/v1",
|
|
51
|
-
id: "the-grid-ai/
|
|
57
|
+
id: "the-grid-ai/agent-max",
|
|
52
58
|
apiKey: process.env.THEGRIDAI_API_KEY,
|
|
53
59
|
headers: {
|
|
54
60
|
"X-Custom-Header": "value"
|
|
@@ -67,7 +73,7 @@ const agent = new Agent({
|
|
|
67
73
|
const useAdvanced = requestContext.task === "complex";
|
|
68
74
|
return useAdvanced
|
|
69
75
|
? "the-grid-ai/text-standard"
|
|
70
|
-
: "the-grid-ai/
|
|
76
|
+
: "the-grid-ai/agent-max";
|
|
71
77
|
}
|
|
72
78
|
});
|
|
73
79
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# xAI
|
|
2
2
|
|
|
3
|
-
Access
|
|
3
|
+
Access 16 xAI models through Mastra's model router. Authentication is handled automatically using the `XAI_API_KEY` environment variable.
|
|
4
4
|
|
|
5
5
|
Learn more in the [xAI documentation](https://docs.x.ai/docs/models).
|
|
6
6
|
|
|
@@ -43,6 +43,7 @@ for await (const chunk of stream) {
|
|
|
43
43
|
| `xai/grok-4.20-multi-agent-0309` | 2.0M | | | | | | $2 | $6 |
|
|
44
44
|
| `xai/grok-4.3` | 1.0M | | | | | | $1 | $3 |
|
|
45
45
|
| `xai/grok-beta` | 131K | | | | | | $5 | $15 |
|
|
46
|
+
| `xai/grok-build-0.1` | 256K | | | | | | $1 | $2 |
|
|
46
47
|
| `xai/grok-imagine-image` | 1K | | | | | | — | — |
|
|
47
48
|
| `xai/grok-imagine-image-quality` | 1K | | | | | | — | — |
|
|
48
49
|
| `xai/grok-imagine-video` | 1K | | | | | | — | — |
|
|
@@ -126,24 +126,32 @@ agent.sendSignal(
|
|
|
126
126
|
)
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
-
Use a
|
|
129
|
+
Use `attributes` to identify different users in a shared thread. The signal type and attributes are rendered as XML so the model can distinguish who said what:
|
|
130
130
|
|
|
131
131
|
```typescript
|
|
132
132
|
agent.sendSignal(
|
|
133
133
|
{
|
|
134
|
-
type: '
|
|
135
|
-
contents: '
|
|
136
|
-
attributes: {
|
|
134
|
+
type: 'user',
|
|
135
|
+
contents: 'Can we simplify the API surface?',
|
|
136
|
+
attributes: { name: 'Devin', from: 'slack' },
|
|
137
137
|
},
|
|
138
138
|
{ resourceId: 'user-123', threadId: 'thread-abc' },
|
|
139
139
|
)
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
+
The model receives this as:
|
|
143
|
+
|
|
144
|
+
```xml
|
|
145
|
+
<user name="Devin" from="slack">Can we simplify the API surface?</user>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The UI sees just the message contents but can also read `attributes` and `metadata` off the signal message for custom rendering (e.g. showing user names, avatars, or platform badges).
|
|
149
|
+
|
|
142
150
|
### `sendSignal(signal, options)`
|
|
143
151
|
|
|
144
152
|
Sends a signal to an active run or memory thread.
|
|
145
153
|
|
|
146
|
-
**signal** (`{ type: 'user-message' | string; contents: string | Array<TextPart | FilePart>; attributes?: Record<string, JSONValue>; metadata?: Record<string, unknown>; providerOptions?: ProviderMetadata }`): \`user-message\` signals are treated as user input.
|
|
154
|
+
**signal** (`{ type: 'user-message' | 'system-reminder' | string; contents: string | Array<TextPart | FilePart>; attributes?: Record<string, JSONValue>; metadata?: Record<string, unknown>; providerOptions?: ProviderMetadata }`): \`user-message\` signals without attributes are treated as plain user input. All other signals — including \`user-message\` with \`attributes\`, \`system-reminder\`, and custom types — are wrapped in an XML element named after the signal type with \`attributes\` rendered as XML attributes (e.g. \`\<user name="Devin" from="slack">message\</user>\`). The model sees the XML; the UI sees the raw contents and can read \`attributes\` for custom rendering. \`providerOptions\` is attached to the resulting prompt turn and persisted on the stored signal message.
|
|
147
155
|
|
|
148
156
|
**options.runId** (`string`): Run ID to target directly. Use this when you already know the active run ID.
|
|
149
157
|
|
|
@@ -31,7 +31,7 @@ export const supportAgent = new Agent({
|
|
|
31
31
|
|
|
32
32
|
**handlers** (`ChannelHandlers`): Override default message handlers for DMs, mentions, and subscribed threads.
|
|
33
33
|
|
|
34
|
-
**inlineMedia** (`string[] | ((mimeType: string) => boolean)`): Controls which attachment types are sent as file parts to the model. Types that do not match are described as text summaries. Accepts an array of mime type globs or a predicate function. (Default: `['image
|
|
34
|
+
**inlineMedia** (`string[] | ((mimeType: string) => boolean)`): Controls which attachment types are sent as file parts to the model. Types that do not match are described as text summaries. Accepts an array of mime type globs or a predicate function. The default matches the formats supported by major vision models. (Default: `['image/png', 'image/jpeg', 'image/webp', 'application/pdf']`)
|
|
35
35
|
|
|
36
36
|
**inlineLinks** (`InlineLinkEntry[]`): Promote URLs found in message text to file parts so the model can process linked content. Each entry matches a domain. Disabled by default.
|
|
37
37
|
|
|
@@ -91,7 +91,7 @@ const agent = new Agent({
|
|
|
91
91
|
|
|
92
92
|
Override built-in event handlers. Each handler can be:
|
|
93
93
|
|
|
94
|
-
- **Omitted**: uses the default Mastra handler (routes
|
|
94
|
+
- **Omitted**: uses the default Mastra handler (routes the message through the agent and posts the response)
|
|
95
95
|
- **`false`**: disables the handler entirely
|
|
96
96
|
- **A function** `(thread, message, defaultHandler) => Promise<void>`: wraps or replaces the default
|
|
97
97
|
|
|
@@ -138,6 +138,8 @@ type ChannelHandler = (
|
|
|
138
138
|
|
|
139
139
|
Controls which attachment types (images, video, PDFs, etc.) are sent as file parts to the model. Types that do not match are described as text summaries so the agent knows about the file without crashing models that reject unsupported types.
|
|
140
140
|
|
|
141
|
+
The default (`['image/png', 'image/jpeg', 'image/webp', 'application/pdf']`) matches the formats supported by major vision models. Override `inlineMedia` to expand the list (e.g. `['image/*', 'audio/*']`) or replace it entirely with a predicate function.
|
|
142
|
+
|
|
141
143
|
Supported glob patterns:
|
|
142
144
|
|
|
143
145
|
| Pattern | Matches |
|
|
@@ -201,7 +201,7 @@ await agent.sendSignal({
|
|
|
201
201
|
|
|
202
202
|
Returns `{ accepted: true, runId: string }`.
|
|
203
203
|
|
|
204
|
-
**signal** (`{ type: 'user-message' | string; contents: string | Array<TextPart | FilePart>; attributes?: Record<string, JSONValue>; metadata?: Record<string, unknown>; providerOptions?: ProviderMetadata }`): \`user-message\` signals are treated as user input.
|
|
204
|
+
**signal** (`{ type: 'user-message' | 'system-reminder' | string; contents: string | Array<TextPart | FilePart>; attributes?: Record<string, JSONValue>; metadata?: Record<string, unknown>; providerOptions?: ProviderMetadata }`): \`user-message\` signals without attributes are treated as plain user input. All other signals — including \`user-message\` with \`attributes\`, \`system-reminder\`, and custom types — are wrapped in an XML element named after the signal type with \`attributes\` rendered as XML attributes (e.g. \`\<user name="Devin" from="slack">message\</user>\`). The model sees the XML; the UI sees the raw contents and can read \`attributes\` for custom rendering. \`providerOptions\` is attached to the resulting prompt turn and persisted on the stored signal message.
|
|
205
205
|
|
|
206
206
|
**runId** (`string`): Run ID to target directly.
|
|
207
207
|
|
|
@@ -63,7 +63,7 @@ export const mastra = new Mastra({
|
|
|
63
63
|
})
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
**enabled** (`boolean`): Whether background
|
|
66
|
+
**enabled** (`boolean`): Whether the background task manager is available. The manager only initializes when this is true and a storage backend is configured. This is a feature-availability switch — it does not opt any tool into background dispatch. Tools must opt in at the tool or agent layer (see the Background tasks guide). (Default: `false`)
|
|
67
67
|
|
|
68
68
|
**globalConcurrency** (`number`): Maximum number of background tasks running concurrently across all agents. (Default: `10`)
|
|
69
69
|
|
|
@@ -36,7 +36,7 @@ OM performs thresholding with fast local token estimation. Text uses `tokenx`, a
|
|
|
36
36
|
|
|
37
37
|
**scope** (`'resource' | 'thread'`): Memory scope for observations. \`'thread'\` keeps observations per-thread. \`'resource'\` (experimental) shares observations across all threads for a resource, enabling cross-conversation memory. (Default: `'thread'`)
|
|
38
38
|
|
|
39
|
-
**activateAfterIdle** (`number | string | false`): Time before buffered observations are forced to activate after inactivity, even before \`observation.messageTokens\` is reached. Accepts a numeric millisecond value such as \`300\_000\`, duration strings like \`"5m"\` or \`"1hr"\`, or \`false\` to disable inherited observation idle activation. Reflections do not inherit this setting. Use \`reflection.activateAfterIdle\` to opt reflections into idle activation.
|
|
39
|
+
**activateAfterIdle** (`number | string | false | "auto"`): Time before buffered observations are forced to activate after inactivity, even before \`observation.messageTokens\` is reached. Accepts a numeric millisecond value such as \`300\_000\`, duration strings like \`"5m"\` or \`"1hr"\`, \`"auto"\` for a provider-aware prompt cache TTL, or \`false\` to disable inherited observation idle activation. Reflections do not inherit this setting. Use \`reflection.activateAfterIdle\` to opt reflections into idle activation.
|
|
40
40
|
|
|
41
41
|
**activateOnProviderChange** (`boolean`): Force buffered observations to activate when the actor provider or model changes. Reflections do not inherit this setting. Use \`reflection.activateOnProviderChange\` to opt reflections into provider-change activation. (Default: `false`)
|
|
42
42
|
|
|
@@ -54,6 +54,8 @@ OM performs thresholding with fast local token estimation. Text uses `tokenx`, a
|
|
|
54
54
|
|
|
55
55
|
**observation.threadTitle** (`boolean`): When \`true\`, the Observer suggests short thread titles and updates the thread title when the conversation topic meaningfully changes. This is opt-in and defaults to disabled.
|
|
56
56
|
|
|
57
|
+
**observation.observeAttachments** (`boolean | string[]`): Controls which image/file attachments are forwarded to the Observer model alongside their placeholder text lines. \`true\` (default) forwards all attachments. \`false\` drops all attachments while keeping placeholders visible. An array is a case-insensitive mimeType allowlist supporting exact matches (\`'application/pdf'\`), wildcard subtypes (\`'image/\*'\`), and bare \`'\*'\` for everything. Useful when the Observer model is text-only (e.g. some DeepSeek endpoints) while the main agent uses a multimodal model. Tool-result attachments are filtered using the same rule.
|
|
58
|
+
|
|
57
59
|
**observation.messageTokens** (`number`): Token count of unobserved messages that triggers observation. When unobserved message tokens exceed this threshold, the Observer agent is called. Text is estimated locally with \`tokenx\`. Image parts are included with model-aware heuristics when possible, with deterministic fallbacks when image metadata is incomplete. Image-like \`file\` parts are counted the same way when uploads are normalized as files.
|
|
58
60
|
|
|
59
61
|
**observation.maxTokensPerBatch** (`number`): Maximum tokens per batch when observing multiple threads in resource scope. Threads are chunked into batches of this size and processed in parallel. Lower values mean more parallelism but more API calls.
|
|
@@ -68,7 +70,7 @@ OM performs thresholding with fast local token estimation. Text uses `tokenx`, a
|
|
|
68
70
|
|
|
69
71
|
**observation.bufferActivation** (`number`): Controls how much of the message window to retain after activation. Accepts a ratio (0-1) or an absolute token count (≥ 1000). For example, \`0.8\` means: activate enough buffers to remove 80% of \`messageTokens\` and leave 20% as active message history. An absolute token count like \`4000\` targets a goal of keeping \~4k message tokens remaining after activation. Higher values remove more message history per activation when using a ratio. Higher values keep more message history when using a token count.
|
|
70
72
|
|
|
71
|
-
**observation.activateAfterIdle** (`number | string | false`): Time before buffered observations are forced to activate after inactivity. Accepts milliseconds, a duration string, or \`false\`. If unset, the top-level \`activateAfterIdle\` value is used for observations. Set \`false\` to disable the top-level idle setting for observations.
|
|
73
|
+
**observation.activateAfterIdle** (`number | string | false | "auto"`): Time before buffered observations are forced to activate after inactivity. Accepts milliseconds, a duration string, \`"auto"\` for a provider-aware prompt cache TTL, or \`false\`. If unset, the top-level \`activateAfterIdle\` value is used for observations. Set \`false\` to disable the top-level idle setting for observations.
|
|
72
74
|
|
|
73
75
|
**observation.activateOnProviderChange** (`boolean`): Force buffered observations to activate when the actor provider or model changes. If unset, the top-level \`activateOnProviderChange\` value is used for observations.
|
|
74
76
|
|
|
@@ -92,7 +94,7 @@ OM performs thresholding with fast local token estimation. Text uses `tokenx`, a
|
|
|
92
94
|
|
|
93
95
|
**reflection.bufferActivation** (`number`): Ratio (0-1) controlling when async reflection buffering starts. When observation tokens reach \`observationTokens \* bufferActivation\`, reflection runs in the background. On activation at the full threshold, the buffered reflection replaces the observations it covers, preserving any new observations appended after that range.
|
|
94
96
|
|
|
95
|
-
**reflection.activateAfterIdle** (`number | string | false`): Time before buffered reflections are forced to activate after inactivity. Accepts milliseconds, a duration string, or \`false\`. Reflections do not inherit top-level \`activateAfterIdle\`; set this explicitly to opt reflections into idle activation.
|
|
97
|
+
**reflection.activateAfterIdle** (`number | string | false | "auto"`): Time before buffered reflections are forced to activate after inactivity. Accepts milliseconds, a duration string, \`"auto"\` for a provider-aware prompt cache TTL, or \`false\`. Reflections do not inherit top-level \`activateAfterIdle\`; set this explicitly to opt reflections into idle activation.
|
|
96
98
|
|
|
97
99
|
**reflection.activateOnProviderChange** (`boolean`): Force buffered reflections to activate when the actor provider or model changes. Reflections do not inherit top-level \`activateOnProviderChange\`; set this explicitly to opt reflections into provider-change activation.
|
|
98
100
|
|
|
@@ -18,7 +18,7 @@ The URL path for the route. Supports path parameters using `:param` syntax.
|
|
|
18
18
|
registerApiRoute("/items/:itemId", { ... })
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
**Note:**
|
|
21
|
+
**Note:** Custom route paths can't start with the server's configured `apiPrefix` (default: `/api`), as that prefix is reserved for built-in Mastra routes. If you set a custom `apiPrefix`, only that prefix is reserved — for example, with `apiPrefix: '/mastra/api'`, paths like `/api/my-endpoint` are allowed.
|
|
22
22
|
|
|
23
23
|
### options
|
|
24
24
|
|
|
@@ -34,7 +34,7 @@ bun add @mastra/convex@latest
|
|
|
34
34
|
|
|
35
35
|
## Convex setup
|
|
36
36
|
|
|
37
|
-
Before using `ConvexStore`,
|
|
37
|
+
Before using `ConvexStore`, set up the Convex schema and storage handler in your Convex project. The schema example below includes the full `ConvexStore` and `ConvexServerCache` setup. If you only use `ConvexStore`, omit `mastraCacheTable` and `mastraCacheListItemsTable`; if you use `ConvexServerCache`, include those tables and create the cache handler.
|
|
38
38
|
|
|
39
39
|
### 1. Set up Convex Schema
|
|
40
40
|
|
|
@@ -50,6 +50,8 @@ import {
|
|
|
50
50
|
mastraScoresTable,
|
|
51
51
|
mastraVectorIndexesTable,
|
|
52
52
|
mastraVectorsTable,
|
|
53
|
+
mastraCacheTable,
|
|
54
|
+
mastraCacheListItemsTable,
|
|
53
55
|
mastraDocumentsTable,
|
|
54
56
|
} from '@mastra/convex/schema'
|
|
55
57
|
|
|
@@ -61,6 +63,8 @@ export default defineSchema({
|
|
|
61
63
|
mastra_scorers: mastraScoresTable,
|
|
62
64
|
mastra_vector_indexes: mastraVectorIndexesTable,
|
|
63
65
|
mastra_vectors: mastraVectorsTable,
|
|
66
|
+
mastra_cache: mastraCacheTable,
|
|
67
|
+
mastra_cache_list_items: mastraCacheListItemsTable,
|
|
64
68
|
mastra_documents: mastraDocumentsTable,
|
|
65
69
|
})
|
|
66
70
|
```
|
|
@@ -75,6 +79,14 @@ import { mastraStorage } from '@mastra/convex/server'
|
|
|
75
79
|
export const handle = mastraStorage
|
|
76
80
|
```
|
|
77
81
|
|
|
82
|
+
If you use `ConvexServerCache`, create `convex/mastra/cache.ts`:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { mastraCache } from '@mastra/convex/server'
|
|
86
|
+
|
|
87
|
+
export const handle = mastraCache
|
|
88
|
+
```
|
|
89
|
+
|
|
78
90
|
### 3. Deploy to Convex
|
|
79
91
|
|
|
80
92
|
```bash
|
|
@@ -86,16 +98,21 @@ npx convex deploy
|
|
|
86
98
|
## Usage
|
|
87
99
|
|
|
88
100
|
```typescript
|
|
89
|
-
import { ConvexStore } from '@mastra/convex'
|
|
101
|
+
import { ConvexServerCache, ConvexStore } from '@mastra/convex'
|
|
90
102
|
|
|
91
103
|
const storage = new ConvexStore({
|
|
92
104
|
id: 'convex-storage',
|
|
93
105
|
deploymentUrl: process.env.CONVEX_URL!,
|
|
94
106
|
adminAuthToken: process.env.CONVEX_ADMIN_KEY!,
|
|
95
107
|
})
|
|
108
|
+
|
|
109
|
+
const cache = new ConvexServerCache({
|
|
110
|
+
deploymentUrl: process.env.CONVEX_URL!,
|
|
111
|
+
adminAuthToken: process.env.CONVEX_ADMIN_KEY!,
|
|
112
|
+
})
|
|
96
113
|
```
|
|
97
114
|
|
|
98
|
-
##
|
|
115
|
+
## ConvexStore parameters
|
|
99
116
|
|
|
100
117
|
**deploymentUrl** (`string`): Convex deployment URL (e.g., https\://your-project.convex.cloud)
|
|
101
118
|
|
|
@@ -103,10 +120,24 @@ const storage = new ConvexStore({
|
|
|
103
120
|
|
|
104
121
|
**storageFunction** (`string`): Path to the storage mutation function (default: 'mastra/storage:handle') (Default: `mastra/storage:handle`)
|
|
105
122
|
|
|
123
|
+
## ConvexServerCache parameters
|
|
124
|
+
|
|
125
|
+
**deploymentUrl** (`string`): Convex deployment URL (e.g., https\://your-project.convex.cloud)
|
|
126
|
+
|
|
127
|
+
**adminAuthToken** (`string`): Convex admin authentication token for backend access
|
|
128
|
+
|
|
129
|
+
**cacheFunction** (`string`): Path to the cache mutation function for ConvexServerCache (default: 'mastra/cache:handle') (Default: `mastra/cache:handle`)
|
|
130
|
+
|
|
131
|
+
**requestTimeoutMs** (`number`): Timeout for Convex cache mutation requests in milliseconds. Set to 0 to disable the client-side timeout. (Default: `30000`)
|
|
132
|
+
|
|
133
|
+
**keyPrefix** (`string`): Prefix applied to ConvexServerCache keys. clear() removes rows whose stored prefix exactly matches this value. (Default: `mastra:cache:`)
|
|
134
|
+
|
|
135
|
+
**ttlMs** (`number`): Default ConvexServerCache TTL in milliseconds. Set to 0 to disable expiry. (Default: `300000`)
|
|
136
|
+
|
|
106
137
|
## Constructor examples
|
|
107
138
|
|
|
108
139
|
```ts
|
|
109
|
-
import { ConvexStore } from '@mastra/convex'
|
|
140
|
+
import { ConvexServerCache, ConvexStore } from '@mastra/convex'
|
|
110
141
|
|
|
111
142
|
// Basic configuration
|
|
112
143
|
const store = new ConvexStore({
|
|
@@ -122,22 +153,53 @@ const storeCustom = new ConvexStore({
|
|
|
122
153
|
adminAuthToken: 'your-admin-token',
|
|
123
154
|
storageFunction: 'custom/path:handler',
|
|
124
155
|
})
|
|
156
|
+
|
|
157
|
+
// Server cache for durable stream replay and response caching
|
|
158
|
+
const cache = new ConvexServerCache({
|
|
159
|
+
deploymentUrl: 'https://your-project.convex.cloud',
|
|
160
|
+
adminAuthToken: 'your-admin-token',
|
|
161
|
+
cacheFunction: 'mastra/cache:handle',
|
|
162
|
+
})
|
|
125
163
|
```
|
|
126
164
|
|
|
165
|
+
## Server cache
|
|
166
|
+
|
|
167
|
+
`ConvexServerCache` implements Mastra's server cache contract with Convex. Use it when you want durable cache state for features such as resumable durable-agent streams, workflow stream replay, or response caching.
|
|
168
|
+
|
|
169
|
+
`ConvexServerCache` stores list entries as separate Convex documents. This avoids growing a stream replay list inside one document and helps stay within Convex's record size limit.
|
|
170
|
+
|
|
171
|
+
Each scalar cache value and each list item is stored as one Convex row and must stay within Convex's row-size limits. Very large lists are still bounded by Convex query limits when replaying a range.
|
|
172
|
+
|
|
173
|
+
Cache cleanup and `clear()` run in bounded batches. A single client call can loop through up to 1,000 Convex mutations, with each mutation handling up to 25 list items. While `clear()` is cleaning a key, reads for that key can return empty results until cleanup finishes.
|
|
174
|
+
|
|
175
|
+
For very large cache namespaces, clear incrementally or use narrower prefixes to avoid long-running cleanup operations.
|
|
176
|
+
|
|
177
|
+
During batched cleanup, cache metadata can temporarily use an internal `deleted` state. The next cleanup pass removes those rows. Avoid writing new values with the same prefix until `clear()` finishes.
|
|
178
|
+
|
|
179
|
+
`clear()` only removes rows whose stored `keyPrefix` exactly matches the configured `keyPrefix`. It does not clear nested prefixes by string prefix matching. Each `listPush()` refreshes the list TTL using the cache's configured `ttlMs`.
|
|
180
|
+
|
|
181
|
+
Use a non-empty `keyPrefix` unless you intentionally want `clear()` to remove every cache key in the deployment. Expired list rows are reclaimed incrementally during reads and writes; `clear()` removes all rows for the prefix.
|
|
182
|
+
|
|
183
|
+
`ConvexServerCache` works best for durable replay of moderate-frequency events. For high-frequency token streams, prefer batching events or using a lower-latency cache backend.
|
|
184
|
+
|
|
185
|
+
`ConvexServerCache` does not replace a distributed pub/sub transport. If your app needs live cross-process event delivery, configure a production pub/sub backend separately.
|
|
186
|
+
|
|
127
187
|
## Additional notes
|
|
128
188
|
|
|
129
189
|
### Schema Management
|
|
130
190
|
|
|
131
191
|
The storage implementation uses typed Convex tables for each Mastra domain:
|
|
132
192
|
|
|
133
|
-
| Domain
|
|
134
|
-
|
|
|
135
|
-
| Threads
|
|
136
|
-
| Messages
|
|
137
|
-
| Resources
|
|
138
|
-
| Workflows
|
|
139
|
-
| Scorers
|
|
140
|
-
|
|
|
193
|
+
| Domain | Convex Table | Purpose |
|
|
194
|
+
| ----------- | --------------------------- | ----------------------------------------- |
|
|
195
|
+
| Threads | `mastra_threads` | Conversation threads |
|
|
196
|
+
| Messages | `mastra_messages` | Chat messages |
|
|
197
|
+
| Resources | `mastra_resources` | User working memory |
|
|
198
|
+
| Workflows | `mastra_workflow_snapshots` | Workflow state |
|
|
199
|
+
| Scorers | `mastra_scorers` | Evaluation data |
|
|
200
|
+
| Cache | `mastra_cache` | Cache values, counters, and list metadata |
|
|
201
|
+
| Cache Items | `mastra_cache_list_items` | Cache list entries |
|
|
202
|
+
| Fallback | `mastra_documents` | Unknown tables |
|
|
141
203
|
|
|
142
204
|
### Architecture
|
|
143
205
|
|
|
@@ -53,7 +53,7 @@ Each server in the `servers` map is configured using the `MastraMCPServerDefinit
|
|
|
53
53
|
|
|
54
54
|
**enableServerLogs** (`boolean`): Whether to enable logging for this server. (Default: `true`)
|
|
55
55
|
|
|
56
|
-
**requireToolApproval** (`boolean | (params: RequireToolApprovalContext) => boolean | Promise<boolean>`): Require human approval before executing tools from this server. When set to \`true\`, all tools require approval. When set to a function, the function is called with the tool name, arguments,
|
|
56
|
+
**requireToolApproval** (`boolean | (params: RequireToolApprovalContext) => boolean | Promise<boolean>`): Require human approval before executing tools from this server. When set to \`true\`, all tools require approval. When set to a function, the function is called with the tool name, arguments, request context, and any tool annotations advertised by the server to dynamically decide whether approval is needed.
|
|
57
57
|
|
|
58
58
|
## Tool approval
|
|
59
59
|
|
|
@@ -76,7 +76,7 @@ const mcp = new MCPClient({
|
|
|
76
76
|
|
|
77
77
|
### Dynamic approval with a function
|
|
78
78
|
|
|
79
|
-
Pass a function to decide per-call whether approval is needed. The function receives the tool name, the arguments the model passed,
|
|
79
|
+
Pass a function to decide per-call whether approval is needed. The function receives the tool name, the arguments the model passed, any request context from the incoming request, and the tool's MCP `annotations` (when the server advertises them):
|
|
80
80
|
|
|
81
81
|
```typescript
|
|
82
82
|
const mcp = new MCPClient({
|
|
@@ -98,6 +98,31 @@ const mcp = new MCPClient({
|
|
|
98
98
|
|
|
99
99
|
The function can also be async. It receives `requestContext` from the incoming request, which you can use for auth checks or other per-request logic.
|
|
100
100
|
|
|
101
|
+
### Use tool annotations from a trusted server
|
|
102
|
+
|
|
103
|
+
If you trust the MCP server, you can use its [tool annotations](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool-annotations) (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`, `title`) to drive approval decisions:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
const mcp = new MCPClient({
|
|
107
|
+
servers: {
|
|
108
|
+
github: {
|
|
109
|
+
url: new URL('http://localhost:3000/mcp'),
|
|
110
|
+
requireToolApproval: ({ annotations }) => {
|
|
111
|
+
// Skip approval for tools the server has marked read-only
|
|
112
|
+
if (annotations?.readOnlyHint) return false
|
|
113
|
+
// Always require approval for destructive tools
|
|
114
|
+
if (annotations?.destructiveHint) return true
|
|
115
|
+
return true
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
})
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Per the MCP specification, **clients MUST consider tool annotations to be untrusted unless they come from trusted servers**. Annotations are advisory hints, not a security boundary — a malicious or buggy server can claim a tool is read-only when it isn't. Only use annotations to relax approval requirements for servers you trust.
|
|
123
|
+
|
|
124
|
+
The same annotations are also exposed on the tools returned by `listTools()` and `listToolsets()` under `tool.mcp.annotations`, so you can inspect them when wiring tools into an agent.
|
|
125
|
+
|
|
101
126
|
## Methods
|
|
102
127
|
|
|
103
128
|
### `listTools()`
|