Doc To Markdown MCP Server
Pricing
Pay per usage
Doc To Markdown MCP Server
An MCP server that converts documents to clean Markdown. Convert PDFs, Word docs, Excel spreadsheets, PowerPoints, HTML, images, and more to AI-friendly Markdown format.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
1
Bookmarked
4
Total users
1
Monthly active users
8 days ago
Last modified
Categories
Share
Document to Markdown MCP Server: Convert Files and Web Pages into Clean Markdown
This actor is a Model Context Protocol (MCP) server that turns documents into clean Markdown text so an AI agent, chatbot, or script can read them directly. Point it at a PDF, Word file, PowerPoint deck, Excel sheet, HTML page, image, audio file, or one of a dozen other formats, and it hands back Markdown, plus an optional metadata header and table of contents. Start a run, connect an MCP client to that run's own web server, and it answers requests over HTTP and MCP for as long as the run stays active. It can convert one document at a time or up to 20 at once in a single batch call.
Why This Scraper?
- Nine MCP tools, one server. Convert a single URL, a single file already stored in the actor's Key-Value Store, raw HTML, or base64 content, plus batch tools that convert up to 20 URLs or files at once.
- 15+ formats. PDF, Word, PowerPoint, Excel, RTF, HTML, XML, JPEG, PNG, GIF, BMP, WAV, MP3 (with speech transcription), CSV, JSON, YAML, and ZIP archives with recursive extraction.
- Runs as a normal Actor run. Each run serves HTTP and MCP requests on its own container for as long as it stays active (up to the run's timeout), rather than starting a fresh run per document.
- Formatting controls. Turn the metadata header and table of contents on or off per call, and choose ATX or Setext (levels 1 and 2 only) heading style.
- Batch calls don't stop at the first bad file. A batch call reports which documents converted and which failed, with a per-document error message, instead of aborting the whole batch.
- No dataset, no export step. Every tool hands the Markdown straight back in its own response; there is nothing to download afterward.
- Works with any MCP client. Point an AI agent, a chatbot, or the Apify MCP proxy at the run's own URL and call the tools directly.
Use Cases
- AI agent builders: turn a retrieved PDF, slide deck, or spreadsheet into Markdown context an LLM can read directly, without a separate parsing step.
- Documentation and migration teams: batch-convert a folder of legacy Word and PowerPoint files into Markdown for a docs site or wiki.
- Research and analysis workflows: strip a report or web page down to clean text before summarizing or indexing it.
- RAG pipeline builders: normalize mixed-format source documents, PDF, HTML, Excel, into one consistent Markdown shape before embedding.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
| Field | Example |
|---|---|
filename | "sample-report.pdf" |
format | "pdf" |
size | "20480 bytes" |
conversion_time | "340ms" |
extracted_at | "2024-01-01T00:00:00" |
modified_time | "2024-01-01T00:00:00" |
content_type | "application/pdf" |
last_modified | "Mon, 01 Jan 2024 00:00:00 GMT" |
etag | "\"sample-etag\"" |
format_description | "Portable Document Format" |
total | 3 |
successful | 2 |
failed | 1 |
url | "https://example.com/sample-report.pdf" |
content_length | "20480" |
status_code | 200 |
key | "report.pdf" |
size_bytes | 20480 |
type | "str" |
error | "File not found: report.pdf" |
None of these come back as separate JSON fields from a conversion call. A single conversion tool returns one Markdown-formatted text block: a metadata header line for each field above that it managed to fill in (filename, format, size, conversion_time, extracted_at, modified_time, and, for a URL source, content_type, last_modified, etag; format and format_description both appear again from a second, overlapping metadata pass), then the converted content. A failed single conversion returns plain text (Error converting <name>: <reason>) instead. A batch tool wraps several of those blocks inside one summary block (# Batch Conversion Results, then Total/Successful/Failed counts, then one Document N: <name> section per input with its own Status line, and either its metadata block and markdown or its own error). extract_metadata is the only tool that returns a plain JSON object instead of text: url/content_type/content_length/last_modified/etag/status_code for a URL, or key/format/size_bytes/type for a Key-Value Store key, or just error if that key doesn't exist.
How to Use
- Start the actor. No Run input is required, you can leave every field empty, since document conversion is not driven by this input form.
- Open the run's own Container URL (shown on the run's Overview tab in the Apify Console once it is running) and add
/mcpto it. - Connect an MCP-compatible client, an AI agent, a chatbot, or the Apify MCP proxy, to that URL with your Apify token, then call one of the tools listed under Input Parameters, for example
convert_url_to_markdown, with the document you want converted. - Read the Markdown straight out of the tool's response. Nothing is written to a dataset, so there is no separate export or download step. The run keeps serving requests until you abort it or it reaches its own timeout, so start a fresh run once that happens.
The Run input below is optional and this build never reads it, every conversion happens through the MCP tool calls in step 3, so most users leave it empty.
Leave it empty (recommended for MCP usage):
{}
Pre-fill a URL, kept for schema completeness only, this build does not read it:
{"urls": ["https://example.com/sample-report.pdf"]}
Pre-fill the default output formatting, also kept for schema completeness only:
{"outputOptions": {"include_metadata": true,"include_toc": false,"heading_style": "atx"}}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/doc-to-markdown-mcp").start()print(run["containerUrl"])# The run never finishes on its own, it just keeps serving requests until its# timeout, so do not call() and wait on it. Point an MCP client at# run["containerUrl"] + "/mcp" with your Apify token instead.
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/doc-to-markdown-mcp').start();console.log(run.containerUrl);// The run never finishes on its own, it just keeps serving requests until its// timeout, so do not call() and wait on it. Point an MCP client at// `${run.containerUrl}/mcp` with your Apify token instead.
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
files | array | none | Optional file uploads, stored in the actor's Key-Value Store. This build does not read this field to trigger a conversion, it is a placeholder for a possible future non-MCP batch mode. |
urls | array | none | Optional list of document URLs. Like files, this build does not read this field either, conversions happen through the MCP tool calls below, not this input form. |
outputOptions | object | {"include_metadata": true, "include_toc": false, "heading_style": "atx"} | Optional. Mirrors the include_metadata, include_toc, and heading_style arguments the MCP tools accept, kept here for schema completeness; it is not applied automatically to a run. |
Note: the Apify Console's own input form for this actor currently shows three different fields (default include-metadata, default include-TOC, default heading style) rather than the ones above. Neither that form nor the fields documented here are read by this build; every conversion happens only through the MCP tool calls below, and the Run input can always be left empty.
Calling the MCP tools directly
Once connected, call any of these 9 tools with their own arguments, separate from the Run input above:
convert_url_to_markdown(url, include_metadata, include_toc, heading_style, table_format, image_handling): download one document from a URL and convert it.table_formatandimage_handlingare accepted but currently have no effect on the output.convert_file_to_markdown(key, store_name, include_metadata, include_toc): convert one file already stored in an Apify Key-Value Store.convert_base64_to_markdown(content, filename, include_metadata, include_toc): convert a document sent as base64 text.convert_html_to_markdown(html, include_metadata, include_toc): convert a raw HTML string.batch_convert_urls(urls, include_metadata, include_toc): convert up to 20 URLs in parallel; anything beyond the first 20 is silently dropped, not reported as failed.batch_convert_files(keys, store_name, include_metadata, include_toc): convert up to 20 Key-Value Store files in parallel; anything beyond the first 20 is silently dropped, not reported as failed.extract_metadata(url, key): return size, content type, and last-modified date without converting. Unlike the conversion tools above, an unreachable URL here can surface as a protocol-level tool error rather than a normal response.get_supported_formats(): list every supported file format.get_output_options(): list the formatting options, includingtable_formatandimage_handling, which are listed here but currently do nothing.
Example call to convert_url_to_markdown:
{"url": "https://example.com/sample-report.pdf","include_metadata": true,"include_toc": false,"heading_style": "atx"}
Output Example
Sample shape: values are illustrative placeholders, not from a live record.
{"content": [{"type": "text","text": "---\nfilename: sample-report.pdf\nformat: pdf\nsize: 20480 bytes\nconversion_time: 340ms\nextracted_at: 2024-01-01T00:00:00\nmodified_time: 2024-01-01T00:00:00\ncontent_type: application/pdf\nlast_modified: Mon, 01 Jan 2024 00:00:00 GMT\netag: \"sample-etag\"\nformat: PDF\nformat_description: Portable Document Format\n---\n\n# Sample Report\n\nThis is a sample paragraph converted from the source file."}],"structuredContent": {"result": "---\nfilename: sample-report.pdf\nformat: pdf\nsize: 20480 bytes\nconversion_time: 340ms\nextracted_at: 2024-01-01T00:00:00\nmodified_time: 2024-01-01T00:00:00\ncontent_type: application/pdf\nlast_modified: Mon, 01 Jan 2024 00:00:00 GMT\netag: \"sample-etag\"\nformat: PDF\nformat_description: Portable Document Format\n---\n\n# Sample Report\n\nThis is a sample paragraph converted from the source file."},"isError": false}
This is a URL conversion, so it carries content_type, last_modified, and etag; a file, base64, or HTML conversion leaves those out. format appears twice, once from the conversion result itself and once from a second metadata pass; both are shown as-is above rather than de-duplicated. Newer MCP client libraries also add a structuredContent field mirroring the same text, shown above; older ones only return content.
Plan Requirement
This actor takes no proxy configuration, there is not one in its input, so there is nothing to pick under Connection. Billing is a charge each time the actor starts (it scales with the memory you give it), plus a small charge for anything written to the dataset (this actor never writes to one, so that charge does not apply in practice). It is not a per-document or per-field charge. Check the Pricing tab on the actor page for the current rates.
FAQ
How much does it cost?
You pay a charge each time the actor starts, which scales with how much memory you give it, shown on the Pricing tab. There is no per-document charge, and no dataset charge in practice since this actor never writes to a dataset.
Is it legal to convert a document I don't own the rights to?
This actor only converts the file or page you give it; it does not search for or discover documents on its own. You are responsible for how you use it: only feed it documents you have the rights or permission to process, and check the source document's own license or copyright terms before you redistribute the converted output.
Why doesn't anything happen when I start a run without connecting an MCP client?
The Run input fields (files, urls, outputOptions) are optional and this build does not read them. Nothing converts until an MCP client connects to that run's own URL and calls one of the tools listed under Input Parameters. Starting the actor on its own just brings the server online and waiting, until the run's timeout is reached.
What happens if a document fails to convert?
For the four conversion tools and the two batch tools, a failed conversion, an unreachable URL, a missing Key-Value Store key, or an unsupported or corrupted file, is caught and returned in the same tool response as an error message naming the file and the reason, rather than raised as a protocol-level error, and does not fail the run. A batch call keeps going after a failed document and reports per-document success and failure counts instead of stopping. extract_metadata, which does not convert anything, does not have the same protection for an unreachable URL and can surface a protocol-level tool error instead. A corrupted file that still looks like a valid one of its type is not always caught; some corrupted input converts without an error into unreadable output rather than failing outright.
Can I use this with AI agents or other MCP clients?
Yes. This actor is itself an MCP server: connect any MCP-compatible client, an agent framework, a chatbot, or the Apify MCP proxy, to that run's own URL and call the tools directly.
🔗 Want more travel data?
Pair this actor with these related scrapers from the same team:
| 🤖 Doc To Markdown Convert documents (PDF, Word, PowerPoint, Excel, HTML, images) to clean Markdown... | 🏨 Airbnb Scraper Scrape Airbnb stays by destination or link: nightly and total price, rating breakdown... |
| 🏨 Yanolja Scraper Scrape Yanolja (NOL), Korea's largest accommodations marketplace, by region or URL. Every... | 🏨 Klook Scraper Scrape Klook activities, tours, attractions and travel experiences from search pages or... |
| 🏨 Rover Pet Care Scraper Scrape Rover.com pet-care providers: sitter search by city, rates per stay type, ratings... | 🏨 Vrbo Scraper Extract vacation rental data from Vrbo.com by location, region, coordinates, property... |
💬 Support
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.