pdfmux/blog
n8n

PDF extraction in n8n: wiring pdfmux into a workflow with the MCP Client node

TL;DRConnect pdfmux to n8n with the native MCP Client node over Streamable HTTP — extract tables, invoices, and scanned PDFs inside any workflow, no custom code node.

Direct answer: Run pdfmux serve --http --port 8000 to start pdfmux’s MCP server over Streamable HTTP, then point n8n’s built-in MCP Client node at http://localhost:8000/mcp (or the Docker-network hostname if n8n and pdfmux run in separate containers). No custom n8n node, no wrapper API — n8n’s MCP Client node discovers pdfmux’s tools (convert_pdf, extract_structured, analyze_pdf, batch_convert) automatically and an AI Agent node in the same workflow can call them directly.


The gap this closes

n8n’s built-in file-handling nodes read plain text out of a PDF and stop there — no OCR, no table structure, no signal about whether the extraction actually worked. That’s fine for a clean, single-column, born-digital PDF. It falls over the moment a workflow has to ingest a scanned invoice, a multi-column report, or a financial statement with a real table in it, which is most of what actually lands in an automation inbox.

The fix isn’t a new n8n node maintained specifically for PDFs. It’s connecting n8n to a tool server that already does document extraction properly, using the connection n8n already has for exactly this purpose: MCP.

Why MCP, not a custom node

n8n added a native MCP Client Tool node (n8n-nodes-langchain.mcpclient) that connects to any external MCP server over SSE or Streamable HTTP and exposes its tools to an AI Agent node in the same workflow. pdfmux, in turn, ships an MCP server with pdfmux serve — the same server used for Claude Desktop, Cursor, and Claude Code, just pointed at a different client.

Neither side had to build anything n8n-specific. That’s the actual point of MCP: pdfmux implements the protocol once, and every MCP-aware client — Claude, Cursor, n8n, whatever adopts it next — can use it without a dedicated integration.

The alternative, wrapping the pdfmux CLI in an HTTP endpoint and calling it from n8n’s generic HTTP Request node, still works and is a reasonable fallback if you’d rather not run a persistent MCP server. But it means writing and maintaining that wrapper yourself, and losing the tool-discovery behavior — with MCP, an AI Agent node in the workflow sees pdfmux’s tool list, descriptions, and parameter schemas automatically, the same way Claude Desktop does.

Step 1: Start pdfmux’s MCP server over Streamable HTTP

pip install "pdfmux[serve]"
pdfmux serve --http --port 8000

By default this binds to 127.0.0.1 — loopback only. If n8n runs in a separate Docker container, either put pdfmux on the same Docker network and use its container hostname, or set --host 0.0.0.0 deliberately and put an auth proxy in front of it. Don’t expose port 8000 to the open internet unauthenticated; MCP servers assume a trusted caller, not a public one.

# same-machine n8n: loopback is enough, this is the default
pdfmux serve --http --port 8000

# n8n in a different container on the same Docker network
pdfmux serve --http --port 8000 --host 0.0.0.0

--http specifically selects Streamable HTTP transport rather than SSE. n8n’s own documentation recommends Streamable HTTP for new MCP connections, so the defaults line up on both sides.

Step 2: Add the MCP Client node in n8n

In your workflow, add an MCP Client Tool node (found under AI nodes / LangChain nodes) and configure:

  • Server Transport: Streamable HTTP
  • Endpoint URL: http://localhost:8000/mcp (or your Docker-network hostname)
  • Authentication: none for a loopback-only local server; add a header-based token if you exposed the server more broadly

Connect the MCP Client node to an AI Agent node’s tool input. On the next run, the agent’s tool list includes pdfmux’s tools automatically — no manual JSON schema entry.

Step 3: Give the agent a task that needs real extraction

With the connection live, a prompt like this inside the AI Agent node routes to pdfmux instead of n8n’s built-in text extraction:

Extract the line items and total from the invoice at {{ $json.filePath }}.
If the document is scanned, mention that in your answer.

The agent calls analyze_pdf first to check whether the document is digital or scanned, then extract_structured with the invoice schema preset to pull line items and totals — the same behavior described in giving an AI agent the ability to read PDFs, now inside an n8n workflow instead of a chat client.

