Author-side hardening primitives for Python MCP servers.
Project description
mcp-server-shield
mcp-server-shield is a Python-first hardening library for MCP server authors. It is not
a scanner, gateway, proxy, or hosted security service. It protects the MCP tool function
boundary directly: validate arguments before execution, use safe wrappers for dangerous
operations, filter outputs before they reach the MCP client, lint tool descriptions, lock
tool manifests, and emit structured audit logs.
The project is built for the way FastMCP and the official Python MCP SDK expose tools: ordinary Python functions decorated as tools.
Install
pip install mcp-server-shield
For local development:
pip install -e ".[dev]"
Quickstart
from mcp_server_shield import ShieldPolicy, shield
from mcp_server_shield.output_filters import PromptInjectionFilter, SecretRedactor
from mcp_server_shield.validators import PathGuard, StringGuard, URLGuard
policy = ShieldPolicy.strict(
paths={"file_path": PathGuard(root="./workspace", read=True, write=False)},
urls={"url": URLGuard(allowed_schemes=["https"], allowed_hosts=["api.github.com"])},
strings={
"query": StringGuard(
max_len=5000,
deny_substrings=["ignore previous instructions"],
)
},
output_filters=[SecretRedactor(), PromptInjectionFilter()],
)
@shield(policy)
def read_file(file_path: str) -> str:
with open(file_path, encoding="utf-8") as handle:
return handle.read()
FastMCP Example
Use @shield(policy) closest to the function so FastMCP sees the preserved signature and
metadata after the wrapper is applied:
from fastmcp import FastMCP
from mcp_server_shield import ShieldPolicy, shield
from mcp_server_shield.validators import PathGuard
mcp = FastMCP("secure-files")
policy = ShieldPolicy.strict(
paths={"file_path": PathGuard(root="./workspace", read=True, write=False)},
)
@mcp.tool()
@shield(policy)
def read_file(file_path: str) -> str:
with open(file_path, encoding="utf-8") as handle:
return handle.read()
Policy File Example
policy_id: secure-fetch-v1
fail_closed: true
audit_log: logs/mcp-shield-audit.jsonl
paths:
file_path:
root: ./workspace
read: true
write: false
allowed_extensions: [".txt", ".md"]
urls:
url:
allowed_schemes: ["https"]
allowed_hosts: ["api.github.com"]
allow_localhost: false
allow_private_ips: false
strings:
query:
max_len: 5000
deny_substrings: ["ignore previous instructions"]
output_filters:
- type: secret_redactor
redact_pii: true
- type: prompt_injection
action: redact
waivers:
- id: WAIVER-001
reason: Temporary partner endpoint migration.
expires_on: 2026-06-30
applies_to: ["URLGuard:url"]
evidence:
ticket: SEC-1234
Load it with:
policy = ShieldPolicy.from_file("mcp-shield-policy.yaml")
CLI
Lint tool descriptions:
mcp-shield lint-descriptions tools.json --json
Generate and verify a descriptor lockfile:
mcp-shield manifest generate tools.json --output mcp-shield.lock.json
mcp-shield manifest verify tools.json --lockfile mcp-shield.lock.json
Validate a policy file:
mcp-shield policy check mcp-shield-policy.yaml
Check the local installation:
mcp-shield doctor
Threat Model
mcp-server-shield assumes MCP tool arguments, external URLs, filesystem paths, command
arguments, tool descriptions, and tool outputs may be attacker influenced. It focuses on
deterministic local controls for:
- Secret exposure and context over-sharing through output redaction.
- Command and argument injection through
safe_run. - Path traversal and symlink escape through
PathGuard. - SSRF, localhost access, and DNS rebinding risk through
URLGuard. - Tool poisoning through description linting and manifest locking.
- Audit gaps through JSONL audit events for allowed, denied, redacted, and errored calls.
What This Library Does Not Solve
This library does not replace authentication, authorization, sandboxing, container policy, dependency scanning, supply-chain review, network egress policy, or a full MCP gateway. It does not claim to detect every prompt-injection phrase or every possible secret format. It does not make unsafe business logic safe by itself. It gives MCP server authors reusable secure-by-default primitives at the point where tool code handles untrusted data.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_server_shield-0.1.0.tar.gz.
File metadata
- Download URL: mcp_server_shield-0.1.0.tar.gz
- Upload date:
- Size: 31.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8e7c738e572c36abf1b73360972bd96bda2becd117b17a9c42c690661427651e
|
|
| MD5 |
2197becec267e8ec71cf091ce91f2a4a
|
|
| BLAKE2b-256 |
7102f783008b227f47afcea39216b95534423d8d5c14a4cc17d32a7b72557c30
|
Provenance
The following attestation bundles were made for mcp_server_shield-0.1.0.tar.gz:
Publisher:
release.yml on Trihedron1240/mcp-server-shield
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_server_shield-0.1.0.tar.gz -
Subject digest:
8e7c738e572c36abf1b73360972bd96bda2becd117b17a9c42c690661427651e - Sigstore transparency entry: 1382434442
- Sigstore integration time:
-
Permalink:
Trihedron1240/mcp-server-shield@15b7917f249bdd25928c916a43a60d8310d0869c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Trihedron1240
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@15b7917f249bdd25928c916a43a60d8310d0869c -
Trigger Event:
release
-
Statement type:
File details
Details for the file mcp_server_shield-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mcp_server_shield-0.1.0-py3-none-any.whl
- Upload date:
- Size: 29.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
90f2705cf52282eb6dc4fb8a8ab204d4c0cbc079e3a3a5927dfc27a626e7a902
|
|
| MD5 |
87a597ce15e85eb0d816ab976eb85b40
|
|
| BLAKE2b-256 |
b039a6fa86d7c1736caa3e2d096b085e90621acc04f5fc897568f9ac7d43c63f
|
Provenance
The following attestation bundles were made for mcp_server_shield-0.1.0-py3-none-any.whl:
Publisher:
release.yml on Trihedron1240/mcp-server-shield
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_server_shield-0.1.0-py3-none-any.whl -
Subject digest:
90f2705cf52282eb6dc4fb8a8ab204d4c0cbc079e3a3a5927dfc27a626e7a902 - Sigstore transparency entry: 1382434470
- Sigstore integration time:
-
Permalink:
Trihedron1240/mcp-server-shield@15b7917f249bdd25928c916a43a60d8310d0869c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Trihedron1240
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@15b7917f249bdd25928c916a43a60d8310d0869c -
Trigger Event:
release
-
Statement type: