### Install and Run PaperFlow Local Web UI Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/index.html Clone the repository, install dependencies, and run the API server to access the local Web UI. The UI guides parser selection and setup. ```bash git clone https://github.com/TylerMorrison21/paperflow cd paperflow pip install -r requirements.txt uvicorn api.main:app --port 8000 # Open http://localhost:8000 ``` -------------------------------- ### Recommended PaperFlow Setup Source: https://github.com/tylermorrison21/paperflow/blob/master/mcp-server/README.md Steps to clone the PaperFlow repository, set up the environment, install dependencies, and run the Uvicorn server for the backend. ```bash git clone https://github.com/TylerMorrison21/paperflow cd paperflow cp .env.example .env pip install -r requirements.txt uvicorn api.main:app --port 8000 ``` -------------------------------- ### Local Development Setup for MCP Server Source: https://github.com/tylermorrison21/paperflow/blob/master/mcp-server/README.md Commands to set up and start the MCP server for local development. ```bash cd mcp-server npm install npm start ``` -------------------------------- ### Local Development Setup for PaperFlow Source: https://context7.com/tylermorrison21/paperflow/llms.txt This script outlines the steps to set up the PaperFlow project for local development. It includes cloning the repository, installing dependencies, and starting the development server. ```bash # Local development startup git clone https://github.com/TylerMorrison21/paperflow cd paperflow cp .env.example .env pip install -r requirements.txt uvicorn api.main:app --port 8000 --reload ``` -------------------------------- ### Install PaperFlow MCP Server Source: https://github.com/tylermorrison21/paperflow/blob/master/mcp-server/README.md Command to globally install the paperflow-mcp package using npm. ```bash npm install -g paperflow-mcp ``` -------------------------------- ### Install PaperFlow Post-processing Engine Source: https://github.com/tylermorrison21/paperflow/blob/master/README.md Install the PaperFlow post-processing engine using pip. This is the primary method for using the post-processing layer. ```bash pip install paperflow-postprocess ``` -------------------------------- ### Start PaperFlow with Docker Compose or Run Directly Source: https://context7.com/tylermorrison21/paperflow/llms.txt Commands to start the PaperFlow service using Docker Compose or a direct `docker run` command. Includes instructions for opening the Web UI. ```bash # Start docker compose up -d # Or run directly docker run --name paperflow \ -p 8000:8000 \ -e DATA_DIR=/data/jobs \ -v $(pwd)/data:/data \ --restart unless-stopped \ ghcr.io/tylermorrison21/paperflow:latest # Open Web UI open http://localhost:8000 ``` -------------------------------- ### Example Summary Response from convert_pdf Source: https://context7.com/tylermorrison21/paperflow/llms.txt Illustrates the summary output format from the `convert_pdf` tool, including job details, parser information, and next steps for retrieving content. ```text # Example summary response from convert_pdf: # --- # Source: https://arxiv.org/pdf/1706.03762 # Job ID: 3fa85f64-5717-4562-b3fc-2c963f66afa6 # Parser: PyMuPDF Local # Markdown size: 42381 characters # Direct markdown URL: http://localhost:8000/api/jobs/.../result # Direct package URL: http://localhost:8000/api/jobs/.../package # Response mode: summary # --- # Title: Attention Is All You Need # Authors: Ashish Vaswani, Noam Shazier # Date: 2017-06-12 # Top headings: Abstract | Introduction | Background | Model Architecture | ... # Next chunk call: {"job_id":"...","start":0,"length":12000} # --- ``` -------------------------------- ### Example Output of `list_parsers` Source: https://context7.com/tylermorrison21/paperflow/llms.txt Shows the detailed output from the `list_parsers` command, including backend information, parser specifics (status, speed, quality), and MCP parser shortcuts. ```text # Example output: # Backend: http://localhost:8000 # Configured PaperFlow parsers: # # - PyMuPDF Local [pymupdf] - ready for MCP # Speed/quality: Free / Fastest # Setup: Ready after install. No API key and no parser-specific CLI required. # Default backend parser: yes # # - Marker API (Datalab.to) [marker_api] - configured but not ready for MCP # Speed/quality: Easy / Best quality # MCP note: requires PAPERFLOW_MARKER_API_KEY in the MCP server environment. # # MCP parser shortcuts: # - auto: best available quality with minimal user setup # - best: prefer marker_local -> marker_api -> paddleocr_vl -> pymupdf # - local: prefer marker_local -> paddleocr_vl -> pymupdf # - fast: prefer pymupdf -> marker_local -> paddleocr_vl -> marker_api # ``` -------------------------------- ### Run PaddleOCR-VL CLI Source: https://github.com/tylermorrison21/paperflow/blob/master/README.md Example of how PaperFlow runs the local paddleocr CLI for processing documents. ```bash paddleocr doc_parser -i input.pdf --device cpu --save_path output ``` -------------------------------- ### Run Enterprise Marker Self-Hosted CLI Source: https://github.com/tylermorrison21/paperflow/blob/master/README.md Example of how PaperFlow runs the local marker_single CLI for processing PDFs. ```bash marker_single input.pdf --output_dir output --output_format markdown ``` -------------------------------- ### List Available Parsers Source: https://context7.com/tylermorrison21/paperflow/llms.txt Retrieve a list of all supported parsers, including their configuration status, performance labels, setup instructions, and CLI commands. This helps in selecting the appropriate parser for document processing. ```bash curl http://localhost:8000/api/parsers # { # "parsers": [ # { # "id": "pymupdf", # "label": "PyMuPDF Local", # "configured": true, # "recommended": true, # "default": true, # "speed": "Free", # "quality": "Fastest", # "setup": "Ready after install. No API key and no parser-specific CLI required.", # "requires_user_key": false # }, # { # "id": "paddleocr_vl", # "label": "PaddleOCR-VL-0.9B", # "configured": false, # "setup": "Install PaddleOCR, make sure the paddleocr command works..." # }, # { # "id": "marker_api", # "label": "Marker API (Datalab.to)", # "configured": true, # "requires_user_key": true # }, # { # "id": "marker_local", # "label": "Enterprise Marker Self-Hosted", # "configured": false # } # ] # } ``` -------------------------------- ### Configure MCP Server for PaperFlow Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/index.html Configure the MCP server settings in your application's configuration file. This example shows configurations for macOS/Linux and Windows. ```json { "mcpServers": { "paperflow": { "command": "npx", "args": ["-y", "paperflow-mcp"] } } } ``` ```json { "mcpServers": { "paperflow": { "command": "cmd", "args": ["/c", "npx", "-y", "paperflow-mcp"] } } } ``` -------------------------------- ### Response Format for `get_markdown_chunk` Source: https://context7.com/tylermorrison21/paperflow/llms.txt Example of the response received from `get_markdown_chunk`, detailing the job, source, parser, character range, and providing information on whether more content is available. ```text # Response: # --- # Job ID: 3fa85f64-5717-4562-b3fc-2c963f66afa6 # Source: https://arxiv.org/pdf/1706.03762 # Parser: PyMuPDF Local # Range: 12000-24000 / 42381 characters # Direct markdown URL: http://localhost:8000/api/jobs/.../result # Has more: yes # Next call: {"job_id":"3fa85f64...","start":24000,"length":12000} # --- # # [markdown content from position 12000 to 24000] # ``` -------------------------------- ### Render Parser Details in UI Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Updates the UI to display detailed information about the selected parser, including its label, readiness status, description, facts, and setup instructions. Handles cases where no parser is selected. ```javascript function renderParserDetails() { const parser = getSelectedParserRecord(); if (!parser) { parserDetailTitle.textContent = "Select a parser"; parserDetailBadge.textContent = "Waiting"; parserDetailHeadline.textContent = "Choose a parser to see which workflow fits your documents."; parserDetailBestFor.textContent = "Pick the option that matches your document type, privacy requirements, and setup tolerance."; parserDetailFacts.innerHTML = ""; parserDetailPositioning.textContent = ""; parserDetailSetup.textContent = ""; parserDetailSteps.innerHTML = ""; parserDetailCommandsLabel.style.display = "none"; parserDetailCommands.innerHTML = ""; return; } const ready = isSelectedParserReady(); parserDetailTitle.textContent = parser.label; parserDetailBadge.textContent = ready ? "Ready" : "Setup required"; parserDetailHeadline.textContent = parser.headline || parser.description; parserDetailBestFor.textContent = parser.best_for || parser.description; parserDetailFacts.innerHTML = ""; parserDetailPositioning.textContent = parser.positioning || ""; parserDetailSetup.innerHTML = `${parser.setup}`; parserDetailSteps.innerHTML = ""; parserDetailCommands.innerHTML = ""; parserDetailCommandsLabel.style.display = (parser.commands || []).length ? "block" : "none"; for (const fact of parser.facts || []) { const card = document.createElement("div"); card.className = "parser-fact"; card.innerHTML = ` ${fact.label}
${fact.value}
`; parserDetailFacts.appendChild(card); } for (const step of parser.instructions || []) { const item = document.createElement("li"); item.textContent = step; parserDetailSteps.appendChild(item); } if (parser.requires_user_key && !markerApiKeyInput.value.trim()) { const item = document.createElement("li"); item.textContent = "Upload is locked until you enter your own Datalab API key below."; parserDetailSteps.appendChild(item); } else if (!parser.configured) { const item = document.createElement("li"); item.textContent = "Upload is locked until PaperFlow detects that this parser is configured."; parserDetailSteps.appendChild(item); } for (const command of parser.commands || []) { const block = document.createElement("pre"); block.className = "parser-command"; block.textContent = command; parserDetailCommands.appendChild(block); } } ``` -------------------------------- ### Use PaperFlow to Convert PDF via Claude Desktop Chat Source: https://context7.com/tylermorrison21/paperflow/llms.txt Examples of how to invoke the PaperFlow conversion tool using natural language prompts within Claude Desktop. Supports various input types and parser selection. ```text # In Claude Desktop chat: "Use PaperFlow to convert https://arxiv.org/pdf/1706.03762" ``` ```text # Convert a local file "Use PaperFlow with best parser on C:\Users\you\Desktop\paper.pdf" ``` ```text # Use fast local mode "Use PaperFlow in fast mode on /home/user/papers/report.pdf" ``` ```text # Force a specific parser "Use PaperFlow with parser=paddleocr_vl on this scanned PDF: /tmp/scan.pdf" ``` -------------------------------- ### Get Selected Parser Record Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Retrieves the configuration object for the currently selected parser from the catalog. Returns null if no parser is selected. ```javascript function getSelectedParserRecord() { return parserCatalog.get(selectedParser) || null; } ``` -------------------------------- ### Python Post-processing with PaperFlow Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/index.html Install the paperflow-postprocess package to enhance raw Markdown output. This function can be used to refine text, add metadata, and prepare it for Markdown editors. ```python from paperflow_postprocess import enhance raw_md = open("parser_output.md").read() result = enhance(raw_md, images={}, metadata={"title": "My Paper"}) ``` -------------------------------- ### Initialize UI Element References Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Selects all necessary DOM elements for the PaperFlow application. Ensure these elements exist in the HTML before this script runs. ```javascript const parserGrid = document.getElementById("parser-grid"); const parserBadge = document.getElementById("parser-badge"); const dropzone = document.getElementById("dropzone"); const fileInput = document.getElementById("file-input"); const fileName = document.getElementById("file-name"); const convertButton = document.getElementById("convert-button"); const batchButton = document.getElementById("batch-button"); const clearButton = document.getElementById("clear-button"); const jobStatus = document.getElementById("job-status"); const statusLog = document.getElementById("status-log"); const preview = document.getElementById("preview"); const downloadMarkdown = document.getElementById("download-markdown"); const downloadPackage = document.getElementById("download-package"); const selectedFilesEl = document.getElementById("selected-files"); const progressBar = document.getElementById("progress-bar"); const batchList = document.getElementById("batch-list"); const markerApiKeyShell = document.getElementById("marker-api-key-shell"); const markerApiKeyInput = document.getElementById("marker-api-key"); const parserDetailTitle = document.getElementById("parser-detail-title"); const parserDetailBadge = document.getElementById("parser-detail-badge"); const parserDetailHeadline = document.getElementById("parser-detail-headline"); const parserDetailBestFor = document.getElementById("parser-detail-best-for"); const parserDetailFacts = document.getElementById("parser-detail-facts"); const parserDetailPositioning = document.getElementById("parser-detail-positioning"); const parserDetailSetup = document.getElementById("parser-detail-setup"); const parserDetailSteps = document.getElementById("parser-detail-steps"); const parserDetailCommandsLabel = document.getElementById("parser-detail-commands-label"); const parserDetailCommands = document.getElementById("parser-detail-commands"); ``` -------------------------------- ### PaperFlow Local API - Get Job Result Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/index.html Retrieve the processed Markdown file for a given job ID. ```APIDOC ## GET /api/jobs/{job_id}/result ### Description Retrieves the processed Markdown file for a specific job. ### Method GET ### Endpoint /api/jobs//result ### Parameters #### Path Parameters - **job_id** (string) - Required - The ID of the job. ### Response #### Success Response (200) - **file content** (file) - The processed Markdown file. ``` -------------------------------- ### MCP Call for `get_markdown_chunk` Source: https://context7.com/tylermorrison21/paperflow/llms.txt The JSON payload structure for invoking the `get_markdown_chunk` tool programmatically. Specify the `job_id`, `start` position, and `length` of the desired chunk. ```json # Equivalent MCP call (tool input): { "job_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "start": 12000, "length": 12000 } ``` -------------------------------- ### Run Benchmark Report Source: https://github.com/tylermorrison21/paperflow/blob/master/mcp-server/README.md Commands to prepare and run the benchmark report for the PaperFlow MCP Server. ```bash cp benchmark/results.template.csv benchmark/results.csv npm run bench:report ``` -------------------------------- ### Enable Download Links Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Sets the href attributes and dataset properties for markdown and zip download links based on the provided job ID. Enables the download buttons. ```javascript function enableDownloads(jobId) { downloadMarkdown.href = "#"; downloadPackage.href = "#"; downloadMarkdown.dataset.url = `/api/jobs/${jobId}/result`; downloadPackage.dataset.url = `/api/jobs/${jobId}/package`; downloadMarkdown.dataset.filename = `paperflow-${jobId}.md`; downloadPackage.dataset.filename = `paperflow-${jobId}.zip`; downloadMarkdown.classList.remove("disabled"); downloadPackage.classList.remove("disabled"); } ``` -------------------------------- ### Get Parser Display Label Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Retrieves the user-friendly label for a given parser ID from the parser catalog. Defaults to 'Unknown parser' if the ID is not found. ```javascript function getParserLabel(parserId) { return parserCatalog.get(parserId)?.label || parserId || "Unknown parser"; } ``` -------------------------------- ### Build and Run PaperFlow Locally with Docker Source: https://github.com/tylermorrison21/paperflow/blob/master/README.md Build the PaperFlow Docker image locally from the repository and then run it, mapping ports and volumes. This allows for local development and testing. ```bash docker build -t paperflow . docker run --name paperflow \ -p 8000:8000 \ -e DATA_DIR=/data/jobs \ -v $(pwd)/data:/data \ --restart unless-stopped \ paperflow ``` -------------------------------- ### Run MCP Savings Benchmark Report Source: https://github.com/tylermorrison21/paperflow/blob/master/mcp-server/benchmark/README.md Execute the benchmark report from the mcp-server directory. This command generates a report based on the benchmark results. ```bash npm run bench:report ``` -------------------------------- ### PaperFlow Local API - Get Job Package Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/index.html Retrieve a zip package containing the processed file and any associated assets for a given job ID. ```APIDOC ## GET /api/jobs/{job_id}/package ### Description Retrieves a zip package containing the processed output and assets for a specific job. ### Method GET ### Endpoint /api/jobs//package ### Parameters #### Path Parameters - **job_id** (string) - Required - The ID of the job. ### Response #### Success Response (200) - **file content** (file) - A zip archive containing the processed output. ``` -------------------------------- ### Download Markdown and Images Package Source: https://github.com/tylermorrison21/paperflow/blob/master/README.md Download a zip package containing the processed markdown and associated images for a completed job. ```bash curl http://localhost:8000/api/jobs//package -o paperflow.zip ``` -------------------------------- ### Download ZIP Bundle with Markdown and Images Source: https://context7.com/tylermorrison21/paperflow/llms.txt Download a ZIP archive containing the processed Markdown file and a directory of extracted images for a completed job. ```bash JOB_ID="3fa85f64-5717-4562-b3fc-2c963f66afa6" curl http://localhost:8000/api/jobs/$JOB_ID/package -o paperflow.zip # Unzip and inspect unzip paperflow.zip -d output/ ls output/ # paper.md # images/ # figure-1.png # figure-2.png ``` -------------------------------- ### Handle Download Button Click Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Configures download links based on the batch ID. Use this function when a user interacts with a download button. ```javascript chDownload(batchId) { downloadMarkdown.classList.add("disabled"); delete downloadMarkdown.dataset.url; delete downloadMarkdown.dataset.filename; downloadMarkdown.removeAttribute("href"); downloadPackage.href = "#"; downloadPackage.dataset.url = `/api/batches/${batchId}/package`; downloadPackage.dataset.filename = `paperflow-batch-${batchId}.zip`; downloadPackage.classList.remove("disabled"); } ``` -------------------------------- ### Trigger File Download Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Initiates a file download by fetching a URL, creating a blob, and simulating a click on a temporary link. Ensure the anchor element has `data-url` and optionally `data-filename` attributes. ```javascript async function triggerDownload(anchor) { if (anchor.classList.contains("disabled")) { return; } const url = anchor.dataset.url; const filename = anchor.dataset.filename || "download"; if (!url) { return; } const response = await fetch(url); if (!response.ok) { setStatus("Error", `Download failed: ${response.status}`, "error"); return; } const blob = await response.blob(); const blobUrl = URL.createObjectURL(blob); const tempLink = document.createElement("a"); tempLink.href = blobUrl; tempLink.download = filename; document.body.appendChild(tempLink); tempLink.click(); tempLink.remove(); URL.revokeObjectURL(blobUrl); } ``` -------------------------------- ### Initialize Application State Variables Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Sets up initial state variables for the PaperFlow application, including parser catalog, selected files, and job IDs. These variables manage the application's dynamic behavior. ```javascript let selectedParser = null; let parserCatalog = new Map(); let selectedFiles = []; let activeJobId = null; let activeBatchId = null; let activeParserLabel = ""; let pollTimer = null; let parserRefreshTimer = null; ``` -------------------------------- ### Run MCP Savings Benchmark Report with Template Data Source: https://github.com/tylermorrison21/paperflow/blob/master/mcp-server/benchmark/README.md Execute the benchmark report using template data. This is useful for testing the report generation process without real data. ```bash npm run bench:report:template ``` -------------------------------- ### Input Synchronization and Button Event Listeners Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Sets up event listeners for input changes and button clicks to trigger file submission and batch processing. Also includes synchronization logic for parser requirements. ```javascript markerApiKeyInput.addEventListener("input", syncParserRequirements); convertButton.addEventListener("click", submitFile); batchButton.addEventListener("click", submitBatch); downloadMarkdown.addEventListen ``` -------------------------------- ### File Input and Dropzone Event Listeners Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Configures event listeners for file uploads via click and drag-and-drop. Includes logic to check parser readiness and provide user feedback during drag operations. ```javascript dropzone.addEventListener("click", () => { if (!isSelectedParserReady()) { setStatus("Setup required", "Finish the selected parser setup before uploading PDFs.", "error"); return; } fileInput.click(); }); dropzone.addEventListener("keydown", (event) => { if (event.key === "Enter" || event.key === " ") { event.preventDefault(); if (!isSelectedParserReady()) { setStatus("Setup required", "Finish the selected parser setup before uploading PDFs.", "error"); return; } fileInput.click(); } }); fileInput.addEventListener("change", (event) => handleFiles(event.target.files)); ["dragenter", "dragover"].forEach((eventName) => { dropzone.addEventListener(eventName, (event) => { event.preventDefault(); dropzone.classList.add("dragging"); }); }); ["dragleave", "drop"].forEach((eventName) => { dropzone.addEventListener(eventName, (event) => { event.preventDefault(); dropzone.classList.remove("dragging"); }); }); dropzone.addEventListener("drop", (event) => { if (!isSelectedParserReady()) { setStatus("Setup required", "Finish the selected parser setup before uploading PDFs.", "error"); return; } handleFiles(event.dataTransfer.files); }); ``` -------------------------------- ### Render Selected Files UI Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Updates the UI to display a list of selected files with their names and sizes. ```javascript function renderSelectedFiles() { selectedFilesEl.innerHTML = ""; for (const file of selectedFiles) { const pill = document.createElement("div"); pill.className = "file-pill"; pill.textContent = `${file.name} / ${(file.size / 1024 / 1024).toFixed(2)} MB`; selectedFilesEl.appendChild(pill); } } ``` -------------------------------- ### Check Parser Readiness Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Determines if the selected parser is ready for use, considering its configuration and whether required inputs like an API key are provided. This is crucial before enabling conversion or batch operations. ```javascript function isSelectedParserReady() { const parser = getSelectedParserRecord(); if (!parser || !parser.configured) { return false; } if (parser.requires_user_key && !markerApiKeyInput.value.trim()) { return false; } return true; } ``` -------------------------------- ### Submit PDF with Marker API Parser Source: https://github.com/tylermorrison21/paperflow/blob/master/README.md Submit a PDF using the Marker API parser. Requires your Datalab API key. ```bash curl -X POST http://localhost:8000/api/submit \ -F "file=@paper.pdf" \ -F "parser=marker_api" \ -F "marker_api_key=your_datalab_api_key" ``` -------------------------------- ### List available parsers Source: https://context7.com/tylermorrison21/paperflow/llms.txt Retrieve a list of all supported parsers, including their configuration status and capabilities. ```APIDOC ## GET /api/parsers — List available parsers ### Description Returns a list of all supported parsers with their configuration status, speed/quality labels, setup instructions, and CLI commands. ### Method GET ### Endpoint /api/parsers ### Response #### Success Response - **parsers** (array) - A list of available parser objects. - **id** (string) - The unique identifier for the parser. - **label** (string) - A human-readable name for the parser. - **configured** (boolean) - Indicates if the parser is configured and ready to use. - **recommended** (boolean) - Indicates if this parser is recommended. - **default** (boolean) - Indicates if this parser is the default. - **speed** (string) - A label describing the parser's speed (e.g., "Free", "Fastest"). - **quality** (string) - A label describing the parser's quality (e.g., "Fastest"). - **setup** (string) - Instructions or status regarding parser setup. - **requires_user_key** (boolean) - Indicates if a user-specific API key is required. #### Response Example ```json { "parsers": [ { "id": "pymupdf", "label": "PyMuPDF Local", "configured": true, "recommended": true, "default": true, "speed": "Free", "quality": "Fastest", "setup": "Ready after install. No API key and no parser-specific CLI required.", "requires_user_key": false }, { "id": "paddleocr_vl", "label": "PaddleOCR-VL-0.9B", "configured": false, "setup": "Install PaddleOCR, make sure the paddleocr command works..." }, { "id": "marker_api", "label": "Marker API (Datalab.to)", "configured": true, "requires_user_key": true }, { "id": "marker_local", "label": "Enterprise Marker Self-Hosted", "configured": false } ] } ``` ``` -------------------------------- ### List PaperFlow Parsers via Claude Desktop Chat Source: https://context7.com/tylermorrison21/paperflow/llms.txt Command to list available backend parsers and their status using PaperFlow through Claude Desktop's chat interface. Provides details on parser readiness, quality, and configuration notes. ```text # In Claude Desktop chat: "List my available PaperFlow parsers" ``` -------------------------------- ### Download Markdown and Images Package Source: https://github.com/tylermorrison21/paperflow/blob/master/README.md Download a zip package containing the processed markdown and any extracted images for a completed job. ```APIDOC ## GET /api/jobs/{job_id}/package ### Description Downloads a zip archive containing the processed markdown and associated images for a completed job. ### Method GET ### Endpoint `/api/jobs//package` ### Parameters #### Path Parameters - **job_id** (string) - Required - The unique identifier for the job. ### Request Example ```bash curl http://localhost:8000/api/jobs//package -o paperflow.zip ``` ### Response Example (Response is a zip file, typically saved to a file using `-o paperflow.zip`) ``` -------------------------------- ### Configure Marker API Key for Direct API Calls Source: https://github.com/tylermorrison21/paperflow/blob/master/README.md When making direct API calls, include the parser and your Marker API key as form data. ```bash -F "parser=marker_api" -F "marker_api_key=your_datalab_api_key" ``` -------------------------------- ### Load Parsers and Error Handling Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Initiates loading of parser options, with an option to preserve the current selection. Includes error handling to update the UI if loading fails. ```javascript loadParsers({ preserveSelection: false }).catch((error) => { parserBadge.textContent = "Load failed"; setStatus("Error", `Failed to load parser options: ${error.message}`, "error"); }); ``` -------------------------------- ### Claude Desktop Config for Windows Source: https://github.com/tylermorrison21/paperflow/blob/master/mcp-server/README.md Configuration for Claude Desktop on Windows to use the PaperFlow MCP server, specifying the command, arguments, and environment variables. ```json { "mcpServers": { "paperflow": { "command": "cmd", "args": ["/c", "npx", "-y", "paperflow-mcp@0.3.1"], "env": { "PAPERFLOW_API_URL": "http://localhost:8000" } } } } ``` -------------------------------- ### Select Parser Logic Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Populates the parser selection grid and handles user clicks to pick a parser. It also determines the default or previously selected parser. ```javascript const data = await response.json(); const parsers = data.parsers || []; parserCatalog = new Map(parsers.map((parser) => [parser.id, parser])); parserGrid.innerHTML = ""; for (const parser of parsers) { const label = document.createElement("label"); label.className = "parser-option"; if (!parser.configured) { label.classList.add("disabled"); } label.dataset.parserId = parser.id; label.innerHTML = `
${parser.label}
${parser.speed} / ${parser.quality}

