@mastra/mcp-docs-server 1.2.12 → 1.2.13-alpha.1

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.
@@ -104,6 +104,78 @@ A tool's own `requireApproval` setting takes precedence over the function above.
104
104
 
105
105
  > **Note:** Function-based `requireToolApproval` is only available on regular `stream()` / `generate()` calls. Durable agents and stored agents persist their options, and a function can't be serialized, so they accept only a boolean. If you pass a function in those contexts it falls back to requiring approval for every tool call.
106
106
 
107
+ #### Bind approval to the exact tool arguments
108
+
109
+ For sensitive tools, bind the approval to the exact tool name and arguments that were shown to the reviewer. If those arguments drift before execution, the tool shouldn't run under the old approval.
110
+
111
+ The `tool-call-approval` chunk already includes `toolName`, `toolCallId`, and `args`. You can fingerprint those fields when the approval request is shown. The example below uses a simple JSON string as the fingerprint, but in production you should use a stable hash of the tool name and arguments:
112
+
113
+ ```typescript
114
+ import { Agent } from '@mastra/core/agent'
115
+
116
+ // For your production usecase, build a stable hash of the tool name and args
117
+ function actionFingerprint(toolName: string, args: unknown) {
118
+ const payload = JSON.stringify({ toolName, args })
119
+ return `fingerprint-${payload}`
120
+ }
121
+
122
+ const sensitiveTools = new Set(['issue_refund', 'delete_record'])
123
+ const approvedFingerprints = new Set<string>()
124
+
125
+ export const approvalBoundAgent = new Agent({
126
+ id: 'approval-bound-agent',
127
+ name: 'Approval Bound Agent',
128
+ model: 'openai/gpt-5.6-sol',
129
+ tools: { issueRefundTool, deleteRecordTool },
130
+ hooks: {
131
+ beforeToolCall: ({ toolName, input }) => {
132
+ if (!sensitiveTools.has(toolName)) return
133
+
134
+ const fingerprint = actionFingerprint(toolName, input)
135
+ if (!approvedFingerprints.delete(fingerprint)) {
136
+ return {
137
+ proceed: false,
138
+ output: `Tool call blocked: approval did not match ${toolName} arguments.`,
139
+ }
140
+ }
141
+ },
142
+ },
143
+ })
144
+ ```
145
+
146
+ ```typescript
147
+ const stream = await approvalBoundAgent.stream('Refund order ord-1042', {
148
+ requireToolApproval: ({ toolName }) => sensitiveTools.has(toolName),
149
+ })
150
+
151
+ async function consumeApprovalStream(currentStream: typeof stream) {
152
+ for await (const chunk of currentStream.fullStream) {
153
+ if (chunk.type === 'tool-call-approval') {
154
+ const { toolName, toolCallId, args } = chunk.payload
155
+ const fingerprint = actionFingerprint(toolName, args)
156
+
157
+ // Present toolName, args, and fingerprint to your approval UI.
158
+ const approved = await showApprovalDialog({ toolName, args, fingerprint })
159
+
160
+ const nextStream = approved
161
+ ? await approveReviewedToolCall(currentStream.runId, toolCallId, fingerprint)
162
+ : await approvalBoundAgent.declineToolCall({ runId: currentStream.runId, toolCallId })
163
+
164
+ await consumeApprovalStream(nextStream)
165
+ }
166
+ }
167
+ }
168
+
169
+ async function approveReviewedToolCall(runId: string, toolCallId: string, fingerprint: string) {
170
+ approvedFingerprints.add(fingerprint)
171
+ return approvalBoundAgent.approveToolCall({ runId, toolCallId })
172
+ }
173
+
174
+ await consumeApprovalStream(stream)
175
+ ```
176
+
177
+ In production, store the approved fingerprint in durable storage scoped to the user, run, tool call, and policy version. The `Set` above is intentionally small so the boundary is easy to see: the approval is consumed once, and only for the same canonical tool arguments that were reviewed.
178
+
107
179
  ### Runtime suspension with `suspend()`
