save_redacted_pdf
Apply redaction annotations to PDF documents and save the secured version, automatically generating output files with '_redacted' suffix when no custom path is specified.
Instructions
Apply all redactions and save the redacted PDF.
This tool applies all pending redaction annotations to the PDF and saves it. By default, it saves to a new file with '_redacted' appended to the original filename.
Args: pdf_path: Path to the PDF file (must be already loaded) output_path: Optional custom output path. If not provided, saves as '<original_name>_redacted.pdf' ctx: MCP context for logging
Returns: Path to the saved redacted PDF
Raises: ToolError: If the PDF is not loaded or save fails
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| output_path | No | Optional output path. If not provided, appends '_redacted' to the original filename | |
| pdf_path | Yes | Path to the loaded PDF file |
Implementation Reference
- src/redact_mcp/server.py:288-358 (handler)The core handler function for the 'save_redacted_pdf' tool. It applies all redaction annotations to the loaded PDF using PyMuPDF's apply_redactions() method on each page, determines the output path (defaulting to appending '_redacted' to the input filename), saves the document, and returns a confirmation message with the save location and number of pages with redactions.@mcp.tool async def save_redacted_pdf( pdf_path: Annotated[str, Field(description="Path to the loaded PDF file")], output_path: Annotated[str | None, Field( description="Optional output path. If not provided, appends '_redacted' to the original filename" )] = None, ctx: Context = None ) -> str: """Apply all redactions and save the redacted PDF. This tool applies all pending redaction annotations to the PDF and saves it. By default, it saves to a new file with '_redacted' appended to the original filename. Args: pdf_path: Path to the PDF file (must be already loaded) output_path: Optional custom output path. If not provided, saves as '<original_name>_redacted.pdf' ctx: MCP context for logging Returns: Path to the saved redacted PDF Raises: ToolError: If the PDF is not loaded or save fails """ try: path = Path(pdf_path).resolve() path_str = str(path) await ctx.info(f"Saving redacted PDF: {path}") # Check if PDF is loaded if path_str not in _loaded_pdfs: raise ToolError( f"PDF not loaded. Please load it first using load_pdf: {path}" ) doc = _loaded_pdfs[path_str] # Determine output path if output_path: out_path = Path(output_path).resolve() else: # Append '_redacted' to the original filename out_path = path.parent / f"{path.stem}_redacted{path.suffix}" # Count total redactions before applying total_redactions = 0 for page in doc: # Apply redactions on this page redact_count = page.apply_redactions() if redact_count: total_redactions += 1 # Note: apply_redactions returns True if any were applied # Save the document doc.save(str(out_path)) await ctx.info(f"Saved redacted PDF to: {out_path}") return ( f"Successfully applied redactions and saved to: {out_path}\n" f"Redactions applied on {total_redactions} page(s)." ) except ToolError: raise except Exception as e: await ctx.error(f"Failed to save redacted PDF: {str(e)}") raise ToolError(f"Failed to save redacted PDF: {str(e)}")
- src/redact_mcp/server.py:288-288 (registration)The @mcp.tool decorator registers the save_redacted_pdf function as an MCP tool with FastMCP, automatically generating schema from type annotations.@mcp.tool
- src/redact_mcp/server.py:290-294 (schema)Input schema defined via Pydantic Annotated fields and type hints: required pdf_path (str), optional output_path (str|None), optional ctx (Context).pdf_path: Annotated[str, Field(description="Path to the loaded PDF file")], output_path: Annotated[str | None, Field( description="Optional output path. If not provided, appends '_redacted' to the original filename" )] = None, ctx: Context = None