MCP security scanner — 55 tools for runtime inspection, static analysis, config audit, dependency analysis. OWASP MCP Top 10 compliance. OAuth, TLS, fuzz testing, prompt injection, tool mutation detection. 100% local, zero external API calls.
mcp-security-scanner demonstrates strong definition quality across 18 security-focused tools. All tools have descriptions exceeding 20 characters with clear explanations of security concerns they detect. Input schemas are present and properly typed with Zod validation. However, several significant gaps prevent a higher score: (1) Output schemas are not documented, tools return formatted text/findings but the exact structure is not specified in schema definitions; (2) Error handling lacks recovery guidance, findings indicate security issues but don't guide what to do next; (3) Parameter descriptions are adequate but some lack constraint details (e.g., max_resources default is stated but no range documented); (4) Tool composition could be improved, several tools operate on the same resource types (e.g., cfg_* tools) making tool selection less obvious; (5) No tool annotations (readOnlyHint/destructiveHint) despite clear safety implications. The rt_fuzz_tools tool correctly marks itself as WRITE risk, but others lack explicit safety signals. Baseline: 18/18 tools have descriptions (100%, meets A+ baseline of 94%). 17/18 tools have visible input schemas with types. Average description length ~150 chars (within 34-392 baseline). However, per-tool parameter descriptions vary, some parameters like 'confirm_execute' are well-explained, others like 'categories' in rt_fuzz_tools lack detail on valid options.
Deep audit of a single MCP config file. Checks for: API keys in args, secrets in env, npx -y auto-install, unknown binaries, HTTP without TLS, missing auth headers, wildcard env passthrough.
Auto-discover all MCP configuration files on the system. Checks Claude Desktop, Claude Code, Cursor, VS Code, Windsurf locations. Returns found config files with server counts.
Check for excessive context exposure: servers inheriting all env vars, sensitive vars shared across unrelated servers, broad resource access patterns.
Check file permissions on MCP config files and related credential files. Flag configs readable by other users (mode > 600), world-readable .env files.
Analyze each server in MCP config for shadow server indicators: unverified npm packages via npx -y, binaries in writable directories (/tmp), suspicious command paths.
Verify transport security: HTTP vs HTTPS, SSE without TLS, WebSocket without WSS, servers bound to 0.0.0.0, tunnel URLs (ngrok, localtunnel), missing Authorization headers.
Output schemas not documented in tool definitions. Tools return structured findings (findings: Finding[]) but this structure is not declared in a JSON Schema 'returns' field. LLMs cannot predict or parse the output structure.
Error handling lacks recovery guidance. Tools return findings with OWASP/CWE mappings and remediation advice, which is good. However, when a tool cannot connect to a server or encounters a fatal error, responses like 'Connection refused' give no recovery path. Example: rt_check_oauth catches connection errors silently but returns an empty result, the LLM doesn't know whether to retry, check the URL, or try a different tool.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | B | 70 | 2026-07-28+ | v2 |
Recursively scan directory for .env files. Detect: high-value API keys, database credentials, private keys, default/weak credentials, overly permissive file permissions.
Parse lockfile (package-lock.json v2/v3, bun.lock) and list all dependencies with versions. Provides dependency tree overview for manual review.
Detect deprecated dependencies by checking package.json 'deprecated' field in node_modules. Deprecated packages no longer receive security patches.
Detect dependencies with lifecycle scripts (preinstall, install, postinstall, prepare) that execute during npm/bun install with full system access.
Check the installed @modelcontextprotocol/sdk version against known vulnerable versions and latest features (OAuth 2.1 support, etc).
Check all dependency names against top popular npm packages using: Levenshtein distance, keyboard-adjacent substitution, vowel swapping, separator confusion, scope squatting.
Detect dependencies with unpinned version ranges: caret (^), tilde (~), star (*), greater-than (>=). Unpinned versions allow silent malicious updates.
Inspect MCP server capabilities advertised during initialization. Flags: experimental features, dynamic tool changes (tools.listChanged), dynamic resource changes (resources.listChanged), logging capability. Also checks server version.
Test if HTTP/SSE MCP server properly validates OAuth tokens. Sends requests with no token, invalid token, and expired-format JWT. Flags servers that accept unauthenticated or invalid requests. Only applies to HTTP/SSE transport.
Read actual content of all MCP resources via readResource() and scan for: poisoning patterns, ANSI escape sequences, hidden Unicode steganography, oversized content (context flooding). Goes beyond URI-based rt_check_resource_exposure by inspecting real content.
Inspect TLS certificate of HTTP/SSE MCP server. Checks: unencrypted HTTP, untrusted/self-signed cert, expired cert, expiring soon (<30d), weak signature (SHA-1), short key (<2048 bits). Only applies to HTTP/SSE transport.
Fuzz-test MCP tools with edge-case inputs: empty strings, long strings, path traversal, command injection, SQL injection, special chars, type confusion. Dry-run by default (schema analysis only) — set confirm_execute=true to actually invoke tools via callTool(). Reports crashes, stack trace leaks, and unhandled errors.
Tool annotations missing. rt_fuzz_tools explicitly marks Risk: WRITE, but other tools lack destructiveHint, readOnlyHint, or idempotentHint annotations in their ToolDef. This prevents agents from reasoning about safety and idempotency automatically.
Parameter descriptions inconsistent. rt_fuzz_tools 'categories' parameter lists valid enum values in description but not as a formal enum constraint in schema. cfg_auto_discover 'scan_home' has description but no pattern/constraint. Without enums, LLMs can hallucinate invalid values.
Tool naming creates disambiguation burden. Multiple cfg_check_* tools (cfg_check_shadow_servers, cfg_check_context_oversharing, cfg_check_transport_security, cfg_check_file_permissions) operate on the same resource (MCP config files). Names follow a pattern but descriptions are needed to distinguish intent. LLMs may struggle to select the right one without detailed descriptions.