Workspaces
Understand the distinction between server-managed workspaces and client-supplied MCP roots to configure access safely.
Concepts at a Glance
| Aspect | Server Workspaces | MCP Roots |
|---|---|---|
| Owner | Server administrator | Client / end user |
| Configuration | Server config (serverWorkspaces) | MCP capability negotiation |
| Purpose | Templates, shared resources, sandbox directories | User project folders |
| Access Control | Enforced by server policies | Granted by the client |
| MCP Role | Not part of roots/list | Exposed via roots/list |
Architecture Overview
flowchart TD
subgraph Client
clientRoots[Client-managed directories<br/>e.g. ~/projects,<br/>/mnt/shared/projectX]
end
subgraph Server
rpcServer((tRPC / MCP Server))
serverWorkspaces[Server Workspaces<br/>Configured via serverWorkspaces]
end
rpcServer -- "roots/list" --> clientRoots
clientRoots -- "registerClientWorkspace" --> rpcServer
rpcServer -- "listFiles / readFile / writeFile" --> serverWorkspaces
Arrow directions reflect who makes each request: the server calls roots/list on the client, whereas the client invokes registerClientWorkspace on the server.
Server Workspaces
Server workspaces are directories registered by the server to expose curated content. They are available via tRPC and MCP tools like getServerWorkspaces, listFiles, and readFile.
Use Cases
- Templates & examples – expose curated sample projects or onboarding kits.
- Reference data – serve static catalogues, project manifests, or SQL migrations.
- Shared resources – provide compliance documents or knowledge-base exports.
- Scratch space – give users a temporary area for uploads with quotas.
Example Configuration
const server = createRpcAiServer({
serverWorkspaces: {
enableAPI: true,
templates: {
path: '/opt/templates',
name: 'Server Templates',
description: 'Pre-built project templates',
readOnly: true,
allowedExtensions: ['.js', '.ts', '.json', '.md']
},
sandbox: {
path: '/tmp/workspace',
name: 'Sandbox',
readOnly: false,
allowedPaths: ['**/*.txt', '**/*.json'],
blockedPaths: ['**/node_modules', '**/.git'],
maxFileSize: 5 * 1024 * 1024,
followSymlinks: false
}
}
});
Security Checklist
- Default to
readOnly: trueunless write access is essential. - Restrict file types with
allowedExtensionsandblockedExtensions. - Limit path traversal with
allowedPathsandblockedPaths. - Set
followSymlinks: falseto avoid symlink escapes. - Impose
maxFileSizelimits for uploads or writes. - Set up monitoring to log high-risk operations (delete/write).
Available Tools
When serverWorkspaces is configured, these tRPC/MCP tools become available:
getServerWorkspaceslistFiles,readFile,writeFile,pathExistsaddServerWorkspace,removeServerWorkspace
MCP Roots
MCP roots represent client-controlled folders. Clients register them with the server and expose them via the MCP roots/list exchange.
await client.registerClientWorkspace({
id: 'project',
uri: 'file:///home/user/projects/sample',
name: 'Sample Project'
});
const roots = await server.mcpCall('roots/list');
// Returns client-advertised directories
Best Practices
- Prompt users for explicit consent before sharing directories.
- Validate incoming
file://URIs on the client side. - Monitor access patterns and audit when sensitive files are involved.
- Ensure MCP clients advertise the
rootscapability ({"roots": {"listChanged": true}}). - Send
notifications/roots/list_changedwhen the client’s workspace list changes. - Handle missing roots gracefully—clients may revoke them at any time.
Configuration Scenarios
const server = createRpcAiServer({
serverWorkspaces: {
templates: {
path: '/opt/templates',
readOnly: true,
allowedExtensions: ['.md', '.json']
},
sandbox: {
path: '/tmp/workspace',
readOnly: false,
maxFileSize: 10 * 1024 * 1024,
allowedPaths: ['**/*.json', '**/*.md'],
blockedPaths: ['**/node_modules/**', '**/.git/**']
}
},
mcp: {
enabled: true,
auth: { requireAuthForToolsCall: true }
}
});
On the MCP client side:
{
"method": "initialize",
"params": {
"capabilities": {
"roots": { "listChanged": true }
}
}
}
Security Considerations
- Principle of least privilege – expose the smallest directory possible.
- Readonly first – flip
readOnlytofalseonly when you truly need write access. - File type allowlists – set
allowedExtensionsrather than relying on defaults. - Symlink protection – keep
followSymlinks: falseunless you trust the tree. - Audit trails – enable structured logging for file operations and review regularly.
Troubleshooting
| Symptom | Likely Cause | Resolution |
|---|---|---|
No workspaces available | serverWorkspaces missing | Add at least one workspace configuration. |
writeFile returns ACCESS_DENIED | Workspace is read-only or path blocked | Toggle readOnly or adjust path rules. |
| MCP client cannot see roots | Client did not advertise roots capability | Ensure initialize payload includes roots. |
| Unexpected files exposed | allowedPaths too broad | Tighten glob patterns or add blockedPaths. |
Enable debug logging to inspect decisions:
const server = createRpcAiServer({
monitoring: {
logging: { level: 'debug' }
}
});
Best Practices Recap
- Keep server workspaces curated and audited.
- Require explicit user consent before registering MCP roots.
- Combine server and client workspaces for a complete experience.
- Review configurations periodically—especially before enabling write access.