Skip to main content
Glama

SCP — Secure Contain Protect

Inspect, sanitize, contain, and quarantine unknown or potentially hazardous content before persisting or feeding to LLM. MCP server for agent-native content safety.

Guard in the Guard–Guide–Build taxonomy. Per OWASP LLM01/LLM06.

Scope: SCP is the Content axis (payload safety into LLM sinks) — not moral Patienthood and not adversarial Threat classification. Full stance: OpenHarness — Patient ≠ Threat ≠ Content.

CI

Problem → Solution → Impact

  • Problem: Untrusted tool output and user content can carry prompt injection, credential leaks, and override phrases into LLM context.

  • Solution: Tiered pipeline (inspect → sanitize → contain → quarantine) exposed as MCP tools; optional promptfoo eval harness (4/4 tier probes).

  • Impact: OWASP LLM01/LLM06-aligned guardrail for agent stacks; composes with OpenHarness contract v1.

Related MCP server: chuangsiai-mcp

Tech stack

Python 3.10+, MCP, optional Ollama semantic judge (off by default in CI), promptfoo for offline evals.

Architecture

flowchart LR
  IN[Untrusted content] --> INSPECT[scp_inspect]
  INSPECT -->|injection| Q[scp_quarantine]
  INSPECT -->|reversal| SAN[scp_sanitize]
  SAN --> CON[scp_contain]
  INSPECT -->|clean| OUT[Safe sink]
  CON --> OUT
  Q --> BLOCK[Block LLM sink]

Pipeline

  1. Inspect — Classify content: injection | reversal | clean

  2. Sanitize — Strip hidden Unicode, redact override phrases (when tier is reversal)

  3. Contain — Wrap content so it is treated as data: Markdown uses a fence at least as long as the longest run of backticks in the payload (info string scp); XML uses a single <data> element with body in CDATA (with ]]> safely split). Unknown wrapper values raise ValueError.

  4. Quarantine — Move suspect content to isolated storage (when tier is injection)

Tier-Based Actions

Tier

Action

injection

Block; do not persist or feed to LLM; optionally quarantine

reversal

Sanitize, then contain

clean

Pass through

MCP Tools

  • scp_inspect(content, context?) — Classify without changing content

  • scp_sanitize(content, mode?) — Strip/neutralize known bad patterns

  • scp_contain(content, wrapper?) — Wrap content as data

  • scp_quarantine(content, reason, source) — Isolate suspect content

  • scp_list_quarantine() — List quarantine entries

  • scp_purge_quarantine(quarantine_id?, older_than_days?) — Purge quarantine

  • scp_validate_output(content, tool_name?) — Check tool output before use

  • scp_mask_secrets(content) — Redact credentials/PII

  • scp_run_pipeline(content, sink, options?) — One-shot for high-risk sinks

  • scp_registry_summary() — Read-only: threat registry path, fingerprint, section sizes

  • scp_registry_section(section, max_chars?) — Read-only excerpt of one allowlisted registry section

OpenHarness contract v1 requires the first nine tools above; registry tools are a documented superset.

Install

pip install -e .
# or: pip install mcp

Run MCP Server

python -m scp.scp_mcp

Add to mcp.json:

{
  "mcpServers": {
    "scp": {
      "command": "python",
      "args": ["-m", "scp.scp_mcp"]
    }
  }
}

Set PYTHONPATH or install the package so scp is importable.

Antigen MCP (registry fetch / contribute)

Second entrypoint for mycelium registry fetch, merge, and contribute flows:

python -m scp.antigen_mcp

Consent and host-allowlist env vars, tool list, and mcp.json example: docs/INTEGRATION.md.

Environment

Variable

Description

SCP_QUARANTINE_DIR

Quarantine storage path (default: ./scp_quarantine)

SCP_QUARANTINE_MAX_CONTENT_BYTES

Max UTF-8 bytes per quarantined payload (default 1048576 = 1 MiB; hard cap 50 MiB)

SCP_QUARANTINE_MAX_TOTAL_BYTES

Max total on-disk bytes for all quarantine pairs under SCP_QUARANTINE_DIR (default 104857600 = 100 MiB)

SCP_QUARANTINE_RETENTION_DAYS_ON_WRITE

If set (positive int), delete quarantine entries whose .json is older than this many days before each new write

SCP_QUARANTINE_EVICT_OLDEST_ON_PRESSURE

When 1 (default), delete oldest-by-mtime entries if a new write would exceed the total cap; set 0 to fail with an error instead

OLLAMA_BASE_URL

