Skip to main content
Glama

catalyst-labs/document-to-markdown

catalyst-labs--document-to-markdown
Destructive

This tool calls the Actor "catalyst-labs/document-to-markdown" and retrieves its output results. Actor description: Tested Oct 25, 2026: 99.9% text fidelity on our test PDFs, 99.3% reading order on 2-column PDFs (MarkItDown 84%), PDF tables as real grids (cell placement 0.70, same as Docling). PDF, DOCX, XLSX, HTML to markdown with token counts. $0.001/page, failures free.

Tool call template

This tool declares no required parameters. Add optional parameters from the input schema as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {},
    "name": "catalyst-labs--document-to-markdown"
  }
}

Input Schema

NameRequiredDescriptionDefault
urlsNoPublic links to PDF, DOCX, XLSX, XLS, CSV, HTML, TXT or MD files (max 100 per call). Type is detected from the file bytes, not the extension. Each document returns exactly one row with `outcome`; failures (404, blocked, scanned PDF, encrypted) are rows, never charged. Example values: ["https://arxiv.org/pdf/1706.03762"]
filesNoOptional inline files for agents that hold the bytes: `[{"name": "report.pdf", "base64": "..."}]`. Keep under ~9 MB total (input size limit).
pagesNoPDF only: pages to convert, e.g. `1-10`, `5`, `20-`. Default all (up to maxPages).
maxCharsNoBudget per document: markdown is cut at a paragraph boundary to this many characters; 0 = no limit. Default 50000 (about 13,000 tokens; each row reports exact `tokens`). You pay only for the pages actually returned. Example values: 50000
maxPagesNoSafety cap on PDF pages per document. Default 200. Example values: 200
waitSecsNoMax seconds (0–45, default 30) to cap the wait for the Actor run to reach terminal state. For long-running Actors the response returns at the cap with the current run status; follow `nextStep` to poll via get-actor-run. Set to 0 to fire-and-forget.
chunkSizeNoFor RAG: split each document into chunks of about this many characters on heading/paragraph boundaries. Each chunk has exact `tokens`, `charStart`/`charEnd` offsets, `headingPath` (all parent headings) and PDF `page`. 0 = off (default).
keepLinksNoKeep `[text](url)` links from DOCX/HTML. Off saves tokens.
pdfTablesNo`auto` (default) finds tables on PDF pages that look tabular, using the same engine as catalyst-labs/pdf-tables-to-json, and writes them as GFM tables in place. Text-only PDFs are not slowed down. `off` is the old, fastest behaviour. Example values: "auto"auto
pageMarkersNoInsert `<!-- page N -->` before each PDF page so citations can point at a page. Example values: true
referrer_idNoReferral code from another user's receipt (ref_...). They earn 10% of this run's price as credit.
timeoutSecsNoPer-document download timeout. Default 60. Example values: 60
chunkOverlapNoCharacters repeated between consecutive chunks. Default 200. Example values: 200
buyerPublicKeyNoBase64 Ed25519 public key (SPKI). Lets you sign a useful/not useful verdict on this run's receipt for 5% off your next run.
maxRowsPerSheetNoSpreadsheets: rows per sheet rendered as a markdown table. Default 500. Example values: 500
includeFullMarkdownNoWhen chunking, also return the whole `markdown` field (doubles output size). Off by default.

Output Schema

