save_redacted_pdf
Apply redaction annotations to PDF documents and save the redacted version to a new file with '_redacted' appended to the original filename or a custom output path.
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 |
|---|---|---|---|
| pdf_path | Yes | Path to the loaded PDF file | |
| output_path | No | Optional output path. If not provided, appends '_redacted' to the original filename |
Implementation Reference
- src/redact_mcp/server.py:288-358 (handler)The handler function decorated with @mcp.tool that implements the save_redacted_pdf tool. It applies all pending redaction annotations to the loaded PDF document and saves it to a new file, either at a specified output_path or by appending '_redacted' to the original filename.@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)}")