The four tools most useful in a workflow context

ToolWhen a workflow calls it
analyze_pdfCheap first step — decide whether a document needs full extraction or OCR before committing
convert_pdfFull text/markdown extraction for documents going into a knowledge base or downstream LLM step
extract_structuredTables, key-values, and schema-mapped output — invoices, receipts, contracts, or a custom schema
batch_convertProcess every PDF dropped into a watched folder in one call, 4 concurrent workers

convert_pdf and extract_structured both return a confidence score, which matters more inside an unattended workflow than in a chat session — a human isn’t watching every run, so a workflow branch that checks confidence < 0.8 and routes to a “needs review” step (Slack alert, a database flag, a human-in-the-loop node) is the difference between an automation you can trust and one that silently ships bad extractions downstream.

A concrete workflow: invoice intake to spreadsheet

  1. Trigger: Watch a folder or email attachment for new PDFs (n8n’s native trigger nodes)
  2. AI Agent + MCP Client (pdfmux): analyze_pdf → if scanned, note it; extract_structured with schema: "invoice" → line items, vendor, total, currency
  3. IF node: branch on the extraction’s confidence — below 0.8 goes to a review step, above continues automatically
  4. Set node: map the structured JSON fields to your spreadsheet’s column names
  5. Google Sheets / Airtable node: append the row

Nothing in that pipeline after step 2 is PDF-specific — it’s the same shape as any other structured-data-in, spreadsheet-out n8n workflow. The MCP connection is what turns “PDF” from a special case n8n can’t handle into a JSON payload like any other trigger.

Troubleshooting

MCP Client node shows no tools after connecting. Confirm the server is actually running (curl http://localhost:8000/mcp should not connection-refuse) and that the endpoint URL in the node matches the port pdfmux serve --http is bound to.

Connection refused from inside a Docker container. localhost inside an n8n container refers to the container itself, not the host. Use the pdfmux container’s service name if both run in the same docker-compose network, or host.docker.internal if pdfmux runs on the Docker host.

Extraction returns low confidence on every document. Check whether the OCR extra is installed — a workflow ingesting scanned documents needs pip install "pdfmux[ocr]" on the machine running the pdfmux server, not on the n8n machine.

Want to skip MCP entirely and just shell out? Use n8n’s Execute Command node to call pdfmux convert {{ $json.path }} --format json directly. It’s simpler for a single fixed extraction step, but the AI Agent node can’t discover or reason about the tool the way it can over MCP.

Try it

pip install "pdfmux[serve]"
pdfmux serve --http --port 8000

Add an MCP Client node pointed at http://localhost:8000/mcp, connect it to an AI Agent node, and any workflow that used to choke on a scanned or table-heavy PDF now has real extraction behind it.

  • GitHub — source, docs, examples
  • PyPIpip install pdfmux

MIT licensed. Runs locally. No API keys needed for the base install.

Last updated: July 2026.

Frequently asked questions

Does pdfmux have an official n8n community node?

No. It doesn't need one — n8n ships a built-in MCP Client node that connects to any MCP server, and pdfmux ships an MCP server (pdfmux serve --http). The two connect directly without either side maintaining an n8n-specific integration.

SSE or Streamable HTTP — which transport should I use?

Streamable HTTP. pdfmux's --http flag runs Streamable HTTP transport specifically, and n8n's own docs recommend Streamable HTTP over SSE for new projects.

Can I run this without exposing the server to the internet?

Yes, and you should by default. pdfmux serve --http binds to 127.0.0.1 (loopback only) unless you explicitly set --host 0.0.0.0. If n8n runs on the same machine or in the same Docker network, loopback or a Docker-internal hostname is enough — never expose port 8000 publicly without adding auth in front of it.

What if I just want to run the pdfmux CLI in a workflow without MCP?

Use n8n's Execute Command node to call the pdfmux CLI directly (pdfmux convert file.pdf --format json). That works and needs no server process, but you lose the tool-discovery and structured-response handling the MCP Client node gives an AI Agent node for free.