Skip to main content
Glama

Server Details

Edit text inside existing PDFs: replace, delete, redact, insert, fill forms; original fonts kept.

Ownership verified
Status
Healthy
Uptime
100.0% over 20 days
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL
Repository
zp130221/pdfedit-mcp
GitHub Stars
0
Server Listing
pdfedit
ChatGPT
–
Claude
–

TDQS

A4.2/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct action: batch mail-merge editing (pdf_batch), single-document editing (pdf_edit), text extraction/search (pdf_find), async job polling (pdf_job), and page rendering (pdf_preview). The only potential overlap, batch vs. single edit, is explicitly disambiguated by the description and the returned job_id. Read vs. render is also cleanly separated by text vs. image output.

Naming Consistency5/5

All five tools use a single consistent `pdf_` prefix followed by one short lowercase word (batch, edit, find, job, preview). No mixed casing or verb-style drift, so the pattern is fully predictable.

Tool Count5/5

Five tools is well-scoped for a PDF editing server: edit, batch, inspect text, preview visually, and retrieve async results. Each tool covers a necessary part of the workflow and none looks redundant.

Completeness4/5

The read/preview/edit/batch/async-retrieval lifecycle is fully covered, including redaction and form/image stamping. Gaps remain at the document level: no creation from scratch, page reordering/deletion/extraction, or merge/split operations, which agents must work around.

Available Tools

5 tools
pdf_batchBatch-edit a PDF templateA
Idempotent
Inspect

Apply the same edits to one template PDF once per record, producing one output document per record — a mail merge over an existing PDF. Returns a job_id: call pdf_job with it for the per-record results. To change text on one page only, set scope.pages; to pick one of several identical matches, use scope.after with nearby text or scope.occurrence. Use op: 'redact' when the text must be unrecoverable.

NameRequiredDescriptionDefault
fileYesThe PDF: an absolute (or ~) local path, which this server uploads for you, an https:// URL the API fetches, or an `f_…` file id from an earlier call. Used as the template for every record.
editsYesThe edits applied to each record, with `{field}` placeholders filled from it.
optionsNo
recordsNoOne object per output document.
passwordNo
records_urlNoA CSV or JSONL file of records, instead of `records`.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotent, non-destructive, open-world behavior, so the description only needs to add flow and risk context — which it does: an async job handle, a required follow-up call, and the warning that redaction (irreversible) is the choice when text must be unrecoverable. It does not mention options that change behavior materially (dry_run, preview, atomic, output zip/files, webhook).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, front-loaded with the core definition, then the job handoff, then scoping hints. No filler, and each sentence maps to a decision the caller must make.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The core workflow and return path are covered, but for a tool with 6 params, deep nested edit objects, and a 20+ field options object, the description never mentions the records vs records_url alternative, dry_run/preview for validation, or output zip vs files. Those gaps matter given there is no output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 67%, and the description fills the most important gap: scope.after and scope.occurrence carry no schema descriptions but are explained here as disambiguators for duplicate matches, along with scope.pages for page limiting. It leaves records vs records_url and most of options undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource with scope: apply the same edits to one template once per record, producing one output per record. The 'mail merge over an existing PDF' framing separates it cleanly from the single-document sibling pdf_edit without requiring the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear operational context: it returns a job_id and pdf_job must be called for per-record results, and it names the conditions that select scope.pages vs scope.after/occurrence vs op:'redact'. It stops short of explicitly contrasting with pdf_edit/pdf_preview, so no exclusion guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pdf_editEdit a PDFA
Idempotent
Inspect

Edit an existing PDF in place: replace, delete, redact or insert text, fill form fields, stamp an image (a signature, a chop) into a box or remove one, keeping the original layout, fonts and everything you did not point at. edits[] is taken exactly as the API takes it (op, scope, match, fit), and the result carries up to 3 before/after previews of the pages that changed. To change text on one page only, set scope.pages; to pick one of several identical matches, use scope.after with nearby text or scope.occurrence. Use op: 'redact' when the text must be unrecoverable.

NameRequiredDescriptionDefault
fileYesThe PDF: an absolute (or ~) local path, which this server uploads for you, an https:// URL the API fetches, or an `f_…` file id from an earlier call.
editsYesThe edits to apply, in order, exactly as `POST /v1/edit` takes them.
optionsNo
passwordNoThe document open password, when it has one.
output_pathNoWhere to write the edited PDF (stdio mode only). Default: `<name>.edited.pdf` next to the input, or `<name>.edited.2.pdf`, `.3.pdf`, ... when that exists; an earlier result is never overwritten.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds real context beyond annotations: the original layout and fonts are preserved, the result returns up to 3 before/after page previews, and redaction is explicitly unrecoverable. That last point sits in mild tension with destructiveHint=false, but the tool writes to a separate output_path and never overwrites a prior result, so the annotation is defensible rather than contradicted.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the operation inventory, then progressively narrows to scoping and redaction guidance. Dense but nearly every clause carries information; the 'taken exactly as the API takes it' phrasing is slightly opaque jargon that costs a little clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex, deeply nested, mutation tool with no output schema, the description covers the essentials: what gets modified, what is preserved, that previews come back, and that writes go to a separate file. It does not touch the options object (async, dry_run, atomic, webhook), which is left entirely to schema descriptions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 80%, and the description still adds meaning on the hardest parameter: edits[] is passed through exactly as the API takes it, with which sub-keys matter (op, scope, match, fit) called out. It also explains the scope.after / scope.occurrence disambiguation, which the schema alone leaves implicit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (edit an existing PDF in place) and enumerates the exact operation families it covers: text replace/delete/redact/insert, form fill, image stamp/remove. This is clearly distinguishable from pdf_find (search) and pdf_preview (render) siblings without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete selection guidance for the ambiguous cases: scope.pages for single-page targeting, scope.after / scope.occurrence to disambiguate identical matches, and op:'redact' when text must be unrecoverable. It does not explicitly say when to prefer this over pdf_batch or pdf_preview, so it stops short of full when/when-not coverage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pdf_findRead the text of a PDFA
Read-onlyIdempotent
Inspect

Read the text of a PDF: every span with its page, position, font and span id, optionally filtered by query (the same four match modes an edit uses) and pages, over the content, forms and annotations layers. Paginated: pass the returned next_cursor back as cursor for the next page. Use it before pdf_edit to check what a document actually says and to pick the scope that selects the match you mean.

NameRequiredDescriptionDefault
fileYesThe PDF: an absolute (or ~) local path, which this server uploads for you, an https:// URL the API fetches, or an `f_…` file id from an earlier call.
limitNo(default: 200)
matchNo
pagesNo
queryNo
cursorNo
imagesNoAlso list the images each page draws (`images[]`: page, name, bbox, pixels) -- what `op: remove_image` takes a box from. (default: false)
layersNo
passwordNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description adds pagination mechanics ('pass the returned `next_cursor` back as `cursor`') plus the fact that filtering spans three layers. It stops short of describing error behavior, password-protected failure modes, or rate limits, which are relevant for an openWorld tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences with the core purpose front-loaded and no filler. The phrase 'the same four `match` modes an edit uses' is compact but assumes the agent already knows pdf_edit's match schema, slightly reducing clarity for a marginal size gain.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-shape burden and does so by naming span fields and `next_cursor`. For a 9-parameter, nested-object read tool it is close to complete, but it omits what `limit` constrains and how protected PDFs behave.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 33%, so the description has to compensate, and it does for the hard ones: it explains `query` is filtered by the same four `match` modes an edit uses, and it names the `layers` values and cursor round-trip. It leaves `limit`, `password`, and the `match.normalize`/`across_lines` sub-options unexplained beyond their schema defaults.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Read the text of a PDF') and immediately characterizes the return unit ('every span with its page, position, font and span id'), so an agent knows exactly what it gets back. It also names pdf_edit and the layering, which separates it from the mutating sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly prescribes usage relative to an alternative: 'Use it before `pdf_edit` to check what a document actually says and to pick the `scope` that selects the match you mean.' That is real routing guidance, though it gives no when-not-to-use cases and says nothing about pdf_preview or pdf_batch as alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pdf_jobJob resultA
Read-onlyIdempotent
Inspect

The result of an async edit or a batch, by job_id: the same body pdf_edit returns once the job is done, plus progress while it is still queued or running, and records for a batch.

