Cross-language S3 file side-channel for remote MCP servers, plus a reusable self-hosted OAuth provider, MCP-Apps upload widget, and convert-on-upload broker route.
Server exhibits significant definition quality gaps. Tool descriptions are verbose and context-heavy (200-400+ chars) rather than LLM-optimized (50-200 chars baseline). Multiple tools share identical names (upload_file, convert) across different examples, creating ambiguity. Input schemas are present but lack proper type constraints and enums. Parameter descriptions are often narrative rather than constraint-focused. No output schemas documented. Error handling guidance absent. Tool composition violates single-responsibility principle (e.g., convert handles both upload-wait and conversion in one call).
Convert the file the user uploaded via `upload_file` (identified by `src_key`) to `target` (e.g. "pdf", "docx", "mobi"). The right converter is chosen automatically — do NOT guess a `tool`. `filename` is the real source filename (the widget passes it); it sets the output name so MyBook.epub → MyBook.mobi. Leave it empty and the name is taken from the upload key. Call this IMMEDIATELY after `upload_file` — do NOT wait for another user message. It BLOCKS until the user finishes uploading (up to ~55s) and then converts automatically, so the user only has to pick the file. If it reports the upload hasn't arrived yet, the user is still picking — just call convert again.
Convert the file the user uploaded via `upload_file` (identified by `src_key`) to Markdown with IBM Docling (layout, tables, reading order, OCR). Waits for the upload to land, then hands Docling a presigned URL for it. Reuses a prior conversion. Returns a context-safe preview + a clickable download link + `md_key` (use read_markdown to page). `target`/`filename` are accepted for widget compatibility and ignored. Call this right after upload_file — the widget auto-drives it.
List the `format,tool` pairs ConvertX can convert `file_type` into.
Read a byte slice [offset, offset+limit) of an already-converted document (md_key from convert), with next_offset — page large Docling exports without loading them all into context.
Duplicate tool names across examples (upload_file appears 3 times, convert appears 2 times). LLMs cannot disambiguate which variant to call. Violates naming clarity principle.
Descriptions are narrative and context-heavy (200-400+ chars) rather than constraint-focused. E.g., convert description is 500+ chars explaining widget behavior, upload mechanics, and retry logic. Should be 50-150 chars stating WHAT, WHEN, and WHAT IT RETURNS.
No output schemas documented. LLMs cannot plan downstream calls or extract required fields (e.g., what does convert return? md_key? download_url? preview?). Violates response-shaper pattern.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 50 | 2025-06-18+ | v2 |
Convert an uploaded file to Markdown using markitdown. Stage the file locally, run markitdown, and return inline markdown or a presigned download link for large results.
Offer for a source file — wired to the widget. src_key carries the real filename.
The upload offer for a source file — wired to the widget. The key carries the REAL filename so the converted output keeps the same stem (MyBook.epub → MyBook.mobi). Returns the full offer (agent PUT url + human /u/ link + src_key).
MCP-Apps inline upload widget tool for markdownify — renders a file picker in claude.ai/ChatGPT.
Tool composition violates single-responsibility. convert() combines upload-wait (blocking up to 55s) + conversion + result retrieval in one call. Should split into separate tools: wait_upload, do_convert, get_result.
No error handling guidance. Descriptions mention 'upload hasn't arrived yet' but do not explain what error code/message the LLM receives or how to recover. No retry guidance, no actionable error messages.