Dev.to AI πŸ€– Ai πŸ‘ 0 πŸ“– 5 min read

MCP server for document and media tools - give Claude or Cursor OCR, PDF and audio tools

An AI agent is good at reading text, but a lot of real work arrives as files: a scanned invoice, a spreadsheet, a voice note, a website that has to be checked. The Model Context Protocol (MCP) lets an agent call tools fo

An AI agent is good at reading text, but a lot of real work arrives as files: a scanned invoice, a spreadsheet, a
voice note, a website that has to be checked. The Model Context Protocol (MCP) lets an agent call tools for that. This
post shows one MCP server that gives Claude, Cursor or any other MCP client nine such tools, and what two of them
returned when an MCP client called them on 15 November 2026.

Disclosure: I built this server and the Apify Actors behind it. The code is open (MIT):
AndriyVK/-apify-document-tools.

The tools

Tool What it does Price (billed by Apify)
convert_document_to_markdown PDF (text and scanned, OCR), images, DOCX/DOC, XLSX/XLS, PPTX/PPT, ODT, RTF, HTML to Markdown, JSON tables, RAG chunks $1 / 1,000 text pages, $4 / 1,000 OCR pages
convert_office_to_pdf Word, Excel, PowerPoint, OpenDocument, RTF, HTML, images to PDF or PDF/A-2b, optional merge $10 / 1,000 documents
convert_pdf_or_images PDF pages to PNG/JPG/WebP/TIFF, images to PDF, iPhone HEIC to JPG, resize $2 / 1,000 images
transcribe_audio Audio and video to text, timestamped segments, SRT/VTT (Whisper large-v3) $5 / 1,000 minutes
ocr_images Images and scanned PDFs to text, lines with confidence and boxes $1.50 / 1,000 images
text_to_speech Text or PDF/DOCX/HTML to MP3/WAV/OGG plus SRT subtitles $10 / 1,000 audio minutes
screenshot_website Full-page screenshots or PDF of web pages or your own HTML $4 / 1,000 pages
check_domains WHOIS/RDAP (registrar, expiry), DNS records, SSL certificate expiry $2 / 1,000 domains
extract_video_frames Video to frames with timecodes, scene changes, contact sheet $1 / 1,000 frames

Every tool takes public file URLs and a max_charge_usd limit per call (default $1), so an agent in a loop cannot
spend more than you allow.

Set it up

The server is a small Python program that runs the Actors with your own Apify token:

git clone https://github.com/AndriyVK/-apify-document-tools
cd -- -apify-document-tools/mcp-server
pip install -r requirements.txt

Then add it to your MCP client. For Claude Desktop or Cursor the config looks like this:

{
  "mcpServers": {
    "document-tools": {
      "command": "python",
      "args": ["/path/to/-apify-document-tools/mcp-server/server.py"],
      "env": { "APIFY_TOKEN": "<YOUR_APIFY_TOKEN>" }
    }
  }
}

The token is in Apify Console, Settings, API & Integrations. New Apify accounts get a free monthly usage credit.

A real session

To show exactly what an agent receives, I called the server from a plain Python MCP client (the official mcp
package, stdio transport), the same way Claude Desktop does it:

import asyncio, sys
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

async def main():
    server = StdioServerParameters(command=sys.executable, args=["server.py"],
                                   env={"APIFY_TOKEN": "<YOUR_APIFY_TOKEN>"})
    async with stdio_client(server) as (read, write):
        async with ClientSession(read, write) as s:
            await s.initialize()
            print([t.name for t in (await s.list_tools()).tools])
            r = await s.call_tool("convert_document_to_markdown", {
                "urls": ["https://api.apify.com/v2/key-value-stores/FloomuI2DrQCJazY8/records/scan-uk.pdf"],
                "ocr_languages": ["ukr"], "max_charge_usd": 0.2})
            print(r.content[0].text)

asyncio.run(main())

The server answered as apify-document-tools 0.3.0 and listed all nine tools.

Call 1: a scanned Ukrainian page to Markdown