NameRequiredDescriptionDefault
tipNoAdvisory guidance RAG Web Browser wrote to its key-value store under the reserved "TIP" key
runIdYesActor run ID
statsNoRun statistics
statusYesRun status: READY | RUNNING | TIMING-OUT | TIMED-OUT | ABORTING | ABORTED | SUCCEEDED | FAILED
actorIdYesStable Apify Actor ID from the run record
summaryYesPast-tense summary of the run state
exitCodeNoActor process exit code; populated for terminal states (especially FAILED)
nextStepYesOne primary follow-up action with identifiers interpolated
storagesYesDataset and key-value store metadata, keyed by alias. "default" is always the primary entry.
actorNameNo"username/actor-name"
startedAtNoISO timestamp when the run started
finishedAtNoISO timestamp when the run finished (terminal states only)
statusMessageNoPass-through from Apify run.statusMessage
apifyConsoleUrlNoPersonalized Apify Console link to the run; present only for Console sessions

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • addedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema
      Added value: +{
      +  "description": "JSON Schema for rows in the dataset at `storages.datasets.default.id` — describes row shape only; the rows themselves are NOT returned inline in this response. Inferred from this Actor's historical successful runs. To fetch actual rows, call `get-dataset-items` with the dataset id and a `fields` projection drawn from this schema.",
      +  "properties": {
      +    "billedPages": {
      +      "type": "number"
      +    },
      +    "chars": {
      +      "type": "number"
      +    },
      +    "chunkCount": {
      +      "type": "number"
      +    },
      +    "chunks": {
      +      "type": "null"
      +    },
      +    "docType": {
      +      "type": "string"
      +    },
      +    "errorCode": {
      +      "type": "null"
      +    },
      +    "errorMessage": {
      +      "type": "null"
      +    },
      +    "fetchedAt": {
      +      "type": "string"
      +    },
      +    "fileName": {
      +      "type": "null"
      +    },
      +    "markdown": {
      +      "type": "string"
      +    },
      +    "ms": {
      +      "type": "number"
      +    },
      +    "outcome": {
      +      "type": "string"
      +    },
      +    "pageCount": {
      +      "type": "null"
      +    },
      +    "pagesProcessed": {
      +      "type": "null"
      +    },
      +    "receipt_key": {
      +      "type": "string"
      +    },
      +    "receipt_verify_url": {
      +      "type": "string"
      +    },
      +    "referral_code": {
      +      "type": "string"
      +    },
      +    "retryable": {
      +      "type": "boolean"
      +    },
      +    "status": {
      +      "type": "string"
      +    },
      +    "title": {
      +      "type": "string"
      +    },
      +    "tokens": {
      +      "type": "number"
      +    },
      +    "totalChars": {
      +      "type": "number"
      +    },
      +    "truncated": {
      +      "type": "boolean"
      +    },
      +    "url": {
      +      "type": "string"
      +    }
      +  },
      +  "type": "object"
      +}
  2. Changed3 schema fields changed
    • addedInput schema / properties / buyerPublicKey
      Added value: +{
      +  "description": "Base64 Ed25519 public key (SPKI). Lets you sign a useful/not useful verdict on this run's receipt for 5% off your next run.",
      +  "title": "Your verdict public key (optional)",
      +  "type": "string"
      +}
    • addedInput schema / properties / referrer_id
      Added value: +{
      +  "description": "Referral code from another user's receipt (ref_...). They earn 10% of this run's price as credit.",
      +  "title": "Referral code (optional)",
      +  "type": "string"
      +}
    • removedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema
      Removed value: -{
      -  "description": "JSON Schema for rows in the dataset at `storages.datasets.default.id` — describes row shape only; the rows themselves are NOT returned inline in this response. Inferred from this Actor's historical successful runs. To fetch actual rows, call `get-dataset-items` with the dataset id and a `fields` projection drawn from this schema.",
      -  "properties": {
      -    "billedPages": {
      -      "type": "number"
      -    },
      -    "chars": {
      -      "type": "number"
      -    },
      -    "chunkCount": {
      -      "type": "number"
      -    },
      -    "chunks": {
      -      "type": "null"
      -    },
      -    "docType": {
      -      "type": "string"
      -    },
      -    "errorCode": {
      -      "type": "null"
      -    },
      -    "errorMessage": {
      -      "type": "null"
      -    },
      -    "fetchedAt": {
      -      "type": "string"
      -    },
      -    "fileName": {
      -      "type": "string"
      -    },
      -    "markdown": {
      -      "type": "string"
      -    },
      -    "ms": {
      -      "type": "number"
      -    },
      -    "outcome": {
      -      "type": "string"
      -    },
      -    "pageCount": {
      -      "type": "number"
      -    },
      -    "pagesProcessed": {
      -      "type": "number"
      -    },
      -    "retryable": {
      -      "type": "boolean"
      -    },
      -    "status": {
      -      "type": "string"
      -    },
      -    "tableCount": {
      -      "type": "number"
      -    },
      -    "title": {
      -      "type": "string"
      -    },
      -    "tokens": {
      -      "type": "number"
      -    },
      -    "totalChars": {
      -      "type": "number"
      -    },
      -    "truncated": {
      -      "type": "boolean"
      -    },
      -    "url": {
      -      "type": "string"
      -    }
      -  },
      -  "type": "object"
      -}
  3. Changed2 schema fields changed
    • addedInput schema / properties / pdfTables
      Added value: +{
      +  "default": "auto",
      +  "description": "`auto` (default) finds tables on PDF pages that look tabular, using the same engine as catalyst-labs/pdf-tables-to-json, and writes them as GFM tables in place. Text-only PDFs are not slowed down. `off` is the old, fastest behaviour.\nExample values: \"auto\"",
      +  "enum": [
      +    "auto",
      +    "off"
      +  ],
      +  "examples": [
      +    "auto"
      +  ],
      +  "title": "PDF tables as markdown tables",
      +  "type": "string"
      +}
    • addedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema
      Added value: +{
      +  "description": "JSON Schema for rows in the dataset at `storages.datasets.default.id` — describes row shape only; the rows themselves are NOT returned inline in this response. Inferred from this Actor's historical successful runs. To fetch actual rows, call `get-dataset-items` with the dataset id and a `fields` projection drawn from this schema.",
      +  "properties": {
      +    "billedPages": {
      +      "type": "number"
      +    },
      +    "chars": {
      +      "type": "number"
      +    },
      +    "chunkCount": {
      +      "type": "number"
      +    },
      +    "chunks": {
      +      "type": "null"
      +    },
      +    "docType": {
      +      "type": "string"
      +    },
      +    "errorCode": {
      +      "type": "null"
      +    },
      +    "errorMessage": {
      +      "type": "null"
      +    },
      +    "fetchedAt": {
      +      "type": "string"
      +    },
      +    "fileName": {
      +      "type": "string"
      +    },
      +    "markdown": {
      +      "type": "string"
      +    },
      +    "ms": {
      +      "type": "number"
      +    },
      +    "outcome": {
      +      "type": "string"
      +    },
      +    "pageCount": {
      +      "type": "number"
      +    },
      +    "pagesProcessed": {
      +      "type": "number"
      +    },
      +    "retryable": {
      +      "type": "boolean"
      +    },
      +    "status": {
      +      "type": "string"
      +    },
      +    "tableCount": {
      +      "type": "number"
      +    },
      +    "title": {
      +      "type": "string"
      +    },
      +    "tokens": {
      +      "type": "number"
      +    },
      +    "totalChars": {
      +      "type": "number"
      +    },
      +    "truncated": {
      +      "type": "boolean"
      +    },
      +    "url": {
      +      "type": "string"
      +    }
      +  },
      +  "type": "object"
      +}
  4. Changed4 schema fields changed
    • changedInput schema / properties / chunkSize / description
      Previous value: -"For RAG: split each document into chunks of about this many characters on heading/paragraph boundaries, each with its heading and page number. 0 = off (default)."New value: +"For RAG: split each document into chunks of about this many characters on heading/paragraph boundaries. Each chunk has exact `tokens`, `charStart`/`charEnd` offsets, `headingPath` (all parent headings) and PDF `page`. 0 = off (default)."
    • changedInput schema / properties / maxChars / description
      Previous value: -"Token budget per document (about 4 characters = 1 token). Cut at a paragraph boundary; 0 = no limit. You pay only for the pages actually returned. Default 50000.\nExample values: 50000"New value: +"Budget per document: markdown is cut at a paragraph boundary to this many characters; 0 = no limit. Default 50000 (about 13,000 tokens; each row reports exact `tokens`). You pay only for the pages actually returned.\nExample values: 50000"
    • changedInput schema / properties / urls / description
      Previous value: -"Public links to PDF, DOCX, XLSX, XLS, CSV, HTML, TXT or MD files (max 100). Type is detected from the file bytes, not the extension.\nExample values: [\"https://arxiv.org/pdf/1706.03762\"]"New value: +"Public links to PDF, DOCX, XLSX, XLS, CSV, HTML, TXT or MD files (max 100 per call). Type is detected from the file bytes, not the extension. Each document returns exactly one row with `outcome`; failures (404, blocked, scanned PDF, encrypted) are rows, never charged.\nExample values: [\"https://arxiv.org/pdf/1706.03762\"]"
    • changedInput schema / properties / urls / items / description
      Previous value: -"Public links to PDF, DOCX, XLSX, XLS, CSV, HTML, TXT or MD files (max 100). Type is detected from the file bytes, not the extension."New value: +"Public links to PDF, DOCX, XLSX, XLS, CSV, HTML, TXT or MD files (max 100 per call). Type is detected from the file bytes, not the extension. Each document returns exactly one row with `outcome`; failures (404, blocked, scanned PDF, encrypted) are rows, never charged."
  5. First observed

