agentmd-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@agentmd-mcpconvert this URL to markdown and keep the tables"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
agentmd-mcp
MCP server for AgentMD — convert PDF, DOCX, HTML, and URLs into clean, LLM-ready markdown, with tables preserved and web-page boilerplate stripped.
Agents ingest documents constantly, and most document formats are hostile to language models. This gives your agent three tools that turn any of them into markdown it can actually read.
Install
Get a free API key (50 conversions, no card) at https://www.getagentmd.com — or fully programmatically:
curl -X POST https://www.getagentmd.com/api/v1/keys/free \
-H "Content-Type: application/json" -d '{"email": "you@example.com"}'Then:
Claude Code
claude mcp add agentmd --env AGENTMD_API_KEY=<your-key> -- npx -y agentmd-mcpAny MCP client (mcp.json / claude_desktop_config.json):
{
"mcpServers": {
"agentmd": {
"command": "npx",
"args": ["-y", "agentmd-mcp"],
"env": { "AGENTMD_API_KEY": "<your-key>" }
}
}
}Docker
docker build -t agentmd-mcp .
docker run -i --rm -e AGENTMD_API_KEY=<your-key> agentmd-mcpThe image runs the stdio server, so pass -i; the API key is supplied at run time with -e rather than baked into the image. To wire the container into an MCP client:
{
"mcpServers": {
"agentmd": {
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "AGENTMD_API_KEY", "agentmd-mcp"],
"env": { "AGENTMD_API_KEY": "<your-key>" }
}
}
}Remote (no install) — the hosted server speaks streamable HTTP directly:
claude mcp add --transport http agentmd https://www.getagentmd.com/api/mcp \
--header "Authorization: Bearer <your-key>"Related MCP server: Markitdown MCP Server
Tools
Tool | Use it for |
| A web page or a document at an http(s) URL |
| A document on the local filesystem, by path |
| Document bytes you already hold, as base64 |
All three return markdown, prefixed with the detected title and any warnings.
Supported formats
PDF — text extraction (scanned/image-only PDFs return a warning; OCR is on the roadmap)
DOCX — headings, lists, and tables preserved
HTML / URLs — main-article extraction, GFM tables, links resolved to absolute URLs
Markdown / plain text — normalized passthrough
Limit: 25 MB per document.
Configuration
Variable | Required | Purpose |
| yes | Your API key |
| no | Point at a different deployment (self-hosting, staging) |
Pricing
First 50 conversions free (per email, no card). After that, $0.002 per successful conversion, billed monthly. No per-seat licensing — you pay for calls your agents actually make.
License
MIT (this client shim). The hosted service has its own terms.
Available Tools
3 toolsconvert_document_to_markdownConvert document bytes to markdownARead-onlyInspect
Converts base64-encoded document bytes that you already hold into clean, LLM-ready markdown, without reading a file or fetching a URL. Use this instead of convert_file_to_markdown when the bytes came from somewhere other than this machine's filesystem (an upload, an earlier tool result, memory), and instead of convert_url_to_markdown when there is no fetchable link to the source. Returns one markdown text block: the detected title as a leading # <title> line when one is found, a > Warnings: ... blockquote line when the converter reports warnings, and tables preserved as GFM. Supported formats are PDF, DOCX, HTML, Markdown, and plain text, up to 25 MB per document — base64 inflates the payload by about a third, so prefer convert_file_to_markdown or convert_url_to_markdown for large files — and PDFs are text-extraction only, so scanned or image-only PDFs yield little or no text (OCR is not available yet). Requires AGENTMD_API_KEY; on a 401, a network failure, malformed base64, or an unsupported format it returns an isError result whose text explains what went wrong. Each successful call consumes one conversion from the account quota. To read only part of a large document, use the optional pages (PDF page ranges), mode: 'outline' then section, and maxTokens parameters instead of pulling the whole thing into context.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | "full" (default) returns the document body. "outline" returns just the heading tree — each line is `- [#3] Heading text (~120 tokens)`. For a long document, call with mode: 'outline' first, then fetch only what you need with section: '#3' or a heading title. | |
| pages | No | PDFs only: 1-indexed, inclusive page ranges to convert, e.g. "1-3,5,8-" (an open-ended range runs to the last page). Ignored with a warning for non-PDF formats. | |
| base64 | Yes | The document's full contents encoded as standard base64 (RFC 4648: A-Z a-z 0-9 + / with = padding). Pass the encoded string on its own — no `data:` URI prefix, no media type, no surrounding quotes. | |
| section | No | Return only one section: either "#<n>" using the index from a mode: 'outline' call (e.g. '#3'), or the heading text itself (case-insensitive; exact match wins, then prefix, then substring). Ignored when mode is 'outline'. | |
| filename | No | Original filename including its extension, e.g. report.pdf or notes.docx. Used for format detection when the bytes alone are ambiguous (HTML vs. Markdown vs. plain text) and to seed the document title. Optional, but supplying it makes detection markedly more reliable. | |
| maxTokens | No | Cap the returned markdown at roughly this many tokens, cutting at a paragraph boundary. When the output is cut, the result starts with a `> Truncated: ~X of ~Y tokens` line — narrow with pages or section rather than raising this. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds substantial behavioral context beyond that: PDFs are text-extraction only with no OCR, base64 inflates payload by a third, each successful call consumes quota, requires AGENTMD_API_KEY, and error conditions (401, network failure, malformed base64, unsupported format) return an isError result. It also discloses the return format (title line, warnings blockquote, GFM tables). The only minor gap is not detailing pagination or rate-limit specifics, but the description carries far more than the annotations require.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence earns its place: purpose, sibling routing, format/limits, error behavior, quota, and partial-read strategy. It is front-loaded with the core purpose and the most important caveats (base64 inflation, PDF text-only) before the error and quota details. It is long, but the tool is complex (6 params, 2 siblings, multiple formats, error modes), so the length is justified. Slightly tighter grouping of the error/quota sentence would push it to 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 6 parameters, 2 siblings, no output schema, and multiple behavioral caveats, the description covers everything an agent needs to call it correctly: when to use it, what formats are supported, size limits, error behavior, quota consumption, return format, and a strategy for partial reads. The absence of an output schema is compensated by the description explicitly stating the return shape (title line, warnings blockquote, GFM tables, truncation line). Nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all six parameters thoroughly. The description adds value by explaining the strategic relationship between parameters (use mode:'outline' first, then section; narrow with pages or section rather than raising maxTokens) and by warning that pages is ignored with a warning for non-PDFs. It doesn't restate the schema; it layers usage strategy on top. A 4 is warranted because the description meaningfully enriches parameter understanding beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb ('Converts'), a precise resource ('base64-encoded document bytes that you already hold'), and an explicit outcome ('into clean, LLM-ready markdown'). It immediately distinguishes itself from both siblings by naming them and stating the exact condition that selects this tool over them. This is a model of purpose clarity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use this tool instead of convert_file_to_markdown (bytes came from somewhere other than this machine's filesystem) and instead of convert_url_to_markdown (no fetchable link). It also gives a concrete alternative for large files (prefer the siblings because base64 inflates payload by ~1/3) and for partial reads (use pages, mode:'outline', section, maxTokens). This is comprehensive routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
convert_file_to_markdownConvert a local file to markdownARead-onlyInspect
Reads a document from the local filesystem by absolute path and converts it to clean, LLM-ready markdown. Use this instead of convert_url_to_markdown when the document is already saved on disk, and instead of convert_document_to_markdown when you have a path and would otherwise have to read and base64-encode the bytes yourself — this tool does that reading and encoding for you. Returns one markdown text block: the detected title as a leading # <title> line when one is found, a > Warnings: ... blockquote line when the converter reports warnings, and tables preserved as GFM. Supported formats are PDF, DOCX, HTML, Markdown, and plain text, up to 25 MB per document; PDFs are text-extraction only, so scanned or image-only PDFs yield little or no text (OCR is not available yet). Requires AGENTMD_API_KEY; on a missing or unreadable file, a 401, a network failure, or an unsupported format it returns an isError result whose text explains what went wrong. Each successful call consumes one conversion from the account quota. To read only part of a large document, use the optional pages (PDF page ranges), mode: 'outline' then section, and maxTokens parameters instead of pulling the whole thing into context.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | "full" (default) returns the document body. "outline" returns just the heading tree — each line is `- [#3] Heading text (~120 tokens)`. For a long document, call with mode: 'outline' first, then fetch only what you need with section: '#3' or a heading title. | |
| path | Yes | Absolute path to the document on the filesystem of the machine running this MCP server, not the client machine (e.g. /home/me/docs/report.pdf or C:\\docs\\report.pdf). The file is read locally and its bytes are sent to the AgentMD API; the basename is used for format detection, so keep the file extension. | |
| pages | No | PDFs only: 1-indexed, inclusive page ranges to convert, e.g. "1-3,5,8-" (an open-ended range runs to the last page). Ignored with a warning for non-PDF formats. | |
| section | No | Return only one section: either "#<n>" using the index from a mode: 'outline' call (e.g. '#3'), or the heading text itself (case-insensitive; exact match wins, then prefix, then substring). Ignored when mode is 'outline'. | |
| maxTokens | No | Cap the returned markdown at roughly this many tokens, cutting at a paragraph boundary. When the output is cut, the result starts with a `> Truncated: ~X of ~Y tokens` line — narrow with pages or section rather than raising this. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description goes well beyond that: it discloses the AGENTMD_API_KEY requirement, error behaviors (missing file, 401, network failure, unsupported format returning an isError result), quota consumption per call, the 25 MB size limit, and the PDF text-extraction-only limitation with no OCR. This is exactly the kind of behavioral context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but nearly every clause earns its place — the information density is high and there is minimal fluff. Core purpose and sibling routing are front-loaded before constraints, error handling, and optimization guidance. It could arguably be split, but as a single block it reads logically and never repeats what the schema already states.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 5 parameters, an output schema that does not exist, error handling, format constraints, and partial-read options, this description is essentially complete. It explains the return format (title line, warnings blockquote, GFM tables, truncation header), supported formats, size limit, OCR limitation, auth requirement, quota impact, and error semantics — nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning beyond the schema: it explains that pages is 'Ignored with a warning for non-PDF formats,' that maxTokens truncation adds a '> Truncated: ~X of ~Y tokens' header line and cuts at paragraph boundaries, and that mode: 'outline' produces a token-estimated heading tree for navigation. These behavioral nuances are not in the schema properties.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource — 'Reads a document from the local filesystem by absolute path and converts it to clean, LLM-ready markdown.' It immediately distinguishes itself from both siblings by naming convert_url_to_markdown and convert_document_to_markdown with the exact conditions that select each. An agent can tell this tool apart without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing guidance: 'Use this instead of convert_url_to_markdown when the document is already saved on disk, and instead of convert_document_to_markdown when you have a path and would otherwise have to read and base64-encode the bytes yourself.' It also advises when NOT to pull a whole document into context, directing agents to pages, mode: 'outline', and section for partial reads. This is model-grade usage direction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
convert_url_to_markdownConvert URL to markdownARead-onlyInspect
Fetches a document at an http(s) URL — web page, PDF, DOCX, HTML, Markdown, or plain text — and converts it to clean, LLM-ready markdown. Use this instead of convert_file_to_markdown when the document lives on the network rather than on the filesystem of the machine running this server, and instead of convert_document_to_markdown when you hold a link rather than the raw bytes; it is the only one of the three that fetches the source itself. Returns one markdown text block: the detected title as a leading # <title> line when one is found, a > Warnings: ... blockquote line when the converter reports warnings, tables preserved as GFM, and for web pages navigation and boilerplate stripped with relative links rewritten to absolute URLs. Limits: 25 MB per document, and PDFs are text-extraction only, so scanned or image-only PDFs yield little or no text (OCR is not available yet). Requires AGENTMD_API_KEY; on a 401, a network or fetch failure, or an unsupported format it returns an isError result whose text explains what went wrong. Each successful call consumes one conversion from the account quota. To read only part of a large document, use the optional pages (PDF page ranges), mode: 'outline' then section, and maxTokens parameters instead of pulling the whole thing into context.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Absolute http(s) URL of the page or document to fetch and convert, e.g. https://example.com/report.pdf. Must be publicly reachable from the AgentMD service; URLs behind a login, a paywall, or a private network will fail. | |
| mode | No | "full" (default) returns the document body. "outline" returns just the heading tree — each line is `- [#3] Heading text (~120 tokens)`. For a long document, call with mode: 'outline' first, then fetch only what you need with section: '#3' or a heading title. | |
| pages | No | PDFs only: 1-indexed, inclusive page ranges to convert, e.g. "1-3,5,8-" (an open-ended range runs to the last page). Ignored with a warning for non-PDF formats. | |
| section | No | Return only one section: either "#<n>" using the index from a mode: 'outline' call (e.g. '#3'), or the heading text itself (case-insensitive; exact match wins, then prefix, then substring). Ignored when mode is 'outline'. | |
| maxTokens | No | Cap the returned markdown at roughly this many tokens, cutting at a paragraph boundary. When the output is cut, the result starts with a `> Truncated: ~X of ~Y tokens` line — narrow with pages or section rather than raising this. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly and openWorld, but the description adds substantial behavior beyond that: 25 MB limit, PDF text-only extraction with OCR unavailable, API key requirement, error handling (isError on 401/failure), quota consumption, return format details (title, warnings, GFM tables, navigation stripping, relative links rewritten). This is rich, non-redundant context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Though long, every sentence carries unique information. It is front-loaded with purpose and sibling differentiation, then covers return format, limits, auth/errors, quota, and usage tips in a logical order. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter tool with no output schema, the description covers everything an agent needs: what it returns (title, warnings, tables, link rewriting), failure modes, limits, and how to use the parameters to avoid pulling entire large documents. The only minor omission is a concrete example of a warning, but that's not essential.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and each parameter already has a detailed description. The description goes further by explaining the intended workflow (outline first, then section) and the semantics of maxTokens ('narrow with pages or section rather than raising this'). That adds value beyond the schema, so a 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (fetch and convert), a resource (URL) and the output (clean markdown). It names both sibling tools and the exact condition that selects this one ('when the document lives on the network', 'when you hold a link'), making differentiation immediate without inspecting schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly gives when-to-use vs both alternatives and adds concrete usage guidance: start with mode:'outline', then fetch specific sections via pages/section/maxTokens. Also notes when not to use (local files or raw bytes). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.4- Changed
convert_document_to_markdown4 fields changed- added
Input schema / properties / maxTokensAdded value: +{ + "description": "Cap the returned markdown at roughly this many tokens, cutting at a paragraph boundary. When the output is cut, the result starts with a `> Truncated: ~X of ~Y tokens` line — narrow with pages or section rather than raising this.", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" +} - added
Input schema / properties / modeAdded value: +{ + "description": "\"full\" (default) returns the document body. \"outline\" returns just the heading tree — each line is `- [#3] Heading text (~120 tokens)`. For a long document, call with mode: 'outline' first, then fetch only what you need with section: '#3' or a heading title.", + "enum": [ + "full", + "outline" + ], + "type": "string" +} - added
Input schema / properties / pagesAdded value: +{ + "description": "PDFs only: 1-indexed, inclusive page ranges to convert, e.g. \"1-3,5,8-\" (an open-ended range runs to the last page). Ignored with a warning for non-PDF formats.", + "type": "string" +} - added
Input schema / properties / sectionAdded value: +{ + "description": "Return only one section: either \"#<n>\" using the index from a mode: 'outline' call (e.g. '#3'), or the heading text itself (case-insensitive; exact match wins, then prefix, then substring). Ignored when mode is 'outline'.", + "type": "string" +}
- Changed
convert_file_to_markdown4 fields changed- added
Input schema / properties / maxTokensAdded value: +{ + "description": "Cap the returned markdown at roughly this many tokens, cutting at a paragraph boundary. When the output is cut, the result starts with a `> Truncated: ~X of ~Y tokens` line — narrow with pages or section rather than raising this.", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" +} - added
Input schema / properties / modeAdded value: +{ + "description": "\"full\" (default) returns the document body. \"outline\" returns just the heading tree — each line is `- [#3] Heading text (~120 tokens)`. For a long document, call with mode: 'outline' first, then fetch only what you need with section: '#3' or a heading title.", + "enum": [ + "full", + "outline" + ], + "type": "string" +} - added
Input schema / properties / pagesAdded value: +{ + "description": "PDFs only: 1-indexed, inclusive page ranges to convert, e.g. \"1-3,5,8-\" (an open-ended range runs to the last page). Ignored with a warning for non-PDF formats.", + "type": "string" +} - added
Input schema / properties / sectionAdded value: +{ + "description": "Return only one section: either \"#<n>\" using the index from a mode: 'outline' call (e.g. '#3'), or the heading text itself (case-insensitive; exact match wins, then prefix, then substring). Ignored when mode is 'outline'.", + "type": "string" +}
- Changed
convert_url_to_markdown4 fields changed- added
Input schema / properties / maxTokensAdded value: +{ + "description": "Cap the returned markdown at roughly this many tokens, cutting at a paragraph boundary. When the output is cut, the result starts with a `> Truncated: ~X of ~Y tokens` line — narrow with pages or section rather than raising this.", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" +} - added
Input schema / properties / modeAdded value: +{ + "description": "\"full\" (default) returns the document body. \"outline\" returns just the heading tree — each line is `- [#3] Heading text (~120 tokens)`. For a long document, call with mode: 'outline' first, then fetch only what you need with section: '#3' or a heading title.", + "enum": [ + "full", + "outline" + ], + "type": "string" +} - added
Input schema / properties / pagesAdded value: +{ + "description": "PDFs only: 1-indexed, inclusive page ranges to convert, e.g. \"1-3,5,8-\" (an open-ended range runs to the last page). Ignored with a warning for non-PDF formats.", + "type": "string" +} - added
Input schema / properties / sectionAdded value: +{ + "description": "Return only one section: either \"#<n>\" using the index from a mode: 'outline' call (e.g. '#3'), or the heading text itself (case-insensitive; exact match wins, then prefix, then substring). Ignored when mode is 'outline'.", + "type": "string" +}
3 tool updates
v0.1.0- First observed
convert_document_to_markdown - First observed
convert_file_to_markdown - First observed
convert_url_to_markdown
TDQS
Scored across 3 tools
Each tool targets a distinct input source — URL, local file path, or base64 bytes — and the descriptions explicitly cross-reference when to use each one. There is no overlap or ambiguity in selecting the right tool.
All three tools follow the exact pattern convert_<source>_to_markdown, using consistent snake_case and a clear verb-noun structure. The naming is predictable and immediately conveys each tool's input method.
Three tools is lean but perfectly scoped for a document conversion server, with each tool covering a distinct input modality and no redundancy. The small count reflects the focused purpose without feeling incomplete.
The three input methods — URL, file path, and raw bytes — cover all plausible ways an agent could possess a document. Advanced needs like partial reads and outline mode are handled via parameters, so there are no obvious gaps in the conversion workflow.
Maintenance
Related MCP Connectors
Convert files, URLs, and documents to clean, AI-ready Markdown via MCP.
OCR, transcription, file extraction, and image generation for AI agents via MCP.
MCP tools for AI agents: render URLs to image/PDF, check link health, convert HTML/CSV/JSON.
Web scraping for AI agents. Converts URLs to clean, LLM-ready Markdown with anti-bot bypass.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to search, deep-read, and build knowledge bases from Markdown, PDF, DOCX, and PPTX documents via MCP tools for retrieval, document navigation, and ingestion.16 npm633MIT
- FlicenseNot gradedqualityDmaintenanceConverts documents (PDF, DOCX, images, etc.) to Markdown using Microsoft's Markitdown library, with no local setup required. Integrates with AI agents via MCP for seamless document conversion.1-
- AlicenseNot gradedqualityCmaintenanceProvides AI agents with comprehensive document parsing capabilities including PDF text extraction, OCR, HTML-to-markdown conversion, table extraction, and summarization, optimized for agent workflows.30 npmMIT
- FlicenseAqualityDmaintenanceConverts files (PDF, DOCX, PPTX, XLSX, images via OCR) and URLs to Markdown, enabling AI clients to read them via a single MCP tool.1-