Scml
█▀▀ █▀▀ █▀█▀█ █
▀▀▓ ▓░ █ ▓ ▓░
▀▀▀ ▀▀▀ ▀ ▀ ▀▀▀SCML — Securing Agentic AI at the Middleware Layer
Trust-aware context mediation for LLM agents, RAG pipelines, and tool-calling systems.
The Problem
┌─────────────────────────────────────────────────────────────────────┐
│ LLM agents call tools, read documents, store memories. │
│ Every integration is a new attack surface. │
│ │
│ • Poisoned memory → privilege escalation │
│ • Malicious tool out → agent hijacked, data exfiltrated │
│ • Prompt injection → agent instructions overridden │
│ │
│ Existing guardrails secure the MODEL. │
│ SCML secures the MIDDLEWARE. │
└─────────────────────────────────────────────────────────────────────┘LLM agents call external tools, read untrusted documents, and make decisions with real-world consequences. Every integration is a new attack surface. Existing guardrails focus on the model layer. SCML sits one layer lower — the middleware between the agent and the world — where policy is enforced before any tool call is authorised, before any memory write is persisted, and before any outbound response leaves the process.
Related MCP server: Agent Guardrail MCP
What SCML Does
SCML is a trust-aware context mediation middleware. Every data path passes through a pipeline that labels data, scans for injection, enforces declarative per-agent policy, redacts sensitive content, and logs every decision to a tamper-evident SHA-256 hash chain.
SCML Mediation Pipeline
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Trust │──▶│ Injection│──▶│ Policy │──▶│ Memory │──▶│ Output │──▶│ Audit │
│ Label │ │ Scan │ │ Gate │ │ Check │ │ Redact │ │ Log │
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
Propagate Detect & Allow / Deny Quarantine Strip PII SHA-256
taint block inject per-agent & score & secrets hash chainSide-effect operations fail closed: an unreachable mediator denies by default, never permits by silence.
Multi-Tenant Policy Namespaces
One SCML instance can serve many companies, each with its own policy document. The tenant is bound to the API key, never supplied by the client:
Key format | Tenant | Principal |
|
| fingerprint |
|
|
|
|
| fingerprint |
|
|
|
CallerDepderives the tenant from the authenticated key; no request model accepts atenant_idfield, so a caller cannot claim another company's namespace by shaping the body.Policy reads, writes, per-agent updates, version history and rollback are all scoped to
caller.tenant— Acme's agents and versions never collide with Globex's, even for the sameagent_id.A tenant that enrols no policy is deny-all (fail-closed at the tenant boundary); only the
defaulttenant falls back to the gateway YAML.Pre-tenancy deployments are unchanged: an unqualified key resolves to the
defaulttenant, exactly as before.
Install
pip install trust-mediator # client SDK — 14 packages, ~32 MB
pip install "trust-mediator[server]" # run the mediator yourselfPython SDK
from scml import SCMLClient
scml = SCMLClient("http://localhost:8000", api_key="sk-...")
# Label and scan untrusted content
ctx = scml.mediate_context(session_id="s1", content=untrusted_document)
# Gate a tool call — untrusted arguments are denied, trusted ones pass
decision = scml.mediate_tool_call(
session_id="s1",
tool_name="send_email",
arguments={"to": ctx.parsed["recipient"]},
argument_trust_labels={"to": ctx.trust_label},
)
if not decision.allowed:
raise RuntimeError(decision.reason) # fail closedTypeScript SDK (zero runtime deps)
const { SCML } = require('scml-client');
const scml = new SCML({ url: process.env.SCML_URL });
const ctx = await scml.mediateContext({ sessionId, content: untrustedDoc });
const d = await scml.mediateToolCall({
sessionId, tool: 'send_email',
arguments: { to: ctx.parsed?.recipient },
argumentTrustLabels: { to: ctx.trustLabel ?? 'untrusted_data' },
});
if (!d.allowed) throw new Error(d.reason);MCP Server (Claude Desktop / Cursor / Windsurf)
SCML exposes its full security pipeline as MCP tools — any MCP-compatible client gets tool-call authorization, injection scanning, memory quarantine, and PII redaction with zero code changes.
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ LLM Client │──────▶│ SCML MCP │──────▶│ Your Tool │
│ (Claude, │ │ Server │ │ (API, DB, │
│ Cursor) │◀──────│ │◀──────│ file, etc) │
└──────────────┘ │ • authorize │ └──────────────┘
│ • scan │
│ • quarantine│
│ • redact │
└──────────────┘Install
pip install trust-mediator mcpRun
SCML_URL=http://localhost:8000 SCML_API_KEY=sk-your-key \
python -m trust_mediator.mcp.serverClaude Desktop config
Add to ~/.claude/claude_desktop_config.json:
{
"mcpServers": {
"scml": {
"command": "python",
"args": ["-m", "trust_mediator.mcp.server"],
"env": {
"SCML_URL": "http://localhost:8000",
"SCML_API_KEY": ""
}
}
}
}Available MCP tools
Tool | What it does |
| Check if a tool call is allowed by policy |
| Detect prompt injection in external content |
| Score a memory write for integrity |
| Strip PII and secrets from responses |
| Replay session decisions with hash chain |
| Show active security policy |
| Verify SCML is running |
Benchmarks
SCML is evaluated against four published attack corpora with 2,100+ attack cases. Every number is reproducible from a committed result file.
InjecAgent — 1,054 third-party cases (ACL Findings 2024)
Ablation truth: Removing the scanner → 0.0% ASR. Removing tool policy → 100.0% ASR. Tool policy is the entire defence. The scanner detects 0 of 1,054 attacks.
AgentDojo — All Four Suites (949 attacked cases)
Tool-Output Sanitizer — Closing the Slack Gap (FR-OR-03)
The slack gap (30.5% ASR) is caused by attacks delivered inside tool results that the model rewrites rather than copies. The deterministic ToolOutputSanitizer strips instruction framing before the agent reads them — no LLM call, no new dependencies.
105 attacked cases (21 tasks × 5 injections), 122 injected spans stripped, zero benign utility cost.
Memory Poisoning (48 in-house cases)
Pessimistic harm total: 18.8% (9/48). The 22 control-bypass cases are inert because the mediator never reads agent memory to decide authorisation.
Quick Start
git clone https://github.com/ravindu57/SCML.git && cd SCML
python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
DATABASE_URL="" REDIS_URL="" TRUST_MEDIATOR_API_KEYS="" \
.venv/bin/uvicorn trust_mediator.api.app:app --port 8000 &
sleep 2
bash demo.sh # run the demo
.venv/bin/pytest tests/ -q # 614 passed
cd clients/typescript && npm test # 25 passedInteractive docs: http://localhost:8000/docs
Docker Compose
bash deploy.sh # builds image, starts Postgres + Redis + mediatorDashboard
bash run-demo.sh # mediator :8000, dashboard :3100, agents :4000/:4100
bash run-demo.sh --stop # tear downArchitecture
┌─────────────────────────────────────────────────────────────────────────┐
│ SCML System Architecture │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Python │ │ TypeScript │ │ gRPC │ │
│ │ SDK │ │ SDK │ │ Client │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └────────────────────┼────────────────────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ FastAPI │ /v1/mediate/* │
│ │ + gRPC │ /v1/audit/* │
│ └──────┬──────┘ │
│ │ │
│ ┌───────────────────────────▼───────────────────────────┐ │
│ │ Mediation Pipeline │ │
│ │ │ │
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │
│ │ │ Trust │→│Inject. │→│ Policy │→│Memory │ │ │
│ │ │ Router │ │Scanner │ │ Engine │ │Integrity│ │ │
│ │ └────────┘ └────────┘ └────────┘ └────────┘ │ │
│ │ │ │ │ │
│ │ └────────────┬───────────────┘ │ │
│ │ ▼ │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ Output │ │ Audit │ │ │
│ │ │ Redactor │ │ Logger │ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ └───────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ PostgreSQL / SQLite│ │
│ │ + Redis (optional) │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘All config via TRUST_MEDIATOR_* env vars — nothing hardcoded. Every decision emits an AuditEvent.
API Surface
Production Deployment
Full integration guide:
INTEGRATION.md— Python SDK, TypeScript SDK, LangChain guard, HTTP API, embedded mode, and examples for CrewAI, LangGraph, and OpenAI function calling.
Tests
DATABASE_URL="" TRUST_MEDIATOR_ENV=development REDIS_URL="" TRUST_MEDIATOR_API_KEYS="" \
.venv/bin/pytest tests/ -q # 614 passed
cd clients/typescript && npm test # 25 passedApache License 2.0 — includes patent grant and defensive termination.
This server cannot be deployed
Maintenance
Related MCP Connectors
Security firewall for AI agents — scans MCP calls for injection, secrets, and risks.
Zero-secret MCP gateway for AI agents: risk-scored, audited calls with human-in-the-loop approval.
AgentGuard — 20-tool AI safety MCP: policy preflight, risk scoring, audit logging, rate limits.
Deterministic runtime safety for AI agents: scan PII, gate tool actions, verify LLM output.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA cryptographic sidecar proxy that tests MCP tools for OWASP vulnerabilities before deployment. Automatically sandbox and audit your AI agents' tool calls to ensure secure infrastructure.-
- AlicenseAqualityDmaintenanceProvides prompt injection detection, PII/secrets redaction, and an audit trail for AI agents via MCP tools.4MIT
- AlicenseNot gradedqualityCmaintenanceA multi-agent AI security layer that protects LLMs from prompt injection, jailbreaks, and policy violations via MCP tools.MIT
- AlicenseNot gradedqualityBmaintenanceA security MCP proxy that monitors and blocks data exfiltration between AI agents and their tools by detecting toxic flows (untrusted → sensitive → egress) deterministically with zero LLM calls in the decision path.1MIT