Skip to main content
Glama
Wsh7Ash

scopeguard-mcp

by Wsh7Ash

scopeguard-mcp

An MCP stdio server that gives bug-hunting AI agents an enforceable authorized-scope guardrail: every target is checked against a declarative allow/deny list before a finding can be recorded, and evidence is stripped of secrets on the way in.

Problem

Agent-driven bug hunting fails in a predictable way: the agent happily turns toward a host the operator never authorized, or it pastes a live credential from a captured response straight into a finding (and from there into an LLM prompt). Human review catches that after the fact — if at all.

scopeguard-mcp puts the check in the middle of the loop, as MCP tools the agent must call:

  1. check_target answers "am I allowed to touch this?" before any request.

  2. add_finding re-checks the same scope itself and refuses out-of-scope records, so a rule skipped by the agent still holds.

  3. redact removes tokens, keys, JWTs, card numbers and e-mail addresses from evidence before it leaves the workstation.

Related MCP server: mcp-vaara

Key features

  • Declarative scope — JSON allow/deny list with host (wildcard *.a.b), url (scheme + path prefix) and cidr rules. Deny always wins; loopback is always allowed so the local lab works out of the box.

  • No network activity, ever — the scope decision is pure string/IP matching. No DNS lookups, no connections, so a check can never become a side channel to an unauthorized host.

  • CVSS v3.1 Base scoring — verified against FIRST's published example vectors (9.8, 8.8, 7.8, 8.1, 7.5, 6.1, 0.0).

  • Evidence redaction — GitHub/Slack/AWS tokens, PEM private keys, JWTs, bearer headers, api_key=... assignments, URL credentials, Luhn-valid card numbers and e-mail addresses.

  • Append-only JSONL ledger — each finding stores the scope verdict that allowed it, with sequential IDs and corrupt-line tolerance.

  • Zero dependencies — Python 3.10+ standard library only, including the JSON-RPC layer.

Example session