The input is a one-page scan with no text layer (a delivery report with a small table). The call took 8.6 seconds
from the client's side, of which the conversion itself was 0.68 s; the rest is starting the run on Apify. The agent
got this back (shortened):

{
  "fileName": "scan-uk.pdf",
  "sourcePages": 1,
  "textPages": 0,
  "ocrPages": 1,
  "warnings": [],
  "characters": 300,
  "tables": [[["Π’ΠΎΠ²Π°Ρ€", "ΠšΡ–Π»ΡŒΠΊΡ–ΡΡ‚ΡŒ", "Π¦Ρ–Π½Π°"],
              ["Π¦Π΅ΠΌΠ΅Π½Ρ‚", "420", "96,50"],
              ["Арматура", "180", "412,00"]]],
  "markdown": "Π—Π²Ρ–Ρ‚ ΠΏΡ€ΠΎ постачання\n\nΠ‘ΠΊΠ»Π°Π΄ Ρƒ Π›ΡŒΠ²ΠΎΠ²Ρ– ΠΎΡ‚Ρ€ΠΈΠΌΠ°Π² 1240 ΠΏΠ°Π»Π΅Ρ‚ Π±ΡƒΠ΄Ρ–Π²Π΅Π»ΡŒΠ½ΠΈΡ… ΠΌΠ°Ρ‚Π΅Ρ€Ρ–Π°Π»Ρ–Π² протягом\n\nΡ‚Ρ€Π΅Ρ‚ΡŒΠΎΠ³ΠΎ ΠΊΠ²Π°Ρ€Ρ‚Π°Π»Ρƒ. ..."
}

Two things matter for an agent here. First, ocrPages: 1 and textPages: 0 tell it the text came from OCR, so it
knows how far to trust it. Second, the table comes back twice: as a Markdown table inside the text and as rows of
cells in tables, so the agent can do arithmetic on it without parsing Markdown.

One small flaw is visible: the OCR split one sentence into two paragraphs (протягом\n\nΡ‚Ρ€Π΅Ρ‚ΡŒΠΎΠ³ΠΎ). For an LLM this does
not change the meaning, but if you index the text for search, join lines inside paragraphs first.

Call 2: check two domains

check_domains with ["andriyvk.github.io", "dev.to"] took 4.6 seconds. For each domain the agent gets the
registration (registrar, created and expiry dates, days left), DNS records and the SSL certificate. A shortened piece:

{
  "domain": "andriyvk.github.io",
  "registrableDomain": "github.io",
  "registration": {"source": "whois", "registrar": "MarkMonitor Inc.", "expiresDate": "2027-03-08", "daysUntilExpiry": 113},
  "dns": {"A": ["185.199.108.153", "185.199.109.153", "185.199.110.153", "185.199.111.153"], "MX": []},
  "ssl": {"valid": true, "protocol": "TLSv1.3", "issuer": "Let's Encrypt", "validTo": "2026-12-29", "daysLeft": 44}
}

Note registrableDomain: for a subdomain the registration data is that of the parent domain (github.io), and the
result says so instead of pretending the subdomain has its own WHOIS record. For dev.to the data came from RDAP
(registrar Tonic, expires 2027-04-05), with SPF and DMARC records parsed out of TXT.

Price

For a buyer the two calls above cost:

  • scan to Markdown: 1 OCR page $0.004 plus run starts $0.0001 = $0.0041;
  • two domains: 2 x $0.002 plus a run start $0.00005 = $0.00405.

About eight tenths of a cent together. You pay Apify at the Actors' prices; the MCP server itself is free and adds no
fee.

Limits

  • Files must be reachable by a public URL. A local file has to be uploaded somewhere first (for example to an Apify key-value store).
  • Each call is a synchronous Actor run, and Apify keeps such a run open for at most 300 seconds. A long video or a big folder needs to be split into several calls.
  • OCR quality depends on the scan. The result says how many pages went through OCR, but it does not check the text against the original.
  • Apify also offers a hosted MCP endpoint with the same Actors (https://mcp.apify.com?tools=ai_admin/document-to-markdown,..., full list in the README). I did not test it for this post; the session above is the local server.

Related posts

Originally published at andriyvk.github.io.

πŸ“° Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.