NameRequiredDescriptionDefault
job_idYesThe `job_id` an async edit or a batch returned.
output_pathNoWhere to write the finished document (stdio mode, single-document jobs only).

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, openWorld, non-destructive, so the safety bar is low. The description adds real value beyond them: the response shape varies by job lifecycle state (progress while queued/running, finished body once done, records for batches). It does not mention that output_path writes a file to disk, which is a minor undisclosed side effect.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence that identifies the resource first, then the two state-dependent fields. Every clause carries information; there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description must describe return values, and it does so for the three main cases (finished body, progress, records). It leaves out error/failure states (e.g., what a failed job returns), which is the only notable gap for a polling tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are already documented at the schema level, which sets the baseline at 3. The description only echoes that job_id comes from an async edit or a batch, adding marginal context and nothing about output_path semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a precise resource (the result of an async edit or batch) keyed by job_id, and explicitly relates it to pdf_edit and pdf_batch, so an agent can tell it is the retrieval/polling counterpart rather than a new operation. The verb 'result' is implicit rather than stated, keeping it short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context: this is what you call with a job_id that an async edit or batch returned, and the payload differs by state (progress while queued/running, records for a batch). It offers no explicit exclusions, but no sibling competes for this job, so the guidance is functionally complete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pdf_previewRender a PDF pageA
Read-onlyIdempotent
Inspect

Render one page of a PDF as a PNG image block, optionally cropped to region and with rectangles drawn over highlight. Use it to see a page before editing it, or to check the result afterwards.

