mcp-proofDelivery report

bad_server

✗ NOT SHIP-READY — 5 MUST conformance check(s) failing; 3 security finding(s)
Server under test
.venv/bin/python demo/bad_server.py
Generated
2026-08-21 19:50 UTC · mcp-proof v0.7.2
Protocol
negotiated 2025-03-26 · initialize-handshake era · newer revision available: 2025-11-25
Behaviour fingerprint
sha256:b6837784150c7f5242837ae8405d4217bef0beb89c8788542242da8314c874ae
Conformance
5/10
MUST checks passed · 6/7 SHOULD
Security
5
findings · 3 blocking · 2 advisory
Behaviour regression
not recorded (run mcp-proof record)
Evidence scope. This report proves what was observed on the wire: protocol conformance of the served surface, static analysis of advertised tool metadata. It does not assess deployment, source code, process controls or authorization/OAuth flows — MSSS controls that need such evidence are marked manual review (or partial), never assumed.

Recommended next steps

  1. P0LIFE-01 — Return protocolVersion, capabilities and serverInfo in the initialize result.
  2. P0RPC-03 — Validate tools/call params and return an error when required fields are missing.
  3. P0TOOL-03 — Fix the inputSchema so it validates under JSON Schema draft 2020-12.
  4. P0TOOL-05 — Validate arguments against the inputSchema and reject calls missing required params.
  5. P0HYG-01 — Send logs and banners to stderr; stdout is reserved for the protocol stream.
  6. P0SEC-01 — Rewrite descriptions to describe tool behaviour; remove instructions aimed at the model.
  7. P0SEC-02 — Strip zero-width, bidi-control and tag-block characters from tool names and descriptions.
  8. P0SEC-03 — Remove embedded credentials from descriptions/schemas and rotate any real keys.

Protocol conformance

CheckLevelResultDetails
LIFE-01 MUST ✗ FAIL
initialize returns protocolVersion, capabilities and serverInfo
initialize result missing: serverInfo
Fix: Return protocolVersion, capabilities and serverInfo in the initialize result.
LIFE-02 SHOULD ! WARN
server negotiates the newest handshake revision (2025-11-25)
negotiated 2025-03-26; the newest handshake revision is 2025-11-25 — a newer server SDK will negotiate it
Fix: Upgrade the server SDK to a release that negotiates the newest initialize-handshake revision (2025-11-25).
LIFE-03 MUST ✓ PASS
server answers tools/list after the initialized notification
tools/list returned 4 tool(s) across 1 page(s) after initialized
LIST-01 MUST ✓ PASS
tools/list pagination terminates (no cursor loop)
single page, no pagination cursor
RPC-01 MUST ✓ PASS
unknown method gets a JSON-RPC error response
unknown method rejected with error code -32603
RPC-02 SHOULD ✗ FAIL
unknown method error code is -32601 (method not found)
expected -32601, got -32603
Fix: Use JSON-RPC 2.0 code -32601 when rejecting unknown methods.
RPC-03 MUST ✗ FAIL
malformed tools/call params are rejected with an error
malformed tools/call params returned a result instead of an error
Fix: Validate tools/call params and return an error when required fields are missing.
TOOL-01 MUST ✓ PASS
every tool has a non-empty name and an inputSchema
all 4 tools have a name and an inputSchema
TOOL-02 SHOULD ! WARN
every tool has a non-empty description
undocumented tools: no_docs_tool
Fix: Add a one-line description to every tool so agents can choose correctly.
TOOL-03 MUST ✗ FAIL
every tool inputSchema compiles as JSON Schema
no_docs_tool: 'strang' is not valid under any of the given schemas
Fix: Fix the inputSchema so it validates under JSON Schema draft 2020-12.
TOOL-04 MUST ✓ PASS
calling a nonexistent tool is rejected
rejected as JSON-RPC error (code -32602)
TOOL-05 MUST ✗ FAIL
a call missing required arguments is rejected
lookup_account called with empty args returned a normal result (silent success)
Fix: Validate arguments against the inputSchema and reject calls missing required params.
TOOL-06 MUST – SKIP
declared outputSchemas compile as JSON Schema
no tool declares an outputSchema
TOOL-08 MUST – SKIP
observed structuredContent matches the declared outputSchema
no tool declares an outputSchema
TOOL-07 SHOULD ! WARN
declared input constraints are enforced
declared constraints not enforced — lookup_account: minimal invalid input (account_id=12345) was answered normally; lookup_account: minimal invalid input (missing required 'account_id') was answered normally; fetch_url: minimal invalid input (url=12345) was answered normally; fetch_url: minimal invalid input (missing required 'url') was answered normally
Fix: Validate tool arguments against the declared inputSchema; inputs that violate it must be rejected, not answered normally.
RES-01 MUST – SKIP
advertised resources capability serves resources/list
resources capability not advertised
RES-02 MUST – SKIP
every resource carries a uri and a name
resources/list unavailable
RES-03 MUST – SKIP
resources/read returns contents for an advertised resource
no listed resource to read
RES-04 MUST – SKIP
resources/list pagination terminates (no cursor loop)
no surface to paginate
PROMPT-01 MUST – SKIP
advertised prompts capability serves prompts/list
prompts capability not advertised
PROMPT-02 MUST – SKIP
every prompt has a name and well-formed argument metadata
prompts/list unavailable
PROMPT-03 MUST – SKIP
prompts/get rejects a call missing required arguments
no prompt declares required arguments
PROMPT-04 MUST – SKIP
prompts/list pagination terminates (no cursor loop)
no surface to paginate
CAP-02 SHOULD ✓ PASS
declared capabilities match served features (resources)
capabilities.resources not declared and resources/list not served
CAP-03 SHOULD ✓ PASS
declared capabilities match served features (prompts)
capabilities.prompts not declared and prompts/list not served
HYG-01 MUST ✗ FAIL
stdout carries only JSON-RPC messages
1 non-JSON-RPC stdout line(s); first 3: Starting bad server...
Fix: Send logs and banners to stderr; stdout is reserved for the protocol stream.
CAP-01 SHOULD ✓ PASS
declared capabilities match served features (tools)
capabilities.tools declared and tools/list served

