The server defines 2 tools with partial schema coverage and inconsistent description quality. nmapScan has a properly defined input schema (target, flags, outputFormat with enum) and a 65-character description that clearly states purpose but lacks detail on when to use it vs alternatives or prerequisites. The flags parameter includes a default (-T4 -p 1-1000) but the description lists examples inline rather than using constraints. getInfo has an empty input schema and a 74-character description that is generic and does not explain its purpose clearly. Output schemas are not documented for either tool, LLMs cannot predict the structure of responses. Input validation logic (validateTarget, validateFlags) exists in the implementation but is not reflected in the schema definitions, creating a gap between declared and actual behavior. The server lacks error handling guidance, idempotency declarations, and security annotations. Both tools are declared READ_ONLY (appropriate) but lack tool annotations (readOnlyHint/destructiveHint) that would make this explicit in the schema.
Tools (2)
getInforead onlysource verified35/100
Returns service information including available tools and session ID
nmapScanread onlysource verified63/100
Performs Nmap network scanning on specified targets
Output schemas are not documented. LLMs cannot predict the structure of tool responses (e.g., what fields nmapScan returns, or what getInfo contains). This forces agents to reason blindly about downstream tool calls and data extraction.
getInfo has an empty input schema ({}) and a vague 74-character description ('Returns service information including available tools and session ID'). The purpose, when to call it, and what 'session ID' means are unclear. This violates the pattern requirement that every parameter must have a description.
nmapScan description includes examples in the description text ('e.g., example.com, 192.168.1.1, 10.0.0.0/24') instead of enforcing constraints in the schema. LLMs may treat these examples as the only valid formats or copy them literally into real scans.
nmapScan
Recommendations
Document output schemas for both tools. For nmapScan, specify: 'Returns an object with fields: summary (string), parsed_result (object for xml format), raw_output (string for normal/grepable formats), scan_duration_ms (number).' For getInfo, specify: 'Returns an object with fields: tools (array of tool names), version (string), session_id (string or null).'
Expand nmapScan description from 65 chars to 150 - 200 chars: 'Performs Nmap network scanning on specified targets. Returns structured scan results (ports, services, OS info) in XML, normal, or grepable format. Use to discover open ports and services on networks. Requires a valid target (domain, IP, or CIDR) and optional Nmap flags for fine-tuning scans (timing, port range, scan type). Scans are read-only and non-destructive.'
Replace example values in nmapScan parameter descriptions with formal constraints. Instead of 'Domain name, IP address, or CIDR notation to scan (e.g., example.com, 192.168.1.1, 10.0.0.0/24)', define: pattern regex or enum for each supported format, and state the validation rule in the description: 'Valid domain name (RFC 1123), IPv4 address, or CIDR block with /0 - /32. Validated against standard domain and IP regex patterns.' Move examples to a separate 'example' or 'examples' field in the schema if needed.
Rewrite getInfo description: 'Returns metadata about the Nmap MCP server, including registered tools and the current session identifier (if stateful). Use to discover what tools are available before making scan requests.' Clarify whether session_id is meaningful (persistent across requests or just per-connection metadata).
The flags parameter description includes examples ('Common options: -T4 (timing), -p 1-1000 (port range)...') rather than documenting the actual constraint validation rules (validateFlags allows all flags with minimal restrictions). The gap between description and implementation will confuse LLMs.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) are declared in the schema, despite tools being marked READ_ONLY in the metadata. These annotations would make the tool's safety properties explicit to LLMs.
Error messages in the implementation (e.g., 'Invalid target format: ...', 'Invalid or potentially unsafe flags detected: ...') are returned to LLMs but do not include recovery guidance. Per the recovery-guide pattern, errors should tell the LLM what to do next.
The nmapScan tool is stateless (no session persistence) but logs include [sessionId || 'N/A'], suggesting the server may be tracking sessions. This creates ambiguity about statefulness for protocol alignment.
nmapScan
Add tool annotations to both tool definitions. In the Zod schema, add a .describe() or attach metadata documenting readOnlyHint: true for both tools (they do not modify state). For nmapScan, add idempotentHint: true (identical scans produce identical results).
Enhance error messages with recovery guidance. Instead of 'Invalid target format: 192.168.1.256', return 'Invalid target format: 192.168.1.256 (IP octet out of range 0 - 255). Use a valid domain, IPv4 address, or CIDR block (e.g., 192.168.1.0/24).'
Document the flags parameter constraint more accurately. Current validation (validateFlags) allows most flags. Clarify in the description: 'Nmap command-line flags (space-separated). Validated for basic structure but allows all flag combinations. Common options: -T4 (timing template 0 - 5), -p <range> (port range), -sS (SYN scan), -A (aggressive: OS + service detection). See nmap man page for full options.' Or, if safety is a concern, whitelist known-safe flags and document the restriction.
Declare timeout and resource limits in the nmapScan description: '5-minute timeout per scan. Max 10 MB output buffer. Large CIDR blocks or aggressive scans may timeout; use smaller targets or less aggressive flags (-T2) for large networks.'
Add a 'dependencies' section to nmapScan description if getInfo is meant to be called first: 'Call getInfo first to verify server availability and tools. Target must resolve (DNS or IP routing) or scan will fail.'
Return structured error objects with error codes and categories (retryable vs user-fixable) so LLMs can decide whether to retry, prompt the user, or bail out. E.g., { error: 'INVALID_TARGET', message: '...', retryable: false, user_action: 'Correct the target and retry.' }