Static source inference · medium confidence · detected: Logging
Deprecated protocol patterns detected
Summary
This Rust MCP server for zero-width character steganography has clear, well-structured tool definitions with proper JSON schemas. However, it suffers from significant quality gaps: (1) descriptions are in Chinese, making them inaccessible to most English-speaking LLM developers; (2) several tools lack explicit 'required' field specifications for mutually exclusive parameters; (3) no output schemas are documented, forcing LLMs to reason about return types blindly; (4) error handling logic exists but descriptions don't guide recovery; (5) tool naming is technically clear (zw_analyze, zw_encode, etc.) but could be more action-verb oriented (analyze_text_for_zero_width_chars). The tools are well-intentioned for a CTF/steganography domain but fall short of production-grade documentation standards.
Descriptions are in Chinese (Simplified), making the server inaccessible to English-speaking developers and LLMs. The rubric expects 10-1024 character descriptions that guide LLM tool selection; descriptions in a language the agent doesn't understand cannot serve this purpose.
No output schemas documented anywhere in the tool definitions. LLMs cannot predict the structure of responses (fields, types, pagination details), forcing them to reason blindly about downstream usage. The rubric requires documented return types for A+ quality.
Mutually exclusive parameters (e.g., 'text' vs 'file_path') lack explicit 'required' field with constraint documentation. zw_analyze, zw_decode, zw_dump_raw have no specified 'required' array or clear statement in descriptions about exclusivity. This allows LLMs to pass both or neither, violating the mutual-exclusion constraint.
Recommendations
Translate all tool descriptions and parameter descriptions to English. Descriptions in Chinese are inaccessible to most LLM developers and LLMs. Update each tool's description to 50-200 characters, using clear imperative language: 'Analyze text for embedded zero-width characters and return counts, types, and distribution statistics.' vs. the current Chinese description.
Document output schemas for all tools. Add an 'output_schema' JSON Schema object to each Tool definition showing: field names, types, and descriptions. Example for zw_analyze: {"type": "object", "properties": {"zero_width_chars": {"type": "array", "items": {"type": "object", "properties": {"codepoint": {"type": "string"}, "count": {"type": "integer"}, "name": {"type": "string"}}}}, "total_count": {"type": "integer"}}}.
Add explicit 'required' field to tools with mutually exclusive parameters. For zw_analyze, zw_decode, zw_dump_raw: add 'required': ["text"] at the schema level OR split into two tool variants (one taking text, one taking file_path) to eliminate ambiguity.
Enhance parameter descriptions to clarify constraints and guide LLM input. For 'method' enum parameters (zw_decode), change description from bare enum list to: 'Decoding algorithm to use. Choose one: auto (try all methods and rank by confidence), unicode_tags, steganographr, binary, or 330k. If unsure, use auto.'
Add recovery guidance to descriptions. E.g., zw_encode description should say: 'If output_path write fails, check file permissions and disk space. If encoding fails with invalid message, try reducing message length or switching method to binary.'
Spec posture evidence
Inferred effective spec: <=2025-11-25.
Relies on Logging (deprecated) - log to stderr or use OpenTelemetry
Tool names do not follow verb-noun convention clearly. 'zw_analyze', 'zw_encode', 'zw_decode' are verb-based but prefix with domain acronym 'zw_', reducing clarity. Names like 'analyze_zero_width_characters' or 'analyze_steganography' would be more self-documenting for LLM disambiguation.
Error handling exists in the implementation (e.g., ToolCallResult::error() calls) but tool descriptions provide NO recovery guidance. When 'file not found' or 'invalid method' errors occur, descriptions don't explain what the LLM should do next. Per the rubric, errors must guide recovery.
zw_analyzezw_decodezw_encodezw_dump_raw
Rename tools to follow clearer verb-noun patterns. Consider: 'analyze_steganography' (instead of zw_analyze), 'decode_steganography' (instead of zw_decode), 'encode_steganography' (instead of zw_encode). This avoids domain-specific prefixes that reduce clarity for LLMs unfamiliar with 'zw' terminology.
Document idempotency for each tool. zw_analyze, zw_decode, zw_dump_raw, zw_list_chars, zw_list_presets are read-only and idempotent (safe to retry). zw_encode modifies state (creates files). Make this explicit in tool descriptions: 'Read-only. Safe to call multiple times with the same input without side effects.' vs. 'Destructive write operation. Creates or overwrites output file.'
Add pagination guidance if list tools can return large results. zw_list_chars returns 182 characters (small), but add note: 'Returns all 182 zero-width Unicode characters. Results may be large; consider filtering client-side if needed.' If any tool scales beyond 100 items, add limit and offset parameters.
Validate mutually exclusive parameters at runtime with clear error messages. When both 'text' and 'file_path' are provided (or both missing), return: 'Error: Provide exactly one of text or file_path, not both and not neither. If reading from file, use file_path="/path/to/file". If analyzing inline text, use text="...".'
Add examples to parameter descriptions (sparingly). Instead of 'file_path: The file to analyze', write: 'file_path: Absolute or relative path to text file (e.g. ./steganography.txt or /tmp/message.txt with zero-width characters embedded).' But avoid literal example values that LLMs might reuse.