Security & hygiene

CheckDomainResultDetails
SEC-01 MCP-INPUT-01 ✗ FAIL
no prompt-injection patterns in tool descriptions
lookup_account: "ignore previous instructions"; lookup_account: "always call this tool first"
Fix: Rewrite descriptions to describe tool behaviour; remove instructions aimed at the model.
SEC-02 MCP-INPUT-01 ✗ FAIL
no invisible or bidi control characters in tool metadata
lookup_account.description: U+200B
Fix: Strip zero-width, bidi-control and tag-block characters from tool names and descriptions.
SEC-03 MCP-LOG-02 ✗ FAIL
no secret-looking strings in tool metadata
lookup_account: sk-demo123… (27 chars)
Fix: Remove embedded credentials from descriptions/schemas and rotate any real keys.
SEC-04 MCP-INPUT-02 ! WARN
injection-surface string params carry constraints
unconstrained injection-surface params: run_shell.cmd, fetch_url.url
Fix: Add enum, pattern or maxLength to path/url/command-like string params.
SEC-05 MCP-INPUT-01 ✓ PASS
tool descriptions stay under 2000 chars
longest description 142 chars across 4 tools
SEC-06 MCP-EXEC-01,MCP-EXEC-02 ! WARN
no tool advertises unconstrained arbitrary execution
exec-style tools with free-form string params: run_shell(cmd)
Fix: Replace free-form command/shell tools with parameterized, allowlisted operations (MSSS MCP-EXEC-01/02).

MSSS compliance

L1: 0/2 auto-assessable controls met · 4 require manual review. Mapped against MSSS v0.1 (control-level mapping v2.0 (2026-01-20)): 3 of 24 controls are auto-assessable from this audit's deterministic checks (partial = evidence ran clean but cannot prove the control on its own); the remaining 21 need deployment, code or process evidence and are marked manual review — never assessed by this tool.