A local policy-enforcement runtime for MCP tool calls.
MCP Shield evaluates tool names and arguments against configurable security policies. It returns an ALLOW or BLOCK decision and records the result in an audit log.
Important
MCP Shield is an early-stage project. The current release does not automatically discover MCP servers or transparently intercept tool calls from Codex, Claude Code, Cursor, Proxyman, or other MCP clients and servers.
MCP Shield provides a command-line interface and local REST API for evaluating MCP tool calls against YAML security policies.
It can:
- Allow or block tools using configurable allowlists
- Recursively inspect tool arguments for dangerous patterns
- Detect common SSRF targets, sensitive paths, and unsafe URL schemes
- Record allowed and blocked decisions in an audit log
- Display audit statistics
- Calculate basic risk scores from tool capabilities
Tool calls must currently be submitted through the mcpshield CLI or the /inspect API. The application making the actual MCP call is responsible for enforcing the returned decision.
The Model Context Protocol (MCP) allows AI applications to connect to external tools and data sources through MCP servers.
Depending on the server, those tools may be able to:
- Read or write files
- Call internal or external APIs
- Query databases
- Access environment variables
- Control browsers
- Execute commands
These capabilities are useful, but a malicious, compromised, or overly permissive server can expose credentials, sensitive files, internal services, or the host system.
MCP Shield provides a policy-decision layer that callers can use before allowing a tool call to continue.
- A caller submits the server name, policy, tool name, and arguments.
- MCP Shield checks whether the tool is permitted by the selected policy.
- It recursively scans the arguments for blocked hosts, paths, schemes, and patterns.
- It returns an
ALLOWorBLOCKdecision with a reason. - It records the decision in the audit log.
Tool call
│
▼
MCP Shield policy evaluation
│
├── BLOCK → record decision and reject the call
│
└── ALLOW → record decision and permit the caller to continue
MCP Shield currently evaluates requests; it is not yet a transparent MCP proxy.
- YAML-based policies
- Per-policy tool allowlists
- Recursive argument inspection
- SSRF and sensitive-path pattern detection
- CLI inspection commands
- REST API
- SQLite audit logging
- Audit statistics
- Basic server risk scoring
- Docker sandbox management endpoints
- Experimental Firecracker backend for Linux/KVM environments
- Python 3.12 or newer
- macOS, Linux, or Windows for the core API and CLI
- Docker only when using the Docker sandbox backend
- Linux with KVM only when using the experimental Firecracker backend
Create and activate a virtual environment:
python3.12 -m venv ~/mcpshield-env
source ~/mcpshield-env/bin/activateInstall MCP Shield:
python -m pip install --upgrade pip
python -m pip install mcpshield-runtimeVerify the installation:
python --version
mcpshield --helpSome macOS installations still provide Python 3.9 through Xcode. Check your version:
python3 --versionIf it is older than Python 3.12, install Python 3.12 with Homebrew:
brew install python@3.12Create the environment using Homebrew’s interpreter:
$(brew --prefix python@3.12)/bin/python3.12 -m venv ~/mcpshield-env
source ~/mcpshield-env/bin/activate
python -m pip install --upgrade pip
python -m pip install mcpshield-runtimeTo reactivate the environment later:
source ~/mcpshield-env/bin/activateTo leave it:
deactivateMCP Shield currently uses two terminal windows:
- Terminal 1 runs the local API.
- Terminal 2 runs the CLI commands.
Release 0.1.2 must be started from the cloned repository so the runtime can locate the policies/ directory:
cd ~
git clone https://github.com/srisowmya2000/mcp-shield.git
cd ~/mcp-shieldIf the repository already exists:
cd ~/mcp-shield
git pull origin maincd ~/mcp-shield
source ~/mcpshield-env/bin/activate
export NO_PROXY=localhost,127.0.0.1
export no_proxy=localhost,127.0.0.1
uvicorn runtime.api.main:app \
--host 127.0.0.1 \
--port 8000Keep this terminal open. The API will be available at:
http://127.0.0.1:8000
Useful pages:
- Health:
http://127.0.0.1:8000/health - API documentation:
http://127.0.0.1:8000/docs - Dashboard:
http://127.0.0.1:8000/dashboard
source ~/mcpshield-env/bin/activate
export NO_PROXY=localhost,127.0.0.1
export no_proxy=localhost,127.0.0.1Check API health:
curl --noproxy "*" http://127.0.0.1:8000/healthExpected response:
{"status":"ok","service":"mcp-shield","version":"0.1.0"}Inspect a tool that should be blocked:
mcpshield inspect read_secretsInspect an allowed tool:
mcpshield inspect safe_toolView audit statistics and recent decisions:
mcpshield stats
mcpshield auditExpected results:
read_secrets → BLOCKED
safe_tool → ALLOWED
mcpshield inspect TOOL_NAMEExample:
mcpshield inspect read_secretsProvide tool arguments as JSON:
mcpshield inspect ssrf_fetch \
--args '{"url":"http://169.254.169.254/latest/meta-data/"}'Select a policy and server label:
mcpshield inspect safe_tool \
--policy default \
--server demo-server \
--args '{"name":"Sri"}'mcpshield risk "read_secrets,ssrf_fetch,safe_tool"mcpshield auditmcpshield statscurl --noproxy "*" http://127.0.0.1:8000/healthcurl --noproxy "*" \
-X POST http://127.0.0.1:8000/inspect \
-H "Content-Type: application/json" \
-d '{
"server_name": "demo",
"policy": "default",
"tool_call": {
"tool_name": "read_secrets",
"arguments": {}
}
}'Example blocked response:
{
"server": "demo",
"tool": "read_secrets",
"policy": "default",
"decision": "BLOCK",
"reason": "Tool 'read_secrets' is not in the allowed_tools list",
"blocked": true
}curl --noproxy "*" http://127.0.0.1:8000/audit
curl --noproxy "*" http://127.0.0.1:8000/audit/statscurl --noproxy "*" \
-X POST http://127.0.0.1:8000/risk/score \
-H "Content-Type: application/json" \
-d '{"tool_names":["read_secrets","ssrf_fetch","safe_tool"]}'Policies are stored as YAML files inside policies/.
Example:
allowed_tools:
- safe_tool
- list_files
- get_time
block_network: true
block_env_access: true
blocked_arg_patterns:
- "169.254.169.254"
- "169.254.170.2"
- "localhost"
- "127.0.0.1"
- "/etc/passwd"
- "/etc/shadow"
- "file://"
- "gopher://"
max_memory_mb: 256
execution_timeout_seconds: 30The repository includes:
default.yaml— general allowlist and argument checksstrict.yaml— more restrictive policy
Select a policy with:
mcpshield inspect safe_tool --policy strictPolicy matching is a security control, not a complete guarantee of safety. Use operating-system isolation, least privilege, network restrictions, and careful review of MCP servers.
Example:
ERROR: Could not find a version that satisfies the requirement mcpshield-runtime
ERROR: No matching distribution found for mcpshield-runtime
Check your Python version:
python3 --versionMCP Shield requires Python 3.12 or newer.
On macOS:
brew install python@3.12
$(brew --prefix python@3.12)/bin/python3.12 \
-m venv ~/mcpshield-env
source ~/mcpshield-env/bin/activate
python -m pip install mcpshield-runtimeUse pip through the active Python interpreter:
python -m pip install mcpshield-runtimeDo not run:
pip3 install --upgrade pip3The package is named pip, not pip3. The correct command is:
python -m pip install --upgrade pipThe CLI requires the local API server.
Start it in another terminal:
cd ~/mcp-shield
source ~/mcpshield-env/bin/activate
uvicorn runtime.api.main:app \
--host 127.0.0.1 \
--port 8000Then verify:
curl --noproxy "*" http://127.0.0.1:8000/healthA system proxy or an application such as Proxyman may be intercepting localhost traffic.
Set localhost bypass variables in both terminals:
export NO_PROXY=localhost,127.0.0.1
export no_proxy=localhost,127.0.0.1Also add localhost and 127.0.0.1 to the proxy application’s bypass or ignore list.
In release 0.1.2, policies are resolved relative to the current working directory.
Start Uvicorn from the cloned repository:
cd ~/mcp-shield
uvicorn runtime.api.main:app \
--host 127.0.0.1 \
--port 8000Confirm that the policy files exist:
ls -la ~/mcp-shield/policiesThis packaging limitation is expected to be corrected in a later release.
This usually means the /inspect endpoint returned an error response instead of a policy decision.
Check the API terminal for a 404 or 500 response.
Confirm that:
- The API is running
- Uvicorn was started from
~/mcp-shield policies/default.yamlexists- Port
8000is available - Localhost proxy bypass variables are configured
This command is incomplete:
mcpshield inspectProvide a tool name:
mcpshield inspect read_secretsIf cloning returns:
fatal: destination path 'mcp-shield' already exists and is not an empty directory
Use the existing repository:
cd ~/mcp-shield
git pull origin mainThe current release does not:
- Automatically discover MCP client configurations
- Automatically discover or scan configured MCP servers
- Transparently intercept MCP protocol traffic
- Automatically integrate with Codex, Claude Code, Cursor, or Proxyman MCP
- Automatically enforce decisions for an external MCP client
- Replace operating-system sandboxing or least-privilege controls
An external caller or future proxy integration must submit the tool call to MCP Shield and honor the returned decision.
MCP Shield is intended as a defense-in-depth policy layer. It should not be treated as a complete sandbox or a replacement for:
- Reviewing third-party MCP server code
- Restricting filesystem permissions
- Limiting environment variables and secrets
- Applying outbound network controls
- Running untrusted code in isolated environments
- Monitoring the host and MCP server processes
See docs/threat-model.md for additional details.
Clone the repository and install it in editable mode:
git clone https://github.com/srisowmya2000/mcp-shield.git
cd mcp-shield
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e .Run the tests:
python -m pip install pytest
pytest tests/ -vStart the development API:
uvicorn runtime.api.main:app --reload- Package built-in policies correctly for installation from any directory
- Add clearer CLI handling for API error responses
- Add
mcpshield serveandmcpshield doctorcommands - Add structured policy validation
- Add per-tool argument-schema validation
- Add prompt-injection detection
- Add webhook alerts for blocked calls
- Explore an optional MCP proxy and enforcement integration
Automatic MCP client/server discovery belongs to a separate scanner project and is not part of the current MCP Shield runtime.
Use MCP Shield only with systems, MCP servers, accounts, and environments you own or are authorized to test.
Review policy decisions and server behavior before relying on the project in a sensitive environment.
MCP Shield is released under the MIT License.
Sri Sowmya Nemani — security researcher and engineer working in MCP security, application security, detection engineering, and responsible vulnerability disclosure.
Contributions, bug reports, and documentation improvements are welcome.