// SAMPLE · the method

MCP testbed matrix

Acme Desk is our deliberately vulnerable MCP server, the Juice Shop of agent surfaces. This is the complete verdict matrix of our MCP probe against it: six tools, six verdicts, every tool called without credentials.

2026-09-01· deterministic, generated in-process· [agent-surfaces]

Reading notes.

  • get_public_status is public by design: the classifier is right that it is an access, and the adjudication layer kills it, because the tool does exactly what it was built to do. That split, classifier versus adjudicator, is the point.
  • admin_settings wraps its auth error inside a successful result. The classifier catches that mechanically, with no adjudication needed. Two teaching tools, caught by two different layers: one product, both layers.
  • debug_stack leaks an internal hostname inside an error (information disclosure). It is a posture finding, deliberately outside FINDINGS: the payable class here is unauthenticated access to data, and this is not that.
  • legacy_endpoint answers success with no data at all: never an access, because access is credited only by structured data, never by the absence of a rejection.
  • Verdict names are the method's proper nouns, kept identical to our console output. Our operators work in Spanish; this matrix is rendered in English for the public artifact, from the same deterministic run.
MCP PROBE https://testbed.local/mcp — server acme-desk-testbed 1.0.0 · format json · session-id absent
auth matrix (6 tools, NO credentials):
  ✓ get_public_status        ACCESO_SIN_AUTH   result.content with data: '{"status": "ok", "uptime_s": 48211, "region": "us-east-1"}' · repro 2/2 · class mcp_unauth_call (HIGH severity base, CVSS at triage discretion)
  ✓ get_customer_records     ACCESO_SIN_AUTH   result.content with data: '{"count": 3, "customers": [{"id": "C-1001", "name": "Ash Delta", "email": "ash.delta@example.test", "plan": "enterprise"' · repro 2/2 · class mcp_unauth_call (HIGH severity base, CVSS at triage discretion)
  ✗ export_audit_log         RECHAZADA_LIMPIA  explicit auth: 'Missing Authorization: Bearer header required for admin export'
  ✗ admin_settings           RECHAZADA_LIMPIA  auth in result.content (anchored prose, isError:false): 'unauthorized: admin token required to read workspace settings'
  ⚠ debug_stack              ERROR_FUGA        leak (plain text) in result.content without isError: 'Traceback (most recent call last):\n  File "/app/services/diagnostics.py", line 88, in dump_stack\n    raise RuntimeError(f\'connection to {DB_'
      leaks: Traceback (most recent call last):
  File "/app/services/diagnostics.py", line 88, in dump_stack
    raise RuntimeError(f'connection to {DB_HOST} lost')
RuntimeError: connection to db-internal.acme-de
  ? legacy_endpoint          INCONCLUSIVA      unstructured payload with no data shape (echo, message, or catch-all?): 'OK: legacy integration acknowledged'
negative control (nonexistent tool): FAILED as it must — the server discriminates tools, the success signal is not an echo
discovery posture: anonymous initialize+tools/list OK — tool inventory visible without credentials (informative, not a payable finding)
FINDINGS (2 ACCESO_SIN_AUTH): get_public_status, get_customer_records

Every verdict above is deterministic: the same probe against the same server produces the same matrix, run after run. The findings that matter are adjudicated by class before you ever see them: a tool that publishes uptime without auth is doing what it was built to do. A tool that hands out customer records is not.

The method behind every verdict is public, and so is the essay that defines the category it belongs to: the five surfaces.