NameRequiredDescriptionDefault
fileYesThe PDF: an absolute (or ~) local path, which this server uploads for you, an https:// URL the API fetches, or an `f_…` file id from an earlier call.
pageNo(default: 1)
scaleNo(default: 2)
regionNo
passwordNo
highlightNo

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior, so the safety profile is covered. The description adds the return format ("PNG image block") and crop/highlight rendering behavior, which is useful, but says nothing about password-protected handling, scale implications, or page limits beyond what the schema implies.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences, front-loaded with the verb and resource before the optional features and usage note. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and 6 parameters at 50% description coverage, the description should do more: the password parameter is unmentioned and the region/highlight formats are unexplained. It adequately conveys purpose and usage but leaves real gaps for an agent calling it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50%; region and highlight have no schema descriptions, and the description names both with their semantic role (crop region, drawn rectangles). However it omits coordinate format for region/highlight and never mentions the password parameter, so it only partly compensates.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb (Render), resource (one page of a PDF), and output format (PNG image block). Its purpose is clearly distinct from the edit/find/job/batch siblings, though it never names them explicitly to sharpen the contrast.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Use it to see a page before editing it, or to check the result afterwards" supplies concrete when-to-use context and implicitly positions it against pdf_edit in a workflow. It stops short of naming alternatives or stating exclusions, so it lands just below the top band.

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.

  1. 3 tool updates
    • Changedpdf_batch1 field changed
      • changedInput schema / properties / edits / items / properties / op / enum
        Previous value: -[
        -  "replace",
        -  "delete",
        -  "redact",
        -  "insert",
        -  "form",
        -  "stamp"
        -]New value: +[
        +  "replace",
        +  "delete",
        +  "redact",
        +  "insert",
        +  "form",
        +  "stamp",
        +  "remove_image"
        +]
    • Changedpdf_edit1 field changed
      • changedInput schema / properties / edits / items / properties / op / enum
        Previous value: -[
        -  "replace",
        -  "delete",
        -  "redact",
        -  "insert",
        -  "form",
        -  "stamp"
        -]New value: +[
        +  "replace",
        +  "delete",
        +  "redact",
        +  "insert",
        +  "form",
        +  "stamp",
        +  "remove_image"
        +]
    • Changedpdf_find1 field changed
      • addedInput schema / properties / images
        Added value: +{
        +  "description": "Also list the images each page draws (`images[]`: page, name, bbox, pixels) -- what `op: remove_image` takes a box from. (default: false)",
        +  "type": "boolean"
        +}
  2. 2 tool updates
    • Changedpdf_batch3 fields changed
      • addedInput schema / properties / edits / items / properties / box
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "h": {
        +          "description": "Height in points.",
        +          "maximum": 14400,
        +          "type": "number"
        +        },
        +        "page": {
        +          "maximum": 9007199254740991,
        +          "minimum": 1,
        +          "type": "integer"
        +        },
        +        "w": {
        +          "description": "Width in points.",
        +          "maximum": 14400,
        +          "type": "number"
        +        },
        +        "x": {
        +          "description": "Left edge, points from the page's left.",
        +          "minimum": 0,
        +          "type": "number"
        +        },
        +        "y": {
        +          "description": "Top edge, points from the page's TOP.",
        +          "minimum": 0,
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "h",
        +        "page",
        +        "w",
        +        "x",
        +        "y"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedInput schema / properties / edits / items / properties / image
        Added value: +{
        +  "description": "The image to place: PNG, JPEG, GIF, BMP or WebP, as base64 (a `data:` URL is accepted). JPEG is stored as sent; PNG keeps its transparency.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • changedInput schema / properties / edits / items / properties / op / enum
        Previous value: -[
        -  "replace",
        -  "delete",
        -  "redact",
        -  "insert",
        -  "form"
        -]New value: +[
        +  "replace",
        +  "delete",
        +  "redact",
        +  "insert",
        +  "form",
        +  "stamp"
        +]
    • Changedpdf_edit3 fields changed
      • addedInput schema / properties / edits / items / properties / box
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "h": {
        +          "description": "Height in points.",
        +          "maximum": 14400,
        +          "type": "number"
        +        },
        +        "page": {
        +          "maximum": 9007199254740991,
        +          "minimum": 1,
        +          "type": "integer"
        +        },
        +        "w": {
        +          "description": "Width in points.",
        +          "maximum": 14400,
        +          "type": "number"
        +        },
        +        "x": {
        +          "description": "Left edge, points from the page's left.",
        +          "minimum": 0,
        +          "type": "number"
        +        },
        +        "y": {
        +          "description": "Top edge, points from the page's TOP.",
        +          "minimum": 0,
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "h",
        +        "page",
        +        "w",
        +        "x",
        +        "y"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedInput schema / properties / edits / items / properties / image
        Added value: +{
        +  "description": "The image to place: PNG, JPEG, GIF, BMP or WebP, as base64 (a `data:` URL is accepted). JPEG is stored as sent; PNG keeps its transparency.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • changedInput schema / properties / edits / items / properties / op / enum
        Previous value: -[
        -  "replace",
        -  "delete",
        -  "redact",
        -  "insert",
        -  "form"
        -]New value: +[
        +  "replace",
        +  "delete",
        +  "redact",
        +  "insert",
        +  "form",
        +  "stamp"
        +]
  3. 2 tool updates
    • Changedpdf_batch1 field changed
      • addedInput schema / properties / options / properties / webhook_url / description
        Added value: +"Called with POST when the job finishes: the body is the job's result (what GET /v1/jobs/{id} returns) plus `event` (job.done, job.failed, batch.done ...) and `job_id`, signed in `X-Signature` (hex HMAC-SHA256 of the raw body with the account's webhook secret). Non-2xx answers are retried after 1, 5 and 30 minutes. https only."
    • Changedpdf_edit2 fields changed
      • addedInput schema / properties / options / properties / webhook_url / description
        Added value: +"Called with POST when the job finishes: the body is the job's result (what GET /v1/jobs/{id} returns) plus `event` (job.done, job.failed, batch.done ...) and `job_id`, signed in `X-Signature` (hex HMAC-SHA256 of the raw body with the account's webhook secret). Non-2xx answers are retried after 1, 5 and 30 minutes. https only."
      • changedInput schema / properties / output_path / description
        Previous value: -"Where to write the edited PDF (stdio mode only). Default: `<name>.edited.pdf` next to the input."New value: +"Where to write the edited PDF (stdio mode only). Default: `<name>.edited.pdf` next to the input, or `<name>.edited.2.pdf`, `.3.pdf`, ... when that exists; an earlier result is never overwritten."
  4. 5 tool updates
    • First observedpdf_batch
    • First observedpdf_edit
    • First observedpdf_find
    • First observedpdf_job
    • First observedpdf_preview

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables editing text in existing PDFs by modifying content stream operators, preserving original fonts and positions. Provides fidelity reports on every edit, indicating font preservation, substitution, overflow, and other degradations.
    2
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI assistants to edit text inside real PDF files in place while preserving fonts and layout, with a before/after preview. Also supports compressing, merging, splitting, converting, translating, generating and querying PDFs through a hosted remote MCP endpoint.
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to open local PDFs and edit existing text, images, annotations and form fields in place using the document's own embedded fonts, baselines and colours, with undo/redo and page rendering for visual checks. It also exposes 67 whole-document tools such as merge, split, compress, OCR, redact, sign, compare, watermark and conversion to and from PDF, all running locally over stdio.
    1
    MIT
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.