Server Workspaces vs MCP Roots: Complete Guide
Overview
This guide explains the fundamental distinction between Server Workspaces (server-managed file access) and MCP Roots (client-managed file exposure) in the Simple RPC AI Backend. Understanding this separation is crucial for proper MCP protocol compliance and secure file access patterns.
Table of Contents
- Architecture Overview
- Server Workspaces (Server-Managed)
- MCP Roots (Client-Managed)
- Configuration Examples
- Security Considerations
- Troubleshooting
Architecture Overview
flowchart TD
subgraph Client
clientRoots[Client-managed directories<br/>e.g. ~/projects,<br/>/mnt/shared]
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
The direction of each arrow mirrors who initiates the call: the server invokes roots/list on the client to discover exposed directories, while the client calls registerClientWorkspace on the server to grant access to its folders.
๐ Key Differences
| Aspect | Server Workspaces | MCP Roots |
|---|---|---|
| Owner | Server | Client |
| Configuration | Server config file | Client capability + registration |
| Purpose | Server resources & templates | User workspace folders |
| Access Control | Server administrator | End user |
| MCP Protocol | Not part of MCP roots/list | Part of MCP roots/list |
| Tools | getServerWorkspaces, listFiles | registerClientWorkspace, roots/list |
Server Workspaces (Server-Managed)
Server Workspaces are directories that the server administrator configures to provide access to server-controlled resources.
๐ฏ Use Cases
- Templates & Examples:
/opt/templates,/usr/share/examples - Reference Data:
/srv/data,/var/app-data - Shared Resources:
/shared/docs,/company/policies - Server Projects:
/home/server/projects
โ๏ธ Configuration
const server = createRpcAiServer({
// Server-managed directories (not MCP roots)
serverWorkspaces: {
enabled: true, // Enable workspace tools
additionalWorkspaces: {
templates: {
path: '/opt/templates',
name: 'Server Templates',
description: 'Pre-built project templates',
readOnly: true,
allowedExtensions: ['.js', '.ts', '.json', '.md']
},
sharedDocs: {
path: '/shared/documentation',
name: 'Shared Documentation',
description: 'Company-wide documentation',
readOnly: true
},
workArea: {
path: '/tmp/workspace',
name: 'Temporary Work Area',
description: 'Temporary file operations',
readOnly: false,
maxFileSize: 10485760 // 10MB limit
}
}
}
});
๐ ๏ธ Available Tools
When serverWorkspaces is configured, these tRPC/MCP tools become available:
getServerWorkspaces: List all configured server workspaceslistFiles: List files in a server workspacereadFile: Read file content from a server workspacewriteFile: Write files to a server workspace (if not readOnly)pathExists: Check if a path exists in a server workspaceaddServerWorkspace: Dynamically add new server workspacesremoveServerWorkspace: Remove server workspaces
๐ Security Features
serverWorkspaces: {
myWorkspace: {
path: '/safe/directory',
readOnly: false,
// Path restrictions
allowedPaths: ['docs/*', 'src/**/*.js'], // Only these patterns
blockedPaths: ['**/node_modules', '**/.git'], // Never these patterns
// File restrictions
allowedExtensions: ['.js', '.ts', '.md'], // Only these file types
blockedExtensions: ['.exe', '.sh'], // Never these file types
maxFileSize: 1048576, // 1MB file size limit
// Symlink handling
followSymlinks: false, // Don't follow symlinks (security)
// File watching
enableWatching: true // Watch for file changes
}
}
MCP Roots (Client-Managed)
MCP Roots are directories that the client/user exposes to the server through the Model Context Protocol.
๐ฏ Use Cases
- IDE Workspaces: VS Code workspace folders
- Project Directories: Userโs active development projects
- Document Folders: Userโs personal documents
- Custom Locations: Any folder the user wants to share
๐ MCP Protocol Flow
sequenceDiagram
participant Client
participant Server
Note over Client,Server: 1. Capability Negotiation
Client->>Server: initialize(capabilities: {roots: {listChanged: true}})
Server->>Client: initialize_response(capabilities: {...})
Note over Client,Server: 2. Root Discovery
Server->>Client: roots/list
Client->>Server: roots/list_response([{uri: "file:///path", name: "Project"}])
Note over Client,Server: 3. Change Notifications
Client->>Server: notifications/roots/list_changed
Server->>Client: (no response - notification only)
๐ ๏ธ Available Tools
For MCP client roots, these tools are available:
registerClientWorkspace: Register a client workspace with the serverunregisterClientWorkspace: Remove a registered client workspacelistClientWorkspaces: List all registered client workspacesroots/list(MCP protocol): Server queries client for exposed roots
๐ Client Root Registration
// Client can register their workspace folders
await client.registerClientWorkspace({
id: 'my-project',
uri: 'file:///home/user/projects/my-project',
name: 'My Project',
description: 'Active development project'
});
๐ Tool Integration Example
Combine server workspaces with MCP tools and custom routers. The snippet below mirrors the structure in examples/02-mcp-server/server.js, exposing two namespaces (workspace and utility) through customRouters while still benefiting from automatic MCP discovery:
import { router, publicProcedure, createRpcAiServer } from 'simple-rpc-ai-backend';
import { z } from 'zod';
// Workspace-related procedures
const workspaceRouter = router({
readFile: publicProcedure
.input(z.object({ path: z.string() }))
.query(async ({ input }) => {
// Wrap MCP file read logic here
return readWorkspaceFile(input.path);
}),
writeFile: publicProcedure
.input(z.object({ path: z.string(), contents: z.string() }))
.mutation(async ({ input }) => {
await writeWorkspaceFile(input.path, input.contents);
return { success: true };
})
});
// Utility procedures (AI helpers, prompts, etc.)
const utilityRouter = router({
summarize: publicProcedure
.input(z.object({ text: z.string() }))
.mutation(async ({ input }) => summarizeText(input.text)),
listTools: publicProcedure.query(() => ({
workspace: ['readFile', 'writeFile'],
utility: ['summarize']
}))
});
const app = createRpcAiServer({
serverWorkspaces: {
docs: { path: '/opt/docs', readOnly: true },
sandbox: { path: '/tmp/sandbox', readOnly: false }
},
customRouters: {
workspace: workspaceRouter,
utility: utilityRouter
}
});
app.start();
๐ Client Security
According to MCP specification, clients MUST:
- Only expose roots with appropriate permissions
- Validate all root URIs to prevent path traversal
- Implement proper access controls
- Monitor root accessibility
- Prompt users for consent before exposing roots to servers
Configuration Examples
Basic Server Setup
import { createRpcAiServer } from 'simple-rpc-ai-backend';
const server = createRpcAiServer({
serverProviders: ['anthropic'],
// Server-managed directories
serverWorkspaces: {
enabled: true,
additionalWorkspaces: {
templates: {
path: './templates',
name: 'Project Templates',
readOnly: true
},
work: {
path: './workspace',
name: 'Work Area',
readOnly: false
}
}
},
// MCP configuration for client roots
mcp: {
enabled: true,
auth: {
requireAuthForToolsList: false,
requireAuthForToolsCall: false
}
}
});
server.start();
Production Security Setup
const server = createRpcAiServer({
// Restricted server workspaces
serverWorkspaces: {
enabled: true,
additionalWorkspaces: {
publicTemplates: {
path: '/opt/secure-templates',
name: 'Approved Templates',
readOnly: true,
allowedExtensions: ['.md', '.json', '.js'],
maxFileSize: 1048576 // 1MB
},
userScratch: {
path: '/tmp/user-workspace',
name: 'User Scratch Area',
readOnly: false,
allowedPaths: ['**/*.txt', '**/*.md'],
blockedPaths: ['**/*.exe', '**/*.sh'],
maxFileSize: 5242880 // 5MB
}
}
},
// Secure MCP configuration
mcp: {
enabled: true,
auth: {
requireAuthForToolsList: true, // Require auth
requireAuthForToolsCall: true, // Require auth
publicTools: [] // No public tools
}
}
});
Development Setup with Both
const server = createRpcAiServer({
// Development server workspaces
serverWorkspaces: {
enabled: true,
additionalWorkspaces: {
examples: {
path: './examples',
name: 'Code Examples',
readOnly: true
},
playground: {
path: './playground',
name: 'Development Playground',
readOnly: false,
enableWatching: true
}
}
},
// Liberal MCP settings for development
mcp: {
enabled: true,
auth: {
requireAuthForToolsList: false,
requireAuthForToolsCall: false,
publicTools: [
'getServerWorkspaces',
'listFiles',
'readFile',
'registerClientWorkspace'
]
}
}
});
Security Considerations
๐ก๏ธ Server Workspace Security
Server administrators must consider:
- Path Traversal Protection
serverWorkspaces: { restricted: { path: '/safe/directory', // Prevent access outside this directory allowedPaths: ['**/*'], // Only within this workspace blockedPaths: ['../**'] // Block parent directory access } } - File Type Restrictions
serverWorkspaces: { documents: { path: './docs', allowedExtensions: ['.md', '.txt', '.json'], blockedExtensions: ['.exe', '.sh', '.bat'] // Block executables } } - Size Limits
serverWorkspaces: { uploads: { path: './uploads', maxFileSize: 10485760 // 10MB per file } }
๐ MCP Root Security
Clients should implement:
- User Consent: Always prompt before exposing directories
- Path Validation: Validate URIs to prevent malicious paths
- Permission Checks: Verify read/write permissions
- Monitoring: Watch for unauthorized access attempts
๐จ Common Security Mistakes
โ DONโT DO THIS:
// WRONG: Exposing system directories
serverWorkspaces: {
system: {
path: '/', // โ Root filesystem access
readOnly: false // โ Write access to system
}
}
// WRONG: No restrictions
serverWorkspaces: {
anything: {
path: '/home/user',
// โ No file type restrictions
// โ No size limits
// โ No path restrictions
}
}
โ DO THIS:
// CORRECT: Restricted access
serverWorkspaces: {
userDocuments: {
path: '/home/user/documents',
readOnly: true, // โ
Read-only
allowedExtensions: ['.md', '.txt'], // โ
Limited file types
maxFileSize: 1048576, // โ
Size limit
allowedPaths: ['**/*.md', '**/*.txt'], // โ
Path restrictions
followSymlinks: false // โ
No symlink following
}
}
Troubleshooting
Common Issues
- โNo workspaces availableโ error
// Problem: serverWorkspaces not configured const server = createRpcAiServer({ // Missing serverWorkspaces configuration }); // Solution: Add serverWorkspaces const server = createRpcAiServer({ serverWorkspaces: { work: { path: './workspace', name: 'Work Area' } } }); - โAccess deniedโ errors
// Problem: Restrictive path/extension rules serverWorkspaces: { docs: { path: './docs', allowedExtensions: ['.md'], // Only .md files allowed readOnly: true // No write access } } // Solution: Adjust restrictions as needed - MCP roots not working
// Problem: Client doesn't support roots capability // Check client initialization: { "method": "initialize", "params": { "capabilities": { "roots": { "listChanged": true // โ Must be present } } } }
Debugging
Enable debug logging:
const server = createRpcAiServer({
monitoring: {
logging: {
level: 'debug' // Enable debug logs
}
}
});
Look for these log messages:
๐๏ธ MCP roots/list: Client supports roots capability๐ Server workspace registered: workspaceId๐ MCP Initialize: clientSupportsRoots: true
Testing Configuration
Test your workspace configuration:
# Test server workspace access
curl -X POST http://localhost:8001/trpc/system.getServerWorkspaces
# Test MCP roots capability
curl -X POST http://localhost:8001/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "roots/list"}'
Best Practices
๐ฏ Server Workspace Best Practices
- Principle of Least Privilege: Only expose necessary directories
- Read-Only by Default: Use
readOnly: trueunless write access is required - File Type Restrictions: Always specify
allowedExtensions - Size Limits: Set reasonable
maxFileSizelimits - Path Validation: Use
allowedPathsandblockedPaths
๐ฏ MCP Root Best Practices
- User Consent: Always get explicit user permission
- Capability Declaration: Properly declare roots capability
- Change Notifications: Send
notifications/roots/list_changedwhen roots change - Error Handling: Handle cases where roots become unavailable
๐ฏ Security Best Practices
- Defense in Depth: Use multiple security layers
- Input Validation: Validate all file paths and names
- Monitoring: Log all file operations
- Regular Audits: Review workspace configurations regularly
- Update Promptly: Keep dependencies updated
Reference
- MCP Specification: Model Context Protocol - Roots
- Server Workspace Types: See
ServerWorkspaceConfiginsrc/services/workspace-manager.ts - MCP Tools: See system router in
src/trpc/routers/system/index.ts - Configuration Types: See
RpcAiServerConfiginsrc/rpc-ai-server.ts
Next Steps:
- Review your current configuration against security best practices
- Test both server workspaces and MCP root functionality
- Set up monitoring and logging for file operations
- Consider implementing user authentication for sensitive workspaces