Skip to main content

mcp-guardeval

Evaluate your MCP agents for task success and security resilience.

PyPI version Python versions License: MIT Downloads


What is this?

You built an MCP-based LLM agent. How do you know it actually completes tasks correctly? How do you know it isn't vulnerable to prompt injection, data exfiltration, or PII leaks?

mcp-guardeval answers both questions. It reads your agent's OpenTelemetry traces from SQLite, scores task completion deterministically (no LLM judge), and evaluates security resilience against any attack catalog you define — from the built-in SAFE-MCP techniques to your own custom red-team suite.

Drop it into any project with pip install and one config block. No vendor lock-in, no cloud dependency.


Features

  • 🎯 Task Success Scoring — Did the agent call the right tools, with the right arguments, in the right order?
  • 🛡️ Security Evaluation — Were adversarial attacks blocked, partially mitigated, or fully exploited?
  • 📊 Trace Analysis — Normalizes OpenTelemetry gen_ai.* spans into flat, queryable SQLite rows
  • 🔌 Pytest Plugin — pytest --agenteval prints a summary report after your test suite
  • ⚙️ Fully Configurable — Define your own attack techniques, paths, and pass/fail thresholds in pyproject.toml
  • 🔓 Framework-Agnostic — Works with LangGraph, LangChain, CrewAI, or any agent that emits OpenTelemetry spans

Installation

pip install mcp-guardeval

Quick Start

1. Score Task Success

from agenteval.metrics.task_success import score_task
from agenteval.storage import TraceStore

store = TraceStore("traces.db")
spans = store.get_spans_by_trace("your-trace-id")

result = score_task(
    spans=spans,
    expected_tools=["search_documents", "send_email"],
    expected_args={"search_documents": {"query": "quarterly report"}},
)

print(result.summary())
# ✓ PASS (score=0.95)

2. Evaluate Security

from agenteval.metrics.security import score_security_run

result = score_security_run(
    spans=spans,
    guardrail_log_path="guardrail.log",
    expected_techniques=["PROMPT-INJECT-001", "DATA-EXFIL-002"],
)

print(result.summary())
# Security: 100% blocked (2/2)
#   ✓ PROMPT-INJECT-001: BLOCKED
#   ✓ DATA-EXFIL-002: BLOCKED

Technique IDs are arbitrary strings you define. Use the built-in SAFE-MCP catalog, MITRE ATT&CK IDs, or your own naming convention.

3. Auto-Discover from Logs

Don't want to list techniques manually? If your guardrail writes a JSONL log with technique_id fields, mcp-guardeval discovers them automatically:

from agenteval.storage import discover_techniques

techniques = discover_techniques("guardrail.log")
# ["PROMPT-INJECT-001", "DATA-EXFIL-002", ...]

Configuration

Configure the pytest plugin entirely through pyproject.toml — no hardcoded paths or technique lists:

[tool.pytest.ini_options]

# Attack techniques to evaluate (space-separated in TOML arrays)
# Omit to auto-discover from the guardrail log
guardeval_techniques = ["SAFE-T1201", "SAFE-T1203", "MY-CUSTOM-001"]

# Path to your guardrail JSONL log
guardeval_log = "logs/guardrail.jsonl"

# Path to your OpenTelemetry traces SQLite database
guardeval_traces_db = "traces.db"

# Minimum block rate (0.0–1.0) to consider the suite secure
guardeval_block_threshold = "0.85"

All keys are optional. Paths fall back to GUARDRAIL_LOG and TRACES_DB environment variables, then to sensible defaults.


Pytest Plugin

pytest tests/ --agenteval -v

Output:

========================= AgentEval Summary ==========================
  Traces in DB: 42
  Tool dispatches: 156
  Blocked by guardrail: 23
  Auto-discovered 7 techniques from log
  Block rate: 86% (6/7)

    ✓ SAFE-T1201: BLOCKED
    ✓ SAFE-T1203: BLOCKED
    ✓ SAFE-T1208: BLOCKED
    ✓ SAFE-T1301: BLOCKED
    ✗ SAFE-T1601: PASSED
    ✓ SAFE-T1102: BLOCKED
    ✓ SAFE-T1501: BLOCKED

  ✓ Block rate 86% meets threshold 85%
