@mastra/mcp-docs-server 1.1.39-alpha.10 → 1.1.39-alpha.11

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.
@@ -88,7 +88,7 @@ const memory = new Memory({
88
88
  options: {
89
89
  observationalMemory: {
90
90
  model: 'google/gemini-2.5-flash',
91
- activateAfterIdle: '5m',
91
+ activateAfterIdle: 'auto',
92
92
  activateOnProviderChange: true,
93
93
  },
94
94
  },
@@ -144,6 +144,28 @@ OM uses fast local token estimation for this thresholding work. Text is estimate
144
144
 
145
145
  The Observer can also see attachments in the history it reviews. OM keeps readable placeholders like `[Image #1: reference-board.png]` or `[File #1: floorplan.pdf]` in the transcript for readability, and forwards the actual attachment parts alongside the text. Image-like `file` parts are upgraded to image inputs for the Observer when possible, while non-image attachments are forwarded as file parts with normalized token counting. This applies to both normal thread observation and batched resource-scope observation.
146
146
 
147
+ If your Observer model is text-only or its API rejects multimodal input, set `observation.observeAttachments` to `false` to drop attachments before they reach the Observer. The readable placeholders (`[Image #1: ...]`, `[File #1: ...]`) are kept in the transcript so the Observer can still reason about what was shared without receiving the binary payload. The same filter applies to tool results that contain image or file parts:
148
+
149
+ ```typescript
150
+ new Agent({
151
+ name: 'assistant',
152
+ instructions: 'You are a helpful assistant.',
153
+ model: 'openai/gpt-5-mini',
154
+ memory: new Memory({
155
+ options: {
156
+ observationalMemory: {
157
+ observation: {
158
+ model: 'deepseek/deepseek-reasoner',
159
+ observeAttachments: false,
160
+ },
161
+ },
162
+ },
163
+ }),
164
+ })
165
+ ```
166
+
167
+ You can also pass an allowlist of mimeType globs (for example `['image/*']`) to forward only the kinds the Observer can handle.
168
+
147
169
  ```md
148
170
  Date: 2026-01-15
149
171
 
@@ -444,35 +466,48 @@ Reflection works similarly — the Reflector runs in the background when observa
444
466
 
445
467
  ### Settings
446
468
 
447
- | Setting | Default | What it controls |
448
- | ------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
449
- | `observation.bufferTokens` | `0.2` | How often to buffer. `0.2` means every 20% of `messageTokens` — with the default 30k threshold, that's roughly every 6k tokens. Can also be an absolute token count (e.g. `5000`). |
450
- | `observation.bufferActivation` | `0.8` | How aggressively to clear the message window on activation. `0.8` means remove enough messages to keep only 20% of `messageTokens` remaining. Lower values keep more message history. |
451
- | `observation.blockAfter` | `1.2` | Safety threshold as a multiplier of `messageTokens`. At `1.2`, synchronous observation is forced at 36k tokens (1.2 × 30k). Only matters if buffering can't keep up. |
452
- | `activateAfterIdle` | none | Forces buffered observations to activate after a period of inactivity, even before `observation.messageTokens` is reached. Accepts a numeric millisecond value such as `300_000`, or duration strings like `"5m"` or `"1hr"`. Set this to your prompt cache TTL if you want activation to happen before the next cold prompt. |
453
- | `activateOnProviderChange` | `false` | Forces buffered observations to activate when the next step uses a different `provider/model` than the one that produced the latest assistant step. Use this when switching providers or models would invalidate prompt cache reuse. |
454
- | `reflection.bufferActivation` | `0.5` | When to start background reflection. `0.5` means reflection begins when observations reach 50% of the `observationTokens` threshold. |
455
- | `reflection.activateAfterIdle` | none | Opts buffered reflections into idle activation. Reflections don't inherit top-level `activateAfterIdle`. |
456
- | `reflection.activateOnProviderChange` | `false` | Opts buffered reflections into provider-change activation. Reflections don't inherit top-level `activateOnProviderChange`. |
457
- | `reflection.blockAfter` | `1.2` | Safety threshold for reflection, same logic as observation. |
458
-
459
- If you're relying on prompt caching, set `activateAfterIdle` to match your cache TTL. That way, once a thread has been idle long enough for the cache to expire, the next request can activate buffered observations first and send a smaller compressed context window.
469
+ | Setting | Default | What it controls |
470
+ | ------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
471
+ | `observation.bufferTokens` | `0.2` | How often to buffer. `0.2` means every 20% of `messageTokens` — with the default 30k threshold, that's roughly every 6k tokens. Can also be an absolute token count (e.g. `5000`). |
472
+ | `observation.bufferActivation` | `0.8` | How aggressively to clear the message window on activation. `0.8` means remove enough messages to keep only 20% of `messageTokens` remaining. Lower values keep more message history. |
473
+ | `observation.blockAfter` | `1.2` | Safety threshold as a multiplier of `messageTokens`. At `1.2`, synchronous observation is forced at 36k tokens (1.2 × 30k). Only matters if buffering can't keep up. |
474
+ | `activateAfterIdle` | none | Forces buffered observations to activate after a period of inactivity, even before `observation.messageTokens` is reached. Accepts a numeric millisecond value such as `300_000`, duration strings like `"5m"` or `"1hr"`, or `"auto"` for a provider-aware prompt cache TTL. |
475
+ | `activateOnProviderChange` | `false` | Forces buffered observations to activate when the next step uses a different `provider/model` than the one that produced the latest assistant step. Use this when switching providers or models would invalidate prompt cache reuse. |
476
+ | `reflection.bufferActivation` | `0.5` | When to start background reflection. `0.5` means reflection begins when observations reach 50% of the `observationTokens` threshold. |
477
+ | `reflection.activateAfterIdle` | none | Opts buffered reflections into idle activation. Reflections don't inherit top-level `activateAfterIdle`. |
478
+ | `reflection.activateOnProviderChange` | `false` | Opts buffered reflections into provider-change activation. Reflections don't inherit top-level `activateOnProviderChange`. |
479
+ | `reflection.blockAfter` | `1.2` | Safety threshold for reflection, same logic as observation. |
480
+
481
+ If you're relying on prompt caching, set `activateAfterIdle` to `"auto"` or to a specific cache TTL. That way, once a thread has been idle long enough for the cache to expire, the next request can activate buffered observations first and send a smaller compressed context window.
482
+
483
+ With `"auto"`, Mastra chooses an idle activation TTL from the active model provider:
484
+
485
+ | Provider | Auto TTL |
486
+ | --------------------------------------------------------------------------------------- | --------- |
487
+ | Anthropic, OpenRouter, unknown providers, xAI | 5 minutes |
488
+ | DeepSeek | 1 hour |
489
+ | Google Gemini | 24 hours |
490
+ | Groq | 2 hours |
491
+ | OpenAI with `providerOptions.openai.promptCacheRetention: "24h"` | 1 hour |
492
+ | OpenAI with `providerOptions.openai.promptCacheRetention: "in_memory"` | 5 minutes |
493
+ | OpenAI `gpt-4*`, `gpt-5`, `gpt-5-*`, `gpt-5.1*`, `gpt-5.2*`, `gpt-5.3*`, and `gpt-5.4*` | 5 minutes |
494
+ | Other OpenAI models | 1 hour |
460
495
 
461
496
  ```typescript
462
497
  const memory = new Memory({
463
498
  options: {
464
499
  observationalMemory: {
465
500
  model: 'google/gemini-2.5-flash',
466
- activateAfterIdle: '5m',
501
+ activateAfterIdle: 'auto',
467
502
  activateOnProviderChange: true,
468
503
  },
469
504
  },
470
505
  })
471
506
  ```
472
507
 
473
- With a 5-minute prompt cache TTL, this activates buffered observations after 5 minutes of inactivity so the next uncached prompt uses compressed observations instead of a larger raw message window. If you prefer, `300_000` works the same way.
508
+ With `"auto"`, this activates buffered observations based on the active provider's prompt cache behavior so the next uncached prompt uses compressed observations instead of a larger raw message window. If you prefer a fixed 5-minute TTL, use `"5m"` or `300_000`.
474
509
 
475
- Changing model or providers mid-thread will invalidate the prompt cache. If your agent can switch between providers or models mid-thread, `activateOnProviderChange: true` forces buffered observations to activate before the new provider runs. That avoids sending a large raw window to a provider that can't reuse the previous prompt cache.
510
+ Changing models or providers mid-thread will invalidate the prompt cache. If your agent can switch between providers or models mid-thread, `activateOnProviderChange: true` forces buffered observations to activate before the new provider runs. That avoids sending a large raw window to a provider that can't reuse the previous prompt cache.
476
511
 
477
512
  ### Disabling
478
513
 
@@ -1,6 +1,6 @@
1
1
  # Netlify
2
2
 
3
- Netlify AI Gateway provides unified access to multiple providers with built-in caching and observability. Access 68 models through Mastra's model router.
3
+ Netlify AI Gateway provides unified access to multiple providers with built-in caching and observability. Access 69 models through Mastra's model router.
4
4
 
5
5
  Learn more in the [Netlify documentation](https://docs.netlify.com/build/ai-gateway/overview/).
6
6
 
@@ -61,6 +61,7 @@ ANTHROPIC_API_KEY=ant-...
61
61
  | `gemini/gemini-3.1-flash-lite-preview` |
62
62
  | `gemini/gemini-3.1-pro-preview` |
63
63
  | `gemini/gemini-3.1-pro-preview-customtools` |
64
+ | `gemini/gemini-3.5-flash` |
64
65
  | `gemini/gemini-flash-latest` |
65
66
  | `gemini/gemini-flash-lite-latest` |
66
67
  | `openai/chat-latest` |
@@ -1,6 +1,6 @@
1
1
  # Model Providers
2
2
 
3
- Mastra provides a unified interface for working with LLMs across multiple providers, giving you access to 4219 models from 121 providers through a single API.
3
+ Mastra provides a unified interface for working with LLMs across multiple providers, giving you access to 4207 models from 121 providers through a single API.
4
4
 
5
5
  ## Features
6
6
 
@@ -1,6 +1,6 @@
1
1
  # ![routing.run logo](https://models.dev/logos/routing-run.svg)routing.run
2
2
 
3
- Access 37 routing.run models through Mastra's model router. Authentication is handled automatically using the `ROUTING_RUN_API_KEY` environment variable.
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 | 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-full` | 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-precision` | 1.0M | | | | | | $0.74 | $1 |
42
- | `routing-run/route/gemma-4-31b-it` | 131K | | | | | | $0.10 | $0.30 |
43
- | `routing-run/route/glm-4.7` | 128K | | | | | | $1 | $4 |
44
- | `routing-run/route/glm-4.7-flash` | 128K | | | | | | $1 | $4 |
45
- | `routing-run/route/glm-5` | 203K | | | | | | $0.79 | $3 |
46
- | `routing-run/route/glm-5-highspeed` | 203K | | | | | | $1 | $4 |
47
- | `routing-run/route/glm-5.1` | 203K | | | | | | $1 | $3 |
48
- | `routing-run/route/glm-5.1-fp16` | 203K | | | | | | $1 | $4 |
49
- | `routing-run/route/glm-5.1-full` | 203K | | | | | | $1 | $4 |
50
- | `routing-run/route/glm-5.1-precision` | 203K | | | | | | $1 | $4 |
51
- | `routing-run/route/kimi-k2.5` | 262K | | | | | | $0.46 | $2 |
52
- | `routing-run/route/kimi-k2.5-highspeed` | 131K | | | | | | $0.65 | $3 |
53
- | `routing-run/route/kimi-k2.6` | 262K | | | | | | $0.46 | $2 |
54
- | `routing-run/route/kimi-k2.6-full` | 262K | | | | | | $0.46 | $2 |
55
- | `routing-run/route/kimi-k2.6-precision` | 262K | | | | | | $0.65 | $3 |
56
- | `routing-run/route/mimo-v2.5` | 256K | | | | | | $0.40 | $2 |
57
- | `routing-run/route/mimo-v2.5-pro` | 1.0M | | | | | | $0.45 | $1 |
58
- | `routing-run/route/mimo-v2.5-pro-precision` | 1.0M | | | | | | $0.45 | $1 |
59
- | `routing-run/route/minimax-m2.5` | 100K | | | | | | $0.19 | $1 |
60
- | `routing-run/route/minimax-m2.5-highspeed` | 100K | | | | | | $0.19 | $1 |
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
 
@@ -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
 
@@ -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, and request context to dynamically decide whether approval is needed.
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, and any request context from the incoming request:
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()`
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @mastra/mcp-docs-server
2
2
 
3
+ ## 1.1.39-alpha.11
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`c272d50`](https://github.com/mastra-ai/mastra/commit/c272d50610a54496b6b6d92ccd4d37b333a2613a), [`d8692af`](https://github.com/mastra-ai/mastra/commit/d8692afa253028e39cdce2aafa0ac414071a762e), [`4bd4e8e`](https://github.com/mastra-ai/mastra/commit/4bd4e8e042f6687559f49a560a7914cee9b85447), [`841a222`](https://github.com/mastra-ai/mastra/commit/841a222560d8c19238f8213713f30535cdd82284)]:
8
+ - @mastra/core@1.36.0-alpha.4
9
+ - @mastra/mcp@1.8.0-alpha.1
10
+
3
11
  ## 1.1.39-alpha.9
4
12
 
5
13
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/mcp-docs-server",
3
- "version": "1.1.39-alpha.10",
3
+ "version": "1.1.39-alpha.11",
4
4
  "description": "MCP server for accessing Mastra.ai documentation, changelogs, and news.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -29,8 +29,8 @@
29
29
  "jsdom": "^26.1.0",
30
30
  "local-pkg": "^1.1.2",
31
31
  "zod": "^4.3.6",
32
- "@mastra/core": "1.36.0-alpha.3",
33
- "@mastra/mcp": "^1.7.1-alpha.0"
32
+ "@mastra/core": "1.36.0-alpha.4",
33
+ "@mastra/mcp": "^1.8.0-alpha.1"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@hono/node-server": "^1.19.11",
@@ -47,7 +47,7 @@
47
47
  "typescript": "^6.0.3",
48
48
  "vitest": "4.1.5",
49
49
  "@internal/types-builder": "0.0.71",
50
- "@mastra/core": "1.36.0-alpha.3",
50
+ "@mastra/core": "1.36.0-alpha.4",
51
51
  "@internal/lint": "0.0.96"
52
52
  },
53
53
  "homepage": "https://mastra.ai",