-> {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26",...}}
<- {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-03-26","capabilities":{"tools":{}},"serverInfo":{"name":"scopeguard-mcp",...}}}
-> {"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"check_target","arguments":{"target":"https://prod.staging.example.test"}}}
<- {"jsonrpc":"2.0","id":4,"result":{"content":[{"type":"text","text":"{\"allowed\": false, \"reason\": \"explicitly denied by deny rule host:prod.staging.example.test\"}"}],"isError":false}}
-> {"jsonrpc":"2.0","id":9,"method":"tools/call","params":{"name":"add_finding","arguments":{"target":"https://victim.example.org",...}}}
<- {"jsonrpc":"2.0","id":9,"result":{"content":[{"type":"text","text":"refused (out of scope): no matching allow rule..."}],"isError":true}}

The full captured run is in results/demo_transcript.txt.

Architecture

MCP client (Claude Code / opencode / Cursor)
        │  newline-delimited JSON-RPC 2.0 over stdin/stdout
        ▼
server.py  ── initialize / tools/list / tools/call / ping
        ├─ scope.py     allow|deny verdicts (pure, no I/O)
        ├─ redact.py    secret + PII scrubbing
        ├─ cvss.py      CVSS:3.1 Base score
        └─ findings.py  append-only JSONL ledger

Protocol revision is pinned to 2025-03-26 (the initialize handshake era); 2024-11-05 clients are negotiated with. See docs/ARCHITECTURE.md.

Requirements

  • Python 3.10 or newer

  • No third-party runtime dependencies

  • An MCP-capable client for interactive use (tests and demo only need Python)

Installation

git clone https://github.com/Wsh7Ash/scopeguard-mcp
cd scopeguard-mcp
pip install -e .            # installs the scopeguard-mcp console script

For a throwaway run without installing:

PYTHONPATH=src python -m scopeguard_mcp

Quick start

# 1. Show the active scope (loopback-only by default)
PYTHONPATH=src python -m scopeguard_mcp --print-scope

# 2. Run the scripted end-to-end session
PYTHONPATH=src python examples/demo_session.py

# 3. Run the test suite
PYTHONPATH=src python -m pytest -q

Usage examples

Register with an MCP client

{
  "mcpServers": {
    "scopeguard": {
      "command": "scopeguard-mcp",
      "args": ["--scope", "examples/scope.json", "--ledger", ".findings.jsonl"]
    }
  }
}

Authorize a staging host

Edit the scope document — see examples/scope.json:

{
  "name": "local-lab",
  "allow": [{ "type": "host", "value": "*.staging.example.test" }],
  "deny": [{ "type": "host", "value": "prod.staging.example.test" }]
}

Record a finding

tools/call add_finding
  title:    Debug endpoint reflects Authorization header
  target:   http://127.0.0.1:8080/debug
  evidence: Authorization: Bearer ghp_... echoed in HTML
  severity: high
  cvss:     CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N
→ stored with id 1, evidence redacted, cvss_score 8.2

Configuration

Flag

Default

Meaning

--scope PATH

loopback-only built-in scope

JSON scope document

--ledger PATH

./scopeguard-findings.jsonl

findings ledger file

--print-scope

–

print the active scope as JSON and exit

Scope document fields: name, description, allow[], deny[], each rule being {"type": "host|url|cidr", "value": "..."}.

Testing

PYTHONPATH=src python -m pytest -q      # 43 tests

Coverage: CVSS fixtures from FIRST, scope matching (wildcards, path prefixes, CIDR, deny precedence), redaction patterns, ledger behaviour, and a subprocess-level MCP protocol test that exercises the real handshake, tool calls, tool errors and JSON-RPC error codes.

Project structure

scopeguard-mcp/
├─ src/scopeguard_mcp/
│  ├─ server.py     JSON-RPC dispatch + tool registry
│  ├─ scope.py      allow/deny evaluation (no I/O)
│  ├─ redact.py     secret/PII scrubbing
│  ├─ cvss.py       CVSS v3.1 Base score
│  ├─ findings.py   JSONL ledger
│  └─ __main__.py   CLI
├─ tests/           unit + protocol tests
├─ docs/            ARCHITECTURE.md, USAGE.md, PROJECT_SPEC.md
├─ examples/        scope.json, demo_session.py
├─ results/         demo_transcript.txt
└─ SECURITY.md

Limitations

  • Base metric group only: Temporal and Environmental scores are not computed.

  • No DNS resolution by design, so cidr rules only match IP-literal targets.

  • The ledger is a local file with no locking; two concurrent writers could interleave lines (corrupt lines are skipped on read).

  • Redaction is pattern-based. It catches common token shapes, not every bespoke secret; treat it as a safety net, not a guarantee.

  • It guards scope, not behaviour: nothing here stops an authorized agent from making a destructive request to an authorized host.

Roadmap

  • Optional tools/list pagination (nextCursor).

  • Ledger export to SARIF for CI consumption.

  • Scope rule unit tests as a CLI subcommand (--check-rule).

Security notes

Defensive tooling for targets you own or are explicitly authorized to test. See SECURITY.md for authorized-use wording, threat model and reporting.

License

MIT — see LICENSE.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    Provides AI agents with standardized security scanning capabilities for authorized assessments, including host detection, port scanning, service fingerprinting, web vulnerability scanning, CVE verification, and report generation, all with unified JSON output and strict compliance controls.
    -
  • A
    license
    A
    quality
    A
    maintenance
    Gates every AI agent tool call against your policy before it runs, then writes a hash-chained, tamper-evident record of what was decided and what happened. Anyone can verify that record offline, without your software, your systems or any key you hold.
    4
    1,134 PyPI
    15
    AGPL 3.0
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to perform safe, authorized penetration testing by managing engagements, enforcing scope and risk policies, and orchestrating tools like Nmap, Nuclei, and Subfinder.
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables authorized autonomous application and API security testing, allowing LLM-driven agents to plan and execute pentest checks while a deterministic policy layer enforces scope and authorization outside the model.
    -