108
180
 
109
181
  A tool can also pause _during_ its `execute` function by calling `suspend()`. This is useful when the tool starts running and then discovers it needs additional user input or confirmation before it can finish.
@@ -65,31 +65,6 @@ export const weatherAgent = new Agent({
65
65
  })
66
66
  ```
67
67
 
68
- ## Use provider web search
69
-
70
- Import `webSearchTool` from `@mastra/core/tools` when you want the model provider to run its native web search tool. The tool has no local `execute` function. Mastra resolves it at run time from the active model, then passes the provider-managed tool to the model.
71
-
72
- ```typescript
73
- import { Agent } from '@mastra/core/agent'
74
- import { webSearchTool } from '@mastra/core/tools'
75
-
76
- export const researchAgent = new Agent({
77
- id: 'research-agent',
78
- name: 'Research Agent',
79
- instructions: `
80
- You are a helpful research assistant.
81
- Use web search when you need current information.`,
82
- model: 'openai/gpt-5.6-sol',
83
- tools: {
84
- webSearch: webSearchTool,
85
- },
86
- })
87
- ```
88
-
89
- `webSearchTool` supports OpenAI, Anthropic, Google Gemini, and xAI models. If Mastra can't infer one of those providers from the active model, the agent run fails with a `MastraError`.
90
-
91
- Only the `webSearchTool` value triggers provider web search. Custom tools with the names `webSearch` or `web_search` stay unchanged.
92
-
93
68
  ## Define schemas
94
69
 
95
70
  You can define the tool's `inputSchema` and `outputSchema` with any library that supports [Standard JSON Schema](https://standardschema.dev/json-schema). This includes libraries like [Zod](https://zod.dev/), [Valibot](https://valibot.dev/), and [ArkType](https://arktype.io/).
@@ -494,14 +469,38 @@ Note that for subagents, you'll see two different identifiers in stream response
494
469
 
495
470
  Mastra includes agent-agnostic built-in tools in `@mastra/core/tools` that add interactive and organizational capabilities to any agent.
496
471
 
497
- | Tool | Purpose |
498
- | --------------- | ------------------------------------------------- |
499
- | `ask_user` | Ask the user a question and wait for their answer |
500
- | `submit_plan` | Submit a plan file for user approval |
501
- | `task_write` | Create or replace a structured task list |
502
- | `task_update` | Update one tracked task by ID |
503
- | `task_complete` | Mark one tracked task completed |
504
- | `task_check` | Check task list completion status |
472
+ | Tool | Purpose |
473
+ | --------------- | ---------------------------------------------------- |
474
+ | `ask_user` | Ask the user a question and wait for their answer |
475
+ | `submit_plan` | Submit a plan file for user approval |
476
+ | `task_write` | Create or replace a structured task list |
477
+ | `task_update` | Update one tracked task by ID |
478
+ | `task_complete` | Mark one tracked task completed |
479
+ | `task_check` | Check task list completion status |
480
+ | `webSearchTool` | Run provider-native web search with the active model |
481
+
482
+ ### Use provider web search
483
+
484
+ Import `webSearchTool` from `@mastra/core/tools` when you want the model provider to run its native web search tool. Mastra resolves it at run time from the active model, then passes the provider-managed tool to the model.
485
+
486
+ ```typescript
487
+ import { Agent } from '@mastra/core/agent'
488
+ import { webSearchTool } from '@mastra/core/tools'
489
+
490
+ export const researchAgent = new Agent({
491
+ id: 'research-agent',
492
+ name: 'Research Agent',
493
+ instructions: 'Use web search when you need current information.',
494
+ model: 'openai/gpt-5.6-sol',
495
+ tools: {
496
+ search: webSearchTool,
497
+ },
498
+ })
499
+ ```
500
+
501
+ `webSearchTool` supports OpenAI, Anthropic, Google Gemini, and xAI models. If Mastra can't infer one of those providers from the active model, the agent run fails with a `MastraError`.
502
+
503
+ The `search` key is only the agent-local tool name. Use any key. The `webSearchTool` value tells Mastra to use provider web search.
505
504
 
506
505
  ### Ask the user a question
507
506
 
@@ -133,7 +133,7 @@ Visit the [Scorers overview](https://mastra.ai/docs/evals/overview) for details
133
133
 
134
134
  ## Tool mocks
135
135
 
136
- When an experiment runs an agent that calls side-effecting tools, you can make the run deterministic by attaching static tool mocks to individual dataset items. During the experiment, a mocked tool returns its declared output instead of executing. Tools that have no mock on the item run live.
136
+ When an experiment runs an agent that calls side-effecting tools, you can make the run deterministic by attaching static tool mocks to individual dataset items. During the experiment, a mocked tool returns its declared output instead of executing. By default, tools that have no mock on the item run live.
137
137
 
138
138
  Mocks live on the dataset item, so they version with the row and travel with the test case. Each mock declares a tool name, the arguments it expects, and the output to return:
139
139
 
@@ -152,6 +152,29 @@ await dataset.addItem({
152
152
 
153
153
  Tool mocks are supported for `agent` targets only.
154
154
 
155
+ ### Block undeclared tools
156
+
157
+ Set `unmockedToolPolicy: 'deny'` on an experiment to block every tool call that doesn't have a mock. This is useful when a live call could cause side effects:
158
+
159
+ ```typescript
160
+ const summary = await dataset.startExperiment({
161
+ targetType: 'agent',
162
+ targetId: 'weather-agent',
163
+ unmockedToolPolicy: 'deny',
164
+ })
165
+ ```
166
+
167
+ The default policy is `'allow'`. You can override the experiment policy on an individual stored or inline item:
168
+
169
+ ```typescript
170
+ await dataset.addItem({
171
+ input: 'What is the weather in Seattle?',
172
+ unmockedToolPolicy: 'allow',
173
+ })
174
+ ```
175
+
176
+ The item value takes precedence over the experiment value. A denied call fails with `TOOL_MOCK_NOT_DECLARED` before the tool executes. The failure isn't retried or added to `liveCalls`.
177
+
155
178
  ### Matching and consumption
156
179
 
157
180
  Arguments are matched strictly: object key order is ignored and array order is substantial, plus there is no type coercion. A mock is served only when the agent calls the tool with arguments that deep-equal the mock's `args`.
@@ -175,14 +198,15 @@ This is useful when a tool's arguments are noisy or generated by the model. The
175
198
 
176
199
  ### Failures
177
200
 
178
- A mocked tool call fails the item when the arguments don't match or all matching mocks have been consumed:
201
+ A tool call fails the item when it violates the mock configuration:
179
202
 
180
203
  - `TOOL_MOCK_MISMATCH`: the tool was called with arguments that no mock matches.
181
204
  - `TOOL_MOCK_EXHAUSTED`: every matching mock has already been consumed.
205
+ - `TOOL_MOCK_NOT_DECLARED`: the tool has no mock and the effective `unmockedToolPolicy` is `'deny'`.
182
206
 
183
- When a mocked tool is mis-called, the agent run is aborted immediately, so the model can't go on to call any further tools, including unmocked, side-effecting tools that would otherwise run live. These failures are deterministic, so they're not retried. Mocks that are declared but never used don't fail the item, they're reported as unconsumed.
207
+ On any of these failures, the agent run is aborted immediately, so the model can't go on to call any further tools, including unmocked, side-effecting tools that would otherwise run live. These failures are deterministic, so they're not retried. Mocks that are declared but never used don't fail the item, they're reported as unconsumed.
184
208
 
185
- While an item has mocks, the agent's tools execute sequentially so repeated `(toolName, args)` mocks are consumed in the provider's call order. This serialization applies only to items that declare mocks.
209
+ While mock interception is active, the agent's tools execute sequentially so repeated `(toolName, args)` mocks are consumed in the provider's call order. Interception is active when the item declares mocks or its effective `unmockedToolPolicy` is `'deny'`.
186
210
 
187
211
  ### Diagnostics
188
212
 
@@ -195,8 +219,8 @@ for (const item of summary.results) {
195
219
 
196
220
  console.log(report.served) // mocks matched and returned
197
221
  console.log(report.unconsumed) // mocks declared but never used
198
- console.log(report.liveCalls) // unmocked tools that ran live
199
- console.log(report.failure) // the mismatch/exhausted failure, if any
222
+ console.log(report.liveCalls) // undeclared tools allowed to run live
223
+ console.log(report.failure) // the first deterministic mock failure, if any
200
224
  }
201
225
  ```
