Skip to main content

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_server_shield-0.1.0.tar.gz (31.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_server_shield-0.1.0-py3-none-any.whl (29.1 kB view details)

Uploaded Python 3

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

Hashes for mcp_server_shield-0.1.0.tar.gz
Algorithm Hash digest
SHA256 8e7c738e572c36abf1b73360972bd96bda2becd117b17a9c42c690661427651e
MD5 2197becec267e8ec71cf091ce91f2a4a
BLAKE2b-256 7102f783008b227f47afcea39216b95534423d8d5c14a4cc17d32a7b72557c30

See more details on using hashes here.

Provenance

The following attestation bundles were made for mcp_server_shield-0.1.0.tar.gz:

Publisher: release.yml on Trihedron1240/mcp-server-shield

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mcp_server_shield-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for mcp_server_shield-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 90f2705cf52282eb6dc4fb8a8ab204d4c0cbc079e3a3a5927dfc27a626e7a902
MD5 87a597ce15e85eb0d816ab976eb85b40
BLAKE2b-256 b039a6fa86d7c1736caa3e2d096b085e90621acc04f5fc897568f9ac7d43c63f

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page