@mastra/mcp-docs-server 1.2.18-alpha.3 → 1.2.18-alpha.6
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/datasets/running-experiments.md +86 -1
- package/.docs/docs/mastra-platform/deploy.md +3 -1
- package/.docs/docs/mastra-platform/workspaces.md +6 -3
- package/.docs/docs/sandbox/filesystem.md +120 -139
- package/.docs/docs/sandbox/lsp.md +195 -143
- package/.docs/docs/sandbox/overview.md +103 -69
- package/.docs/docs/sandbox/search.md +172 -153
- package/.docs/docs/sandbox/skills.md +94 -151
- package/.docs/integrations/deploy/render.md +136 -89
- package/.docs/integrations/observability/arize.md +8 -6
- package/.docs/models/index.md +1 -1
- package/.docs/models/providers/edenai.md +2 -3
- package/.docs/models/providers/empiriolabs.md +1 -1
- package/.docs/models/providers/kilo.md +2 -2
- package/.docs/models/providers/llmgateway.md +2 -1
- package/.docs/models/providers/nano-gpt.md +3 -1
- package/.docs/models/providers/ofox.md +1 -1
- package/.docs/models/providers/opencode.md +65 -65
- package/.docs/reference/cli/mastra.md +2 -2
- package/.docs/reference/client-js/datasets.md +146 -0
- package/.docs/reference/configuration.md +58 -0
- package/.docs/reference/datasets/createExperiment.md +76 -0
- package/.docs/reference/datasets/finalizeExperiment.md +43 -0
- package/.docs/reference/datasets/runExperimentItem.md +55 -0
- package/.docs/reference/datasets/submitExperimentResult.md +56 -0
- package/.docs/reference/index.md +5 -0
- package/.docs/reference/observability/tracing/exporters/langfuse.md +2 -0
- package/.docs/reference/pubsub/redis-streams.md +11 -1
- package/.docs/reference/rag/metadata-filters.md +16 -8
- package/.docs/reference/rag/retrieval.md +113 -5
- package/.docs/reference/server/routes.md +111 -0
- package/CHANGELOG.md +14 -0
- package/package.json +3 -3
|
@@ -1,30 +1,28 @@
|
|
|
1
1
|
> Discover all available pages from the documentation index: https://mastra.ai/llms.txt
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# Sandboxes and filesystems
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
A sandbox gives your agent an environment where it can run commands, execute code, install dependencies, and manage processes. Sandboxes can isolate potentially risky agent-run code from your host, and they can also provide a place to run longer-lived or more resource-intensive work outside your application process.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[Filesystems](https://mastra.ai/docs/sandbox/filesystem) give the agent files it can read, write, and [search](https://mastra.ai/docs/sandbox/search). They can provide a knowledge base for your agent, or be shared with a sandbox so commands can work with the same files and keep data beyond the sandbox's lifetime.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## When to use sandboxes
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Sandboxes are useful for:
|
|
11
|
+
Sandboxes work well for:
|
|
14
12
|
|
|
15
13
|
- **Coding agents and software factories**: Clone repositories and run shell, Git, build, or test workflows without giving autonomous agents access to the host system.
|
|
16
14
|
- **Deep research and analysis**: Use specialized libraries to process downloaded PDFs or presentations and produce new artifacts.
|
|
17
15
|
- **Long-running and parallel tasks**: Run work in separate environments without tying it to one request or sharing files and processes.
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
If an agent only needs to read, write, or search files, configure [direct filesystem access](https://mastra.ai/docs/sandbox/filesystem).
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
## Quickstart
|
|
22
20
|
|
|
23
|
-
|
|
21
|
+
Give an agent a local sandbox and filesystem:
|
|
24
22
|
|
|
25
23
|
```typescript
|
|
26
24
|
import { Agent } from '@mastra/core/agent'
|
|
27
|
-
import { LocalSandbox, Workspace } from '@mastra/core/workspace'
|
|
25
|
+
import { LocalFilesystem, LocalSandbox, Workspace } from '@mastra/core/workspace'
|
|
28
26
|
|
|
29
27
|
export const codingAgent = new Agent({
|
|
30
28
|
id: 'coding-agent',
|
|
@@ -35,16 +33,21 @@ export const codingAgent = new Agent({
|
|
|
35
33
|
sandbox: new LocalSandbox({
|
|
36
34
|
workingDirectory: './workspace',
|
|
37
35
|
}),
|
|
36
|
+
filesystem: new LocalFilesystem({
|
|
37
|
+
basePath: './workspace',
|
|
38
|
+
}),
|
|
38
39
|
}),
|
|
39
40
|
})
|
|
40
41
|
|
|
41
|
-
await codingAgent.generate('List the files in the
|
|
42
|
+
await codingAgent.generate('List the files in the sandbox directory')
|
|
42
43
|
```
|
|
43
44
|
|
|
44
45
|
> **Warning:** `LocalSandbox` is the quickest sandbox to set up, but commands run on the host by default. Enable [native isolation](#localsandbox) whenever possible. For applications exposed to untrusted users, use a remote or container backend with a stronger isolation boundary instead.
|
|
45
46
|
|
|
46
47
|
To use a different sandbox for each user, tenant, or thread, configure a [sandbox resolver](#multi-tenant-sandboxes) instead.
|
|
47
48
|
|
|
49
|
+
The `LocalSandbox` above is one static instance. Every request and memory thread that uses `codingAgent` shares its files, processes, and lifecycle state. A memory thread doesn't create an isolated sandbox by itself.
|
|
50
|
+
|
|
48
51
|
## Using the sandbox
|
|
49
52
|
|
|
50
53
|
Agents receive tools for the capabilities supported by the sandbox backend:
|
|
@@ -55,12 +58,29 @@ Agents receive tools for the capabilities supported by the sandbox backend:
|
|
|
55
58
|
| `get_process_output` | Gets stdout, stderr, and status for a background process. Supports `tail` to limit output and `wait: true` to wait for the process to exit. This tool and `kill_process` are only added when the backend supports background processes. |
|
|
56
59
|
| `kill_process` | Stops a background process and returns its recent output. |
|
|
57
60
|
|
|
58
|
-
|
|
61
|
+
Configured capabilities determine which tools are available. Tool configuration can then disable, rename, or add policies to those tools:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { LocalSandbox, Workspace, WORKSPACE_TOOLS } from '@mastra/core/workspace'
|
|
65
|
+
|
|
66
|
+
const workspace = new Workspace({
|
|
67
|
+
sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
|
|
68
|
+
tools: {
|
|
69
|
+
requireApproval: true,
|
|
70
|
+
[WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: {
|
|
71
|
+
enabled: false,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
})
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Omitting a tool entry keeps its capability-driven default. Set `{ enabled: false }` on one tool to remove it, or set the top-level `enabled: false` to disable generated tools by default. A per-tool `{ enabled: true }` overrides that global setting. The top-level `requireApproval` policy applies to every generated tool unless a per-tool entry overrides it.
|
|
78
|
+
|
|
79
|
+
See the [sandbox tools reference](https://mastra.ai/reference/workspace/workspace-class) for all generated tools and the [tool configuration reference](https://mastra.ai/reference/workspace/workspace-class) for approvals, output limits, and hooks.
|
|
59
80
|
|
|
60
|
-
Authored runtime functions, including tools and workflow steps, can get the live sandbox from their execution context.
|
|
81
|
+
Authored runtime functions, including tools and workflow steps, can get the live sandbox from their execution context. Use it to execute commands, install dependencies, process files, or spawn a long-running process.
|
|
61
82
|
|
|
62
83
|
```typescript
|
|
63
|
-
import type { ProcessHandle } from '@mastra/core/sandbox'
|
|
64
84
|
import { createTool } from '@mastra/core/tools'
|
|
65
85
|
import { z } from 'zod'
|
|
66
86
|
|
|
@@ -71,15 +91,24 @@ export const startServerTool = createTool({
|
|
|
71
91
|
command: z.string(),
|
|
72
92
|
}),
|
|
73
93
|
execute: async ({ command }, ctx) => {
|
|
74
|
-
|
|
75
|
-
|
|
94
|
+
if (!ctx.workspace || !ctx.requestContext) {
|
|
95
|
+
throw new Error('This tool requires a workspace execution context')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const sandbox = await ctx.workspace.resolveSandbox({
|
|
99
|
+
requestContext: ctx.requestContext,
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
if (!sandbox?.processes) {
|
|
103
|
+
throw new Error('The configured sandbox does not support background processes')
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const server = await sandbox.processes.spawn(command)
|
|
76
107
|
return { pid: server.pid }
|
|
77
108
|
},
|
|
78
109
|
})
|
|
79
110
|
```
|
|
80
111
|
|
|
81
|
-
The authored function itself runs in your application process. Only operations called through the sandbox handle run inside the sandbox.
|
|
82
|
-
|
|
83
112
|
## Supported backends
|
|
84
113
|
|
|
85
114
|
### `LocalSandbox`
|
|
@@ -102,11 +131,11 @@ const sandbox = new LocalSandbox({
|
|
|
102
131
|
})
|
|
103
132
|
```
|
|
104
133
|
|
|
105
|
-
Use `LocalSandbox.detectIsolation()` to check whether Seatbelt or Bubblewrap is available on the current operating system. The `nativeSandbox` options control network access, read-only or writable paths,
|
|
134
|
+
Use `LocalSandbox.detectIsolation()` to check whether Seatbelt or Bubblewrap is available on the current operating system. The [`nativeSandbox` options](https://mastra.ai/reference/workspace/local-sandbox) control network access, read-only or writable paths, write access to the working directory, and system binaries. You can also provide a custom Seatbelt profile or Bubblewrap arguments. See [`LocalSandbox`](https://mastra.ai/reference/workspace/local-sandbox) for the full configuration.
|
|
106
135
|
|
|
107
136
|
### Other backends
|
|
108
137
|
|
|
109
|
-
Use a remote or container backend when commands need a stronger boundary from the host application. Each backend has its own isolation, persistence, networking, and mount behavior:
|
|
138
|
+
Use a remote or container backend when commands need a stronger boundary from the host application or when workloads need to scale beyond the resources of your application server. Each backend has its own isolation, persistence, networking, and mount behavior:
|
|
110
139
|
|
|
111
140
|
- [AgentCore](https://mastra.ai/integrations/sandboxes/agentcore)
|
|
112
141
|
- [Apple Container](https://mastra.ai/integrations/sandboxes/apple-container)
|
|
@@ -120,39 +149,47 @@ Use a remote or container backend when commands need a stronger boundary from th
|
|
|
120
149
|
- [Railway](https://mastra.ai/integrations/sandboxes/railway)
|
|
121
150
|
- [Vercel](https://mastra.ai/integrations/sandboxes/vercel)
|
|
122
151
|
|
|
123
|
-
If Mastra doesn't support your execution backend, implement [
|
|
152
|
+
If Mastra doesn't support your execution backend, implement the [sandbox provider interface](https://mastra.ai/reference/workspace/sandbox) to add it.
|
|
153
|
+
|
|
154
|
+
## Filesystem
|
|
124
155
|
|
|
125
|
-
|
|
156
|
+
Each sandbox has a native filesystem that commands can use. Treat it as ephemeral because its contents follow the sandbox's lifecycle.
|
|
126
157
|
|
|
127
|
-
|
|
158
|
+
To seed a sandbox with files or keep files between runs, give the agent a [filesystem](https://mastra.ai/docs/sandbox/filesystem). Use mounts when sandbox commands need access to the same files.
|
|
128
159
|
|
|
129
|
-
|
|
160
|
+
## Multi-tenant sandboxes
|
|
161
|
+
|
|
162
|
+
Use a **resolver** when each user, tenant, or thread needs a separate sandbox. Set `sandboxCacheKey` to the identity that owns the sandbox so later requests reuse the same live environment.
|
|
163
|
+
|
|
164
|
+
This example creates and caches one Daytona sandbox per user:
|
|
130
165
|
|
|
131
166
|
```typescript
|
|
167
|
+
import type { RequestContext } from '@mastra/core/request-context'
|
|
132
168
|
import { Workspace } from '@mastra/core/workspace'
|
|
133
169
|
import { DaytonaSandbox } from '@mastra/daytona'
|
|
134
|
-
|
|
170
|
+
|
|
171
|
+
const getUserId = (requestContext: RequestContext) => {
|
|
172
|
+
const userId = requestContext.get('user-id')
|
|
173
|
+
if (typeof userId !== 'string' || !userId) {
|
|
174
|
+
throw new Error('A user ID is required to resolve this sandbox')
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return userId
|
|
178
|
+
}
|
|
135
179
|
|
|
136
180
|
const workspace = new Workspace({
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}),
|
|
181
|
+
sandbox: async ({ requestContext }) => {
|
|
182
|
+
const sandbox = new DaytonaSandbox({ id: `user-${getUserId(requestContext)}` })
|
|
183
|
+
await sandbox.start()
|
|
184
|
+
return sandbox
|
|
142
185
|
},
|
|
143
|
-
|
|
186
|
+
sandboxCacheKey: ({ requestContext }) => getUserId(requestContext),
|
|
144
187
|
})
|
|
145
188
|
```
|
|
146
189
|
|
|
147
|
-
The
|
|
148
|
-
|
|
149
|
-
Mount support varies by sandbox backend. See [Filesystem](https://mastra.ai/docs/sandbox/filesystem) for supported storage backends, detailed mount configuration, and how to mount multiple filesystems.
|
|
150
|
-
|
|
151
|
-
## Multi-tenant sandboxes
|
|
152
|
-
|
|
153
|
-
Use a **resolver** when each user, tenant, or thread needs a separate sandbox. Set `sandboxCacheKey` to the identity that owns the sandbox so later requests reuse the same live environment.
|
|
190
|
+
The first request from a user creates the sandbox. Later requests with the same user ID reuse it.
|
|
154
191
|
|
|
155
|
-
This example creates one Daytona sandbox and one S3 storage prefix per memory thread
|
|
192
|
+
For a sandbox with persistent storage, create the filesystem and mount it inside the resolver. This example creates one Daytona sandbox and one S3 storage prefix per memory thread, then mounts the storage at `/workspace`:
|
|
156
193
|
|
|
157
194
|
```typescript
|
|
158
195
|
import { MASTRA_THREAD_ID_KEY, type RequestContext } from '@mastra/core/request-context'
|
|
@@ -163,7 +200,7 @@ import { S3Filesystem } from '@mastra/s3'
|
|
|
163
200
|
const getThreadId = (requestContext: RequestContext) => {
|
|
164
201
|
const threadId = requestContext.get(MASTRA_THREAD_ID_KEY)
|
|
165
202
|
if (typeof threadId !== 'string' || !threadId) {
|
|
166
|
-
throw new Error('A memory thread is required to
|
|
203
|
+
throw new Error('A memory thread is required to resolve this sandbox')
|
|
167
204
|
}
|
|
168
205
|
|
|
169
206
|
return threadId
|
|
@@ -195,32 +232,27 @@ const workspace = new Workspace({
|
|
|
195
232
|
|
|
196
233
|
The first request in a thread runs the resolver and starts the sandbox. Later requests with the same thread ID reuse the cached sandbox. A different thread ID creates a different sandbox and storage prefix.
|
|
197
234
|
|
|
198
|
-
|
|
235
|
+
The example mounts the filesystem inside the resolver because static `mounts` can't be combined with a sandbox resolver. Generated tools resolve the filesystem and sandbox from the request context automatically.
|
|
199
236
|
|
|
200
237
|
### Resolver ownership
|
|
201
238
|
|
|
202
|
-
|
|
239
|
+
You are responsible for every sandbox returned by a resolver. It must be ready to use when returned. Keep track of it and destroy it through your application lifecycle code when it's no longer needed. `workspace.destroy()` doesn't destroy resolver-returned sandboxes.
|
|
203
240
|
|
|
204
|
-
Resolvers are incompatible with `mounts` and [`lsp: true`](https://mastra.ai/docs/sandbox/lsp), because both require a static sandbox
|
|
241
|
+
Resolvers are incompatible with `mounts` and [`lsp: true`](https://mastra.ai/docs/sandbox/lsp), because both require a static sandbox during configuration. Using a resolver with `mounts` throws an `INVALID_CONFIG` error. With `lsp: true`, Mastra disables LSP and logs a warning.
|
|
205
242
|
|
|
206
243
|
### Tool availability
|
|
207
244
|
|
|
208
|
-
With a static sandbox, Mastra knows which capabilities the backend supports and only gives the agent the corresponding tools.
|
|
209
|
-
|
|
210
|
-
For example, this resolver returns a Daytona sandbox for development requests and an AgentCore sandbox for other requests:
|
|
245
|
+
With a static sandbox, Mastra knows which capabilities the backend supports and only gives the agent the corresponding tools. Application code should also check that an optional capability is available before using it:
|
|
211
246
|
|
|
212
247
|
```typescript
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
agentRuntimeArn: process.env.AGENTCORE_RUNTIME_ARN!,
|
|
219
|
-
}),
|
|
220
|
-
})
|
|
248
|
+
const processManager = workspace.sandbox?.processes
|
|
249
|
+
|
|
250
|
+
if (processManager) {
|
|
251
|
+
await processManager.spawn('pnpm dev')
|
|
252
|
+
}
|
|
221
253
|
```
|
|
222
254
|
|
|
223
|
-
|
|
255
|
+
With a [resolver-backed sandbox](#multi-tenant-sandboxes), the backend isn't known until a request runs, so Mastra initially makes all sandbox tools available. If the resolved backend doesn't support the tool the agent calls, the call fails with `SandboxFeatureNotSupportedError`.
|
|
224
256
|
|
|
225
257
|
## Background processes
|
|
226
258
|
|
|
@@ -247,26 +279,26 @@ These callbacks fire for all background processes started by the agent through `
|
|
|
247
279
|
|
|
248
280
|
By default, background processes inherit the agent's abort signal and stop when the agent disconnects. Set `abortSignal` to a custom signal, or use `null` or `false` when the process should continue after the request ends.
|
|
249
281
|
|
|
250
|
-
For the full `SandboxProcessManager` API
|
|
282
|
+
For the full `SandboxProcessManager` API, including programmatic process spawning, output, and standard input, see the [`SandboxProcessManager` reference](https://mastra.ai/reference/workspace/process-manager).
|
|
251
283
|
|
|
252
284
|
## Lifecycle and persistence
|
|
253
285
|
|
|
254
|
-
|
|
286
|
+
Who shares a sandbox depends on where you configure it and whether you use a resolver:
|
|
255
287
|
|
|
256
|
-
| Configuration
|
|
257
|
-
|
|
|
258
|
-
| Mastra-level
|
|
259
|
-
| Agent-level
|
|
260
|
-
| Resource-scoped resolver
|
|
261
|
-
| Thread-scoped resolver
|
|
288
|
+
| Configuration | Who shares the sandbox |
|
|
289
|
+
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
290
|
+
| Mastra-level configuration | Agents that inherit the configuration from the [`Mastra`](https://mastra.ai/reference/configuration) instance use the same sandbox. |
|
|
291
|
+
| Agent-level configuration | Every request handled by that agent instance uses the same sandbox. |
|
|
292
|
+
| Resource-scoped resolver | The resolver caches one sandbox for each resource ID. |
|
|
293
|
+
| Thread-scoped resolver | A memory thread keeps its sandbox across requests in that thread. |
|
|
262
294
|
|
|
263
295
|
A static sandbox isn't automatically scoped to the current resource or memory thread. For resource or thread scope, use a resolver and set `sandboxCacheKey` to the corresponding ID. See [Multi-tenant sandboxes](#multi-tenant-sandboxes).
|
|
264
296
|
|
|
265
297
|
### Start
|
|
266
298
|
|
|
267
|
-
Static sandbox
|
|
299
|
+
Static sandbox environments usually start when the first command runs, so most applications don't need to initialize them explicitly. Call `workspace.init()` during application startup only when you want to start a static sandbox and prepare its mounts before serving requests. This is useful when credential, network, or provider errors need to surface during startup instead of on the first command.
|
|
268
300
|
|
|
269
|
-
|
|
301
|
+
`workspace.init()` doesn't start resolver-backed sandboxes because no sandbox is selected until a request runs. The resolver must return a sandbox that's already started or can start itself on first use.
|
|
270
302
|
|
|
271
303
|
### Hooks
|
|
272
304
|
|
|
@@ -285,9 +317,11 @@ const sandbox = new LocalSandbox({
|
|
|
285
317
|
|
|
286
318
|
### Cleanup
|
|
287
319
|
|
|
288
|
-
|
|
320
|
+
When you configure a sandbox directly instead of using a resolver, Mastra owns it. `mastra dev` and the generated Mastra server handle shutdown signals and destroy registered resources automatically. If you embed Mastra in a custom server or process, call `mastra.shutdown()` from its shutdown hook. For standalone use, call `workspace.destroy()` directly.
|
|
321
|
+
|
|
322
|
+
The backend decides what `stop()` and `destroy()` do. For example, stopping may shut down compute while preserving an environment that can restart, while destroying may delete the environment and its ephemeral files. Check the selected backend before relying on either behavior.
|
|
289
323
|
|
|
290
|
-
Sandboxes returned by a resolver are owned by your application. `workspace.destroy()` and `mastra.shutdown()` clear
|
|
324
|
+
Sandboxes returned by a resolver are owned by your application. `workspace.destroy()` and `mastra.shutdown()` clear cached references but don't destroy resolved sandboxes. Application lifecycle code must keep track of them, call `destroy()` when their user, thread, or session ends, and then call `workspace.clearSandboxCache(cacheKey)`. This prevents unused compute from continuing to run and later requests from reusing a stale sandbox.
|
|
291
325
|
|
|
292
326
|
### Persistence
|
|
293
327
|
|
|
@@ -335,5 +369,5 @@ await sandbox.executeCommand('node', ['scripts/download-reports.js'], {
|
|
|
335
369
|
## Related
|
|
336
370
|
|
|
337
371
|
- [`SandboxProcessManager` reference](https://mastra.ai/reference/workspace/process-manager)
|
|
338
|
-
- [
|
|
372
|
+
- [Sandbox provider interface](https://mastra.ai/reference/workspace/sandbox)
|
|
339
373
|
- [Filesystem](https://mastra.ai/docs/sandbox/filesystem)
|