202
226
 
@@ -205,7 +229,7 @@ In [Studio](https://mastra.ai/docs/studio/overview), edit a dataset item to auth
205
229
  ### Limitations
206
230
 
207
231
  - **No tool span for mocked calls.** A mocked call returns its output before the tool executes, so it doesn't create a tool span. Trajectory scorers backed by stored traces may therefore not see mocked tool calls. Trajectory extraction that falls back to the agent's message output still sees them, so trajectory scoring can differ depending on your observability configuration.
208
- - **Storage support.** Tool mocks and tool mock reports are persisted by the LibSQL, PostgreSQL, MongoDB, and Spanner adapters. The MySQL adapter doesn't support them and rejects writes that carry tool mocks or a tool mock report so the feature never silently runs tools live.
232
+ - **Storage support.** Tool mocks and tool mock reports are persisted by the LibSQL, PostgreSQL, MongoDB, and Spanner adapters. The MySQL adapter doesn't support them and rejects writes that carry tool mocks or a tool mock report. All dataset storage adapters persist `unmockedToolPolicy`.
209
233
 
210
234
  ## Async experiments
211
235
 
@@ -56,6 +56,7 @@ List of required environment variables for each model provider and gateway suppo
56
56
  | [GitHub Models](https://mastra.ai/models/providers/github-models) | `github-models/*` | `GITHUB_TOKEN` |
57
57
  | [GMI Cloud](https://mastra.ai/models/providers/gmicloud) | `gmicloud/*` | `GMICLOUD_API_KEY` |
58
58
  | [Google](https://mastra.ai/models/providers/google) | `google/*` | `GOOGLE_API_KEY`, `GOOGLE_GENERATIVE_AI_API_KEY` |
59
+ | [GreenPT](https://mastra.ai/models/providers/greenpt) | `greenpt/*` | `GREENPT_API_KEY` |
59
60
  | [Groq](https://mastra.ai/models/providers/groq) | `groq/*` | `GROQ_API_KEY` |
60
61
  | [Helicone](https://mastra.ai/models/providers/helicone) | `helicone/*` | `HELICONE_API_KEY` |
61
62
  | [Hetzner](https://mastra.ai/models/providers/hetzner) | `hetzner/*` | `HETZNER_API_KEY` |
@@ -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 5118 models from 163 providers through a single API.
5
+ Mastra provides a unified interface for working with LLMs across multiple providers, giving you access to 5145 models from 164 providers through a single API.
6
6
 
7
7
  ## Features
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  # ![Cortecs logo](https://models.dev/logos/cortecs.svg)Cortecs
4
4
 
5
- Access 57 Cortecs models through Mastra's model router. Authentication is handled automatically using the `CORTECS_API_KEY` environment variable.
5
+ Access 58 Cortecs models through Mastra's model router. Authentication is handled automatically using the `CORTECS_API_KEY` environment variable.
6
6
 
7
7
  Learn more in the [Cortecs documentation](https://cortecs.ai).
8
8
 
@@ -72,6 +72,7 @@ for await (const chunk of stream) {
72
72
  | `cortecs/kimi-k2.5` | 256K | | | | | | $0.55 | $3 |
73
73
  | `cortecs/kimi-k2.6` | 256K | | | | | | $0.81 | $4 |
74
74
  | `cortecs/kimi-k2.7-code` | 262K | | | | | | $1 | $5 |
75
+ | `cortecs/kimi-k3` | 1.0M | | | | | | $3 | $15 |
75
76
  | `cortecs/llama-3.1-405b-instruct` | 128K | | | | | | — | — |
76
77
  | `cortecs/llama-3.3-70b-instruct` | 131K | | | | | | $0.09 | $0.28 |
77
78
  | `cortecs/llama-4-maverick` | 1.0M | | | | | | $0.12 | $0.60 |
@@ -0,0 +1,98 @@
1
+ > Discover all available pages from the documentation index: https://mastra.ai/llms.txt
2
+
3
+ # ![GreenPT logo](https://models.dev/logos/greenpt.svg)GreenPT
4
+
5
+ Access 26 GreenPT models through Mastra's model router. Authentication is handled automatically using the `GREENPT_API_KEY` environment variable.
6
+
7
+ Learn more in the [GreenPT documentation](https://docs.greenpt.ai).
8
+
9
+ ```bash
10
+ GREENPT_API_KEY=your-api-key
11
+ ```
12
+
13
+ ```typescript
14
+ import { Agent } from "@mastra/core/agent";
15
+
16
+ const agent = new Agent({
17
+ id: "my-agent",
18
+ name: "My Agent",
19
+ instructions: "You are a helpful assistant",
20
+ model: "greenpt/devstral-2-123b-instruct-2512"
21
+ });
22
+
23
+ // Generate a response
24
+ const response = await agent.generate("Hello!");
25
+
26
+ // Stream a response
27
+ const stream = await agent.stream("Tell me a story");
28
+ for await (const chunk of stream) {
29
+ console.log(chunk);
30
+ }
31
+ ```
32
+
33
+ > **Info:** Mastra uses the OpenAI-compatible `/chat/completions` endpoint. Some provider-specific features may not be available. Check the [GreenPT documentation](https://docs.greenpt.ai) for details.
34
+
35
+ ## Models
36
+
37
+ | Model | Context | Tools | Reasoning | Image | Audio | Video | Input $/1M | Output $/1M |
38
+ | --------------------------------------------- | ------- | ----- | --------- | ----- | ----- | ----- | ---------- | ----------- |
39
+ | `greenpt/devstral-2-123b-instruct-2512` | 200K | | | | | | $0.57 | $3 |
40
+ | `greenpt/gemma-3-27b-it` | 40K | | | | | | $0.34 | $0.68 |
41
+ | `greenpt/gemma4` | 262K | | | | | | $0.57 | $2 |
42
+ | `greenpt/glm-5.1` | 200K | | | | | | $2 | $6 |
43
+ | `greenpt/glm-5.2` | 1.0M | | | | | | $1 | $5 |
44
+ | `greenpt/gpt-oss-120b` | 131K | | | | | | $0.23 | $0.80 |
45
+ | `greenpt/green-l` | 128K | | | | | | $0.28 | $0.91 |
46
+ | `greenpt/green-l-raw` | 128K | | | | | | $0.28 | $0.91 |
47
+ | `greenpt/green-r` | 131K | | | | | | $0.40 | $1 |
48
+ | `greenpt/green-r-raw` | 131K | | | | | | $0.40 | $1 |
49
+ | `greenpt/green-s` | — | | | | | | $0.00 | — |
50
+ | `greenpt/green-s-pro` | — | | | | | | $0.00 | — |
51
+ | `greenpt/holo2-30b-a3b` | 22K | | | | | | $0.40 | $0.97 |
52
+ | `greenpt/kimi-k2.6` | 262K | | | | | | $0.83 | $4 |
53
+ | `greenpt/kimi-k2.6-fast` | 262K | | | | | | $2 | $9 |
54
+ | `greenpt/kimi-k2.7-code` | 262K | | | | | | $0.94 | $4 |
55
+ | `greenpt/llama-3.3-70b-instruct` | 100K | | | | | | $1 | $1 |
56
+ | `greenpt/minimax-m2.5` | 205K | | | | | | $0.19 | $1 |
57
+ | `greenpt/mistral-medium-3.5-128b` | 262K | | | | | | $2 | $10 |
58
+ | `greenpt/mistral-small-3.2-24b-instruct-2506` | 128K | | | | | | $0.23 | $0.46 |
59
+ | `greenpt/pixtral-12b-2409` | 128K | | | | | | $0.28 | $0.28 |
60
+ | `greenpt/qwen3-235b-a22b-instruct-2507` | 262K | | | | | | $1 | $3 |
61
+ | `greenpt/qwen3-coder-30b-a3b-instruct` | 128K | | | | | | $0.28 | $1 |
62
+ | `greenpt/qwen3.5-397b-a17b` | 262K | | | | | | $0.80 | $5 |
63
+ | `greenpt/qwen3.6-35b-a3b` | 262K | | | | | | $0.34 | $2 |
64
+ | `greenpt/voxtral-small-24b-2507` | 33K | | | | | | $0.23 | $0.51 |
65
+
66
+ ## Advanced configuration
67
+
68
+ ### Custom headers
69
+
70
+ ```typescript
71
+ const agent = new Agent({
72
+ id: "custom-agent",
73
+ name: "custom-agent",
74
+ model: {
75
+ url: "https://api.greenpt.ai/v1",
76
+ id: "greenpt/devstral-2-123b-instruct-2512",
77
+ apiKey: process.env.GREENPT_API_KEY,
78
+ headers: {
79
+ "X-Custom-Header": "value"
80
+ }
81
+ }
82
+ });
83
+ ```
84
+
85
+ ### Dynamic model selection
86
+
87
+ ```typescript
88
+ const agent = new Agent({
89
+ id: "dynamic-agent",
90
+ name: "Dynamic Agent",
91
+ model: ({ requestContext }) => {
92
+ const useAdvanced = requestContext.task === "complex";
93
+ return useAdvanced
94
+ ? "greenpt/voxtral-small-24b-2507"
95
+ : "greenpt/devstral-2-123b-instruct-2512";
96
+ }
97
+ });
98
+ ```
@@ -58,6 +58,7 @@ Direct access to individual AI model providers. Each provider offers unique mode
58
58
  - [FrogBot](https://mastra.ai/models/providers/frogbot)
59
59
  - [GitHub Models](https://mastra.ai/models/providers/github-models)
60
60
  - [GMI Cloud](https://mastra.ai/models/providers/gmicloud)
61
+ - [GreenPT](https://mastra.ai/models/providers/greenpt)
61
62
  - [Helicone](https://mastra.ai/models/providers/helicone)
62
63
  - [Hetzner](https://mastra.ai/models/providers/hetzner)
63
64
  - [HPC-AI](https://mastra.ai/models/providers/hpc-ai)
@@ -77,6 +77,8 @@ console.log(`Status: ${summary2.status}`)
77
77
 
78
78
  **maxRetries** (`number`): Maximum retries per item on failure. Defaults to 0 (no retries). Abort errors are never retried.
79
79
 
80
+ **unmockedToolPolicy** (`'allow' | 'deny'`): Controls undeclared agent tool calls. allow executes them live. deny fails the item with TOOL\_MOCK\_NOT\_DECLARED before execution. An item-level value overrides this experiment default. (Default: `'allow'`)
81
+
80
82
  ## Returns
81
83
 
82
84
  **result** (`Promise<ExperimentSummary>`): Summary of the completed experiment.
@@ -53,14 +53,12 @@ const agent = new Agent({
53
53
  id: 'my-agent',
54
54
  name: 'my-agent',
55
55
  model: 'openai/gpt-5-nano',
56
- processors: {
57
- input: [
58
- new RegexFilterProcessor({
59
- presets: ['pii', 'secrets'],
60
- strategy: 'block',
61
- }),
62
- ],
63
- },
56
+ inputProcessors: [
57
+ new RegexFilterProcessor({
58
+ presets: ['pii', 'secrets'],
59
+ strategy: 'block',
60
+ }),
61
+ ],
64
62
  })
65
63
  ```
66
64
 
@@ -80,6 +78,8 @@ const agent = new Agent({
80
78
 
81
79
  **phase** (`'input' | 'output' | 'all'`): Phases to apply the filter. 'input' filters input messages. 'output' filters output stream and result. 'all' filters both. (Default: `'all'`)
82
80
 
81
+ **includeRedactedValues** (`boolean`): Include the text that was redacted in each report entry. Off by default, because the values are the data the processor removes. (Default: `false`)
82
+
83
83
  ## Returns
84
84
 
85
85
  **id** (`'regex-filter'`): Processor identifier.
@@ -106,4 +106,76 @@ When the `block` strategy is active (default), `RegexFilterProcessor` throws a `
106
106
  | --------- | ------------------------------------------------ | ---------------------------------------------- |
107
107
  | `pii` | Emails, phone numbers, SSNs, credit card numbers | `[EMAIL]`, `[PHONE]`, `[SSN]`, `[CREDIT_CARD]` |
108
108
  | `secrets` | API keys, bearer tokens, AWS access keys | `[API_KEY]`, `[BEARER_TOKEN]`, `[AWS_KEY]` |
109
- | `urls` | HTTP/HTTPS URLs | `[URL]` |
109
+ | `urls` | HTTP/HTTPS URLs | `[URL]` |
110
+
111
+ ## Redaction behavior
112
+
113
+ Every rule is matched independently, so two rules can claim text that overlaps. A card number written without separators matches both `phone` and `credit-card`, for example. Overlapping matches are combined into a single region and replaced once, using the replacement of the longest match.
114
+
115
+ ```typescript
116
+ const filter = new RegexFilterProcessor({
117
+ presets: ['pii'],
118
+ strategy: 'redact',
119
+ })
120
+
121
+ // "Charge 4111111111111111 today" becomes "Charge [CREDIT_CARD] today"
122
+ ```
123
+
124
+ A replacement string can reference capture groups with `$1` or `$&`. Those references resolve for a single match whose pattern also matches the matched text on its own. In a combined region, or for a rule anchored on its surroundings with a lookbehind or lookahead, the replacement string is inserted as written. The region is redacted either way.
125
+
126
+ ## Redaction reporting
127
+
128
+ The `redact` strategy rewrites text in place, so nothing downstream can tell what changed. Assign `onViolation` to record it. The processor calls it once per redacted message, message part, or stream chunk, and offsets are relative to that piece of text. Async callbacks are awaited, and errors are caught so an unavailable audit sink cannot fail the request.
129
+
130
+ ```typescript
131
+ import { RegexFilterProcessor, type RegexRedactionDetail } from '@mastra/core/processors'
132
+
133
+ const filter = new RegexFilterProcessor({
134
+ presets: ['pii'],
135
+ strategy: 'redact',
136
+ })
137
+
138
+ filter.onViolation = async ({ detail }) => {
139
+ const redaction = detail as RegexRedactionDetail
140
+
141
+ for (const entry of redaction.redactions) {
142
+ await auditLog.write({
143
+ phase: redaction.phase,
144
+ messageId: redaction.messageId,
145
+ rule: entry.rule,
146
+ offset: entry.index,
147
+ length: entry.length,
148
+ })
149
+ }
150
+ }
151
+ ```
152
+
153
+ The callback is awaited, including in `processOutputStream`, where it runs for every chunk that contains a match. Keep the callback fast, or hand the work to a queue, so a slow audit sink doesn't stall a streaming response. With no callback attached, the `redact` path stays synchronous.
154
+
155
+ The `block` strategy reports through the same callback. There the processor runner invokes it when it catches the `TripWire`, so `detail` holds the tripwire metadata described under [Error behavior](#error-behavior) rather than the shape below.
156
+
157
+ `detail` for a redaction is a `RegexRedactionDetail`:
158
+
159
+ **strategy** (`'redact'`): Distinguishes a redaction report from the block strategy payload.
160
+
161
+ **phase** (`'processInput' | 'processOutputStream' | 'processOutputResult'`): Processor method that applied the redactions.
162
+
163
+ **messageId** (`string`): Id of the message the text came from. Absent for stream chunks.
164
+
165
+ **partIndex** (`number`): Index of the redacted part in the message's parts array, which also contains non-text parts. Absent for string content and stream chunks.
166
+
167
+ **redactions** (`RegexRedaction[]`): Redactions in the order they appear in the text.
168
+
169
+ **redactions.rule** (`string`): Name of the rule whose replacement was used.
170
+
171
+ **redactions.index** (`number`): Start offset of the redacted span in the text.
172
+
173
+ **redactions.length** (`number`): Length of the redacted span.
174
+
175
+ **redactions.replacement** (`string`): Text that replaced the span.
176
+
177
+ **redactions.overlappingRules** (`string[]`): Names of all rules that matched this span, set only when more than one overlapped.
178
+
179
+ **redactions.value** (`string`): The text that was redacted. Set only when includeRedactedValues is enabled.
180
+
181
+ Values are left out by default. An audit trail that copies the data it protects widens the exposure it was added to narrow. Set `includeRedactedValues` only when the destination is as protected as the original, and note that the `block` strategy also withholds matched text from its `TripWire` metadata for the same reason.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @mastra/mcp-docs-server
2
2
 
3
+ ## 1.2.13-alpha.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`7f4e26d`](https://github.com/mastra-ai/mastra/commit/7f4e26dd57bd9b23c278ea21235ab823a3810a6c), [`b582f7f`](https://github.com/mastra-ai/mastra/commit/b582f7fa2f9c1f87d19efc63d344fbe5dda2608c), [`b582f7f`](https://github.com/mastra-ai/mastra/commit/b582f7fa2f9c1f87d19efc63d344fbe5dda2608c)]:
8
+ - @mastra/core@1.56.0-alpha.0
9
+
3
10
  ## 1.2.12
4
11
 
5
12
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/mcp-docs-server",
3
- "version": "1.2.12",
3
+ "version": "1.2.13-alpha.1",
4
4
  "description": "MCP server for accessing Mastra.ai documentation, changelogs, and news.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -28,8 +28,8 @@
28
28
  "jsdom": "^26.1.0",
29
29
  "local-pkg": "^1.1.2",
30
30
  "zod": "^4.4.3",
31
- "@mastra/mcp": "^1.15.0",
32
- "@mastra/core": "1.55.0"
31
+ "@mastra/core": "1.56.0-alpha.0",
32
+ "@mastra/mcp": "^1.15.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@hono/node-server": "^1.19.14",
@@ -47,7 +47,7 @@
47
47
  "vitest": "4.1.10",
48
48
  "@internal/lint": "0.0.119",
49
49
  "@internal/types-builder": "0.0.94",
50
- "@mastra/core": "1.55.0"
50
+ "@mastra/core": "1.56.0-alpha.0"
51
51
  },
52
52
  "homepage": "https://mastra.ai",
53
53
  "repository": {