Assembly MCP
Summary: This MCP server exposes two document-conversion tools — PDF → Markdown and Markdown → PDF — though the README advertises additional upload tools not present in the schema.
convert_pdftomd(pdf_path, output_path?, strip_watermarks=true, front_matter=true)— Convert a PDF to Markdown text, optionally writing a.mdfile. Handles font-size heading detection, running header/footer removal, table extraction, and watermark stripping. Returns the Markdown string.convert_mdtopdf(output_path, md_path? | markdown_text?, title?, css?)— Convert Markdown (from a file or raw text) to a PDF using WeasyPrint with a clean print stylesheet;output_pathis required. Returns a confirmation with path, byte size, and page count.Requirements: Python ≥ 3.11, Node ≥ 22 plus an assembly-app checkout (
ASSEMBLY_APP_DIR) for PDF→MD, and WeasyPrint native libraries (GTK/Pango) for MD→PDF.Not in the schema: the README's
upload_issue,issue_draft, andupload_renderstools (draft issues and Renders-tab image uploads via assembly-app CLIs) are described but absent from the exposed tool list.Usage: runs over MCP stdio, registered via
claude mcp add assembly -- uv --directory <path> run --no-sync assembly-mcp, with matching/convert-pdftomdand/convert-mdtopdfslash commands.
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., "@Assembly MCPConvert the file report.pdf to Markdown and save as report.md"
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.
Assembly MCP
A small Model Context Protocol server that gives any MCP client (Claude Code, Claude Desktop, …) document-conversion and assembly-app upload tools:
Tool | Direction | Engine |
| PDF → Markdown | assembly-app |
| Markdown → PDF | |
| files → draft issue → issued | assembly-app |
| images → Renders tab | assembly-app |
convert_pdftomd is a thin wrapper — it shells out to
node --experimental-strip-types --no-warnings <assembly-app>/apps/frontend/scripts/pdf2md.ts,
the assembly-app pdf2md converter (pdf.js: headings, lists, ruled tables,
images saved to <stem>_images/). Requires Node ≥ 22 and an assembly-app
checkout — see ASSEMBLY_APP_DIR below. convert_mdtopdf renders
Markdown/HTML → PDF with WeasyPrint (pure-Python, no TeX toolchain).
Requirements
Python ≥ 3.11
uv (recommended) or
pipNode ≥ 22 and an assembly-app checkout — required for
convert_pdftomd, which shells out to that repo'sapps/frontend/scripts/pdf2md.ts. By default it looks for a siblingassembly-appcheckout next to this repo; point it elsewhere with theASSEMBLY_APP_DIRenvironment variable.WeasyPrint native libraries — only needed for
convert_mdtopdf(convert_pdftomdworks without them):Linux (Debian/Ubuntu):
apt install libpango-1.0-0 libpangoft2-1.0-0 libgdk-pixbuf-2.0-0 libffi-devmacOS:
brew install pango gdk-pixbuf libffiWindows: install the GTK3 runtime. Without it,
convert_pdftomdstill works andconvert_mdtopdfreturns a clear "install GTK" error.
Related MCP server: mcp-pdf2md
Install
git clone https://github.com/AssemblyJustin/assembly-mcp.git
cd assembly-mcp
uv sync # creates .venv and installs everythingRun the server directly to confirm it starts (it speaks MCP over stdio and will
wait for a client — Ctrl-C to exit):
uv run assembly-mcpAdd to Claude Code
From anywhere, register the server (adjust the path to your clone):
claude mcp add assembly -- uv --directory /ABSOLUTE/PATH/TO/assembly-mcp run --no-sync assembly-mcp(--no-sync: on Windows, a second Claude session's uv run otherwise tries to reinstall the
assembly-mcp.exe the first session is running, fails with "file in use", and the server never
connects. Run uv sync yourself after pulling.)
Then the tools are available in your session. This repo also ships matching slash commands — run
Claude Code from inside the repo (or copy .claude/commands/* into your project) to use:
/convert-pdftomd report.pdf report.md
/convert-mdtopdf notes.md notes.pdf
/upload issues
/upload rendersAdd to Claude Desktop
Edit claude_desktop_config.json
(macOS: ~/Library/Application Support/Claude/,
Windows: %APPDATA%\Claude\) and add:
{
"mcpServers": {
"assembly": {
"command": "uv",
"args": ["--directory", "C:\\ABSOLUTE\\PATH\\TO\\assembly-mcp", "run", "--no-sync", "assembly-mcp"]
}
}
}Restart Claude Desktop. The tools appear under the 🔌 tools menu.
Tools
convert_pdftomd
Convert a PDF file to Markdown. PDF→Markdown runs the assembly-app pdf2md
converter (pdf.js) — headings, lists, ruled tables, images (saved to
<stem>_images/). Requires node ≥ 22 and the assembly-app checkout
(ASSEMBLY_APP_DIR).
Argument | Type | Default | Description |
| string | — | Path to the source |
| string |
| Optional path to also write the |
| bool |
| Kept for compatibility; always on in the unified converter. |
| bool |
| Kept for compatibility; always on in the unified converter. |
Returns the Markdown text (prefixed with a <!-- pdf2md: … --> summary
comment giving page/table/image counts and the output path).
This is a code-only extraction. It does not run vision-based verification, so treat the output as a high-quality first pass, not a certified copy.
convert_mdtopdf
Convert Markdown to a PDF file. Provide either md_path or
markdown_text.
Argument | Type | Default | Description |
| string | — | Where to write the |
| string |
| Path to a source |
| string |
| Raw Markdown (alternative to |
| string |
| Document title (falls back to front-matter |
| string |
| CSS to replace the built-in print stylesheet. |
Renders Markdown → HTML → PDF with a clean A4 print stylesheet (tables, code blocks, page numbers) and verifies the PDF magic bytes before writing.
upload_issue / issue_draft / upload_renders
Upload to an assembly-app project as the person doing it. These are thin wrappers over the
assembly-app CLIs apps/frontend/scripts/upload-issues.ts and upload-renders.ts (node ≥ 22 +
an assembly-app checkout, ASSEMBLY_APP_DIR). Each signs in as uploader_email, so the database's own
permission rules apply: people can only upload to projects they're on, and viewers and clients can't upload.
The slash command /upload issues / /upload renders (.claude/commands/upload.md) drives them.
Tool | Does |
| Files → a draft issue (Transmittal) on the project's Documents tab. Returns |
| Issues that draft (allocates the issue number, which can't be undone). |
| Images → the project's Renders tab. Skips non-images and images already there. |
project is the project number (e.g. 2610) or UUID. issue_type is the issue purpose: For
Information / Review / Approval / Construction / Tender / Coordination / Record (or an org's own).
Setup (once per machine):
Password: never a tool argument. Set
ASSEMBLY_PASSWORD, or create~/.assembly/credentials.jsonas{"you@assembly.nz": "<your app password>"}. The second form supports several people on one machine.Prod: set
ASSEMBLY_SUPABASE_ANON_KEYto the prod app's public anon key (URL defaults tohttps://newapi-next.assembly.nz; override withASSEMBLY_SUPABASE_URL).Dev (
env="dev"): read from the checkout'sapps/frontend/.env.local.
Develop
uv run pytest # smoke tests (PDF→MD skips without node/assembly-app; MD→PDF skips without GTK)Project layout:
src/assembly_mcp/
server.py FastMCP server — registers the tools (stdio); convert_pdftomd
shells out to the assembly-app pdf2md CLI (_app_dir())
md_to_pdf.py python-markdown → WeasyPrint rendering
.claude/commands/ /convert-pdftomd, /convert-mdtopdf and /upload slash commands
tests/ smoke testsLicense
MIT — see LICENSE.
Available Tools
2 toolsconvert_mdtopdfA
Convert Markdown to a PDF file.
Renders Markdown → HTML → PDF with WeasyPrint (the Assembly MD→PDF stack)
using a clean print stylesheet. Provide EITHER `md_path` OR `markdown_text`.
A PDF is binary, so `output_path` is required.
Args:
output_path: Path to write the resulting `.pdf` (required).
md_path: Path to a source `.md` file.
markdown_text: Raw Markdown string (alternative to `md_path`).
title: Optional document title (falls back to front-matter `title`).
css: Optional CSS to replace the built-in print stylesheet.
Returns:
A confirmation string with the output path, byte size, and page count.
| Name | Required | Description | Default |
|---|---|---|---|
| css | No | ||
| title | No | ||
| md_path | No | ||
| output_path | Yes | ||
| markdown_text | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully carries the burden of behavioral disclosure. It reveals the rendering stack (WeasyPrint), input alternatives, the binary nature of output requiring a path, the title fallback to front-matter, and the exact return format (confirmation string with output path, byte size, page count). It does not mention overwrite behavior or error conditions when both inputs are provided, but the disclosed details substantially exceed what a minimal description would provide.
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 longer than average but well-structured: a one-line purpose, a pipeline/usage explanation, an Args list, and a Returns note. Every sentence carries information—there is no filler or repetition of schema fields. The front-loaded purpose sentence ensures the core meaning is immediately visible.
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?
Given the tool has 5 parameters, 0% schema description coverage, no annotations, and an output schema, the description covers the essentials well: pipeline, input constraints, parameter semantics, and return value format. Minor gaps exist—such as overwrite policy or behavior when both md_path and markdown_text are supplied—but the description is largely complete for an AI agent to select and use the tool correctly.
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 0%, so the description must compensate entirely. It does so comprehensively with an Args block that explains all five parameters: output_path (required), md_path, markdown_text (the alternative), title (with fallback behavior), and css (replacement for built-in stylesheet). This adds meaning far beyond the bare schema types and defaults.
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+resource: 'Convert Markdown to a PDF file.' It then details the rendering pipeline (Markdown → HTML → PDF with WeasyPrint), which clearly distinguishes this tool from its sibling convert_pdftomd (the reverse conversion). This is a precise, unambiguous purpose statement.
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 provides clear usage context: 'Provide EITHER `md_path` OR `markdown_text`' and explains why `output_path` is required (PDF is binary). It also notes the title fallback behavior and CSS replacement option. However, it does not explicitly name convert_pdftomd as the alternative for the reverse conversion, so it stops short of an explicit when-not-to-use statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
convert_pdftomdA
Convert a PDF file to Markdown.
Uses PyMuPDF with font-size heading detection, running header/footer
removal, table extraction, and optional watermark stripping — the Assembly
PDF→MD pipeline. Returns the Markdown text; when `output_path` is given it
also writes a `.md` file there.
Args:
pdf_path: Path to the source `.pdf` file.
output_path: Optional path to also write the Markdown to (`.md`).
strip_watermarks: Remove Standards-NZ / IHS style watermark lines and
light-grey overlay text.
front_matter: Prepend YAML front-matter linking back to the source PDF.
Returns:
The converted Markdown as a string.
| Name | Required | Description | Default |
|---|---|---|---|
| pdf_path | Yes | ||
| output_path | No | ||
| front_matter | No | ||
| strip_watermarks | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses the conversion process (PyMuPDF, heading detection, header/footer removal, table extraction), optional watermark stripping, side effects (writing a file when output_path is given), and the return value. This goes well beyond basic expectations.
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 well-structured with a clear summary, Args section, and Returns section. It is appropriately sized for a tool with four parameters, and every sentence adds value without redundancy.
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?
The description is complete: it covers the conversion process, all parameters, side effects, and return value. The presence of an output schema doesn't override the need for context, and the description provides rich behavioral context.
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 0%, so the description must explain each parameter. It does so clearly: pdf_path as source .pdf, output_path as optional write target, strip_watermarks for specific watermark removal, and front_matter for YAML prepending. This adds meaning beyond the raw 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 clearly states the tool's function: 'Convert a PDF file to Markdown.' It identifies the specific resource (PDF), the output format (Markdown), and the direction of conversion, which distinguishes it from the sibling tool convert_mdtopdf.
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 implies usage by stating the conversion direction and pipeline details, but it does not explicitly mention when to use this tool instead of the sibling convert_mdtopdf, nor does it provide any exclusions or alternative scenarios.
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.
2 tool updates
v0.1.0- First observed
convert_mdtopdf - First observed
convert_pdftomd
TDQS
Scored across 2 tools
The two tools are exact inverses: one converts PDF to Markdown, the other Markdown to PDF. There is zero overlap or ambiguity between them.
Both tool names follow the identical convert_<source>to<target> pattern (convert_pdftomd, convert_mdtopdf). The naming is perfectly consistent and predictable.
The server has only 2 tools, which is on the low end, but the scope is tightly focused on bidirectional PDF/Markdown conversion. The count is slightly under the typical 3-15 range yet entirely reasonable for the stated purpose.
The tool surface fully covers the domain of PDF-Markdown conversion in both directions. There are no obvious missing operations for a conversion-focused utility.
Maintenance
Related MCP Connectors
- blinkpdfOAuthio.blinkpdf
Render Markdown and LLM output into accessible PDF/UA-1 PDFs. No headless Chromium.
Convert Markdown, HTML, and web pages to high-quality PDF with Prince.
Markdown in, any format out. PDFs merged, split, watermarked. Runs on our own doc engines.
Convert PDFs/images to Word, Excel, and Markdown. Split, merge, and watermark PDF files.
Related MCP Servers
- AlicenseAqualityDmaintenanceConverts various file types and web content to Markdown format. It provides a set of tools to transform PDFs, images, audio files, web pages, and more into easily readable and shareable Markdown text.10345 npm2,997MIT
- MIT
- AlicenseAqualityDmaintenanceConverts Markdown documents to PDF files with support for syntax highlighting, custom styling, Mermaid diagrams, optional page numbers, and configurable watermarks.145 npmMIT
- FlicenseNot gradedqualityDmaintenanceProvides tools for converting Markdown content and files into professional PDF documents with full support for Mermaid diagrams and LaTeX rendering. It allows for high-quality output customization, including paper size, table of contents, and syntax highlighting styles.-