37 attacks. One survivor.
Level 1 tested resilience. Level 2 tests stress. 10MB payloads, 1,000 concurrent requests, max int IDs, wrong types everywhere. Which frameworks survive under pressure?
Combined results (L1 + L2)
22 Level 1 attacks + 15 Level 2 attacks = 37 total. ZeroMCP is the only framework that passes all of them.
| Framework | Language | L1 (22) | L2 (15) | Total (37) | Failures |
|---|---|---|---|---|---|
| ZeroMCP | Node.js | 22/22 | 15/15 | 37/37 | None |
| Official SDK | Node.js | 22/22 | 15/15 | 37/37 | None |
| fastmcp | Node.js | 22/22 | 15/15 | 37/37 | None |
| mcp-framework | Node.js | 22/22 | 15/15 | 37/37 | None |
| mcp-go (mark3labs) | Go | 22/22 | 14/15 | 36/37 | max_int_id corrupted |
| fastmcp | Python | 22/22 | 14/15 | 36/37 | max_int_id corrupted |
| zeromcp-mrexodia | Python | 22/22 | 14/15 | 36/37 | string_id crashed |
| Spring AI MCP | Java | 23/23 (SSE) | 23/23 | None | |
| fast-mcp | Ruby | 23/23 (SSE) | 23/23 | None | |
Level 2 attack list
15 attacks designed to break edge cases that Level 1 doesn't cover.
Single tool call with a 10MB string argument. Tests memory handling and request size limits.
Deeply nested JSON object as tool argument. Tests recursion limits and stack depth.
50 simultaneous tool calls. Tests connection handling and response routing.
Tool arguments full of emoji, RTL text, and Unicode edge cases. Tests string handling.
Null bytes embedded in tool arguments. Tests binary safety of JSON parsing.
Multiple tool calls sent before any response. Tests out-of-order response handling.
1,000 requests as fast as possible. Tests throughput under extreme concurrency.
A single tool call with 10,000 key-value pairs. Tests schema validation performance.
JSON-RPC request ID set to Number.MAX_SAFE_INTEGER. Tests large integer handling.
JSON-RPC request ID as a floating point number. Tests ID type handling.
JSON-RPC request ID as a string. Valid per spec but many implementations assume integer.
All arguments set to empty strings. Tests null vs empty handling.
Arguments passed as arrays instead of objects. Tests type validation.
Arguments passed as booleans where strings expected. Tests type coercion.
Arguments passed as numbers where strings expected. Tests type coercion.
What broke
Go and Python frameworks corrupt Number.MAX_SAFE_INTEGER (9007199254740991) in JSON-RPC response IDs. Large integer IDs are valid per JSON-RPC spec.
Crashes on string request IDs. JSON-RPC 2.0 spec allows string, number, or null.