PDF Redaction Server
БесплатноНе проверенA Model Context Protocol (MCP) server that provides comprehensive PDF redaction capabilities, including text and image redaction, search, and session-based in-m
Описание
A Model Context Protocol (MCP) server that provides comprehensive PDF redaction capabilities, including text and image redaction, search, and session-based in-memory operations using FastMCP and pymupdf.
README
A Model Context Protocol (MCP) server that provides comprehensive PDF redaction capabilities using FastMCP and pymupdf.
Features
This MCP server enables LLMs to:
- Session-based in-memory operations - load PDFs once and perform multiple operations without repeated file I/O
- Load and save PDFs - explicit control over when documents are read from and written to disk
- Extract text from PDFs in multiple formats (plain text, JSON, or structured blocks)
- Search for text patterns using exact match or regex with location information
- Redact text by search - automatically find and redact all occurrences of specified strings
- Redact by coordinates - precisely redact specific areas of a PDF
- Redact images - remove images from PDFs with customisable overlays
- Verify redactions - confirm that sensitive information has been properly removed
- Get PDF information - retrieve metadata and structure information
Installation
Prerequisites
- Python 3.10 or higher
- uv (recommended) or pip
Using uv (Recommended)
# Clone or download the project
cd pdf-redaction-mcp
# Install dependencies
uv sync
# Run the server
uv run pdf-redaction-mcp
Using pip
pip install -e .
pdf-redaction-mcp
Usage
Running the Server
The server supports multiple transport modes and configurations via command-line flags:
# Show all available options
uv run pdf-redaction-mcp --help
# STDIO mode (default) - for desktop clients
uv run pdf-redaction-mcp
# SSE mode - for mobile apps and remote clients
uv run pdf-redaction-mcp --transport sse --port 8000
# HTTP mode - for web-based clients
uv run pdf-redaction-mcp --transport http --host 0.0.0.0 --port 8080
# With custom PDF directory (relative paths resolved against this)
uv run pdf-redaction-mcp --pdf-dir /path/to/pdfs
# Combined options
uv run pdf-redaction-mcp --transport sse --port 8000 --pdf-dir ~/Documents/pdfs
Command-Line Options
--transport {stdio,http,sse}: Transport mode (default: stdio)--host HOST: Host to bind to for HTTP/SSE mode (default: 127.0.0.1)--port PORT: Port to listen on for HTTP/SSE mode (default: 8000)--pdf-dir PDF_DIR: Base directory for PDF files. Relative paths in tools will be resolved against this directory.
Available Tools
All tools work with in-memory PDF documents using a session-based workflow:
- Load a PDF into memory with
load_pdf - Operate on it with any of the tools below
- Save changes to disk with
save_pdf
This approach avoids repeated file I/O and allows multiple operations on the same document efficiently.
1. load_pdf
Load a PDF file into memory for session-based operations.
Parameters:
pdf_path(str): Path to the PDF file to loaddocument_id(str, optional): Identifier for this document (defaults to filename)
Returns: JSON with document_id and basic info
Example:
load_pdf(
pdf_path="/path/to/document.pdf",
document_id="my_doc"
)
# Returns: {"document_id": "my_doc", "pages": 10, "status": "loaded"}
2. save_pdf
Save an in-memory PDF document to disk.
Parameters:
document_id(str): Identifier of the loaded documentoutput_path(str): Path where the PDF will be saved
Returns: JSON with save confirmation
Example:
save_pdf(
document_id="my_doc",
output_path="/path/to/output.pdf"
)
3. close_pdf
Close and remove an in-memory PDF document to free memory.
Parameters:
document_id(str): Identifier of the loaded document
Returns: JSON with close confirmation
Example:
close_pdf(document_id="my_doc")
4. list_loaded_pdfs
List all currently loaded PDF documents in memory.
Returns: JSON with information about all loaded documents
Example:
list_loaded_pdfs()
# Returns: {"total_documents": 2, "documents": [{...}, {...}]}
5. extract_text_from_pdf
Extract text from a loaded PDF document.
Parameters:
document_id(str): Identifier of the loaded documentpage_number(int, optional): Specific page to extract (0-indexed)format(str): Output format - "text", "json", or "blocks"
Example:
# Load document first
load_pdf(pdf_path="/path/to/document.pdf", document_id="doc1")
# Extract all text
extract_text_from_pdf(
document_id="doc1",
format="text"
)
# Extract specific page as JSON
extract_text_from_pdf(
document_id="doc1",
page_number=0,
format="json"
)
6. search_text_in_pdf
Search for text patterns and get their locations in a loaded PDF document.
Parameters:
document_id(str): Identifier of the loaded documentsearch_string(str): Text or regex pattern to search forcase_sensitive(bool): Whether search should be case sensitiveuse_regex(bool): Whether to treat search_string as regexpage_number(int, optional): Specific page to search
Example:
# Load document first
load_pdf(pdf_path="/path/to/document.pdf", document_id="doc1")
# Search for email addresses using regex
search_text_in_pdf(
document_id="doc1",
search_string=r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b",
use_regex=True
)
7. redact_text_by_search
Automatically find and redact all occurrences of specified strings in a loaded PDF document.
Parameters:
document_id(str): Identifier of the loaded documentsearch_strings(List[str]): List of strings to redactfill_color(Tuple[float, float, float]): RGB colour (0-1 range)overlay_text(str): Optional text over redacted areatext_color(Tuple[float, float, float]): RGB colour for overlay text
Example:
# Load document
load_pdf(pdf_path="/path/to/input.pdf", document_id="doc1")
# Redact sensitive information (modifies in-memory document)
redact_text_by_search(
document_id="doc1",
search_strings=["CONFIDENTIAL", "[email protected]", "123-45-6789"],
fill_color=(0, 0, 0), # Black
overlay_text="[REDACTED]"
)
# Save the redacted document
save_pdf(document_id="doc1", output_path="/path/to/redacted.pdf")
8. redact_by_coordinates
Redact specific areas by their exact coordinates in a loaded PDF document.
Parameters:
document_id(str): Identifier of the loaded documentredactions(List[Dict]): List of redaction areas with page, bbox, and optional textfill_color(Tuple[float, float, float]): RGB colouroverlay_text(str): Default overlay text
Example:
# Load document
load_pdf(pdf_path="/path/to/input.pdf", document_id="doc1")
# Redact specific areas (modifies in-memory document)
redact_by_coordinates(
document_id="doc1",
redactions=[
{"page": 0, "bbox": [100, 100, 300, 150], "text": "REDACTED"},
{"page": 1, "bbox": [50, 200, 250, 250]}
],
fill_color=(0, 0, 0)
)
# Save the redacted document
save_pdf(document_id="doc1", output_path="/path/to/redacted.pdf")
9. redact_images_in_pdf
Remove all images from specified pages of a loaded PDF document.
Parameters:
document_id(str): Identifier of the loaded documentpage_numbers(List[int], optional): Pages to process (all if None)fill_color(Tuple[float, float, float]): RGB colouroverlay_text(str): Text over redacted images
Example:
# Load document
load_pdf(pdf_path="/path/to/input.pdf", document_id="doc1")
# Redact all images on first two pages (modifies in-memory document)
redact_images_in_pdf(
document_id="doc1",
page_numbers=[0, 1],
overlay_text="[IMAGE REMOVED]"
)
# Save the redacted document
save_pdf(document_id="doc1", output_path="/path/to/no_images.pdf")
10. verify_redactions
Verify that redactions were applied correctly by comparing two loaded PDF documents.
Parameters:
original_document_id(str): Identifier of the original documentredacted_document_id(str): Identifier of the redacted documentsearch_strings(List[str], optional): Strings that should be gone
Example:
# Load both documents
load_pdf(pdf_path="/path/to/original.pdf", document_id="original")
load_pdf(pdf_path="/path/to/redacted.pdf", document_id="redacted")
# Verify sensitive data was removed
verify_redactions(
original_document_id="original",
redacted_document_id="redacted",
search_strings=["CONFIDENTIAL", "[email protected]"]
)
11. get_pdf_info
Get metadata and structure information about a loaded PDF document.
Parameters:
document_id(str): Identifier of the loaded document
Example:
# Load document first
load_pdf(pdf_path="/path/to/document.pdf", document_id="doc1")
# Get PDF information
get_pdf_info(document_id="doc1")
Configuration
This section covers how to configure the PDF Redaction MCP Server with various MCP clients.
Quick Links:
- Claude Desktop - Most common desktop setup
- Cursor IDE - For developers using Cursor
- Cline (VSCode) - VSCode MCP extension
- Other MCP Clients - Generic STDIO configuration
Claude Desktop
Add to your claude_desktop_config.json:
Basic Configuration (STDIO mode):
{
"mcpServers": {
"pdf-redaction": {
"command": "uv",
"args": [
"--directory",
"/path/to/pdf-redaction-mcp",
"run",
"pdf-redaction-mcp"
]
}
}
}
With Custom PDF Directory:
{
"mcpServers": {
"pdf-redaction": {
"command": "uv",
"args": [
"--directory",
"/path/to/pdf-redaction-mcp",
"run",
"pdf-redaction-mcp",
"--pdf-dir",
"/Users/yourname/Documents/PDFs"
]
}
}
}
This allows you to use relative paths like "document.pdf" instead of full paths.
Cursor IDE
Add to your .cursor/mcp.json:
{
"mcpServers": {
"pdf-redaction": {
"command": "uv",
"args": [
"--directory",
"/path/to/pdf-redaction-mcp",
"run",
"pdf-redaction-mcp"
]
}
}
}
Cline (VSCode Extension)
Add to your Cline MCP settings:
{
"mcpServers": {
"pdf-redaction": {
"command": "uv",
"args": [
"--directory",
"/path/to/pdf-redaction-mcp",
"run",
"pdf-redaction-mcp",
"--pdf-dir",
"${workspaceFolder}/pdfs"
]
}
}
}
Other MCP Clients
For any MCP client supporting STDIO transport, use:
Command: uv
Args:
--directory /path/to/pdf-redaction-mcp
run
pdf-redaction-mcp
[optional flags like --pdf-dir]
Environment Variables (Optional)
For production deployments, you can use environment variables:
# Set PDF directory via environment
export PDF_DIR=/var/pdfs
# Then reference in your startup script
uv run pdf-redaction-mcp --pdf-dir "$PDF_DIR"
Real-World Configuration Examples
Example 1: Personal Use with Claude Desktop
Store all PDFs in your Documents folder:
{
"mcpServers": {
"pdf-redaction": {
"command": "uv",
"args": [
"--directory",
"/Users/yourname/workspace/pdf-redaction-mcp",
"run",
"pdf-redaction-mcp",
"--pdf-dir",
"/Users/yourname/Documents"
]
}
}
}
Now you can say: "Redact emails from report.pdf" instead of using full paths.
Example 2: Team Deployment with Shared PDFs
Deploy remotely with network-mounted PDF storage:
# On your server
uv run pdf-redaction-mcp \
--transport sse \
--host 0.0.0.0 \
--port 8000 \
--pdf-dir /mnt/shared-pdfs
Team members configure their clients to use the remote server.
Example 3: Development Setup
Use project-relative paths during development:
{
"mcpServers": {
"pdf-redaction": {
"command": "uv",
"args": [
"--directory",
"${workspaceFolder}/pdf-redaction-mcp",
"run",
"pdf-redaction-mcp",
"--pdf-dir",
"${workspaceFolder}/test-pdfs"
]
}
}
}
Workflow Examples
Example 1: Redact Personal Information
Session-based workflow (new approach):
User: "Please redact all email addresses and phone numbers from report.pdf"
1. LLM loads the document:
load_pdf(pdf_path="report.pdf", document_id="report")
2. LLM searches for patterns:
search_text_in_pdf(
document_id="report",
search_string=r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b",
use_regex=True
)
3. LLM redacts in-memory:
redact_text_by_search(
document_id="report",
search_strings=["[email protected]", "555-123-4567", ...]
)
4. LLM saves the result:
save_pdf(document_id="report", output_path="report_redacted.pdf")
5. LLM reports: "Successfully redacted 5 email addresses and 3 phone numbers"
Benefits of session-based approach:
- PDF loaded once, multiple operations performed
- No repeated file I/O
- Can verify, modify, and re-verify without reloading
Example 2: Redact Specific Section
1. User: "Redact the financial table on page 3 of the report"
2. LLM loads document:
load_pdf(pdf_path="report.pdf", document_id="report")
3. LLM extracts page structure:
extract_text_from_pdf(document_id="report", page_number=2, format="blocks")
4. LLM identifies table coordinates from block structure
5. LLM redacts in-memory:
redact_by_coordinates(
document_id="report",
redactions=[{"page": 2, "bbox": [100, 200, 500, 400]}]
)
6. LLM verifies by extracting text again:
extract_text_from_pdf(document_id="report", page_number=2)
7. LLM saves:
save_pdf(document_id="report", output_path="report_redacted.pdf")
Example 3: Remove All Images
1. User: "Remove all images from the document but keep the text"
2. LLM loads document:
load_pdf(pdf_path="document.pdf", document_id="doc")
3. LLM checks for images:
get_pdf_info(document_id="doc")
4. LLM redacts images:
redact_images_in_pdf(document_id="doc")
5. LLM verifies and saves:
get_pdf_info(document_id="doc") # Verify images are gone
save_pdf(document_id="doc", output_path="document_no_images.pdf")
6. LLM cleans up:
close_pdf(document_id="doc") # Free memory
Example 4: Multi-Step Verification Workflow
1. User: "Redact all SSNs, then verify they're gone, then redact names too"
2. LLM loads document:
load_pdf(pdf_path="sensitive.pdf", document_id="sensitive")
3. LLM redacts SSNs:
redact_text_by_search(
document_id="sensitive",
search_strings=[r"\d{3}-\d{2}-\d{4}"],
use_regex=True
)
4. LLM creates checkpoint by saving:
save_pdf(document_id="sensitive", output_path="sensitive_step1.pdf")
5. LLM loads original for comparison:
load_pdf(pdf_path="sensitive.pdf", document_id="original")
6. LLM verifies:
verify_redactions(
original_document_id="original",
redacted_document_id="sensitive",
search_strings=["123-45-6789", "987-65-4321"]
)
7. LLM continues with name redaction:
redact_text_by_search(
document_id="sensitive",
search_strings=["John Doe", "Jane Smith"]
)
8. LLM saves final version:
save_pdf(document_id="sensitive", output_path="sensitive_final.pdf")
9. LLM cleans up:
close_pdf(document_id="original")
close_pdf(document_id="sensitive")
- LLM verifies using get_pdf_info that images are gone
---
## Troubleshooting
### Claude Desktop Connection Issues
**Problem:** MCP server not connecting in Claude Desktop
**Solutions:**
1. Verify the path in `claude_desktop_config.json` is correct:
```bash
# Check if the directory exists
ls -la /path/to/pdf-redaction-mcp
Test the server manually:
cd /path/to/pdf-redaction-mcp uv run pdf-redaction-mcp --helpCheck Claude Desktop logs:
- macOS:
~/Library/Logs/Claude/ - Windows:
%APPDATA%\Claude\logs\ - Linux:
~/.config/Claude/logs/
- macOS:
PDF Path Issues
Problem: "File not found" errors when using relative paths
Solution: Configure --pdf-dir flag in your MCP client config:
{
"mcpServers": {
"pdf-redaction": {
"command": "uv",
"args": [
"--directory", "/path/to/pdf-redaction-mcp",
"run", "pdf-redaction-mcp",
"--pdf-dir", "/your/pdf/directory"
]
}
}
}
Port Already in Use (HTTP/SSE mode)
Problem: Address already in use error when starting server
Solution:
Use a different port:
uv run pdf-redaction-mcp --transport sse --port 8001Or find and kill the process using the port:
# macOS/Linux lsof -ti:8000 | xargs kill -9 # Windows netstat -ano | findstr :8000 taskkill /PID <PID> /F
UV Not Found
Problem: uv: command not found
Solution: Install UV package manager:
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
# Or use pip
pip install uv
Development
Running Tests
uv run pytest
Project Structure
pdf-redaction-mcp/
├── src/
│ └── pdf_redaction_mcp/
│ ├── __init__.py
│ └── server.py # Main MCP server implementation
├── tests/
│ └── test_server.py # Unit tests
├── pyproject.toml # Project dependencies
└── README.md # This file
Technical Details
Redaction Implementation
The server uses pymupdf's redaction annotations, which:
- Add redaction annotations to mark areas for removal
- Apply redactions to permanently remove content
- Cannot be undone once saved - content is truly deleted from PDF structure
Colour Format
Colours are specified as RGB tuples with values from 0 to 1:
- Black:
(0, 0, 0) - White:
(1, 1, 1) - Red:
(1, 0, 0) - Green:
(0, 1, 0) - Blue:
(0, 0, 1)
Coordinate System
PDF coordinates use bottom-left origin:
x0, y0: Bottom-left corner of rectanglex1, y1: Top-right corner of rectangle
Bounding boxes: [x0, y0, x1, y1]
Security Considerations
- Permanent Removal: Redactions permanently remove content from PDF structure
- Verify Redactions: Always use
verify_redactionsto confirm sensitive data is gone - Backup Original: Keep original files backed up before redacting
- File Paths: Ensure proper file path validation in production
- Access Control: Implement appropriate access controls for sensitive documents
Limitations
- Only works with PDF files (use pymupdf's supported formats)
- Encrypted PDFs may require password authentication
- Very large PDFs may require significant memory
- Redactions are permanent once saved
Contributing
Contributions are welcome! Please ensure:
- Code follows existing style
- Tests pass (
uv run pytest) - Documentation is updated
- Commit messages are clear
Licence
MIT Licence - see LICENCE file for details
Acknowledgements
- FastMCP - MCP framework
- pymupdf - PDF manipulation library
- Model Context Protocol - MCP specification
Support
For issues, questions, or contributions:
- Open an issue on GitHub
- Check the FastMCP documentation
- Check the pymupdf documentation
Установка PDF Redaction Server
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/marc-hanheide/pdf-redaction-mcpFAQ
PDF Redaction Server MCP бесплатный?
Да, PDF Redaction Server MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для PDF Redaction Server?
Нет, PDF Redaction Server работает без API-ключей и переменных окружения.
PDF Redaction Server — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить PDF Redaction Server в Claude Desktop, Claude Code или Cursor?
Открой PDF Redaction Server на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
Omni Video
An MCP server that transforms LLM-enabled IDEs into professional video editors by pre-processing footage into text proxies, generating motion graphics via HTML/
автор: buildwithtazaARA
Generate images, video and audio from any AI agent — one connector.
автор: ARAYouTube
Transcripts, channel stats, search
автор: YouTubeEverArt
AI image generation using various models.
автор: modelcontextprotocolCompare PDF Redaction Server with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории media
