@mastra/mcp-docs-server 1.1.28-alpha.3 → 1.1.28-alpha.4

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.
@@ -93,6 +93,58 @@ const workspace = new Workspace({
93
93
 
94
94
  When `contained` is `false`, absolute paths are treated as real filesystem paths with no restriction.
95
95
 
96
+ ## Dynamic filesystem
97
+
98
+ The `filesystem` option accepts a resolver function instead of a static instance. The resolver receives `requestContext` and returns a filesystem per request, allowing a single workspace to serve different filesystems based on the caller's identity, role, or tenant.
99
+
100
+ ```typescript
101
+ import { Agent } from '@mastra/core/agent'
102
+ import { Workspace, LocalFilesystem } from '@mastra/core/workspace'
103
+
104
+ const workspace = new Workspace({
105
+ filesystem: ({ requestContext }) => {
106
+ const role = requestContext.get('agent-role') || 'guest'
107
+ return new LocalFilesystem({
108
+ basePath: `/workspaces/${role}`,
109
+ readOnly: role !== 'admin',
110
+ })
111
+ },
112
+ })
113
+
114
+ const agent = new Agent({
115
+ id: 'multi-role-agent',
116
+ model: 'openai/gpt-4o',
117
+ workspace,
118
+ })
119
+ ```
120
+
121
+ Each request resolves its own filesystem at tool execution time:
122
+
123
+ ```typescript
124
+ import { RequestContext } from '@mastra/core/request-context'
125
+
126
+ // Admin request — reads and writes from /workspaces/admin/
127
+ const adminCtx = new RequestContext([['agent-role', 'admin']])
128
+ await agent.generate('Write report.txt with Q4 results', { requestContext: adminCtx })
129
+
130
+ // Viewer request — reads from /workspaces/viewer/, writes are blocked
131
+ const viewerCtx = new RequestContext([['agent-role', 'viewer']])
132
+ await agent.generate('Read info.txt', { requestContext: viewerCtx })
133
+ ```
134
+
135
+ The resolver can also be asynchronous, for example to look up configuration from a database:
136
+
137
+ ```typescript
138
+ const workspace = new Workspace({
139
+ filesystem: async ({ requestContext }) => {
140
+ const tenantConfig = await db.getTenant(requestContext.get('tenant-id'))
141
+ return new LocalFilesystem({ basePath: tenantConfig.storagePath })
142
+ },
143
+ })
144
+ ```
145
+
146
+ > **Note:** `filesystem` and `mounts` are mutually exclusive. You cannot use a resolver function together with `mounts` in the same workspace.
147
+
96
148
  ## Read-only mode
97
149
 
98
150
  To prevent agents from modifying files, enable read-only mode:
@@ -106,7 +158,9 @@ const workspace = new Workspace({
106
158
  })
107
159
  ```
108
160
 
109
- When read-only, write tools (`write_file`, `edit_file`, `delete`, `mkdir`) aren't added to the agent's toolset. The agent can still read and list files.
161
+ With a static filesystem, write tools (`write_file`, `edit_file`, `delete`, `mkdir`) are excluded from the agent's toolset entirely. The agent can still read and list files.
162
+
163
+ When using a [dynamic filesystem](#dynamic-filesystem), write tools are always included because `readOnly` isn't known until the resolver runs. Instead, write operations are blocked at runtime — the tool returns an error if the resolved filesystem is read-only.
110
164
 
111
165
  ## Mounts and `CompositeFilesystem`
112
166
 
@@ -153,15 +153,34 @@ const workspace = new Workspace({
153
153
 
154
154
  The agent receives the `execute_command` tool.
155
155
 
156
+ ### Dynamic filesystem (per-request)
157
+
158
+ Pass a resolver function to `filesystem` to return a different filesystem per request. This is useful for multi-tenant applications or multi-role agents where each request needs a different storage root or different permissions.
159
+
160
+ ```typescript
161
+ const workspace = new Workspace({
162
+ filesystem: ({ requestContext }) => {
163
+ const role = requestContext.get('agent-role') || 'guest'
164
+ return new LocalFilesystem({
165
+ basePath: `/workspaces/${role}`,
166
+ readOnly: role !== 'admin',
167
+ })
168
+ },
169
+ })
170
+ ```
171
+
172
+ One workspace instance serves all requests. The resolver runs at tool execution time, so each request gets its own filesystem. See [dynamic filesystem](https://mastra.ai/docs/workspace/filesystem) for details.
173
+
156
174
  ### Which pattern should I use?
157
175
 
158
- | Scenario | Pattern |
159
- | ----------------------------------------------------- | ----------------------------------------------------- |
160
- | Local development with files and commands | `filesystem` + `sandbox` (both local, same directory) |
161
- | Cloud storage accessible inside a cloud sandbox | `mounts` + `sandbox` |
162
- | Multiple cloud providers in one sandbox | `mounts` + `sandbox` (one mount per provider) |
163
- | Agent reads/writes files, no command execution needed | `filesystem` only |
164
- | Agent runs commands, no file tools needed | `sandbox` only |
176
+ | Scenario | Pattern |
177
+ | --------------------------------------------------------- | ----------------------------------------------------- |
178
+ | Local development with files and commands | `filesystem` + `sandbox` (both local, same directory) |
179
+ | Cloud storage accessible inside a cloud sandbox | `mounts` + `sandbox` |
180
+ | Multiple cloud providers in one sandbox | `mounts` + `sandbox` (one mount per provider) |
181
+ | Agent reads/writes files, no command execution needed | `filesystem` only |
182
+ | Agent runs commands, no file tools needed | `sandbox` only |
183
+ | Multi-role or multi-tenant agent with per-request storage | `filesystem` with resolver function |
165
184
 
166
185
  ## Tool configuration
167
186
 
@@ -29,7 +29,7 @@ const workspace = new Workspace({
29
29
 
30
30
  **name** (`string`): Human-readable name (Default: `workspace-{id}`)
31
31
 
32
- **filesystem** (`WorkspaceFilesystem`): Filesystem provider instance (e.g., LocalFilesystem)
32
+ **filesystem** (`WorkspaceFilesystem | WorkspaceFilesystemResolver`): Filesystem provider instance, or a resolver function that receives \`requestContext\` and returns a filesystem per request. See \[dynamic filesystem]\(/docs/workspace/filesystem#dynamic-filesystem).
33
33
 
34
34
  **sandbox** (`WorkspaceSandbox`): Sandbox provider instance (e.g., LocalSandbox)
35
35
 
@@ -122,7 +122,7 @@ Tool names must be unique across all workspace tools. Setting a custom name that
122
122
 
123
123
  **status** (`WorkspaceStatus`): 'pending' | 'initializing' | 'ready' | 'paused' | 'error' | 'destroying' | 'destroyed'
124
124
 
125
- **filesystem** (`WorkspaceFilesystem | undefined`): The filesystem provider
125
+ **filesystem** (`WorkspaceFilesystem | undefined`): The static filesystem provider. Returns \`undefined\` when a resolver function is configured — use \`hasFilesystemConfig()\` to check availability.
126
126
 
127
127
  **sandbox** (`WorkspaceSandbox | undefined`): The sandbox provider
128
128
 
@@ -251,6 +251,37 @@ workspace.setToolsConfig(undefined)
251
251
 
252
252
  **config** (`WorkspaceToolsConfig | undefined`): New tool configuration to apply. Pass undefined to reset to defaults.
253
253
 
254
+ ### Dynamic filesystem
255
+
256
+ #### `hasFilesystemConfig()`
257
+
258
+ Check whether a filesystem is configured, either as a static instance or a resolver function. Use this instead of checking `workspace.filesystem` directly, because a resolver-based workspace returns `undefined` from the `filesystem` property.
259
+
260
+ ```typescript
261
+ if (workspace.hasFilesystemConfig()) {
262
+ // Filesystem tools are available
263
+ }
264
+ ```
265
+
266
+ **Returns:** `boolean`
267
+
268
+ #### `resolveFilesystem({ requestContext })`
269
+
270
+ Resolve the filesystem for a given request context. When a resolver function is configured, calls it with the provided `requestContext`. When a static filesystem is configured, returns it directly. Returns `undefined` if no filesystem is configured.
271
+
272
+ ```typescript
273
+ import { RequestContext } from '@mastra/core/request-context'
274
+
275
+ const ctx = new RequestContext([['agent-role', 'admin']])
276
+ const fs = await workspace.resolveFilesystem({ requestContext: ctx })
277
+ ```
278
+
279
+ **Parameters:**
280
+
281
+ **requestContext** (`RequestContext`): The request context to pass to the resolver function.
282
+
283
+ **Returns:** `Promise<WorkspaceFilesystem | undefined>`
284
+
254
285
  ## Agent tools
255
286
 
256
287
  A workspace provides tools to agents based on what's configured.
@@ -270,7 +301,7 @@ Added when a filesystem is configured:
270
301
  | `mastra_workspace_mkdir` | Create a directory. Creates parent directories automatically if they don't exist. |
271
302
  | `mastra_workspace_grep` | Search file contents using regex patterns. Supports glob filtering, context lines, and case-insensitive search. |
272
303
 
273
- Write tools (`write_file`, `edit_file`, `delete`, `mkdir`) are excluded when the filesystem is in read-only mode.
304
+ With a static filesystem, write tools (`write_file`, `edit_file`, `delete`, `mkdir`) are excluded when the filesystem is in read-only mode. With a [dynamic filesystem](https://mastra.ai/docs/workspace/filesystem), write tools are always included and read-only is enforced at runtime.
274
305
 
275
306
  ### Sandbox tools
276
307
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @mastra/mcp-docs-server
2
2
 
3
+ ## 1.1.28-alpha.4
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`45e29cb`](https://github.com/mastra-ai/mastra/commit/45e29cb5b5737f3083eb3852db02b944b9cf37ed), [`696694e`](https://github.com/mastra-ai/mastra/commit/696694e00f29241a25dd1a1b749afa06c3a626b4)]:
8
+ - @mastra/core@1.28.0-alpha.2
9
+
3
10
  ## 1.1.28-alpha.2
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.1.28-alpha.3",
3
+ "version": "1.1.28-alpha.4",
4
4
  "description": "MCP server for accessing Mastra.ai documentation, changelogs, and news.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -29,7 +29,7 @@
29
29
  "jsdom": "^26.1.0",
30
30
  "local-pkg": "^1.1.2",
31
31
  "zod": "^4.3.6",
32
- "@mastra/core": "1.28.0-alpha.1",
32
+ "@mastra/core": "1.28.0-alpha.2",
33
33
  "@mastra/mcp": "^1.5.1"
34
34
  },
35
35
  "devDependencies": {
@@ -47,8 +47,8 @@
47
47
  "typescript": "^5.9.3",
48
48
  "vitest": "4.1.5",
49
49
  "@internal/lint": "0.0.85",
50
- "@internal/types-builder": "0.0.60",
51
- "@mastra/core": "1.28.0-alpha.1"
50
+ "@mastra/core": "1.28.0-alpha.2",
51
+ "@internal/types-builder": "0.0.60"
52
52
  },
53
53
  "homepage": "https://mastra.ai",
54
54
  "repository": {