MCP server for converting documents (PDF, DOC, DOCX, PPT, PPTX, PNG, JPG, JPEG, HTML) to Markdown using MinerU API
This MCP server exhibits significant definition quality gaps. Tool names follow verb-noun conventions, but descriptions lack LLM-optimization depth. Input schemas are present but incomplete, many parameters lack type constraints and enums where applicable. Output schemas are undocumented. Error handling is absent from tool definitions. The two duplicate tools (convert_to_markdown and convert_pdf_to_markdown) signal composition issues. Parameter descriptions are generic and fail to guide LLM reasoning. No documentation of pagination, result limits, or response structures.
Alias for convert_to_markdown. Same one-step workflow for Supported formats: PDF, DOC, DOCX, PPT, PPTX, PNG, JPG, JPEG, HTML.
One-step document conversion. Purpose: Submit URL, poll until done, return download link. Constraints: Supported formats: PDF, DOC, DOCX, PPT, PPTX, PNG, JPG, JPEG, HTML. Auto-configures model and OCR. Side effect: Creates task and polls MinerU API. Use for quick conversion.
Create a document parsing task on MinerU API. Purpose: Submit a document URL for async conversion. Returns task_id for tracking. Constraints: Supported formats: PDF, DOC, DOCX, PPT, PPTX, PNG, JPG, JPEG, HTML only. Side effect: Calls MinerU API.
Get the download URL for a completed parsing result. Purpose: Return the zip URL from get_task_status. After calling, download with curl to ./temp/ and unzip: curl -L -o ./temp/<name>.zip "<zip_url>" --retry 3 -f -s -S && unzip -o ./temp/<name>.zip -d ./temp/<name>. No side effect.
Check the status of a document parsing task. Purpose: Poll task progress and get download URL when done. Provide task_id (URL) or batch_id (file upload). Returns state and full_zip_url. Side effect: Read-only API call.
Duplicate tools: convert_to_markdown and convert_pdf_to_markdown perform identical tasks with identical schemas. This violates the composition principle (one tool per responsibility) and forces LLMs to waste reasoning deciding between them.
Output schemas completely undocumented. create_parse_task returns a task_id but the response structure is never specified. get_task_status returns 'state and full_zip_url' in prose but no formal schema. LLMs cannot plan downstream calls or extract required fields. Violates pattern:tool which mandates documented return types.
Missing enum constraints on model_version parameter. Both create_parse_task and convert_to_markdown accept 'model_version' with default 'vlm' and a note that 'MinerU-HTML' is used for HTML. The valid set is not enumerated, LLMs may hallucinate other values like 'gpt-4' or 'claude-3'.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 50 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 43 | - | v1 |
download_result description instructs users to manually run curl and unzip commands ('curl -L -o ./temp/<name>.zip...'), but MCP tools should handle this internally. The description is procedural rather than declarative, violating the chat data model principle. Tool should download and unzip automatically, returning the extracted path.
No pagination or result limits documented. Tools accept async polling but max_wait_seconds and poll_interval parameters lack constraints (min/max values). No guidance on what happens if conversion takes >5 minutes (the default timeout). Baseline requires documenting limits and pagination.
Error handling is absent from tool definitions. No recovery guidance provided. Descriptions mention constraints (supported formats, file size, page limits from FileValidator class) but tools do not specify error conditions or recovery actions. Violates pattern:recovery-guide which requires actionable error messages.
Parameter descriptions lack format specifications. 'url' parameter accepts 'URL of the document' but does not specify HTTP/HTTPS only, URL length limits, or behavior for redirects. 'poll_interval' is a number with default 10 but no min/max bounds stated in description (code shows it's seconds, not milliseconds). Violates param-validation-rules.
Mutually exclusive parameters not documented. get_task_status accepts both 'task_id' and 'batch_id' but description does not state they are mutually exclusive or what happens if both/neither are provided. Baseline requires explicit mutual exclusivity documentation.
No dependency hints or discovery guidance. Descriptions do not explain the required sequence: create_parse_task → get_task_status (poll) → download_result. Users/LLMs must infer this workflow. Baseline requires: 'If you only have a name, call search_users() first.' This server should state: 'Call create_parse_task first, then poll get_task_status until state=completed, then call download_result.'
Inconsistent parameter naming. create_parse_task uses 'is_ocr' and 'enable_formula', but if other tools were added they might use 'ocr_enabled' or 'formula_enabled'. Parameter naming should be consistent across related tools to reduce LLM confusion.