TDQS

B3.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare openWorldHint=true and destructiveHint=true; the description usefully adds cost ($0.001/page) and the critical failure policy ('failures are rows, never charged'), which an agent can't get from the annotations. It stops short of explaining run lifecycle/polling behavior, which matters given the 45s wait cap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The first sentence is a tautological wrapper ('calls the Actor ... and retrieves its output results'), and the second is marketing copy with unverifiable future-dated benchmarks ('Tested Oct 25, 2026') and competitor comparisons that don't help an agent invoke the tool. Some content (formats, pricing) earns its place; the fidelity stats do not.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 16 parameters, an output schema, and async run semantics (waitSecs cap, nextStep polling), the description should say more about what happens when a run doesn't finish in the wait window. Cost and failure handling are covered, but run lifecycle and the relationship to the dataset/run siblings are not.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

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 16 parameters thoroughly (page ranges, chunking, token counts, referral fields). The description adds no parameter-level meaning beyond the schema, which is the baseline-3 case.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names the concrete transformation (PDF, DOCX, XLSX, HTML to markdown) and states it runs the named Actor and returns its output, so the verb and resource are clear. It does not differentiate from siblings, but the sibling set (abort-actor-run, get-actor-run, get-dataset-items, get-key-value-store-record) is a different category of tool anyway.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No indication of when to choose this over alternatives, how to handle long-running runs, or how the output relates to get-dataset-items/get-actor-run. The only routing hint ('follow nextStep to poll via get-actor-run') lives in the waitSecs schema field, not the description.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.