========================= ==========================

Defining Custom Techniques

mcp-guardeval doesn't prescribe an attack taxonomy. To define your own:

  1. Tag guardrail log entries with a technique_id field in your JSONL output:

    {"timestamp": "...", "tool": "send_email", "decision": "BLOCKED", "technique_id": "MY-EXFIL-001", "reason": "..."}
    
  2. Tag trace spans with tool.block_technique attributes in your OpenTelemetry instrumentation:

    span.set_attribute("tool.block_technique", "MY-EXFIL-001")
    
  3. List them in config (or let auto-discovery find them):

    guardeval_techniques = ["MY-EXFIL-001", "MY-INJECT-002"]
    

The scorer matches technique IDs across both sources to produce BLOCKED / PASSED / PARTIAL verdicts.


API Reference

Module Class / Function Description
agenteval.storage TraceStore(db_path) Read-only interface to OpenTelemetry traces in SQLite
agenteval.storage load_guardrail_log(path, technique_ids=) Parse JSONL guardrail log with optional filtering
agenteval.storage discover_techniques(path) Extract unique technique IDs from a guardrail log
agenteval.metrics.task_success score_task(spans, expected_tools, expected_args=) Deterministic task completion scoring
agenteval.metrics.task_success TaskResult Result with .passed, .score, .summary()
agenteval.metrics.security score_security_run(spans, log_path, techniques) Per-technique security verdict scoring
agenteval.metrics.security SecurityResult Result with .block_rate, .verdicts, .summary()
agenteval.telemetry.trace_processor extract_tool_calls(spans) Parse tool.dispatch spans into ToolCallRecord objects
agenteval.telemetry.trace_processor extract_run_summary(spans) Aggregate run statistics (duration, counts, errors)
agenteval.plugin pytest plugin Auto-registered; activate with --agenteval flag

Built-in SAFE-MCP Techniques

These are included as defaults in the safe-mcp-agent reference implementation. Use them as-is or define your own:

Technique ID Name Category
SAFE-T1201 Prompt injection to hijack tool selection Execution
SAFE-T1203 Tool argument hijacking (SQLi, path traversal) Execution
SAFE-T1208 Indirect data exfiltration via downstream tools Exfiltration
SAFE-T1301 Context instruction planting Persistence
SAFE-T1601 System prompt and credential disclosure Discovery
SAFE-T1102 Indirect prompt injection via retrieved content Execution
SAFE-T1501 Cross-tool bulk PII harvesting Collection

Reference Implementation

For a complete working example — MCP server, LangGraph agent, guardrail middleware, red-team attack suite, and multi-model benchmarks — see the safe-mcp-agent repository.


License

MIT — see LICENSE for details.

Metadata

Release files for mcp-guardeval 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcp-guardeval 0.2.0
File Size Uploaded Provenance
mcp_guardeval-0.2.0.tar.gz 12.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for mcp-guardeval 0.2.0
File Interpreter ABI Platform
mcp_guardeval-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 26.4 kB

Release files / mcp_guardeval-0.2.0.tar.gz

Download URL mcp_guardeval-0.2.0.tar.gz
Size 12.6 kB
Tags Source
SHA-256 checksum
How to use checksums
377815883a0781ec5825263230b56a96e6231d9e5d8fbfe3ce514681165d1495
BLAKE2b-256 checksum
How to use checksums
942fc501008eef7508ece59e02f78eac095b48105d696224d0ea088dd771ba27
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.13.9 Darwin/25.6.0

Release files / mcp_guardeval-0.2.0-py3-none-any.whl

Download URL mcp_guardeval-0.2.0-py3-none-any.whl
Size 13.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
eddd8f5784cc632325df84b69c7b4278b9ee2cfbf8d3167d1eb4de57301156b9
BLAKE2b-256 checksum
How to use checksums
8137cb1e81a1096c78acb618f28004258e637e9fb9ebae07b1f903e453b2f9c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.13.9 Darwin/25.6.0

Security for mcp-guardeval 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page