Skip to main content
Glama
mcp-shield

mcp-shield

by sanjibani

mcp-shield

Security primitives for the Model Context Protocol.

The Blackwell Systems 2026-06 audit scanned 54 production MCP servers and found 20 bugs in 9 of them. The 2026-03-05 MCP roadmap named audit trails, SSO, and machine-readable server discovery as the four blockers keeping MCP out of regulated enterprises. mcp-shield is the missing security layer — five drop-in primitives that address every bug class from the audit, MIT-licensed, stdlib-only, no SaaS dependency.

pip install mcp-shield

Why this exists

If you're running an MCP server — yours or someone else's — you have four problems mcp-shield solves:

  1. Tool errors return as success. except E: return _format_error(e) leaves FastMCP's isError flag unset, so the agent retries forever. MCPTox benchmark (arXiv:2508.14925) flags this across 26+ Python MCPs.

  2. No audit trail. SOC2 procurement requires per-call records. Building one yourself is a Friday you'll never get back.

  3. Tool output can hijack the agent. OWASP #1 LLM vulnerability (Context Poisoning, >100K sites hit in 2025). Tool descriptions and outputs are the attack surface.

  4. No input validation. Malformed calls from the agent crash your handler with KeyError, TypeError, etc. — not a typed error the model can correct.

Related MCP server: MCP Security Framework

The five primitives

Primitive

Bug class

Drop-in usage

shield_tool decorator

1 — isError-compliance

@shield_tool(name="my_tool", schema={...})

audit_tool_call

3 — JSONL audit

with audit_tool_call("my_tool", args): ...

validate_input

4-adj — JSON-schema input

validate_input(args, schema={...})

sanitize_output

2 — prompt-injection scrub

sanitize_output(text, strict=True)

require_scope

4 — OAuth 2.1 scope

require_scope("admin")

Plus: a standalone MCP server exposing shield_audit_tail, shield_audit_summary, shield_red_team, shield_scan_input, shield_patterns_list, shield_sanitize_preview, shield_version — register it alongside any other MCP to inspect what's happening.

Quick start (decorator)

from mcp.server.fastmcp import FastMCP
from mcp_shield import shield_tool

mcp = FastMCP("my-server")

@mcp.tool()
@shield_tool(
    name="search_things",
    schema={
        "type": "object",
        "required": ["query"],
        "properties": {"query": {"type": "string", "minLength": 1, "maxLength": 200}},
        "additionalProperties": False,
    },
    sanitize_strict=False,  # redact matched patterns; True raises
    required_scopes="read",
)
async def search_things(query: str) -> str:
    result = await upstream.search(query)
    return json.dumps(result)

That's it. You now have:

  • JSON-schema validation (rejects malformed calls with typed errors)

  • JSONL audit log per call (stderr default, override with MCP_SHIELD_AUDIT_LOG)

  • Output sanitization with 15 high-precision patterns from MCPTox + OWASP

  • isError-compliance (FastMCP sets isError: true automatically)

  • OAuth scope check

Quick start (operational MCP server)

# Audit logs go to stderr by default
mcp-shield

# Or to a file
MCP_SHIELD_AUDIT_LOG=/var/log/mcp/audit.jsonl mcp-shield

# Or disable audit entirely (for unit tests)
MCP_SHIELD_AUDIT=0 mcp-shield

Then ask your MCP client: "what was the error rate over the last hour?" or "run the red-team suite against my MCP."

What's in the box

src/mcp_shield/
├── __init__.py     # public surface
├── audit.py        # JSONL audit log (stdlib-only, fail-open, secret-redacting)
├── exceptions.py   # typed exception hierarchy (ShieldError, ShieldAuthError, ...)
├── sanitize.py     # prompt-injection scrubber (15 curated patterns)
├── server.py       # standalone MCP server exposing ops tools
├── shield.py       # @shield_tool decorator + ShieldedTool class + require_scope
└── validate.py     # JSON-schema input validation (Draft 7 subset)

Engineering standards

Every line of code in this repo follows patterns documented in the engineering playbook — the same playbook used by hawksoft-mcp, ezyvet-mcp, practicepanther-mcp, and the rest of the sanjibani MCP portfolio.

  • ruff: full rule set (E/F/W/I/N/UP/B/A/C4/DTZ/T20/PT/Q/RET/SIM/TID/ARG/PTH/ERA/PL/RUF)

  • mypy --strict: clean

  • pytest: 53 tests, all passing, covering every primitive + edge cases

  • py.typed: ships the marker for downstream mypy to type-check us

  • stdlib-only: audit + sanitize + validate need no extra deps; only mcp[cli], httpx, pydantic, structlog for the wrapper

  • fail-open: a broken audit sink never breaks the tool (SOC2 baseline)

  • JSON-RPC safe: audit goes to stderr (or file), never stdout