${parser.headline || parser.description}

${parser.best_for || parser.description}

${parser.default ? 'Default' : ""} ${parser.recommended ? 'Recommended' : ""} ${parser.configured ? "Configured" : "Not configured"} ${parser.requires_user_key ? 'BYOK' : ""}

${parser.setup}

`; label.addEventListener("click", () => pickParser(parser.id)); parserGrid.appendChild(label); } const preservedParser = previousSelection && parserCatalog.has(previousSelection) ? parserCatalog.get(previousSelection) : null; const defaultParser = parsers.find((parser) => parser.default && parser.configured) || parsers.find((parser) => parser.configured); const parserToSelect = preservedParser?.id || defaultParser?.id || parsers[0]?.id || null; if (parserToSelect) { pickParser(parserToSelect); const configuredCount = parsers.filter((parser) => parser.configured).length; parserBadge.textContent = `${configuredCount}/${parsers.length} ready`; } else { parserBadge.textContent = "No parser configured"; setStatus("Blocked", "No parser is configured. Install PyMuPDF locally, add your Datalab key for Marker API, or install PaddleOCR-VL locally.", "error"); } ``` -------------------------------- ### Load Available Parsers Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Fetches the list of available parsers from the API and updates the UI. Optionally preserves the current parser selection and shows a loading indicator. ```javascript async function loadParsers({ preserveSelection = true, showLoading = true } = {}) { const previousSelection = preserveSelection ? selectedParser : null; if (showLoading) { parserBadge.textContent = "Loading"; } const response = await fetch("/api/parsers" ``` -------------------------------- ### Run PaperFlow Postprocessing Helpers Source: https://github.com/tylermorrison21/paperflow/blob/master/README.md Apply a sequence of postprocessing functions to a markdown string. Ensure raw markdown is read with UTF-8 encoding before processing. ```python from paperflow_postprocess import ( clean_headers_footers, convert_to_footnotes, fix_latex_delimiters, linkify_figures, linkify_tables, ) md = open("raw.md", encoding="utf-8").read() md = fix_latex_delimiters(md) md = clean_headers_footers(md) md = convert_to_footnotes(md) md = linkify_figures(md) md = linkify_tables(md) ``` -------------------------------- ### Select a Parser Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Handles the selection of a parser by updating the UI to highlight the chosen parser and setting it as the active selection. It then synchronizes the UI with the parser's requirements. ```javascript function pickParser(parserId) { selectedParser = parserId; document.querySelectorAll(".parser-option").forEach((card) => { const isSelected = card.dataset.parserId === parserId; card.classList.toggle("selected", isSelected); const radio = card.querySelector('input[type="radio"]'); if (radio) { radio.checked = isSelected; } }); syncParserRequirements(); } ``` -------------------------------- ### Submit PDF via API Source: https://github.com/tylermorrison21/paperflow/blob/master/README.md Use this endpoint to submit a PDF file for processing. The default PyMuPDF parser is used. ```bash curl -X POST http://localhost:8000/api/submit \ -F "file=@paper.pdf" ``` -------------------------------- ### Handle Download Trigger Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Attaches an event listener to trigger a download action when a specific element is clicked. Prevents default behavior and calls a download function with provided data. ```javascript er("click", async (event) => { event.preventDefault(); await triggerDownload(downloadMarkdown); }); ``` ```javascript downloadPackage.addEventListener("click", async (event) => { event.preventDefault(); await triggerDownload(downloadPackage); }); ``` -------------------------------- ### Unraid Template Configuration Source: https://github.com/tylermorrison21/paperflow/blob/master/docs/unraid.md Use these values when setting up the PaperFlow container via the Unraid Community Apps template. Ensure the AppData path is correctly mapped and the DATA_DIR environment variable is set. ```text Repository: ghcr.io/tylermorrison21/paperflow:latest WebUI: http://[IP]:[PORT:8000]/ Container Port: 8000 AppData path: map /data to /mnt/user/appdata/paperflow DATA_DIR=/data/jobs ``` ```text DATALAB_API_KEY=your_datalab_api_key ``` ```text http://UNRAID-IP:8000/ ``` -------------------------------- ### Configure Enterprise Marker Self-Hosted Command Source: https://github.com/tylermorrison21/paperflow/blob/master/README.md Set the MARKER_SINGLE_CMD environment variable if using a custom path for the marker_single CLI. ```env MARKER_SINGLE_CMD=marker_single MARKER_SINGLE_ARGS= ``` -------------------------------- ### Run Full PaperFlow Post-processing Pipeline Source: https://context7.com/tylermorrison21/paperflow/llms.txt Applies all five transforms plus YAML frontmatter to raw Markdown. Accepts optional image metadata and a metadata dict for title, authors, source, and date. Returns a structured Markdown string. ```python from paperflow_postprocess import enhance raw_markdown = """ # Attention Is All You Need Ashish Vaswani, Noam Shazier ## Abstract The dominant sequence transduction models [1] rely on complex RNNs or CNNs. We propose the Transformer, based solely on attention mechanisms [2, 3]. See results in [Fig. 1] and [Table 1]. \[ E = mc^2 \] ## References [1] Sutskever et al. Sequence to Sequence Learning. NeurIPS 2014. [2] Bahdanau et al. Neural Machine Translation by Jointly Learning. ICLR 2015. [3] Luong et al. Effective Approaches to Attention. EMNLP 2015. Figure 1: Transformer architecture overview. Table 1: BLEU scores on WMT 2014 English-to-German. """ result = enhance( raw_markdown=raw_markdown, images={}, metadata={ "title": "Attention Is All You Need", "authors": ["Ashish Vaswani", "Noam Shazier"], "source": "https://arxiv.org/abs/1706.03762", "date": "2017-06-12", }, ) print(result) # Output begins with YAML frontmatter: # --- # title: "Attention Is All You Need" # authors: # - "Ashish Vaswani" # - "Noam Shazier" # source: "https://arxiv.org/abs/1706.03762" # date: "2017-06-12" # extracted: "2025-01-01" # hash: "a1b2c3d4" # tags: [paperflow, academic] # --- # # Citations converted: [1] -> [^1], [2, 3] -> [^2][^3] # LaTeX converted: \[ E = mc^2 \] -> $$ E = mc^2 $$ # Figures linked: [Fig. 1] -> [[#^fig-1|Fig. 1]] # Tables linked: [Table 1] -> [[#^tab-1|Table 1]] # References section becomes footnote definitions [^1]: ..., [^2]: ..., [^3]: ... ``` -------------------------------- ### Download ZIP bundle Source: https://context7.com/tylermorrison21/paperflow/llms.txt Download a ZIP archive containing the processed Markdown and extracted images for a completed job. ```APIDOC ## GET /api/jobs/{job_id}/package — Download ZIP bundle ### Description Returns a ZIP archive containing `paper.md` and an `images/` directory with all extracted figures. ### Method GET ### Endpoint /api/jobs/{job_id}/package ### Parameters #### Path Parameters - **job_id** (string) - Required - The unique identifier for the job. ### Response #### Success Response (200) Content-Type: application/zip ### Response Example ```bash curl http://localhost:8000/api/jobs/$JOB_ID/package -o paperflow.zip ``` **Archive Contents:** - `paper.md`: The processed Markdown file. - `images/`: A directory containing all extracted figures. ``` -------------------------------- ### Claude Desktop Config for macOS/Linux Source: https://github.com/tylermorrison21/paperflow/blob/master/mcp-server/README.md Configuration for Claude Desktop on macOS and Linux to use the PaperFlow MCP server, specifying the command, arguments, and environment variables. ```json { "mcpServers": { "paperflow": { "command": "npx", "args": ["-y", "paperflow-mcp@0.3.1"], "env": { "PAPERFLOW_API_URL": "http://localhost:8000" } } } } ``` -------------------------------- ### Download Processed Markdown Source: https://github.com/tylermorrison21/paperflow/blob/master/README.md Retrieve the processed markdown content for a completed job. ```bash curl http://localhost:8000/api/jobs//result -o paper.md ``` -------------------------------- ### Submit PDF for processing via `POST /api/submit` Source: https://context7.com/tylermorrison21/paperflow/llms.txt Submits a PDF for asynchronous processing using `multipart/form-data`. Supports multiple parsers and caching for duplicate submissions. The response immediately returns a job ID. ```bash # Submit with default PyMuPDF parser curl -X POST http://localhost:8000/api/submit \ -F "file=@paper.pdf" # {"job_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "message": "Processing. Poll /api/jobs/..."} # Submit with Marker API parser (requires your own Datalab key) curl -X POST http://localhost:8000/api/submit \ -F "file=@paper.pdf" \ -F "parser=marker_api" \ -F "marker_api_key=your_datalab_key_here" # Submit with PaddleOCR-VL for scanned PDFs curl -X POST http://localhost:8000/api/submit \ -F "file=@scanned_paper.pdf" \ -F "parser=paddleocr_vl" ``` -------------------------------- ### Configure PaddleOCR-VL Command Source: https://github.com/tylermorrison21/paperflow/blob/master/README.md Set the PADDLEOCR_VL_CMD environment variable if using a custom path for the paddleocr executable. ```env PADDLEOCR_VL_CMD=paddleocr PADDLEOCR_VL_ARGS= ``` -------------------------------- ### Render Batch Processing List Source: https://github.com/tylermorrison21/paperflow/blob/master/frontend/app.html Renders a list of items for batch processing, displaying filename, status, and any errors. Each item is represented as a div element. ```javascript function renderBatchItems(items = []) { batchList.innerHTML = ""; for (const item of items) { const row = document.createElement("div"); row.className = "batch-item"; row.innerHTML = `
${item.filename} ${item.error || item.parser || ""}
${item.status || "queued"}
`; batchList.appendChild(row); } } ``` -------------------------------- ### enhance() — Full post-processing pipeline Source: https://context7.com/tylermorrison21/paperflow/llms.txt The primary entry point for PaperFlow. Applies all five transforms plus YAML frontmatter to raw Markdown from any PDF parser. Accepts optional image metadata and a metadata dict for title, authors, source, and date. Returns a structured Markdown string ready for knowledge bases or RAG pipelines. ```APIDOC ## enhance() ### Description Applies all five transforms plus YAML frontmatter to raw Markdown from any PDF parser. Accepts optional image metadata and a metadata dict for title, authors, source, and date. Returns a structured Markdown string ready for knowledge bases or RAG pipelines. ### Parameters - **raw_markdown** (str) - Required - The raw Markdown string to process. - **images** (dict) - Optional - Metadata for images. - **metadata** (dict) - Optional - Metadata for the document, including title, authors, source, and date. ### Returns - **str** - The structured Markdown string. ### Request Example ```python from paperflow_postprocess import enhance raw_markdown = """ # Attention Is All You Need Ashish Vaswani, Noam Shazier ## Abstract The dominant sequence transduction models [1] rely on complex RNNs or CNNs. We propose the Transformer, based solely on attention mechanisms [2, 3]. See results in [Fig. 1] and [Table 1]. \[ E = mc^2 \] ## References [1] Sutskever et al. Sequence to Sequence Learning. NeurIPS 2014. [2] Bahdanau et al. Neural Machine Translation by Jointly Learning. ICLR 2015. [3] Luong et al. Effective Approaches to Attention. EMNLP 2015. Figure 1: Transformer architecture overview. Table 1: BLEU scores on WMT 2014 English-to-German. """ result = enhance( raw_markdown=raw_markdown, images={}, metadata={ "title": "Attention Is All You Need", "authors": ["Ashish Vaswani", "Noam Shazier"], "source": "https://arxiv.org/abs/1706.03762", "date": "2017-06-12", }, ) print(result) ``` ### Response Example ``` --- title: "Attention Is All You Need" authors: - "Ashish Vaswani" - "Noam Shazier" source: "https://arxiv.org/abs/1706.03762" date: "2017-06-12" extracted: "2025-01-01" hash: "a1b2c3d4" tags: [paperflow, academic] --- Citations converted: [1] -> [^1], [2, 3] -> [^2][^3] LaTeX converted: \[ E = mc^2 \] -> $$ E = mc^2 $$ Figures linked: [Fig. 1] -> [[#^fig-1|Fig. 1]] Tables linked: [Table 1] -> [[#^tab-1|Table 1]] References section becomes footnote definitions [^1]: ..., [^2]: ..., [^3]: ... ``` ``` -------------------------------- ### Submit PDF with PaddleOCR-VL Parser Source: https://github.com/tylermorrison21/paperflow/blob/master/README.md Submit a PDF using the PaddleOCR-VL parser, suitable for scanned documents and complex layouts. ```bash curl -X POST http://localhost:8000/api/submit \ -F "file=@paper.pdf" \ -F "parser=paddleocr_vl" ``` -------------------------------- ### Configure Environment Variables for PaperFlow Source: https://context7.com/tylermorrison21/paperflow/llms.txt This file contains essential configuration variables for the PaperFlow application, including API keys, file paths, and operational limits. Ensure these are set correctly before running the application. ```env DATALAB_API_KEY=your_datalab_key_here # For Marker API parser MARKER_API_URL=https://www.datalab.to/api/v1/marker MARKER_SINGLE_CMD=marker_single # Path to marker_single CLI MARKER_SINGLE_ARGS= # Extra flags for marker_single PADDLEOCR_VL_CMD=paddleocr # Path to paddleocr CLI PADDLEOCR_VL_ARGS= # Extra flags for paddleocr RESEND_API_KEY= # For email delivery (optional) FROM_EMAIL=delivery@paperflowing.com CORS_ORIGINS=* DATA_DIR=./data/jobs DAILY_SUBMISSION_LIMIT=300 MONTHLY_PAGE_LIMIT=8000 PER_EMAIL_DAILY_LIMIT=3 MAX_FILE_SIZE_MB=15 MAX_PAGES=15 ``` -------------------------------- ### Configure Claude Desktop MCP Servers Source: https://context7.com/tylermorrison21/paperflow/llms.txt Configuration for PaperFlow's MCP server within Claude Desktop on macOS/Linux. Ensure the PAPERFLOW_API_URL is set to your local PaperFlow instance. ```json // Claude Desktop config (macOS/Linux): ~/Library/Application Support/Claude/claude_desktop_config.json { "mcpServers": { "paperflow": { "command": "npx", "args": ["-y", "paperflow-mcp@0.3.1"], "env": { "PAPERFLOW_API_URL": "http://localhost:8000", "PAPERFLOW_MARKER_API_KEY": "your_datalab_key_optional" } } } } ``` -------------------------------- ### Download combined batch package Source: https://context7.com/tylermorrison21/paperflow/llms.txt Download a ZIP archive containing all processed papers and their associated images from a batch job. ```APIDOC ## GET /api/batches/{batch_id}/package — Download ZIP bundle ### Description Returns a ZIP archive containing processed Markdown files and extracted images for all papers in a batch job. Each paper will have its own subdirectory. ### Method GET ### Endpoint /api/batches/{batch_id}/package ### Parameters #### Path Parameters - **batch_id** (string) - Required - The unique identifier for the batch job. ### Response #### Success Response (200) Content-Type: application/zip ### Response Example ```bash curl http://localhost:8000/api/batches/abc12345-.../package -o batch.zip ``` **Archive Contents:** - `paper1/paper.md`: Processed Markdown for the first paper. - `paper1/images/*`: Extracted images for the first paper. - `paper2/paper.md`: Processed Markdown for the second paper. - `paper2/images/*`: Extracted images for the second paper. - `summary.json`: A summary file for the batch. ```