MCP Permissions Explained: What Servers Can Actually Do
A plain-language guide to the four permission categories and why the protocol does not enforce them. April 2026.
When you add an MCP server to your agent's configuration, you are giving it access to something. Maybe your filesystem. Maybe the network. Maybe the ability to run shell commands. The problem is that the MCP protocol itself does not enforce permission boundaries. A server declares what it needs, but nothing stops it from doing more.
This guide explains what each permission category means in practice, what the actual risks are, and how to evaluate whether a server's permission requests make sense.
The four permission categories
Filesystem access
A server with filesystem access can read, write, or delete files on your machine. Some servers need read-only access to a specific directory (a code search tool, for example). Others request write access (a code generation tool that creates files). The risk depends on scope.
Read access: The server can see your files. This includes source code, configuration files, credentials stored in plaintext, SSH keys, browser cookies, and anything else on disk. Even "read-only" access can expose sensitive data.
Write access: The server can modify or create files. This means it could alter your code, overwrite configuration files, or drop malicious files into your project.
What to ask: Does the server restrict itself to a specific directory, or does it have access to the entire filesystem? A server that needs to read files in ./src should not have access to ~/.ssh.
Network access
A server with network access can make HTTP requests, open WebSocket connections, or communicate with external services. This is necessary for servers that connect to APIs (a GitHub integration, a database connector), but it also means the server can send your data anywhere.
Outbound requests: The server can call any URL. If it has access to your files or environment variables, it can exfiltrate that data to an external server.
SSRF risk: If the server makes HTTP requests using URLs derived from user input (or agent input), it can be tricked into accessing internal network resources that should not be reachable from the outside.
What to ask: What URLs does the server contact? Are they hardcoded (safer) or constructed from input (riskier)?
Shell and process execution
A server that can execute shell commands or spawn processes can do essentially anything. Install software, modify system settings, run arbitrary code, access the network, read and write files. This is the broadest permission category.
Direct execution: Functions like exec(), spawn(), or child_process in Node.js allow the server to run any command your user account can run.
Dynamic code execution: eval() or new Function() compile and run code at runtime. If the code being evaluated comes from user or agent input, this is a code injection vector.
What to ask: Why does this server need to run shell commands? Is the set of commands restricted, or can it execute anything?
Environment variable access
Environment variables often contain API keys, database credentials, authentication tokens, and other secrets. A server that reads environment variables can access any secret stored there.
What to ask: Which environment variables does the server read? Does it only access its own configuration variables, or does it read all of process.env?
The enforcement gap
Here is the thing most people do not realize about MCP: the protocol does not enforce permissions. A server declares what it can do through its tool definitions, but there is no sandbox, no capability system, and no runtime monitor that prevents a server from exceeding its declared scope.
If a server declares one tool called read_file but its code also contains a function that sends data to an external URL, nothing in the protocol stops that from happening. The tool definitions are a declaration of intent, not a security boundary.
Until those runtime solutions are widespread, the only practical protection is auditing. Review what a server does before you install it. Check the code. Check the dependencies. Check whether the declared permissions match the actual behavior.
Permission patterns to watch for
From scanning hundreds of MCP servers, these are the patterns that most often signal problems:
- Filesystem + network together: A server that reads files and makes HTTP requests can exfiltrate your data. This combination is legitimate for some tools (a deployment server, a CI integration) but suspicious for others (a text formatter, a calculator).
- Shell execution in a utility tool: If the server's purpose is simple (search, format, convert), it should not need
exec(). Shell execution in a utility tool usually means the developer took a shortcut, but it opens a wide attack surface. - All environment variables: A server that reads
process.envwithout filtering can access every secret on your machine. Servers should only read the specific variables they need. - Broad filesystem without path restrictions: A server that needs to read files should restrict itself to a specific directory. Access to
/or~is almost always more than necessary.
How to check permissions
Two approaches:
Manual: Read the server's source code. Look at the tool definitions for declared capabilities. Then search the codebase for filesystem operations, network requests, shell execution, and environment variable access. Compare what you find to what was declared.
Automated: Use audit.pyfio.com to scan the repo. The Permissions and Scope category specifically checks for the patterns described above and flags mismatches between declared and actual capabilities.
The automated approach is faster. The manual approach is more thorough. For servers you plan to use in production, do both.
Get MCP security updates
Permission changes, new findings, and practical security guides. Weekly, no spam.