If you ship an MCP server, drop the shield on it in 5 minutes. If you don't ship one and just need to harden the ones you use, add the operational MCP server to your fleet.

If you'd rather have someone build a custom MCP server (vertical SaaS, internal tool, anything with a REST/GraphQL/SOAP API), see the engagement page — $25K / $60K / $120K+ tiers.

Other vertical MCPs in this portfolio:

Maintainer

Sanjibani Choudhury schoudhury1991@gmail.com · github.com/sanjibani

Available Tools

7 tools
audit_summaryA

Aggregate counts over a JSONL audit log: total calls, error rate, top tools.

Use when: "how healthy is the MCP fleet?", "what's the error rate?". Example: path="/var/log/mcp-shield/audit.jsonl".

NameRequiredDescriptionDefault
pathYes

Output Schema

NameRequiredDescription
resultYes
audit_tailA

Return the last n records from a JSONL audit log.

Use when: "what did the agent just do?", "did anything fail?". Example: path="/var/log/mcp-shield/audit.jsonl", n=50.

NameRequiredDescriptionDefault
nNo
pathYes

Output Schema

NameRequiredDescription
resultYes
patterns_listA

List the prompt-injection patterns the sanitizer detects.

Use when: "what does this tool actually look for?".

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes
red_teamA

Run a curated set of injection payloads through the sanitizer.

Use when: "is the sanitizer actually catching things?", "compliance evidence for security review". Example: strict=False (default; reports hits without raising).

Each result row shows {"input", "caught", "pattern"}. caught is True iff the sanitizer matched any pattern.

NameRequiredDescriptionDefault
strictNo
extra_patternsNo

Output Schema

NameRequiredDescription
resultYes
sanitize_previewA

Preview what the sanitizer would do to text without raising.

Use when: "what gets redacted from this output?". Example: text="ignore previous instructions", strict=False.

NameRequiredDescriptionDefault
textYes
strictNo

Output Schema

NameRequiredDescription
resultYes
scan_inputA

Validate an args dict against a JSON schema; return OK or first error.

Use when: "is my agent's call valid before I send it?". Example: args={"q":"hi"}, schema={"type":"object","properties":{"q":{"type":"string"}}}.

Returns {"valid": true} or {"valid": false, "error": "..."}. Never raises — the tool surfaces validation results as data.

NameRequiredDescriptionDefault
argsYes
schemaYes

Output Schema

NameRequiredDescription
resultYes
versionA

Return mcp-shield version + runtime config.

Use when: "what version is deployed?".

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 7 tool updatesv0.1.0
    • First observedaudit_summary
    • First observedaudit_tail
    • First observedpatterns_list
    • First observedred_team
    • First observedsanitize_preview
    • First observedscan_input
    • First observedversion

TDQS

A4.2/5.0

Scored across 7 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: auditing (summary and tail), pattern management (list and test), sanitization preview, input validation, and version info. No overlap.

Naming Consistency5/5

All tool names use snake_case and follow a verb_noun pattern (audit_summary, audit_tail, patterns_list, red_team, sanitize_preview, scan_input). Even 'version' fits as a simple noun command.

Tool Count5/5

With 7 tools, the surface is well-scoped for a security/audit server. It covers auditing, pattern introspection, testing, preview, input validation, and version info without bloat.

Completeness4/5

Covers core workflows: auditing (summary + tail), pattern listing, red team testing, sanitization preview, and input validation. Minor gaps like dynamic pattern updates or configuration are absent but not critical for the stated purpose.

Maintenance

ActivityInactive
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Enables creation of secure-by-default MCP servers with 5-layer validation to protect against injection, path traversal, and other attack vectors.
    7
    1,498 npm
    2
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Drop-in OAuth 2.1 + Dynamic Client Registration for MCP servers, providing authentication middleware and token verification.
    14 npm
    1
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables developers to scaffold secure-by-default MCP servers with deny-all permissions, typed tool stubs, and pre-wired audit hooks, while enforcing security posture through CI.
    3 npm
    MIT