macOS native OCR MCP server powered by the Vision framework
The OCRToolMCP server defines a single tool 'ocr_extract_text' with a comprehensive input schema, but has moderate issues in naming clarity, description optimization for LLM use, and output schema documentation. The tool name is reasonably action-oriented (extract_text) but the description, while detailed, is verbose and not optimized for LLM decision-making. Input parameters have type declarations and descriptions, which is strong. However, the output schema is not explicitly documented in the visible code, only internal data structures (OCRResult, BoundingBox, OCRLine) are visible, and the actual JSON response format returned to the MCP client is not shown. Error handling is present (OCRExecutionError enum with message property) but lacks recovery guidance for the LLM.
Extract text from images using OCR with support for multiple input sources (file path, URL, base64) and output formats (text, markdown, structured)
Output schema not documented. The tool processes OCRResult internally, but the actual JSON response structure returned to MCP clients is not visible in the provided code. LLMs cannot plan downstream calls without knowing what fields to expect (e.g., does response include confidence scores, image dimensions, language detection results, or only text+bounding boxes?).
Tool description is verbose (209 chars) and mixes concerns. Currently: 'Extract text from images using OCR with support for multiple input sources (file path, URL, base64) and output formats (text, markdown, structured)'. Better: 'Extract text and bounding boxes from images using Vision Framework OCR. Accepts file path, HTTP(S) URL, or base64. Returns plain text, markdown table, JSON with coordinates, or auto-detected format.' The description should answer: what does it return? When use it instead of other tools? Current text buries the 'output formats' feature which is critical for LLM selection.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 50 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 31 | - | v1 |
Mutually exclusive parameters (image_path, url, base64) lack clear documentation of mutual exclusivity. The description states all three exist but does not say 'Provide exactly one of: image_path, url, or base64.' This forces LLMs to reason about valid combinations and risks invalid calls with multiple sources provided.
Language parameter description includes example values ('zh+en') rather than a formal constraint. The code defines supportedVisionLanguages as a Set, but the parameter description lists examples. LLMs may hallucinate invalid language codes or attempt to use the 'zh+en' syntax literally for combinations. Use an enum of valid codes or a detailed pattern constraint.
Error handling does not provide recovery guidance. The OCRExecutionError enum (fileNotFound, visionFailed, etc.) carries messages, but there is no indication in the tool definition how errors are communicated to the LLM or what recovery steps are suggested. Example: 'File not found at /path/to/img.png. Use list_directory() to find valid image paths.' Currently the LLM receives only the error message with no next steps.
Output configuration object (insertAsComment, language) is under-documented. The 'output' parameter is described as 'Optional output formatting configuration' but the nested 'language' field description only says 'Comment style language (python, shell, bash, html, xml, or default for //-style comments)'. It is unclear whether these fields are mutually exclusive, required together, or independent. What happens if insertAsComment=false but language='python'?