Security model
This page states what each of the six servers is and — just as importantly — what it is not. The servers run with the OS permissions of the MCP server process; none of them is a sandbox. Connect them only to clients you trust, and never expose them over an untrusted network.
Filesystem server: path and symlink controls
All filesystem operations are restricted to the directories passed on the command line, or to the process's current directory when none are supplied (AccessControl in src/support/access.rs).
- Roots are canonicalized at startup. Each allowed directory is stored both as given (lexically normalized) and as canonicalized. This fixes symlinked-path mismatches such as macOS
/tmp→/private/tmp: a path requested as/tmp/xstill validates when the allowed root was given as/private/tmp. - Requested paths are lexically normalized (
.collapsed,..resolved where possible, redundant separators stripped) before any check, blocking..escapes like/allowed/../../etc/passwd. ~is expanded to the user's home directory for both roots and requested paths.- Relative paths resolve against the first allowed directory.
- Symlink escapes are rejected. For existing paths, the canonicalized target must still be inside an allowed root. For paths that do not exist yet (new files/directories), the deepest existing ancestor is canonicalized and must resolve inside an allowed root — so whole trees can be created at once without allowing a symlinked ancestor to escape.
- Writes are atomic.
write_file/edit_filewrite a unique temp file next to the target and rename it into place, so a symlink that appears between validation and the write is never followed. - Search and tree walks re-validate every visited entry against the allowed roots and silently skip anything that resolves outside.
This is access control, not a sandbox: within an allowed directory the server can do anything the process user can do.
Fetch server: network exposure
The fetch server makes real HTTP(S) requests on behalf of the model. Key facts:
- It can reach local and internal IP addresses. There is no SSRF protection:
http://127.0.0.1/..., link-local, or RFC 1918 addresses are fetchable. Only enable this server when you trust the clients connected to it. - Only
httpandhttpsschemes are accepted; anything else is rejected before any network I/O. - Every request has a 30-second timeout.
- robots.txt policy: checks are disabled by default. When the server is started with
--respect-robots-txt:- robots.txt unreachable → the fetch is blocked with an error;
- robots.txt returns 401/403 → blocked (assumed not allowed);
- any other 4xx (for example 404) → allowed;
- otherwise robots.txt is parsed and matched against the configured user agent; a disallow rule blocks the fetch.
- The
fetchprompt never checks robots.txt: it is user-initiated regardless of this option.
- Default User-Agent for tool and prompt requests (customizable with
--user-agent):Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 - Response bodies are decoded as text (charset-aware); HTML is simplified to markdown with
style,script,noscript, andtemplatecontent suppressed rather than leaked into model output.
Memory server: process permissions and plaintext data
- The knowledge graph is persisted as a plaintext JSONL file, written with the OS permissions of the server process. There is no encryption.
- The file location is resolved in this order:
--memory-fileflag, then theMEMORY_FILE_PATHenvironment variable, thenmemory.jsonlin the current working directory. - A corrupt file fails loads with an explicit error (never silently truncated), and concurrent mutations are serialized with a mutex.
- The file format matches the reference memory server (
{"type":"entity",...}/{"type":"relation",...}lines), so a file written by this server is readable by the reference server and vice versa. - Data at rest is protected only by filesystem permissions; treat the memory file like any other sensitive local data.
Shell server: not a sandbox, no command filter
execute_command runs one local program directly (no shell) with the OS permissions of the MCP server process: user identity, environment, network access, filesystem access — everything the user can do.
- The
cwdrestriction only constrains the working directory of each command. A program running in an allowed directory can still read, write, and execute anything the user can. The cwd restriction is not a sandbox. - There is no command allow/deny filter. This is deliberate: blacklisting strings like
rmorsudowould be ineffective and is intentionally avoided. - There is no implicit shell (
sh -c/bash -c/cmd /Care never spawned), so shell metacharacters in arguments are inert — but a model can trivially run a shell itself (program: "bash", args: ["-lc", ...]), which is documented behavior. - Guards that do exist:
cwdmust resolve inside an allowed directory (same validation as the filesystem server, including symlink checks),timeout_msterminates runaway processes (withkill_on_dropreaping the child even if the request is cancelled), and stdout/stderr capture is bounded to 1 MiB per stream. - Only enable this server for clients you trust completely, and never expose it over a network you do not control.
CLI-level protections
- Exactly one of six servers can be selected, and server-specific options may only be combined with their server (see CLI); misconfigurations fail loudly instead of being silently ignored.
- Startup validation rejects unusable configurations (for example no accessible allowed directory) before serving.
Logging and secrets
- All logs go to stderr (never stdout, which is reserved for JSON-RPC).
- The E2E acceptance suite sanitizes its output: the API key, authorization headers, and raw response bodies are never printed (see OpenRouter E2E).
Skills server: instructions, not execution
Skills are repository content. The server constrains discovery and manifests to the selected workspace and rejects escaping symlink targets, but that is workspace access control rather than an OS sandbox. activate_skill returns instructions and resource paths only: it never automatically executes a skill body, script, command, or resource. Review and trust the workspace before enabling this server.
Agents server: external authority
Agents send prompts to their configured external model provider and can start configured child MCP commands or call child HTTP servers. Definitions and skills are therefore trusted workspace inputs, not a security boundary. Provider credentials come only from the environment variable named by env_key; literal key/token fields are rejected. Do not commit or log those environment values. Agent permission, sandbox, and isolation fields do not create OS-level isolation. Enable agents only for a workspace, client, and child-server configuration you trust.