For semantic judge: origin only (default http://localhost:11434). Allowed hosts: localhost, 127.0.0.1, ::1, plus comma-separated OLLAMA_ALLOWED_HOSTS. No path, query, or userinfo. HTTP redirects to another host are not followed.

OLLAMA_ALLOWED_HOSTS

Optional extra hostnames/IPs (comma-separated, case-insensitive) allowed for OLLAMA_BASE_URL

OLLAMA_URL_STRICT

Set to 1 to reject names that resolve to private or link-local addresses (mitigates some SSRF/DNS cases)

OLLAMA_MODEL

For semantic judge (default: llama3.2)

OLLAMA_API_KEY

Optional bearer token for Ollama (sent as Authorization: Bearer …; never put secrets in the URL)

SCP_SEMANTIC_JUDGE

Set to 1 to enable semantic judge globally

SCP_MAX_INPUT_CHARS

Maximum string length for inspect, classify, sanitize, contain, and mask_secrets (default 2000000; hard ceiling 50000000)

SCP_THREAT_REGISTRY_PATH

Optional override path to the threat-registry JSON (default: packaged src/scp/scp_threat_registry.json)

Trust: Point Ollama only at hosts you control. On shared runners or CI, keep the semantic judge off unless required; use firewall rules so the process cannot reach sensitive internal subnets unless intended.

Threat Registry

Packaged patterns in src/scp/scp_threat_registry.json (override with SCP_THREAT_REGISTRY_PATH): power_words, multilingual_override, semantic_aliases, jailbreak_nicknames, mythic_framing, hostile_ux, bitcoin_inscription_override, bitcoin_tx_mempool_override. Version bump on change.

Test harness matrix

Where

Suite

What it validates

This repo (CI job contract)

pytest tests/test_mcp_contract_v1.py

MCP tool names vs OpenHarness v1 set

This repo (local / optional)

pytest tests/test_contract_document_hash.py

Vendored docs/contracts/scp_mcp_v1.md SHA-256 (sync with OpenHarness); not run in CI today

This repo (CI job promptfoo-eval)

examples/promptfoo / npx promptfoo eval

scp_utils.inspect tier labels (offline, no API keys; 4/4 probes)

portfolio-harness

Workflow scp_pipeline_regression + daggr_workflows/tests/test_scp_pipeline_golden.py

run_pipeline / Daggr alignment (install this repo with pip install -e in that workspace)

CI and quarantine

  • GitHub Actions: contract (Python matrix + pytest) and promptfoo-eval (Node 22, examples/promptfoo).

  • Quarantine: Default directory scp_quarantine/ (or SCP_QUARANTINE_DIR) must not be committed—listed in .gitignore. Writes enforce per-entry and total byte limits (see environment table); optional age-based purge and oldest-first eviction reduce disk exhaustion from repeated or oversized blocked payloads. Lifecycle (write → retain → purge) and non-claims vs Patient “retirement”: docs/QUARANTINE_LIFECYCLE.md.

Documentation

FAQ: PDFs and binary files

SCP tools take text (content: str). PDFs and other binaries are not scanned directly. For documents:

  1. Extract text (e.g. pypdf, pdftotext, pymupdf).

  2. Run scp_inspect / scp_run_pipeline on the extracted text before LLM or handoff sinks.

  3. Use OS antivirus or equivalent on the original files separately (malware is out of scope for SCP).

See also: local-proto docs HUMAN_WELLBEING_CORPUS.md for a full private-PDF pipeline (provenance, chunks, optional RAG).

Guardrail

SCP has no shutdown, suicide, or self-termination commands. SCP inspects, sanitizes, contains, and quarantines content—it does not self-destruct.

Roadmap

  • GitHub topics: mcp, llm-security, prompt-injection

  • Shared threat registry — scp-mycelium-registry @ v0.2.0 (R2 spec)

  • MCP Registry listing when governance doc is ready

Red-team eval (SCP-R2)

pip install -e .
cd examples/promptfoo && npm ci && cd ../..
npx promptfoo eval -c promptfoo-scp.yaml

Or from examples/promptfoo: npx promptfoo eval -c promptfooconfig.yaml

See examples/promptfoo/README.md and docs/LEARNINGS_PROMPTFOO.md.

License

MIT — see LICENSE.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides real-time content safety protection for large language models by detecting and preventing risks in both input and output content across multiple dimensions including compliance, ethics, and security.
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides real-time content security for large language models by identifying and intercepting risks across compliance, ethics, and safety dimensions. It enables secure input and output monitoring through a customizable policy engine using an SSE-based interface.
    1
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Protects AI agents from threats like prompt injection, jailbreaks, and SQL injection through a multi-layer scanning pipeline. It also enables PII redaction and rehydration to ensure data privacy during LLM interactions.
    12
    62 npm
    2
    Apache 2.0
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides a pre-flight/post-flight firewall for LLM calls with comprehensive detection, classification, policy enforcement, reversible redaction, output safety, and immutable audit logging.
    1
    MIT