Skip to main content
Glama

pdfnative-mcp

PDF 생성, PDF/A 보관, 장기 검증을 포함한 PAdES 서명, AcroForms, 병합/분할, 암호화 및 레이아웃 미리보기용 MCP 서버 — pdfnative 엔진(제로 의존성, ISO 32000-1 준수) 기반의 28개 도구로, Claude Desktop, Cursor, ChatGPT 및 모든 Model Context Protocol 클라이언트에서 사용할 수 있습니다.

npm version npm downloads Node version License: MIT CI MCP pdfnative TypeScript OpenSSF Scorecard CodeQL


✨ 기능

pdfpdfnative-mcp는 모든 MCP 호스트에 프로덕션급 도구 28개를 제공합니다:

도구

용도

generate_basic_pdf

13가지 블록 유형 — heading, paragraph, list, table, image (JPEG/PNG), link, toc(인쇄된 목차), barcode, svg, formField, chart, pageBreak, spacer — 즉, 엔진이 지원하는 모든 DocumentBlock에서 다중 페이지 문서를 생성합니다. 포함된 줄바은 자동으로 블록으로 분 할됩니다. 선택 사항: pdfA, print, metadata, embedFonts, watermark, outline, layout 옵션(pageSize, margins, headerTemplate / footerTemplate, compress, debug, encrypt).

inspect_layout (v1.6.0 신규)

동일한 blocks(+ title, footerText, pdfA, normalize, embedFonts, pageSize, margins, headerTemplate, footerTemplate)를 대상으로 한 읽기 전용 페이지 매김 드라이 런 — 페이지 수와 각 블록이 위치할 곳을 알려줍니다. PDF는 생성하지 않습니다.

add_barcode

QR Code, Code 128, EAN-13, Data Matrix, PDF417 — 단일 페이지 PDF에 포함됩니다.

add_international_text

꿜가지 스크립트(Latin 및 Safe COLRv1 컬러 이모지 포함 — 깃발/ZWJ 시스 사용)와 BiDi & OpenType 이핑을 지원합니다. 문서이 다국어 지원이 가능합니다.

add_table

스마트 필드(wrap, repeatHeader, zebra z, caption, minRowHeight, cellPadding)를 갖춘 표 형식 레포트를 생성합니다.

add_form

텍스트 필드, 텍스트 영역, 체크박스, 라디오 버튼, 드롭다운, 목록 큽(+ placeholder 안내 텍스트)을 갖춘 새로운 인터랙티브 AcroForm 타입의 PDF를 생성합니다.

read_form_fields

기존 AcroForm의 필드 트리(이름, 유형, 값, 위젯)를 읽기 전용으로 열기합니다.

fill_form

기존 AcroForm을 채우고/또는 평탄화합니다(비파괴적 증子 업데이트).

add_chart

네이티브 벡터 차트 v2 — bar / barH / stackedBar / stackedBarH / line / area / scatter / pie / donut, 보조 축, 로그 및 시간 스케일, 데이터 레이블(순수 PDF 경로 연산자, PDF/A-안전).

embed_image

JPEG 또는 PNG 이미지(base64)를 제목이 있는 PDF 문서에 포함합니다(Attribute은 선택, 태그된 출력을 위한 첨부: alt text).

prepare_signature_placeholder

서명 워크플로의 선택적인 1단계 — 서명자 메타데이터와 subFilter, reserveTimestamp을 포함해 /Sig placeholder가 있는 PDF를 만듭니다.

sign_pdf

PAdES B-B / B-T 시그니처 (RSA-SHA256/384/512, ECDAS-SHA256 P-256; profile: 'pades', timestamp, certChainDerBase64, multiple 서명, 고정 가능한 signingTime). 필요한 서 placeholder을 자동으로 삽입합니다.

add_ltv (v1.6.0 신규)

PAdES B-RH — certs + OCSPA/CRL 재료가 dropped in /DSS (operator-configured Provider, or caller-provided 오프라인 재료)를 듣입니다.

timestamp_pdf (v1.6.0 신규)

PAdES B-LTA — 운영자가 구성한 TSA의 RFC 3161 /DocTimeStamp를 추가합니다. 보존 체인을 연장하려면 다시 실행합니다.

verify_details

모든 PAdES 서명과 문서 타임스탬프를 검독합니다(무결성 + 서명 값 + 선택적인 체인 신; /DocTimeStamp는 다른 서명들처럼 allValid에 포함됩니다); ltv: true로 B-B…B-LTA 레벨을 확인합니다.

validate_pdf

PDF/UA (ISO 14289-1) 구조적 준비 여부를 위해 태그(태그된 PDF)의 구조를 검중합니다(읽기 전용).

add_attachment

포함 파일(Factur-X / ZUGFeRD 계산서)이 든 들PDF-A/3 문서를 생성합니다.

extract_attachments

포함된(계정) 파일을 바이트 단위 원본 그다로 읽기 전용으로 추출한합니다(Factur-X / ZUGFeRD XML 라운드트립).

extract_text

유니코드 텍스트 추출(/ToUnicode 정의/해한), 위치 지정된 연속(미션)도 선택 가능합니다. keyword를 사용해 암호화된 PDF도 열니다.

inspect_pdf

읽기 전용 검사: PDF 버전, 페이지 수, 암호화(구체적인 encryptionInfo), PDF/A 주장, 서명(+inventory, /DSS, 문서타임스탭프), 페이지 상자, /Trapped, 첨부파일, 플레이스홀더 상태, annotations: true로 기존 페이지 주(annotations) 목록.

update_metadata (v1.6.0 신규)

기존 PDF의 /Info 제목/저자/주제/키워드(+ XMP 등 metadata)를 점子 업데이트로 다시 십니니다. 동일 호스트 시간대에서 다른 바이트가 같으면 modDate를 홀드합니다.

encrypt_pdf

AES-128/AES-256 으로 PDF를 다시 보호합니다(소주자/사용자 암호문, 권한, 암호 교환).

decrypt_pdf

RC4 / AES-128 / AES-256 문서의 비암호화 복사본을 추출합니다.

merge_pdfs

pdfnative의 페이지-트리 API를 사용해 2–50개의 PDF를 하나로 병합합니다(page boxes 유지).

split_pdf

하나의 PDF를 페이지 범위별로 문서 하나로 나눕니다(여러 output 이용).

extract_pages

임의의 페이지 부분 집합을 단일 PDF로 추출합니다.

annotate_pdf

시각 ✕ 오버레이로 마크업 어노테이션(하이라이트, 노트, 사각형/원, 선, 재택)을 추가합니다 — redaction (삭제)이 아닙니다.

draft_governance_issue

거버넌스에 부합하는 GitHub Issue 초안을 로컬에서 사람이 검토 할 수 있도록 작성합니다. 절대 제출 / 네트워크 사용이 없습니다.

v1.6.0의 새로운 기능:

  • 원 전체 엔진 커버리즈 — 13종 블록 — generate_basic_pdf는 pdfnative가 제공하는 모든 DocumentBlock을 허용합니다. table, image, link, toc, barcode, svg, formField 블록은 각 각전용 도구(add_table, embed_image, add_barcode, add_form)와 본문을 공유하므로, 독립 아티팩트/인라인이든 동일한게 검증/렌더링됩니다. 규칙: link는 http: / https: / mailto:만 받습니다(제어 문자가 포含되면 가부). image는 크기 제이(각 12 M base64 문자열, 호출당 24 MiB 해동; PNG는 8버트/non-interlaced/alpha/paleteless pay be used, 그렇지 않을면 해석안내와 함게 버됨). svg는 path, 기본 도형, <text>를 담당합니다 (transform, <g>, 그라데이션, CSS는 무시 — 외부에서 리소스를 가여 오지 않음). toc은 outline: 'auto'와 짝을 이룸니다. PDF/A 청구가 있는 문서에서 formField를 사용하면 PDFA_UNEMBEDDED_FORM_FONT(을를) 보고합니다. barcode에는 alt가 없습니다(엔진 제한).

  • 📐 레이이웃 옵션 — 9개 문서 도구에 pageSize(포멧 기본, 특수: A4 기본?, Letter, Legal, A3, Tabloid), margins(네 면 모두, 0–200pt), headerTemplate / footerTemplate 및 {page} {pages} {title} {date}(footerTemplate을 지정하면 기본 footer가 교체되고 footerText는 무시됩니다. {date}는 빌드 당시 벽시계 시간이지 creationDate가 아닙니다), compress(FlateDecode스트림 — 파일 을 축소, 바이트는 달라짐, PDF/A에서XMP는 평문 유지)와 debug`(가이디 도형/무표시 컨텐츠, PDF/UA 아님) 지이. 기본값은 본래 없기 때문에 기본 출력은 바이트 단위로 완전히 동일합니다.

  • 🔐 빌드 시 암호화 — encrypt 옵션이 7개 문서 도구(generate_basic_pdf, add_table, add_form, add_international_text, embed_image, add_barcode, add_chart)에 추가되었습니다. 표준 보안 핸들러, AES-128 기본(또는 AES-256), AcroForm을 유지(encrypt_pdf는 페이지 트리를 재구축하는 것과 대조됨). pdfA와 동시 사용 불가능(VALIDATION_ERROR), 캐시 없음, prepare_signature_placeholder(서명 가능을 유지해야 함)와 add_attachment(PDF/A-3)에는 제공되지 않습니다.

  • 📏 inspect_layout — 열여덟 번째 도구: 동일한 blocks와 레이아웃 입력을 읽기 전용으로 페이지네이션 예시(dry run) 실행. PDF를 랜더링하지 않고 totalPages와 각 블록의 page / x / top / width / height를 반환합니다. 알려진 엔진 간극: toc 블록이 0pt로 측정되므로, 목차가 포함된 문서는 미리보기보다 한 페이지 늦게 페이지네이션될 수 있습니다.

  • 🔎 inspect_pdf annotations: true — 모든 페이지 주석을 나열합니다(하위 유형, 0-시작 페이지, rect, 200자로 수정된 contents, title, color, color, color, link URL) 및 annotationCount; 새로 check: 'annotations' 추가됨었습니다.

  • 이미지 워터마크 — generate_basic_pdf와 add_table에서 watermark.image(JPEG/PNG, 기본 불투명도 0.10, 자체 8 MB 상한)를 단독 또는 text(기본 불투명도 0.16)와 함께 니다. position: 'background' | 'foreground'는 etc. 불투명도 1.0 미만은 pdfa1b 아래 거부됩니다.

  • 원 **PDFNONATIVE_MCP_MAX_INFLATE_BYTES** — 엔진의 스트림 당 100 MiB 풀기 상한를 오버라이터가 덮어쓰능(자연수 ≥1024; 잘못된 값은 시작되지 않습니다). 컴압된 첨부 스트림은 extract_attachments includeData: true에서 PDF_PARSE_FAILED로 실패하고, extract_text`은 페이트 텍스트로 감지됩니다(엔진은 각 페이지 디코딩 오류를 삼승).

  • 원 Form — add_form и formField block 에 listbox/placeholder 추가. fieldType: 'textarea' enters engine as multilineText (formerly not map귏 so one-line field로 그려짐 — 해당 입력에 대해 byte를 변경하는 버그 수정 포함). embed_image에는 align and word alt추가.

  • 🔏 PAdES 장기 검증 라더 — sign_pdf에 profile: 'pades'(ETSI EN 319 142-1 기반, ESS signing-certificate-v2, ETSI.CAdES.detached), timestamp: true(이-T, RFC 3161), RSA-SHA384/512, certChainDerBase64, fieldName/allowMultiple(여러 sign) 지원. 새 add_ltv는 /DSS(이-LT, mode: 'online (operator provider) or mode: 'offline with caller- provided BER) 등 supports. 새 timestamp_pdf은 /DocTimeStmap를 뒤에추가(B-LTA). verify_pdf ltv: true는 profile, timestamp, revoc 상태와 ltLevel을 reports. docs/guides/LTV.md 참조.

  • 외부 네트워크 차트 — 기본적으로 어떤 외부 요청도 발생하지 않습니다. 서버가 할 수 있는 유일한 외부 접속은 운영커 구성한 RFC 3161 / OCSP / CRL 엔드포인트(PDFNATIVE_MCP_TSA_URL, PDFNATIVE_MCP_REVOCATION, PDFNATIVE_MCP_NETWORK_ALLOWED_HOSTS)뿐이며, SSRF 가드가 있습니다. 도구 주장에서 URL을 제공할 는 없습니다.

  • 원 인1 프로덕션 — 모든 도구에서 print(TrimBox)/BleedBox/ArtBox/CropBox, 그리고 bleed 생략 표기, crop + marks, /UserUnit), metadata(/Author, /Key, /Subject, /Trapped), outputIncent(파/A의 custom RGB ICC) and deviewer etc. viewerPrefereces는 duplex, pickTrayByPDFSize, printPageRange, numCopyies를 사용. inspect_pdf pages: true the find the box; merge/split/extract가 프리즈를 보존. PRINT.md` 참조.

  • ✍지 update_metadata — 기존 PDF의 /Info와 XMP를 incremental update로 교체(이전 판본과 서명을 그대로 유지).

  • 차트 v2 — stackedBar / stackedBarH / area / s, top, axis.scale: 'log', xAxis.type: 'linear' | 'time', dataLabels', labelStride/labelRotation`; overlapping Labels는 자동으로 생략니다.

  • 직한 PDF/A — embedFonts: true는 Noto Sans Latin을 embeddes(기본 14 Helvetica가 embed되있지 않으므로 일반 Animals 텀스트와 PDF/A가 veraPDF에 검증되어 거부됩니다). strict: true는 비준수 파일을 생산하지 않고 실패합니다. strict진 – includeDiagnostics: trueengine diagnostics.scripts (npm run validate:pdfa) — 24문자(^) 등 : 26-file corpus 대한 검증(24국가,3 pass negative ) , have : page-tree 2 건 생략) and VERAPDF_REQUIRED=1fails-closed(모드. CI workflow sha-1 고정, v1.6번에서 비치단 – 문). Injury gap:add_form은 embedFonts가 있어도 PDF/A-2b 실패?(/DR /Helv안 엔베드),prepare_signature_placeholder` 결과는 한번 sign 해야만 compliant.

  • 🧰 inspect_pdf — signatures: true (리스트 표시), dss/docTimestampCount/trapped(존재시에만 노출), 새 check 값 dss, docTimestamp, trapped, checks 요청 키만 나열합니다. 참고: signed는 구조적인 것입니다(서명된 필드 존재; 유효성 검증은 verify_pdf 담당).

  • 반복 가능한 출력 — 9개 문서도구의 creationDate가 /CreationDate, XMP 날짜, trailer /ID를 고정. prepare_signature_placeholder의 signingTime (sign_time too, now timezone) 및 signing_pdf의 signingTime에 /Sig /M 고정). 동일 host timezone에서는 byte가 동일. reproducible_output 프롬프트에서 제공.

  • 강화된 경계 — 딱딱한 input z칭(예: 모르는/오타 키는 조용히 무시하지 않고 VALIDATION_ERROR); data:…;base64,prefixل, "PEM where DER"와 double-encoded payload는 정확한 해결 방법과 함께 거부, page tree tools의 page index 오류는 0-based 힌트와 함께VALIDATION_ERROR, 미지의 tool name은 JSON-RPC 프로토콜 오류(-32602, [UNKNOWN_TOOL]`).

  • 🔑 HTTP Bearer Media — 선택 PDFNATIVE_MCP_HTTP_TOKEN을 Streamable HTTP endpoint 401/WWW-Authenticate를 열어 주는 켜는 토큰이 없으면 loopback은 인증이 없습니다(참 SECURITY 참조).

  • 카탈로그 — localhost/list 는 1.5.0 108KB 대비 1.6.0 파일은 ~245kB. 전 블록 종류, 레이이아웃 옵션, encrypt fragment are inline advertised, policy 상 $ref/$defs 없음 — inputSchema를 function-call API에 전달하는 host는 ref를 만하지 않습니다. server Instructions는 12.9 KB에서 ~6.7KB. Structure is guard by scripts/tool-shape.mjs + tests/catalogue-parity.test.ts, and tests/catalogue-susert.test.ts proves live catalog super set of 1.5.0 catalog; tool _meta.examples max 2, the others in examples/. New recipe prompts 4개: pades_ladder, print_ready, reproducible_output, pdfa_valid.

  • Fixes — pdfnative < 1.7에서 surrounder metadata (signerName/reason/location/contactInfo)가 /Sig 사전에 도달하지 못했으므로, placeholder time에 기록 하도록 수정. verify_pdf B-LTA문서에서 잘못된 allValid: false (DocTimeStamp가 CMS signature로 parse된 등)을 수정.

  • MCP 2026-07-28 — MCP TypeScript SDK v2 (@modelcontextprotocol/server)에 automatic fallback to 2025-era initialize handshake, existing hosts는 그대로 동작. MCP 프로토콘 준수 참조.

  • ⬆ 엔진 업그레이드 — pdfnative v1.7.0 (LTV, 인쇄 production, charts v2, digest agility, flag/ZWJ emoji sequences, UAX #9 fixes).

새로운 v1.5.0:

  • 📊 Native vector charts — add_chart 를 사용해 bar/horizontal-bar/line/pie/donut charts를 PDF path operators로 렌더링(no rasterisation, PDF/A, aut alt text) . generate_basic_pdf는 chart block을 함께 컴포지션할 수 있습니다.

  • 📝 Fill & flatten form — read_form_fields는 기존 AcroForm intent; fill_form은 비-파 incremental update로 채우고/펠che(add_form 카운터파트).

  • 🔐 암호화 라운드-trip — encrypt_pdf AES-128/256 암호화 재실 . (RC4 not출력), decrypt_pdf 암호화 되지 않은 복사가 가능. password를 받아 read-only tools에서 암호화 원본 열, plus merge_pdfs/split_pdf/extract_pages에 password+encrypt 추가.

  • 🔤 실제 텍스트 추출 — extract_text은 이제 각 글의 /ToUnicode CMap을 리졸브(ney 더 glyph-index)하읿, position. text output support.

  • 🔗 네이티브 MCP resources — sandboxed PDF files pdfnative://output/…의 (resource resources/list+resources/read). 파일 모드 결과에 resource_link 포함.

  • 구 주석 달 — 모든 도구에 readOnlyHint/destructiveHint/idempotentHint/openWorldHint 선택지정.

  • 엔진 업그레이드 — pdfnative v1.6.0 (decrypt/re-도구-엔, extractText, fill/flatten, charts; color-emoji subset 221 → 1167) .

새로운 v1.4.0:

  • 🤝 AI 거버넌스 + 사람-in-the-loop — draft_governace_issue는 완전히 규합된 GitHub 이슈를 로컬(주)로 초안(.md + 기기 판독 compliance report)한다. 로트는 그리 로무로, 스스스트로 제출는 불가; 서버는 GitHub에 젂0 쓰기 (그리고 v1.6.0 이후에는 운영자가 구한 TSA/OCSP/CRL 만) 수행. governance_contract 및 draft_issue_workflow MCP 프롬프트로 지원.

  • ✏️ Markup annotation — annotate_pdf 는기존 PDF에 highlight, stickynote, uline, Plato, squi글 (..., line, and freext annotations를 incremental update로 입힌. 이 것을 에디토 리와 레이어(? visual review layer) not redaction — bottom bytes나 그대로 유지.

  • 🔢 inspect_pdf의 page labels — /PageLabels (로만, decimal, prefixed) 읽‑only.

  • Math / scientific script — add_international_text에 lang: 'math'(명시) for fot is part of emoji (Noto Sans Math font는 on-demand embed).

  • MCP prompts — 서버는 prompts 능력을 광고, governance_contract 및 draft_issue_workflow (이트).

  • 엔진 업그레이드 — pdfnative v1.5.0.

v1.3.0의 새 기능:

  • ** 페이지 트리 도구 3개** — merge_pdfs, split_pdf, extract_pages (pdfnative v1.4.0의 페이지 트리 API 기반; v1.5.0에서 password가 추가되기 전까지 암호화된 입력은 거부되었습니다).

  • 🔖 북마르크, 페이지 라벨 ... — generate_basic_pdf에 outline('auto또는 명시적 트리),pageLabels, 다단계 list항목,viewerерPreferences`가 추가되었습니다.

  • 📐 표 셀 테두리 및 정렬 — add_table에 cellBorders, cellVAlign, viewerPreferences가 추가되었고, add_international_text에 viewerPreferences가 추가되었습니다.

  • 🔐 상수 시간 서명 — sign_pdf는 node:crypto 프로바기더를 통해 RSA 및 EC-DER를 키로 서명하며, 투명한 순수 JS 폴백이 있습니다 (raw P-256 스칼라 서명은 순수 JS이며, 검즉도 순수 JS). 서명은 계속 상호 운영 가능합니다.

  • 엔진 업그레이드 — pdfnative v1.4.0.

  • 🆕 Tool extract_attachments — "PDF에서 임베드된 파일을 다시 읽어낸다" (Factur-X / ZUGFeRD 왕복을 완성) : Byte 단위 그대로의 페이로드, filename 필터, includeData: false 메타데이터 전용 프로브.

  • 💧 워터마크 — generate_basic_pdf 및 add_table은 선택 적 watermark(텍스트, 불투명도, 각도, 색, 위차; v1.6.0 이후 image)를 모든 페이지에 렌더링할 수 있습니다.

  • 🌐 Unicode normalize — generate_basic_pdf와 add_international_text에서 선택적 NFC/NFD/NFKC/NFKD 정규화를 지원합니다.

  • 토큘 절약형 읽기 — 읽기 전용 도구들을 담당합니다 (inspect_pdf, verify_pdf, validate_pdf, extract_text, extract_attachments; v1.5.0부터 read_form_fields) 옵션 verbosity: 'summary' 및 fields: […]를 수용하여 큰 결과에서 응답 크기를 약90% 줄이면서, 에이전트가 분기하는 데 쓰는 필드는 잃지 않습니다. 기본값은 다른 점 없습니다.

  • base64 중복 없음 — 생성된 PDF(base64 모드)는 structuredContent에도 복사되는 대신, 임베드드 resource 콘텐츠 블록으로 한 번만 반환됩니다.

  • 🔧 MCP 레지스트리 발행 수정 — mcpName이 표준 GitHub 로그인 대소문자(io.github.Nizoka//pdfnative-mcp)를 사용하므로 레지스트리의 대소문자 구분 검증이 npm 패키지를 승인합니다.

  • Well존성 — zod 4로 업그레이드.

v1.1.0의 새 기능:

  • 🆕 Tool validate_pdf — 읽기 전용 PDF/UA (ISO 14289-1) 구조 적합성 검사.

  • 🆕 6개의 새 스크립트 — 텔르구, 신hasil, 티베트, 크메르, 미얼마, 이티오피아 (총 24개 스크립트).

  • 🆕 COLRv1 색상 이모지 — 기본 색상 이모지 + 단색 폴백.

  • 🆕 새 줄 처리기 — 문단에 내장된 \n이 자동으로 별도의 문단으로 분해됩니다 (PDF/AA 안전).

  • add_international_text 자동 NFC 정규화.

  • 엔진 업그레이드 — pdfnative v1.3.0: 유로 기호/CP-1252 심볼이 이제 올르게 추출되고, 줄바 테이블 는 행별 고유 MCID를 갖게 됨니다 (PDF/UA 안전).

v1.0.0의 새 기능:

  • 새 도구 3개: verify_pdf, add_attachment (Factur-X / ZUGFeRD), extract_text.

  • 🆕 스마트 테이블 필드: wrap, repeatHeader, zebra, caption, minRowHeight, cellPadding.

  • 을 inspect_pdf**이제 hasSignaturePlaceholder 및 첨부 파일별 요약을 보고합니다; 새 check 값 'placeholder', 'attachments' 추가.

  • 서명 사용성개선 — sign_pdf가 ECDSA SEC1 / PKCS#8 DER 키를 수용하며, 누락된 /Sig placeholder를 필요 시 자동으로 삽입합니다 (모든 PDF을 한 번의 호출로 서명).

  • **Opt-in cache** (PDFNATIVE_MCP_CACHE_DIR`): SHA-256 키, 1시간 TTL, 256 MiB LRU.

  • **_meta.apiVersion** 및 도구별 **_meta.examples** — AI 에이에이전트 탐지를 위해 — [docssolete/API_STABILITY.md`](docs/API_STABILITY.md) 참조.

  • **AI 에디 지도**: [docs/AI_GUIDE.md`](docs/AID_GUIDE.md) — 결정 트리 + 함의 사용 요인 참조. 트의 AGENTS.md 운영 설명서론.

  • 🆕 PDF/A 작성 가이드 — docs/guid/PDFA.md.

  • 환경 변수 이름 옮: PDFNATIVE_MCP_OUTUT_DST (기존 PDFNATIVE_MPC_OOUTPUT_DIR, 구 이는 일회 반환 경고와 함께 계속 동작).

  • ✅ 이제 출시됨: merge_pdfs, split_pdf, extract_pages (v1.3.0), annotate_pdf (v1.4.0), add_chart / read_form_fields / fill_form / encrypt_pdf / decrypt_pdf 는그리고 암호화 왕보 방 및 네이티브 MC P 리소스 (v1.5.0), add_ltv / timepstamp_pdf / update_metadata / 인도 및 차트 v2 (v1.6.0). redact_pdf는 보류 상태로 — pdfnative는 콘텐츠를 덮어쓰기/평탄화할 수 있지만 제거는 할 수 없고, 덮어쓰기만 하는 "redaction"은 허위 보안을 만들기 대문에 의도적 출시하지 않았습니다(상위 콘텐츠 제거 요청로 추저).

모든 도구는 두 가지 출력 모드를 지원합니다:

  • base64 (기본) — 생성된 PDF는 한 번만 resource 콘텐츠 블록 (data:application/pdf;base64,… URI)로 반환됩니다. structuredContent는 { mode, sizeBytes }만을 담습니다(includeDiagnostics: true일 때 diagnostics[], add_ltv에 summary 추가).

  • file — PDF은 PDFNATIVE_MCP_OUTPUT_DIR로 지정된 샌드박스 폴더에 기록됩니다. PDFNATIVE_MCP_OUTPUT_DIR가 setting되지 않으면 파일 출력이 비활성화됩니다; 절대 경로, 경로 트래버셜, .pdf 아닌 확장자, NUL 바이트는 모두 거부됩니다.

v1.1.1.0에서 업그레이드하는 사례: 유일한 동작 변경은 base64 모드 바이트가 더 이상 structuredContent.base64에 중복되지 않는 것입니다. 대신 내장된 resource 블록에서 읽으세요:

- const base64 = response.structuredContent.base64;   // v1.1.0
+ const block = response.content.find((c) => c.type === 'resource');
+ const base64 = block.resource.blob;                  // v1.2.0

토큔 절약형 읽기 (v1.2.0). 일곱 개 읽기 전용 도구 (inspect_pdf, verify_pdf, validate_pdf, extract_text, extract_attachments, read_form_fields, inspect_layout)는 두 개의 선택 입력을 지원합니다:

  • verbosity: 'summary' — 스칼라 전용의 경량 결과를 반환합니다(대용량 배열/전문 텐스트 생략). 예: verify_pdf → { signureCount, allValid, invalid, summary } (ltv: true 필요시 ltvLevel 추가); inspect_pdf는 docTimestampCount / ddState / trapped / checksPassed가 있면 보존합니다.

  • fields: ['a','b.c'] — 구조된 결과를 지정된 dot-path로 투영; verbosity 후 적용됩니다. 일치 하한 경로 누락되고 _meta.unmatchedFields에 보고됩니다(_meta.availableFields 포함).

가장 작은 "이 PDF가 서명되고 유효한가?" 프로버: { "pdfBase64": "…", "verbosity":"summary", "fields": ["allValid"] }.

"formatted Not classic" etc.

Doe pdfnative?

pdfnative-cp는 하부 엔진의 모드를 보증합니다:

  • 엔진의 럁타임 의존성 제거 — 순수 JavaScript, 네이티트 바인딩 없음 (이 서버는 MC P SDK와 zod만 추가하여 총 럁타임 의존성이 3개).

  • ISO 32000-1 (PDF 1.7) 수준 출력.

  • PDF/A-1b/2b/2u/3b, AES-128/256 암호화, AcroForm, 전자 서명.

  • 24개 스크립트 (emo 및 math동 총 25개 lang 코드) — 기본 BiDi 재병렬, Arabic 위상 조성, Thai/Devanagogari/Bengali/Tamil OTL shaping 지원.

  • Tree-shakeele ESM 빌르.


Related MCP server: document-intelligence-mcp

🚀 Install

# Run directly with npx (recommended for MCP clients)
npx -y pdfnative-mcp

# Or install globally
npm install -g pdfnative-mcp
pdfnative-mcp

요구 사항: Node.js ≥ 22.

⚙️ 구성

Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json (macOS) 또는 %APEDATA%\Claude\claude_desktop_config.json (Windows) 편집:

{
  "mcpServers": {
    "pdfnative": {
      "command": "npx",
      "args": ["-y", "pdfnative-mcp"],
      "env": {
        "PDFNATIVE_MCP_OUTPUT_DIR": "/Users/you/Documents/mcp-pdfs"
      }
    }
  }
}

Cursor / Continue / Zed / Windsurf / Cline / Roo Code

stdio 서버를 지원하는 어떤 MCP-호환 클라이언트든 작동합니다. 동일한 command + args + env 삼중값을 사용합니다. Cursor의 예 (~/.cursor/mcp.json):

{
  "mcpServers": {
    "pdfnative": {
      "command": "npx",
      "args": ["-y", "pdfnative-mcp"],
      "env": { "PDFNATIVE_MCP_OUTPUT_DIR": "/Users/you/Documents/mcp-pdfs" }
    }
  }
}

Windsurf / Cline / Roo Code도 각각의 MCP 구성 파일에서 같은 형태를 사용합니다.

🌐 지원되는 AI 생태계 및 클라이언트

pdfnative-mcp는 MCP-네이티브 환경용으로 설계되었으며, stdio 또는 Streamable HTTP를 지원하는 클라이언트와 작동합니다.

커니티 확인된 호환성:

  • Ontheia — 자체 호스팅오, 오.소스 AI 에이Д전트 플랏트홀ဘ (개인정보 우선). issue #41에 규인된 작동 확인 및 Ontheia의 호환 MCP 서버 목록.

🔌 MCP 프로토콜 준수

v1.6.0서버는 MCP TypeScript SDK v2(@modelcontext/sdk) 기반으로 구축되어 MCP 2026-07-28을 지원합니다:

  • Stateless 서빙 — server/discover가 session handshake를 대체. 모든 결과에 resultType, _meta, serverInfo의 _meta envelope 포함. HTTP에서는 2026-07-28 린라이언트가 각 POST /mcp에 McP-Method / Mcp-Name 헤더를 전송.

  • Cache 힌트 — tools/list / promts/list는 public + TTL 24h *server/discover는 public+ 1h,resources/list/resources/templates/list/resources/read는 private ttlMs: 0` (생성된 PDF는 호스트별 사용자 데이터).

  • 리소스 오류 — unknow resource URI는 2026-07-28스펙 요구에 따라 JSON-PC 오류 (-32602, Invalid params)로 보고.

  • 레거시 자동 폴백 — initialize(2025-11-25, 2025-06-18, 2025-03-26)로 시작하는 by클라이언트는 SDK의 레서 경로로 제공 (stdio 및 HTTP 모두). 기존 호스트는 변동 없음.

  • HTTP — GET / DELET /mcp는 405 응답 (SSE 재개 수 없음; server stateless). loopback binding 및 Host / Origin 가로드는 동일하지만 Origin 포트는 이제 서버 포트와 일치해야 합니다 (SDK 검사만으로는 다를 수 있음); PDFNATIVE_MCP_HTTP_TOKEN은 선택적 bearer-token gate를 추가 (401 + WWW-Authenticate if without). HTTP에서 JSON-RPC batch arrays(2025-03-26)가 수용됩니다. doof-lived keep-alive연결은 더 이상 socket listener를 남긴지 않습니다.

  • stdio — 이전 SDK 릴리이스와 마찬가찌, initialize 전 request는 응답 없이 드롭되며, stdio에서 JSON-RPC batch arrays를 않습니다 (1.5.0과 동일).

  • 프로토콜 오류 — tools/call에 알려지 도구 이름은 JSON-RCP 오류 (-32602, [UNKNOWN_TOOL] Unknown tool…)로,spec에서 분류한 대isError 결과가 아니다. isError: true는실행 실패에만 예 서됩니다. * 출력 스키마 — 모든 structuredContent는 도구의 outputSchema (2026-07-28 필수)를 준수하며, verbosity: 'summary' 및 fields 투자도 포함 (7개 읽기 도구는 모든 속성이 선택의 additionalProperties: false 프로젝팅 스키마를 선언). 입력 스키마는 정책상 $schema 없이 제공됩니다 (MCP ≥ 2025-11-25는 JSON Schema 2020-12; 일부 호스트는 unknown 키워드를 거부하는함수-호출 APIs로 inputSchema를 전달). serverInfo에 websiteUrl 포함; 리소스 템플릿는 pdfnative://output/{+path}.

tools/call 페이로드 (content, structuredContent, isError)는 2026-07-28 경로와 레거시 경로에서 동일합니다; tests/http-modern.tests.s가 이를 어서트하며, tests/schema-conformance.tests.s가 JSON Schema 2020-12 발리데이터로 structuredContent를 검증합니다.

클라이언트

트랜스포트

협상된 프로토콜

Claude Desktop, Cursor, Continue, Zeb, Windsurf, Cline

stdio

레거시 initialize (2025-xx) — 변경 있음

ChatGPT200, 그 확장 Streamable HTTP 호스트

HTTP POST /mcp

레거시 stateless streamable streamable HTTP — 변경 없음

MC P 2026-07-28 클라이언트 (SDK v2, Client, 현재 MCP Inspector)

stdio / HTTP

server/discover, cache hints, _meta envelope

Ontheia

stdio

레거시 initialize (커뮤니티 verification, #41)

환경 변수

변수

용도

PDFNATIVE_MCP_OUTPUT_DIR

샌드박스 디렉터리의 절대 경로. outputMode: 'file'을 활성화하는 데 필수입니다.

PDFNATIVE_MCP_CACHE_DIR

절대 경로로 설정하면 영구적인 SHA-256 키 기반 결과 캐시를 활성화합니다(1시간 TTL, 256 MiB LRU, 키는 도구 API + 패키지 버전으로 네임스페이스가 구분됩니다). 미설정 시 캐시는 비활성화됩니다. encrypt_pdf / decrypt_pdf / sign_pdf / add_ltv / timestamp_pdf / update_metadata 또는 파일 모드 호출은 절대 캐시하지 않습니다. 캐시 적중 시 _meta.cached: true를 포함하며 이전 호출의 바이트를 반환합니다.

PDFNATIVE_MCP_PORT

유효한 포트(1–65535)로 설정하면 stdio 대신 http://127.0.0.1:<port>/mcp에서 HTTP 서버를 시작합니다. 프에만 바인딩하이며 DNS 리바인딩 보호가 활성화됩니다(외부 Host/Origin → 403). PDFNATIVE_MCP_HTTP_TOKEN이 설정되지 않으면 인증이 없습니다 — 다른 로컬 프로세스가 엔드포인트에 접근할 수 있습니다.

PDFNATIVE_MCP_HTTP_TOKEN

(v1.6.0, 비밀) HTTP 전송을 위한 옵트인 베어러 토큰(≥16자, 공백 없음 — 더 약한 값은 시작을 거부합니다). 설정하면 모든 /mcp 요청은 Authorization: Bearer <token>을 포함해야 하며, 그렇지 않으면 401 + WW-Authenticate: Bearer realm="pdf-native-mcp"(자격 증명이 전송된 경우에만 error="invalid_token" 포함 — RFC 6750 §3.1). 상시 시간 비교방식이며, 절대 로그되지 않습니다.

PDFNATIVE_MCP_MAX_INFLATE_BYTES

(v1.6.0) 엔진의 스트림당 100MiB 압축 해제 상한(압축폭탄 방지)을 재저으합니다: 1024바이트 이상의 양의 정수 바이트 수, 시각 시 한 번만 읽고, 유효하지 않은 값이면 시긁을 거부합니다. 공유 호스트에서는 낮추고, 큰 스Ẽ의 신할 수 있는 아카이브에서는 높이십시오. 상한이 도달한 액부는 스트림은 extract_attachments includeData: true 호출을 PDF_PARSE_FAILED로 만듭니다. extract_text는 PDF_PARSE_FAILED 출력에 빈 페이지 텍스트로 대체됩니다(엔진 직관, 오류가 나타지지 않음).

PDFNATIVE_MCP_TSA_URL

(v1.6.0) sign_pdf timestamp: true 및 timestamp_pdf가 사용하는 RFC 3161 타임스탬프 기관의 절대 http(s) URL. 미설정 시 TSA_NOT_CONFIGURED가 발생하며 요청을 보내지 않습니다.

화

PDFNATIVE_MCP_TSA_AUTH

(v1.6.0, 비밀) ATS에 보내는 선택적 Authorization 헤더 값. 결카 로그 같은 에코에 되지 않습니다.

PDFNATIVE_MCP_REVOCATION

(v1.6.0) ocsp, crl 또는 ocsp,crl — add_ltv mode: 'online'에 대한 온라인 폐지 수집을 활성화합니다. 미설정 시 REVOCATION_NOT_CONFIGURED.

PDFNATIVE_MCP_NETWORK_ALLOWD_HOSTS

(v1.6.0) OCSP/CRL 응답자용 쉼표로분 구분된 허용 목록(host, host:port, *.suffix). PDFNATIVE_MCP_REVOCATION 설정 시 필수 — 응답자 URL은 신뢰할 수 없는 페기에서 옵니다.

PDFNATIVE_MCP_NETWORK_TIMEOUT_MS

(v1.6.0) TSA / OCSP / CRL 호출의 요청당 타임아웃, 1000–120000ms(기본값 10000).


🛠 도구 참조

generate_basic_pdf

{
  "title": "Q1 2026 Report",
  "blocks": [
    { "type": "heading", "text": "Executive summary", "level": 1 },
    { "type": "paragraph", "text": "Revenue grew 24% year over year." },
    { "type": "list", "style": "bullet", "items": ["Strong APAC", "Stable EU", "Soft NA"] },
    { "type": "pageBreak" },
    { "type": "heading", "text": "Details", "level": 2 }
  ],
  "footerText": "Confidential — Internal use only",
  "outputMode": "base64"
}

13가지 블록 종류: heading, paragraph, list, table, image, link, toc, barcode, svg, formField, chart, pageBreak, spacer. 복합 보고서:

{
  "title": "Quarterly report",
  "blocks": [
    { "type": "toc" },
    { "type": "heading", "text": "Sales", "level": 1 },
    { "type": "table", "headers": ["Region", "Revenue"], "rows": [["EMEA", "1.2 M"], ["APAC", "0.9 M"]], "zebra": true },
    { "type": "image", "imageBase64": "<base64 JPEG>", "mimeType": "image/jpeg", "width": 300, "alt": "Revenue chart" },
    { "type": "svg", "data": "M10 10 H 90 V 90 H 10 Z", "viewBox": [0, 0, 100, 100], "fill": "#0a7e8c" },
    { "type": "barcode", "format": "qr", "data": "https://example.com/q1", "align": "center" },
    { "type": "link", "text": "Full dataset", "url": "https://example.com/data" },
    { "type": "formField", "fieldType": "text", "name": "reviewer", "label": "Reviewed by" }
  ],
  "outline": "auto",
  "pageSize": "Letter",
  "headerTemplate": { "right": "{title} — page {page}/{pages}" },
  "embedFonts": true
}

블록 규칙: table, barcode, formField, chart는 add_table / add_barcode / add_form / add_chart와 동일한 본문을 사용합니다. link URL은 http:, https: 또는 mailto:여야 합니다. image 블록은 각각 base64 것 12M자씩, 호출당 24MiB 디코딩 상한이 있습니다(PNG: 8비트 그레이스케일/RGB, 비-인터레이스, 알파가 없고 팔레트가 없음 — 그렇지 않으면 해결책과 함께 VALIDATION_ERROR). svg는 <path>, <rect>, <circle>, <ellipse>, <line>, <polyline>, <polygon>, <text>/<tspan>을 지원하며 transform, <g>, <use>, <image>, 그래디언트, 불투명도, CSS를 조용히 무시합니다(외부 참조를 가져오지 않습니다). toc은 heading 블록으로 만들이지며 outline: 'auto'와 함께 사됩니다. pdfA에서 formField는 PDFA_UNEMBEDDED_FORM_FONT를 보고합니다(strict: true이면 실패). barcode에는 alt가 없습니다. 렌더링 전에 동일한 입력을 inspect_layout에 넘겨 페이네이션을 미리 볼 수 있습니다.

add_barcode

{
  "format": "qr",
  "data": "https://pdfnative.dev",
  "caption": "Scan to learn more",
  "ecLevel": "H",
  "outputMode": "file",
  "outputPath": "tickets/event-42.pdf"
}

지원 형식: qr, code128, ean13, datamatrix, pdf417.

add_international_text

{
  "title": "مرحبا بالعالم",
  "lang": "ar",
  "paragraphs": [
    "هذا اختبار للنص العربي مع تشكيل OpenType ومحارف ثنائية الاتجاه.",
    "Mixed content: العربية + English ✓"
  ]
}

지원하는 lang 코드(25개): ar, he, th, ja, zh, ko, el, hi, bn, ta, ru, ka, hy, tr, pl, vi, latin, te, si, bo, km, my, am, emoji, math. 폰트는 항상 임베드됩니다(embedFonts 입력 없음). 바이트 단위로 동일한 출역에는 creationDate를 정하십시오.

다중 스크립트 문서 — 베열 또는 콤마로 구분된 목록을 전달하세요:

{
  "title": "Mixed Script",
  "lang": ["ar", "emoji"],
  "paragraphs": ["العربية مع رموز 🎉🚀"],
  "pdfA": "pdfa2u"
}

sign_pdf

v1.6.0부터 sign_pdf은 /Sig 자리표시자가 없으면 자동으로 추입합니다 — 단일 호출으로 어떤 PDF든 서명할 수 있습니다:

{
  "pdfBase64": "<any base64 PDF>",
  "algorithm": "rsa-sha256",
  "certDerBase64": "<base64 X.509 cert in DER>",
  "rsaKeyPkcs1DerBase64": "<base64 PKCS#1 RSAPrivateKey DER>",
  "signerName": "Alice",
  "reason": "Approval",
  "location": "Paris, FR",
  "signingTime": "2026-01-15T10:30:00Z"
}

ECDSA P-256의 경우: algorithm: "ecdsa-sha256"을 사용하고 ecPrivateKeyDerBase64(SE/C1 또는 PKCS#8 DER또는ecPrivateScalerHex`(64자 16진수) 중 하을 제공하세요.

PEM → DER 변환:

openssl x509 -in cert.pem -outform DER | base64 -w0                 # cert
openssl rsa  -in key.pem  -outform DER -traditional | base64 -w0    # RSA PKCS#1
openssl pkey -in key.pem  -outform DER | base64 -w0                 # ECDSA

prepare_signature_placeholder는 자리 표시자를 조정해야 할 때만 사용하세요(예: 4096비트 이상 RSA 키용 더 큰 placeholderBytes, subFilter: 'ETSI.CAdES.detached', reserveTimestamp: true). 그 외에는 sign_pdf를 직접 사용하세요.

PAdES 단계 (v1.6.0). profile: "pades"를 사용한 sign_pdf는 B-B 서명을 생성하며, timestamp: true를 추가하면 B-T(PDFNATIVE_MCP_TSA_URL 필요), 그 다음 add_ltv (B-LT), timestamp_pdf (B-LTA) 순서로 진행합니다:

// 1. sign_pdf  { ..., "profile": "pades", "timestamp": true, "certChainDerBase64": ["<intermediate DER>"] }
// 2. add_ltv   { "pdfBase64": "<signed>", "mode": "online" }            // or "offline" + certificatesDerBase64 / ocspResponsesDerBase64 / crlsDerBase64
// 3. timestamp_pdf { "pdfBase64": "<ltv>" }                              // re-run before the TSA certificate expires
// 4. verify_pdf { "pdfBase64": "<final>", "ltv": true }                  // -> ltvLevel: "B-LTA"

서명자 메타데이터(signerName, reason, location, contactInfo)는 자리표시자에 포함됩니다. fieldName은 서명되지 않은 여러 자리표시자 중 하나를 선택하며(PLACEHOLDER_AMBIGUOUS는 그 외의 경우), allowMultiple: true는 서명을 더 추가합니다. 자세한 내용은 docs/guides/LTV.md를 참조하세요.


add_table

{
  "title": "Monthly Sales",
  "headers": ["Region", "Units", "Revenue"],
  "rows": [
    ["APAC", "1200", "$240,000"],
    ["EMEA", "800", "$160,000"]
  ],
  "infoItems": [{ "label": "Period", "value": "January 2025" }],
  "footerText": "Internal use only",
  "outputMode": "base64"
}

add_form

{
  "title": "Employee Onboarding",
  "fields": [
    { "fieldType": "text", "name": "fullName", "label": "Full Name", "required": true },
    { "fieldType": "dropdown", "name": "dept", "label": "Department", "options": ["Engineering", "Sales", "HR"] },
    { "fieldType": "checkbox", "name": "agree", "label": "I agree to the terms", "checked": false },
    { "fieldType": "listbox", "name": "skills", "label": "Skills", "options": ["TypeScript", "PDF", "MCP"] },
    { "fieldType": "textarea", "name": "notes", "label": "Notes", "placeholder": "Anything we should know?" }
  ],
  "outputMode": "base64"
}

필드 유형: text, textarea(여러 줄, /Ff 4096), checkbox, radio, dropdown, listbox; placeholder는 필드가 비어 있는 동안 힌트 텍스트를 표시합니다. encrypt를 추하하면 AcroForm을 유지하는 암호 보호 폼양식이 생성됩니다. PDF/A 선언 하에서 위젯 외관 폰트가 임베드되지 않습니다(PDFA_UNEMBEDDED_FORM_FONT).

embed_image

{
  "title": "Product Photo",
  "imageBase64": "<base64-encoded JPEG bytes>",
  "mimeType": "image/jpeg",
  "caption": "Front view of Model X",
  "width": 400,
  "align": "center",
  "alt": "Front view of the Model X chassis",
  "outputMode": "base64"
}

참고: 엔진의 PNG디코더는 8비트, 비-인터레이스 그레이 스케일 / RG이미지만을 지원합니다. 알파 채널(컬러 타입 4/6), 팔레트(타입 3), 16비트 그리고 인터레이스 PNG는 VALIDATION_ERROR와 함께 경고에서 거부됩니다(평면화하거나 다시 인출하는 안내 포함) — 동일한 규칙이 image 블록과 이미지 워터마크에도 적용됩니다. embed_image.imageBase64는 바운드 없는 1.5.0 계약을 유지하며, 12M 자 상한은 인라인 image 블록과 워터마크 이미지에만 적용됩니다.

prepare_signature_placeholder

{
  "title": "Service Agreement",
  "signerName": "Alice Dupont",
  "reason": "Approved",
  "location": "Paris, FR",
  "blocks": [
    { "type": "paragraph", "text": "By signing below, I accept the terms and conditions." }
  ],
  "outputMode": "base64"
}

sign_pdf에 반환된 PDF 바이트를 전달하하여 서명 워크플로를 완료하세요.

inspect_pdf

읽기 전용 구조 및 보안 검사 — 다운스트림 검증, CI 어서션, PDF에 행동하기 전에 그내용을 파아야 하는 AI 에이전트에 유용합니다.

{
  "pdfBase64": "<base64 PDF>",
  "pages": true,
  "check": ["pdfa", "signed", "attachments"]
}

반환 값:

{
  "version": "1.7",
  "pageCount": 3,
  "encryption": "none",          // 'none' | 'aes-128' | 'aes-256' | 'rc4' | 'unknown'
  "pdfA": "3B",                  // null when no PDF/A claim is present
  "signatureCount": 1,
  "hasSignaturePlaceholder": false,
  "attachments": [{ "filename": "factur-x.xml", "mimeType": "application/xml", "sizeBytes": 1234, "relationship": "Source" }],
  "info": { "Producer": "pdfnative", "Title": "Invoice INV-2025-001" },
  "perPage": [{ "index": 0, "width": 595, "height": 842 }],
  "checks": { "pdfa": true, "signed": true, "attachments": true },
  "checksPassed": true
}

check[]는 'pdffa', 'igned', 'encrypted', 'placeholder', 'attachments', 'Dss', 'DocTimestamp', 'Trapped', 'annotations' 중 하나를 허용합니다(마지막 네 개는 v1.6.0부터). checksPassed는 요청한 모든 검사 결과의 AND입니다. signatures: true는 필드별 인밴토리(subFilter, isDocTimestamp, isPlaceholder, byteRange, vriKey)를 추고합니다. annotations: true는 annotations[](모든 /Annots 항목: 0 기반 page, subtype, rect, 그리고 해당 시 contents(200자로 잘림), url, quadPoints, 링크 url)와 annotationCount를 추고합니다. dss, docTimestampCount, trapped는 존재하는 경우에만 표시됩니다. pages: true면 각 perPage 항목도 trimBox / bleedBox / artBox / cropBox / userUnit를 설정된 때 함게 실어 갑니다.

inspect_layout

읽기 전용 페이지 임의 드라이 러 — generate_basic_pdf의 동일한 blocks 추가로 블록을 옴기는 모든 입력(title, footerText, pdfA, normalize, embedFonts, pageSize, margins, headerTemplate, footerTemplate)을 포함합니다. PDF는 생산되지 않습니다. generate_basic_pdf에 전달할 것과 동일한 값을 전달하면 totalPages가 일치합니다.

{ "title": "Memo", "blocks": [{ "type": "paragraph", "text": "Short note." }], "pageSize": "Letter", "verbosity": "summary", "fields": ["totalPages"] }

전체 결과는 pageWidth, pageHeight, margin, totalPages, pages[].blocks[](type, page, x, top, width, height, 포인트, 소수점 두 자리에서 반올림)를 로합니다. 알려진 엔진 격: toc 블록은 여기에스 0포인트로 측저되므로, 인된 목차가 있는 문서는 미리 보기보다 한 페이지 늦漫가 나니다.

validate_pdf

읽기 전용 PDF/UA (ISO 14289-1) 구조 검사: 태그된 PDF를 위한 검사입니다. 임의 도구로 pdfA(예: pdfA: 'pdfa2u')를 사용하야 접근 가능한 문서를 생산한 후 결과를 검중하세요:

{ "pdfBase64": "<tagged-pdf-base64>" }

Return:

{
  "standard": "pdf-ua-1",
  "valid": true,
  "errors": [],          // blocking structural violations (empty when valid)
  "warnings": [],        // non-blocking best-practice recommendations
  "summary": "PDF/UA structural prerequisites hold."
}

카탈로그의 /MarkInfo /Marked true, /StructTreeRoot (+ /ParentTree), /Metadata (XMP), /Lang, 그리고 페이지별 MCID 고유성을 검증합니다. 이는 개발자 시간 절약을 위한 빠른 게이트로, 글트·색상·렌더링까지 추가로 검사하는 완전한 참조 구현 검증기(veraPDF)의 대체 가 아닙니다.

annotate_pdf

기존 PDF에 증분 업데이트 방삭으로 마크업 주석을 오버레이합니다. 이는 시각적리 검토 레이어이지 교체(redaction)가 아닙니다 — 기존 콘텐츠는 그대로 유지됩니다.

{
  "pdfBase64": "<base64 PDF>",
  "annotations": [
    { "type": "highlight", "page": 0, "rect": [72, 700, 520, 715], "color": [1, 1, 0], "contents": "Check this figure" },
    { "type": "text", "page": 0, "rect": [540, 700, 560, 720], "contents": "Reviewer note" }
  ]
}

유형: text, highlight, underline, strikeout, squiggly, square, circle, line, freetext. 페이지 인덱스는 0부터 시작합니다. 암호화된 소스는 거부됩니다(ENCRYPTED_SOURCE) — 먼저 decrypt_pdf를 실행(서명/AcroForm은 제거됨)하여 주석을 단 후, 다시 encrypt_pdf를 실행하세요.

draft_governance_issue

거버넌스 요구사항을 충족하는 GitHub issue를 사람이 검토하고 제출할 수 있도록 로컬에서 초안을 작성합니다. 서버는 GitHub에 연락하지 않습니다 (유일한 외부 연결 경로는 운영자가 PAdES 장기 검증용으로 구성한 TSA / OCSP / CRL 엔드포인트뿐이며 — 외부 네트워크 및 이그레스 참고); 초안 Markdown과 함께 기계가 읽을 수 있는 규정 준수 보고서를 반환합니다.

{
  "title": "add_table drops the caption on the second page",
  "issueType": "bug",
  "summary": "The table caption is only rendered on page 1 when repeatHeader is true.",
  "reproduction": { "command": "add_table with caption + repeatHeader over 2 pages (examples/bordered-table.json, then inspect_pdf)", "result": "Page 2 has no caption row." },
  "expectedBehavior": "The caption repeats with the header on every page.",
  "duplicateSearchPerformed": true
}

런타임 의존성을 추가하거나, 재현 절차를 누락하거나, duplicateSearchPerformed: false로 지정하는 초안은 GOVERNANCE_VIOLATION 오류로 거부됩니다. 전체 human-in-the-loop 계약은 docs/guides/AI_GOVERNANCE.md에서 확인하세요.

verify_pdf, add_attachment, extract_text

자세한 내용은 docs/AI_GUIDE.md의 해당 섹션과 docs/KNOWLEDGE_BASE.md의 참조 자료를 확인하세요. 바로 실행할 수 있는 예제는 examples/에 있습니다.


🔐 보안 모델

pdfnative-mcp는 호스트 프로세스 내부에서 실행되며 stdio MCP 서버(또는 루프백 전용 HTTP 엔드포인트)를 제공합니다. 구성된 샌드박스 외부에서는 어떤 I/O도 수행하지 않습니다.

  • 파일 쓰기는 PDFNATIVE_MCP_OUTPUT_DIR에 의해 제한됩니다. 이 값이 설정되지 않으면 file 출력 모드는 SecurityError 오류로 거부됩니다.

  • 경로 붙석은 절대경로, 상위 경로 탐색(..), NUL 바이트, 그리고 .pdf 외의 확장자를 거부합니다.

  • 출력 크기는 호출당 50 MB로 제한됩니다.

  • 입력은 모든 도구의 경계에서 엄격한 JSON Schema와 Zod 런타임 체크를 통해 검증됩니다. 알 수 없거나 잘못 표기된 키(최상위·중첩)는 VALIDATION_ERROR 오류로 거부되며, base64 / DER 페이로드는 파서가 실행되기 전에 정전성 검사를 받습니다(data: 접두사 허용, PEM또는 이중 인코딩된. (입력은 해결책과 함께 거부됩니다).

  • HTTP 전송 (PDFNATIVE_MCP_PORT)는 프백에만 바인딩됩니다. PDFNATIVE_MCP_HTTP_TOKEN이 설정되지 않은 경우 인증이 없으며, 설정된 경우 유효한 Bearer 토큰이 없으면 401이 반환됩니다.

외부 네트워크 및 이그레스

서버는 기본적으로 외부 네트워크 호출을 수행지 않습니다. 수행할 수 있는 유일한 이그레스는 운용자가 PAdES 장기 검증을 위해 환경에 설정한 RFC 3161 / OCSP / CRL 엔드포인트로만 이동합니다(PDFNATE_MCP_TSA_URL, PDFNATIVE_MCP_REVOCATION, PDF_NATIVE_MCP_NETWORK_ALLOWED_HOSTS) — 도구 인자로 제공된 URL에는 절대 연락하지 않으며, GitHub나 원격지에 있는 것도 무엇에로 이동하지 않습니다. 이런 구성이 없이 sign_pdf timestamp: true, timestamp_pdf, add_ltv mode: 'online'은 멈버에 TSA_NOT_CONFIGURED / REVOCATION_NOT_CONFIGURED 오류와 함의 실패하며 문서에는 아무 것도 하지 않습니다. add_ltv mode: 'offline'은 네트워크 접이 전혀 없이 호출자에게 받은 MRI를 내장합니다.

OCSP / CRL URL은 PDF 내부의 신되지 문화된 인가 인증서 확장 영역(AIA / CRL 배포 지점)에서 옵니다. 따라서 모든 요청은 SSRF 가드를 통과해야 합니다:

  • 호스트는 운영자 Ann- allow-list(host, host:port 또는 *.suffix)와 일치해야 하며, 륀일 와일드카드(*)만으로 된 항로그 거부됩니다. 항목은 호스트이며 (not URL)입니다. host:port 항목은 명시적으로 포트와 함께 명기된 URL일 경우에만 일치합니다 (URL 박서는 :80/443 기본 포트를 생략하므로 해당 포트는 호스트만 len항 등록). 와이드카드 항목은 포트를 포함할 수 없으며, IDN 호스트명은 퓨니코드(xn--…)로 등록, IPv6 리터럴은 대괄호([2001:db8::1])로 표시해야 합니다.

  • http: / https: 프로토콜만 허용하며, independently 내장 인증 정보는 허용되지 않고, 리다이렉트는 절속 방생하지 않습니다.

  • loopback, 기밀 link-local, 비공개 private, unique-local, 통신사업자(CG-), unspecified, 그리고 “멀티브 (मulticast) 주소 리터럴 — 거부되든 decimal / octal / hex 표기와 IPv4-ma은-apped IPv6를 포함 — These are allowed to be allowed only if exactly. Guard checks literals only: a listed hostname that resolves to an internal address (DNS rebinding)를 감지하지 않습니다 (리졸버를 추가하지 않으면 이를 거부할 방법이 업기 때문; 당신이 제어할 수 있는 호스트 only 등록).

  • 요청별 타임아웃 (PDFNATIVE_MCP_NETWORK_TIMEOUT_MS) 및 응답 크기 상한(TSA 256 KiB, OCSP 1 MiB, CRL 16 MiB)은 스트리밍밍에서 강제됩니다. 따라서 매우 큰 응답은 버퍼에 저장되는 대신 보통할 수 있습니다.

  • 응답자(responder)가 반환한 OCSP 응답과 CRL은 add_lt_mode: 'online'에서 사용하기 전에 파서 검사를 수행합니다.

  • TSAR URL은 운영자 신외 근거로 검사됩니다(scheme + 접차 확인만 하며, 인증 정보는 확인하지 않음). PDFNATE_MCP_TSA_AUTH 시크릏 정보는 로그나 오류 메시지에 나타나지 않습니다.

Providers(자원 공급자)는 호출 시 각 영향을 생성되고 pdfnative의 per-call 옵션으로 전달됩니다. 프로세스 전역 providers setter는 업 사용되지 않으므로, 동시 처리되는 요청들은 사이에 상태 공유가 없습니다. server/discover 응답은 현재 이그레스 정책을 (항목의 종류만, 시크릏(secrets)는 제외) 보고합니다.

책임 있는 문정보 자례: SECURITY.md에, 운영자 설정계 안내는 docs/guides/LTV.md를 참고하세요.


🧪 개발

git clone https://github.com/Nizoka/pdfnative-mcp.git
cd pdfnative-mcp
npm install
npm run typecheck
npm run lint
npm test
npm run build
npm run validate:pdfa     # advisory: veraPDF over the 26-file PDF/A corpus (24 validated; skips when veraPDF is absent; VERAPDF_REQUIRED=1 fails closed)
node scripts/tool-shape.mjs --write   # only after a deliberate tools/list schema change (catalogue parity fixture)

stdio로 밍 “스모크 테스트”를 실행하세요:

node dist/cli.js
# In another terminal, send a JSON-RPC initialize request via stdin (e.g. with mcp-inspector).

기여자: 로컬 검증 워크플로우 전체(game gate, examples-as-tests, 생성된 PDF 형식가ộc 구조 검증 (assertValidPdf, inspect_pdf, validate_pdf, verify_pdf), 뷰어에서 결과를 열어 확인, veraPDF 외부 PDF/A 검사, MCP Inspector)는 docs/guides/LOCAL_TESTING.md을 확인하세요.

📣 릴리이스 프로세

pdfnative-mcp은 pdfnative과 동일한 릴리이스 방식을 따릅니다:

  • 태그별 릴리스 노트 파일: release-notes/vX.Y.Z.md

  • CHANGELOG.md 은 각 릴리미스 릴리스트를 반영합니다.

  • GitHub Release 게시명은 release-notes/vX.Y.Z.md에서 가져옵니다.

  • npm 배포는 NPM_TOKEN 없이 GitHub Actions Trusted Discloser(OIDC)를 통해 수행합니다.

정식 구성과 배포 체크리스트 병목은 release-notes/TEMPLATE.md를 확인하세요.


📁 프로젝크 트 구조

src/
├── cli.ts                      # entrypoint: stdio (default) or Streamable HTTP (PDFNATIVE_MCP_PORT)
├── http.ts                     # Node http <-> Web Request/Response bridge + Host/Origin loopback guard
├── auth.ts                     # opt-in HTTP bearer token (PDFNATIVE_MCP_HTTP_TOKEN)
├── base64.ts                   # base64 / DER boundary decoding with agent-facing diagnostics
├── index.ts                    # public library exports
├── server.ts                   # Server factory, tool registry, cache hints, SERVER_INSTRUCTIONS
├── network.ts                  # operator-configured TSA / OCSP / CRL egress + SSRF guard
├── print.ts                    # print-production schema (boxes, bleed, marks, userUnit, outputIntent, metadata, creationDate)
├── diagnostics.ts              # PDF/A diagnostics sink, strict / includeDiagnostics / embedFonts
├── chart.ts                    # charts v2 schema + ChartBlock mapper
├── blocks.ts                   # the 7 extended document blocks (table, image, link, toc, barcode, svg, formField)
├── layout.ts                   # pageSize / margins / header & footer templates / compress / debug / encrypt (PdfLayoutOptions)
├── table.ts, barcode.ts, form.ts, image.ts   # bodies shared by a dedicated tool and its inline block
├── watermark.ts                # text and/or image watermark + position, PDF/A-1b transparency guard
├── encryption.ts               # password + encrypt schema (Standard Security Handler), decrypt error mapping
├── inflate-cap.ts              # PDFNATIVE_MCP_MAX_INFLATE_BYTES (engine decompression cap) + PDF_PARSE_FAILED mapping
├── output.ts                   # sandboxed file writer / base64 emitter (single + multi)
├── text.ts                     # newline sanitizer (Safe PDF/A)
├── doc-features.ts             # nested lists, outline, page labels, viewer prefs (+ print-dialog defaults)
├── pagetree.ts                 # page-tree error mapping (merge/split/extract)
├── crypto-provider.ts          # node:crypto signing provider for DER keys (SHA-256/384/512); verification stays pure JS
├── projection.ts               # verbosity / fields projection for the seven read tools
├── errors.ts                   # ToolError, SecurityError, GovernanceError
└── tools/
    ├── generate-basic-pdf.ts
    ├── inspect-layout.ts
    ├── add-barcode.ts
    ├── sign-pdf.ts
    ├── add-ltv.ts
    ├── timestamp-pdf.ts
    ├── update-metadata.ts
    ├── add-international-text.ts
    ├── add-table.ts
    ├── add-form.ts
    ├── read-form-fields.ts
    ├── fill-form.ts
    ├── add-chart.ts
    ├── embed-image.ts
    ├── inspect-pdf.ts
    ├── verify-pdf.ts
    ├── validate-pdf.ts
    ├── add-attachment.ts
    ├── extract-attachments.ts
    ├── extract-text.ts
    ├── merge-pdfs.ts
    ├── split-pdf.ts
    ├── extract-pages.ts
    ├── annotate-pdf.ts
    ├── encrypt-pdf.ts
    ├── decrypt-pdf.ts
    ├── draft-governance-issue.ts
    └── prepare-signature-placeholder.ts
scripts/
├── verify-issue.mjs            # governance draft checker (npm run verify:issue)
├── validate-pdfa.mjs           # veraPDF run (npm run validate:pdfa; PASS/FAIL/XFAIL/XPASS/INFRA/SKIP)
├── generate-pdfa-corpus.mjs    # builds the 26-file PDF/A corpus (24 validated incl. 3 negative canaries, 2 page-tree outputs)
└── tool-shape.mjs              # structural tools/list fingerprint (--write refreshes tests/_fixtures/tool-shape.json)
.github/workflows/ci.yml        # Linux (Node 22 / 24) + Windows quality gate
.github/workflows/verapdf.yml   # non-blocking veraPDF CI job (SHA-256-pinned installer, VERAPDF_REQUIRED=1)
tests/                          # vitest suites (one per tool / module; document-blocks, layout-options, inspect-layout,
                                #   watermark, inflate-cap, catalogue-parity + catalogue-superset vs the 1.5.0 fixture)

Pe Ploadmap

v1.6.0은 출시되었습니다 (전체 엔진 커버밍 — 13 종류의 블록, 레이아웃 옵션, inspect_layout — PAdES LTV ladder, 인쇄 production, 카트트 v2, update_metadata, MCP 2026-07-28). 전체 계획 — 출시된 이정도, 진행 중인 작업, 장기 방향 — 로드맵인 ROADMAP.md에서 확인할 수 있습니다.

아직은 보류되어 있습니다:

  • redact_pdf — pdfnative에는 콘텐츠 제거 API가 없습니다. 오버레이만 하는 “redaction은 안전을 가장하게 만드는 것 입니다.

  • 네이티브 ECDSA 검증 — pdfnative는 ecdsaVerifyHash를 내보내지 않으므로, verify_pdf는 P-256용 순수-JS 경로를 유지합니다.

  • HTTP 페이지 스트리밍 dump — MCP 2026-07-28은 여전히 partial structuredContent를 지원하지 않으므로 대규모 결과는 원샷으로만 반환합니다.

새로운 기능에 대한 아이디어가 있으세요? 이슈 또는 PR을 열고 알려주세요.


⭐ 스타(Star) 주세요

pdfnative-mcp가 유용하다면, ⭐ 이 저장소를 눌러주세요. 그리고 밑에 있는 엔진 Nizoka/pdfnative도 함께 고려해 주세요. 별빌은 다른 사람들이 프로젝트를 발견하고 지속 개발을 지속하는 데 도움이 됩니다.


✉ 참여 방법

기여는 언제나 환영합니다. CONTRIBUTING.md를 읽고 오 이슈를 확인한 뒤 행동 강령을 준수해 주세요.


📄 라이센스

MIT © 2026 Nizoka

pdfnative-mcp은 pdfnative와 [Model Context Protocol TypeScript SDK](https://github.com/modelcontext protocol/typecript-sdk) 기반으로 구축되었습니다.

Available Tools

28 tools
add_attachmentAdd embedded file attachment (PDF/A-3, Factur-X)A
Idempotent

PDF/A-3b document with embedded files — the tool for Factur-X / ZUGFeRD e-invoices (one XML attachment, relationship 'Source', mimeType application/xml) or any PDF carrying machine-readable side-files (≤ 8 MiB each). Body via blocks (same schema as generate_basic_pdf). Pair with embedFonts:true for a valid PDF/A-3 claim (strict:true fails otherwise). Read them back with extract_attachments. Print, metadata and creationDate options as on every document tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
debugNoDraw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.
printNoPrint production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.
titleYesDocument title (also written to the /Info dictionary).
blocksNoOptional human-readable document body (same block schema as generate_basic_pdf). When omitted, a minimal cover paragraph is emitted so the PDF is not empty.
strictNoFail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true.
marginsNoMargins in points, all four required (0–200). Default 45 / 36 / 35 / 36.
compressNoFlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.
metadataNo/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.
pageSizeNoPortrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.
embedFontsNoEmbed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB.
footerTextNoOptional footer text rendered on every page.
outputModeNo'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..').
typographyNoFine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.
attachmentsYesOne or more files to embed. Auto-enables PDF/A-3 (ISO 19005-3). Factur-X invoices use a single attachment with relationship=Source and mimeType=application/xml.
creationDateNoISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs.
outputIntentNoCustom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space.
footerTemplateNoRunning footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.
headerTemplateNoRunning header on every page (left / center / right zones); reserves 15 pt.
includeDiagnosticsNoReturn the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty).

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already cover the safety profile (not read-only, idempotent, non-destructive), and the description adds useful constraints beyond that: the 8 MiB per-attachment ceiling, the requirement to pair with embedFonts:true for a valid PDF/A-3 claim, and that strict:true will fail rather than warn. It does not say what happens on size or strict failure in terms of error surfaces, but the added operational context is substantive.

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?

One dense paragraph, front-loaded with the identity and intended use case, then the critical caveats (size limit, embedFonts pairing), then the read-back pointer and the note that shared options behave as on other document tools. No sentence is filler.

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

Completeness5/5

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

For a 20-parameter creation tool with an output schema and full schema coverage, the description supplies exactly the non-schema-critical knowledge an agent needs: when to choose it, the font-embedding prerequisite for compliant output, the per-file size cap, and where to read attachments back. Nothing essential is left implicit.

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 100%, so the baseline is 3; the description still adds the 8 MiB attachment size limit (not in the schema) and the Factur-X recipe (single XML attachment, relationship 'Source', mimeType application/xml) that tells the agent how to fill the required attachments array for the most common case. The blocks parity note with generate_basic_pdf is also useful cross-tool parameter context.

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 output type (PDF/A-3b with embedded files) and names the concrete use cases (Factur-X / ZUGFeRD e-invoices, machine-readable side-files), so the agent can distinguish it from generate_basic_pdf and the other document-producing siblings without reading the schema. The 'the tool for X' framing makes the resource and scope unambiguous.

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 selection context (use this when a PDF must carry embedded side-files, e.g. Factur-X) and names a follow-up tool explicitly ('Read them back with extract_attachments'). It stops short of an explicit when-not rule contrasting it with generate_basic_pdf for ordinary documents, which would have made it a 5.

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

add_barcodeAdd barcode / QR codeA
Idempotent

Single-page PDF with a barcode: qr (URLs, vCards, UTF-8 ≤ 4296 chars; ecLevel 'H' for print, 'M' default), code128 (ASCII SKUs), ean13 (12–13 digits, checksum auto), datamatrix (dense industrial marks), pdf417 (ID cards, boarding passes). data is the raw payload — never pre-encode. Typical: { format:'qr', data:'https://example.com', caption:'Scan me' }. PDF/A, print, metadata and creationDate options as on every document tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
dataYesRaw payload to encode — do NOT URL-encode. For QR/URL pass e.g. "https://example.com" verbatim. EAN-13 must be 12 or 13 digits (13th is auto-computed). Code 128 accepts ASCII alphanumerics.
pdfANoPDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md.
pdfxNoPDF/X-4 print exchange (ISO 15930-7). REQUIRES outputIntent with the printer's ICC profile (device class 'prtr'; CMYK or Gray — none is bundled); needs embedFonts:true for a conformant file (PDFX_NO_FONT_ENTRIES otherwise, strict:true refuses). Exclusive with pdfA and encrypt; metadata.trapped must be 'True' or 'False'; TrimBox or ArtBox, not both. Links and form fields are reported (PDFX_ANNOTATIONS). Check with validate_pdf standard:'pdf-x-4'. See the print_ready prompt.
debugNoDraw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.
printNoPrint production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.
titleNoPDF document title (also rendered as page heading).Barcode
widthNoBarcode width in PDF points.
formatYesBarcode symbology to render.
heightNoBarcode height in PDF points (ignored for square symbologies like QR/Data Matrix).
strictNoFail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true.
captionNoOptional caption rendered above the barcode.
ecLevelNoQR ONLY. Error correction level (L=7%, M=15%, Q=25%, H=30%). Ignored for code128/ean13/datamatrix/pdf417. Use H for printed media that may get smudged or partially covered (e.g. logo overlay).M
encryptNoEncrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.
marginsNoMargins in points, all four required (0–200). Default 45 / 36 / 35 / 36.
compressNoFlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.
metadataNo/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.
pageSizeNoPortrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.
embedFontsNoEmbed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB.
outputModeNo'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..').
typographyNoFine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.
creationDateNoISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs.
outputIntentNoCustom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space.
footerTemplateNoRunning footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.
headerTemplateNoRunning header on every page (left / center / right zones); reserves 15 pt.
includeDiagnosticsNoReturn the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty).

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already cover the safety profile (destructiveHint=false, idempotentHint=true, openWorldHint=false), and the description adds real behavioral context beyond them: the result is a single-page PDF, `data` must be raw (never pre-encoded), and ecLevel should be 'H' for print. It does not discuss outputMode/file sandbox or error escalation, which keeps it below a 5.

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?

Front-loaded with the format taxonomy, then the critical `data` caveat, then a concrete call example — every clause carries information and nothing is redundant.

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 26-parameter tool with full schema coverage and an output schema, the description focuses correctly on what is distinctive (barcode creation, single page, raw payload) and delegates shared options to 'as on every document tool'. A note on outputMode defaults or the returned artifact would make it fully self-contained.

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 100%, so the baseline is 3, but the description meaningfully enriches the two most important parameters: it explains the format enum semantics beyond the schema's terse labels and warns that `data` is the raw payload that must not be pre-encoded, plus ecLevel guidance not fully captured in the schema.

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 ('Single-page PDF with a barcode') and immediately enumerates the supported symbologies with their intended payloads, so an agent can distinguish this from generate_basic_pdf or other document builders without opening 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 per-format selection guidance (qr for URLs/vCards, code128 for ASCII SKUs, ean13 for 12-13 digits, datamatrix for dense industrial marks, pdf417 for ID/boarding passes) with constraints like the 4296-char limit and auto-checksum. It stops short of naming an alternative tool or stating when not to use it, so it is strong but not fully routing.

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

add_chartAdd native vector chartA
Idempotent

Single-page PDF with a native vector chart (pure path operators, no raster): bar, barH, stackedBar, stackedBarH, line (markers), area, scatter, pie, donut. Multi-series, legends, 'nice' ticks, gridlines, negatives; per-series xValues with xAxis.type 'linear' | 'time' (ISO-8601), secondary right axis (axis2 + yAxis:'right'), axis.scale 'log', dataLabels, labelStride / labelRotation. Pie/donut take exactly one series. Colours are hex ('#3366cc'). Tagged /Figure + /Alt (auto when altText is omitted). Engine cross-field rules surface as CHART_ERROR with the remedy. Inside a longer document use a 'chart' block in generate_basic_pdf. PDF/A (pdfA + embedFonts:true), print, metadata and creationDate as on every document tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
axisNoValue-axis options (bar/line only).
pdfANoPDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md.
pdfxNoPDF/X-4 print exchange (ISO 15930-7). REQUIRES outputIntent with the printer's ICC profile (device class 'prtr'; CMYK or Gray — none is bundled); needs embedFonts:true for a conformant file (PDFX_NO_FONT_ENTRIES otherwise, strict:true refuses). Exclusive with pdfA and encrypt; metadata.trapped must be 'True' or 'False'; TrimBox or ArtBox, not both. Links and form fields are reported (PDFX_ANNOTATIONS). Check with validate_pdf standard:'pdf-x-4'. See the print_ready prompt.
alignNoHorizontal alignment within the content width. Default 'left'.
axis2NoSecondary RIGHT value axis (drawn only when a series sets yAxis:'right').
debugNoDraw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.
introNoOptional introductory paragraph rendered above the chart. The chart `title` (if any) is also used as the PDF metadata title.
printNoPrint production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.
titleNoChart title rendered above the plot.
widthNoPlot width in points (clamped to content width). Default 460.
xAxisNoHorizontal axis. 'category' (default) positions points by index; 'linear' / 'time' position them by series xValues (line/area/scatter only). Time ticks are UTC-deterministic.
colorsNoPalette override (per-series for bar/line, per-slice for pie/donut).
heightNoPlot-area height in points. Default 240.
legendNoLegend placement. Defaults to 'bottom' for multi-series/pie, else 'none'.
seriesYesData series. Pie/donut charts use exactly one series (each value becomes a slice).
strictNoFail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true.
altTextNoAlt text for the tagged-PDF /Figure /Alt. Auto-generated when omitted.
encryptNoEncrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.
marginsNoMargins in points, all four required (0–200). Default 45 / 36 / 35 / 36.
markersNoDraw point markers on line series. Default false.
compressNoFlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.
metadataNo/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.
pageSizeNoPortrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.
chartTypeYesChart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'stackedBar'/'stackedBarH'/'line'/'area'/'scatter' support multiple series. 'scatter' requires xValues on every series and a positional xAxis.type ('linear' or 'time').
categoriesNoCategory / slice labels (x-axis). Defaults to 1-based indices when omitted.
dataLabelsNoPer-point value labels: true for defaults, or an object to format them.
embedFontsNoEmbed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB.
outputModeNoEither 'base64' (returns the PDF inline) or 'file' (writes into the PDFNATIVE_MCP_OUTPUT_DIR sandbox).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf.
typographyNoFine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.
labelStrideNoDraw every Nth category label. Default: automatic (measured non-overlap); 1 draws every label.
creationDateNoISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs.
outputIntentNoCustom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space.
labelRotationNoRotate category labels counter-clockwise by this many degrees (disables the automatic stride).
footerTemplateNoRunning footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.
headerTemplateNoRunning header on every page (left / center / right zones); reserves 15 pt.
includeDiagnosticsNoReturn the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty).

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.4/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=false, idempotentHint=true and destructiveHint=false, but the description adds substantive behavior beyond them: alt text is auto-generated when omitted, /Figure tagging, cross-field engine rules surfacing as CHART_ERROR with the remedy, and the PDF/A requirement (pdfA + embedFonts:true, plus print/metadata/creationDate notes). That is real operational context an agent needs before calling a 37-parameter generator.

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

Conciseness3/5

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

Purpose and chart types are front-loaded and almost every clause carries information, so there is little waste. However, the whole description is a single run-on paragraph that mixes chart-feature semantics with PDF/A, print and metadata concerns, producing a dense wall of semicolon clauses that is hard to scan before a call.

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 an output schema present, return values need no explanation, and the 100%-covered schema carries the per-field detail. The description covers the headline capabilities and the composition/PDF-A constraints, which is sufficient for a tool of this complexity, though it does not mention pagination/sandbox expectations for outputMode beyond what the schema says.

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 description coverage is 100%, so the baseline is 3. The description earns the extra point by explaining cross-parameter coupling that the flat schema only states locally: per-series xValues must pair with xAxis.type 'linear'|'time', the secondary axis is engaged only via axis2 + series yAxis:'right', and pie/donut accept exactly one series. Those are integration-level semantics rather than restatements.

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?

Specific verb+resource ('Add native vector chart') immediately qualified by what it produces ('Single-page PDF with a native vector chart ... pure path operators, no raster') and an enumerated chart-type list that an agent can match against a request. It also routes the agent to the sibling case ('Inside a longer document use a 'chart' block in generate_basic_pdf'), so add_chart is clearly distinguishable from generate_basic_pdf.

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 an explicit alternative and the condition that selects it: standalone one-chart PDFs here, embedded charts via generate_basic_pdf's 'chart' block in longer documents. It also states form constraints (pie/donut take exactly one series). It does not spell out when the tool should not be used at all (e.g. raster image charts), 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.

add_formAdd interactive formA
Idempotent

New PDF with an interactive AcroForm: text fields, text areas, checkboxes, radio buttons, dropdowns (data capture, surveys, fillable templates). To fill or flatten an EXISTING form use read_form_fields + fill_form. PDF/A, print, metadata and creationDate options as on every document tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
pdfANoPDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md.
debugNoDraw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.
printNoPrint production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.
titleYesForm title rendered at the top of the document.
fieldsYesOrdered list of form field definitions.
strictNoFail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true.
encryptNoEncrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.
marginsNoMargins in points, all four required (0–200). Default 45 / 36 / 35 / 36.
compressNoFlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.
metadataNo/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.
pageSizeNoPortrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.
embedFontsNoEmbed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB.
footerTextNoOptional footer text rendered at the bottom of every page.
outputModeNoEither 'base64' (returns the PDF inline) or 'file' (writes to a sandboxed path inside PDFNATIVE_MCP_OUTPUT_DIR).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf.
typographyNoFine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.
creationDateNoISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs.
outputIntentNoCustom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space.
footerTemplateNoRunning footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.
headerTemplateNoRunning header on every page (left / center / right zones); reserves 15 pt.
includeDiagnosticsNoReturn the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty).

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=false and destructiveHint=false, so the safety profile is covered. The description adds useful context beyond that: this produces a brand-new document rather than mutating an existing one, and it names the correct pathway for existing forms. It doesn't discuss permissions or caching, but with annotations carrying the safety load that is acceptable.

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?

Two front-loaded sentences with the creation semantics first and the routing rule second. The parenthetical use-case list is mild padding and 'as on every document tool' is vague delegation, keeping it just under a perfect score.

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?

An output schema exists, so return values need no explanation, and the 21 parameters are fully schema-documented. For a complex creation tool the description covers the key agent decision points (what it makes, where the alternative tool lives) and delegates the shared option details appropriately.

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 the baseline is 3. The description lists the field types ('text fields, text areas, checkboxes, radio buttons, dropdowns') and characterizes them as use cases (data capture, surveys, fillable templates), but adds no syntax or format detail beyond what the schema already documents.

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 ('New PDF with an interactive AcroForm') and enumerates the field types it can build. The explicit 'New PDF' framing distinguishes it from siblings like fill_form/read_form_fields 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 an explicit routing rule: 'To fill or flatten an EXISTING form use read_form_fields + fill_form.' That names the alternative and the condition selecting it. However, it doesn't cover when-not-to-use for other scenarios (e.g., adding fields to an existing document), so it stops short of a full 5.

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

add_international_textAdd international textA
Idempotent

PDF rendering text in 27 scripts (Arabic, Hebrew, Thai, Lao, CJK, Devanagari, Bengali, Tamil, Telugu, Sinhala, Tibetan, Khmer, Myanmar, Tai Tham, New Tai Lue, Tai Le, Cham, Ethiopic, Cyrillic, Greek, Georgian, Armenian, Vietnamese, …; ha / yo / ig / sw are aliases of latin with anchored combining marks), COLRv1 colour emoji and mathematical symbols ('math': ∀ ∃ √ ∑ ∫ ∞). BiDi (UAX #9), Arabic joining and complex-script shaping are automatic; input is NFC-normalised; newlines split paragraphs. lang is a code or an array for mixed runs (['ar','emoji'], ['latin','math']). Fonts are always embedded, so embedFonts does not exist here. PDF/A, print, metadata and creationDate options as on every document tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
langYesLanguage / script identifier. Either a single code (e.g. 'ar'), a comma-separated list ('ar,emoji'), or an array (['ar','emoji']). Multiple codes enable multi-font run splitting (script + emoji + Latin fallback). 27 scripts; ha / yo / ig / sw (Hausa, Yoruba, Igbo, Swahili) are aliases of latin, whose combining marks are anchored.
pdfANoPDF/A level (Tagged PDF + sRGB OutputIntent + XMP). Fonts are embedded here, so the claim is valid as-is. See docs/guides/PDFA.md.
pdfxNoPDF/X-4 print exchange (ISO 15930-7). REQUIRES outputIntent with the printer's ICC profile (device class 'prtr'; CMYK or Gray — none is bundled); needs embedFonts:true for a conformant file (PDFX_NO_FONT_ENTRIES otherwise, strict:true refuses). Exclusive with pdfA and encrypt; metadata.trapped must be 'True' or 'False'; TrimBox or ArtBox, not both. Links and form fields are reported (PDFX_ANNOTATIONS). Check with validate_pdf standard:'pdf-x-4'. See the print_ready prompt.
debugNoDraw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.
printNoPrint production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.
titleYesPDF title (rendered as page heading and stored as document metadata).
strictNoFail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true.
encryptNoEncrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.
marginsNoMargins in points, all four required (0–200). Default 45 / 36 / 35 / 36.
compressNoFlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.
metadataNo/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.
pageSizeNoPortrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.
normalizeNoUnicode normalization before shaping. Default 'NFC' (widest glyph coverage); NFD/NFKC/NFKD or false for special needs.
outputModeNo'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..').
paragraphsYesOrdered list of paragraphs to render in the chosen script.
typographyNoFine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.
creationDateNoISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs.
outputIntentNoCustom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space.
footerTemplateNoRunning footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.
headerTemplateNoRunning header on every page (left / center / right zones); reserves 15 pt.
viewerPreferencesNoReader presentation hints (catalog /PageLayout, /PageMode, /ViewerPreferences). PDF/A-safe; all optional.
includeDiagnosticsNoReturn the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty).

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A3.7/5.0
Behavior4/5

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

Beyond the annotations (idempotent, non-destructive), the description discloses real behavioural traits: fonts are always embedded so `embedFonts` does not exist here, input is NFC-normalised, newlines split paragraphs, and BiDi/Arabic joining/shaping are automatic. These are non-obvious engine behaviours an agent could not derive from the schema.

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?

A single dense paragraph, front-loaded with the script inventory before mechanics. Every clause carries information (script list, aliases, emoji/math, BiDi, NFC, newline behaviour), though the parenthetical script enumeration is long and could be trimmed.

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 23-parameter tool with an output schema, the description correctly focuses on the international-text differentiators and delegates the shared document options (PDF/A, print, metadata, creationDate) to 'as on every document tool'. That delegation assumes cross-tool documentation the agent may not have, which is the only gap.

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 the schema already carries parameter meaning, and the description mostly restates the `lang` semantics (single code, comma list, array of mixed runs) that the schema documents in full. It adds the useful note that the tool has no `embedFonts`, but little else beyond the schema.

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 states a specific verb+resource and scope: rendering PDF text across 27 named scripts, colour emoji and math, with BiDi/shaping/normalisation details. It implicitly distinguishes itself from generate_basic_pdf by positioning this as the international/multilingual entry point, but never names that sibling explicitly.

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

Usage Guidelines3/5

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

Usage is only implied: an agent reads the script list and infers 'use this when text is non-Latin'. There is no explicit when-to-use versus generate_basic_pdf, and no statement of what happens (or which tool to use) if the input is plain ASCII. Adequate but leaves selection to inference.

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

add_ltvEmbed LTV validation material (PAdES B-LT)A

PAdES B-LT: embed a Document Security Store (/DSS + per-signature /VRI) with the certificates and OCSP/CRL material future verifiers need ('LTV enabled' in Adobe Reader once the root is trusted). Ladder step 3: sign_pdf (profile:'pades', timestamp:true) → add_ltv → timestamp_pdf. mode 'online' (default) fetches through the OPERATOR revocation provider (PDFNATIVE_MCP_REVOCATION + PDFNATIVE_MCP_NETWORK_ALLOWED_HOSTS; REVOCATION_NOT_CONFIGURED otherwise — no network without it); mode 'offline' embeds caller-supplied DER certificates / OCSP responses / CRLs with zero network. Incremental (existing /DSS merged). Needs ≥ 1 signed signature; unencrypted PDFs only.

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNo'online': fetch OCSP/CRL through the operator provider (PDFNATIVE_MCP_REVOCATION + allow-list; REVOCATION_NOT_CONFIGURED otherwise). 'offline': embed the caller-supplied DER material, zero network.online
pdfBase64YesBase64-encoded SIGNED PDF (unencrypted). Sign with sign_pdf (profile=pades recommended) first.
outputModeNo'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured).base64
outputPathNoRelative path inside PDFNATIVE_MCP_OUTPUT_DIR (required when outputMode='file').
preferOcspNoonline: try OCSP before CRL for each certificate (default true).
crlsDerBase64Nooffline: DER CertificateList (RFC 5280) blobs to embed in /DSS /CRLs.
certificatesDerBase64Nooffline: DER X.509 certificates to embed in /DSS /Certs.
ocspResponsesDerBase64Nooffline: DER OCSPResponse (RFC 6960) blobs to embed in /DSS /OCSPs.
extraCertificatesDerBase64Noonline: additional DER certificates (intermediates / roots) to complete chains the CMS does not carry.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only flag openWorldHint and non-idempotence; the description adds the substantive behavior: incremental update with existing /DSS merged, network gated on PDFNATIVE_MCP_REVOCATION + allow-list with REVOCATION_NOT_CONFIGURED otherwise, and the fact that offline mode performs zero network I/O. These are the operational details an agent needs before invoking.

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?

Dense but front-loaded: the PAdES B-LT action leads, then the ladder, then mode semantics, then constraints. Every sentence carries information, though the heavy parenthetical/env-var stacking makes it harder to scan than it could be.

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

Completeness5/5

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

With an output schema present, return values need not be described, and the description covers what remains: prerequisites, mode selection, network configuration requirements, and failure conditions. Nothing needed to invoke it correctly is missing.

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 description coverage is 100%, so baseline is 3. The description nonetheless adds value beyond the schema by framing mode 'online'/'offline' as a network-vs-no-network tradeoff with named env vars and by explaining that extraCertificates complete chains the CMS does not carry.

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 ('embed a Document Security Store (/DSS + per-signature /VRI)') and pins the exact spec level (PAdES B-LT). It also situates itself against siblings by naming the ladder (sign_pdf → add_ltv → timestamp_pdf), so an agent can place it without opening other schemas.

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

Usage Guidelines5/5

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

Explicitly states when to use it (ladder step 3, after signing with profile:'pades', before timestamp_pdf) and when each mode applies: 'online' fetches via the operator revocation provider, 'offline' embeds caller-supplied DER with zero network. Prerequisites are given too: ≥1 signed signature and unencrypted PDFs only.

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

add_tableAdd table / reportA
Idempotent

Tabular PDF report from headers + rows (every row the same length). Smart-table options: wrap, repeatHeader (header on every page), zebra, caption (tagged for PDF/A), minRowHeight, cellPadding, cellBorders, cellVAlign, autoFitColumns, clipCells. Inside a longer document use a 'table' block of generate_basic_pdf instead. PDF/A (pdfA + embedFonts:true), print, metadata, watermark and creationDate options as on every document tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
pdfANoPDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md.
pdfxNoPDF/X-4 print exchange (ISO 15930-7). REQUIRES outputIntent with the printer's ICC profile (device class 'prtr'; CMYK or Gray — none is bundled); needs embedFonts:true for a conformant file (PDFX_NO_FONT_ENTRIES otherwise, strict:true refuses). Exclusive with pdfA and encrypt; metadata.trapped must be 'True' or 'False'; TrimBox or ArtBox, not both. Links and form fields are reported (PDFX_ANNOTATIONS). Check with validate_pdf standard:'pdf-x-4'. See the print_ready prompt.
rowsYesData rows. Each row is an array of cell strings with the same length as `headers`.
wrapNoCell wrap policy: 'auto' (default) wraps only overflowing cells; 'always' wraps every cell; 'never' truncates.
debugNoDraw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.
printNoPrint production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.
titleYesReport title rendered at the top of the document and used as PDF metadata title.
zebraNoAlternate-row light tint (static fill, PDF/A-1b safe).
strictNoFail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true.
captionNoCaption rendered above the table (tagged as /Caption under PDF/A).
encryptNoEncrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.
headersYesColumn header labels. Must have the same length as each row in `rows`.
marginsNoMargins in points, all four required (0–200). Default 45 / 36 / 35 / 36.
compressNoFlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.
metadataNo/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.
pageSizeNoPortrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.
clipCellsNoClip cell contents to the column bounds (PDF clip operators). Recommended for PDF/A and visual safety.
infoItemsNoOptional key-value metadata rows rendered below the title (e.g. date, author).
watermarkNoOptional semi-transparent watermark rendered centred on every page: `text` (e.g. 'DRAFT'), `image` (JPEG/PNG), or both combined. At least one of text / image is required. opacity < 1.0 (text or image, including the defaults) is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency).
cellVAlignNoVertical alignment of cell content.
embedFontsNoEmbed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB.
footerTextNoOptional text rendered at the bottom of every page.
outputModeNoEither 'base64' (returns the PDF inline) or 'file' (writes to a sandboxed path inside PDFNATIVE_MCP_OUTPUT_DIR).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf.
typographyNoFine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.
cellBordersNoPer-cell vector borders (pure strokes, PDF/A-safe). Choose individual sides or `all`.
cellPaddingNoHorizontal cell padding in points (default 3).
creationDateNoISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs.
minRowHeightNoMinimum row height in points (default 12).
outputIntentNoCustom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space.
repeatHeaderNoRepeat the header row on every continuation page (default true).
autoFitColumnsNoAuto-fit column widths to content. Output bytes then depend on text metrics (not byte-deterministic across content changes).
footerTemplateNoRunning footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.
headerTemplateNoRunning header on every page (left / center / right zones); reserves 15 pt.
viewerPreferencesNoReader presentation hints (catalog /PageLayout, /PageMode, /ViewerPreferences). PDF/A-safe; all optional.
includeDiagnosticsNoReturn the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty).

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.1/5.0
Behavior5/5

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

Though annotations declare non-readOnly/non-destructive, the description adds substantial behavioral context beyond them: embedFonts adds ~0.3 MiB, creationDate omission causes byte-differences across calls while pinning it gives deterministic output, and autoFitColumns makes output non-byte-deterministic. These are non-obvious traits that meaningfully inform invocation.

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 core purpose and constraint in the opening sentence, followed by the alternative routing and a compact option summary. Given 36 parameters, the length is justified, though the option-name enumeration is somewhat redundant with the schema.

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?

An output schema exists, so return values need no explanation. The description covers purpose, the sibling alternative for longer documents, and PDF/A pairing; with 100% schema coverage the remaining parameter detail is delegated appropriately. Some behavioral nuance could still be richer, but it is complete enough to call correctly.

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 the schema already carries the parameter semantics. The description's smart-table option list (wrap, repeatHeader, zebra, caption, etc.) largely restates what the schema documents, adding only marginal value over the structured fields.

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 first sentence gives a specific verb-resource pairing ('Tabular PDF report from `headers` + `rows`') with a concrete constraint (rows the same length), and later names the sibling alternative (generate_basic_pdf's 'table' block) for longer documents. It is clear, though the core purpose arrives without an explicit action verb and is partly buried under the feature enumeration.

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?

It gives an explicit routing condition: 'Inside a longer document use a "table" block of generate_basic_pdf instead,' which tells the agent when to prefer the sibling. It also notes 'Pair with embedFonts=true for a valid PDF/A claim.' No explicit when-not/exclusion list beyond these, but the context is clear.

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

annotate_pdfAnnotate PDF (markup / drawing)A
Idempotent

Append markup annotations (ISO 32000-1 §12.5) to an existing PDF as a non-destructive incremental update (original bytes preserved). Types: text (sticky note), highlight | underline | strikeout | squiggly, square | circle, line (needs start/end), freetext. Each needs a 0-based page and rect [x1,y1,x2,y2]; optional contents, color, opacity, title and type-specific fields. VISUAL OVERLAY ONLY — nothing is removed or redacted (covered text stays extractable). Encrypted sources → ENCRYPTED_SOURCE (decrypt_pdf first).

ParametersJSON Schema
NameRequiredDescriptionDefault
pdfBase64YesBase64-encoded source PDF to annotate.
outputModeNo'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..').
annotationsYesMarkup / drawing annotations to add. Each is attached to a 0-based page index.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.6/5.0
Behavior5/5

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

Discloses behavior well beyond annotations: non-destructive incremental update preserving original bytes, VISUAL OVERLAY ONLY semantics (covered text remains extractable — critical for anyone who might assume redaction), and the encrypted-source error code with remediation. Annotations declare idempotent=true and destructive=false, consistent with the description.

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?

Dense but front-loaded: purpose, non-destructive guarantee, type list, coordinates, then the critical visual-only caveat and error handling. A bit packed but every clause carries information; no filler.

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

Completeness5/5

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

Given the output schema exists, return values need not be explained. The description covers mutation semantics, coordinates, type-specific fields, error handling for encrypted sources, and the crucial non-redaction caveat — everything an agent needs to invoke correctly.

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 100%, so baseline is 3. Description adds derivative value by summarizing type-specific requirements (line needs start/end, each needs page+rect) and the page-0-based convention, though the schema itself documents these in detail.

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 (append) and resource (markup annotations), enumerates the annotation types supported, and distinguishes the tool from siblings like generate_basic_pdf or inspect_pdf by naming the ISO spec section.

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 handles the encrypted-source case by pointing to decrypt_pdf first via the ENCRYPTED_SOURCE error. The 'non-destructive' framing clarifies that this is for overlay markup, but it doesn't contrast against sibling tools like fill_form or add_table for agent routing.

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

decrypt_pdfDecrypt a PDFA
Idempotent

Emit an UNENCRYPTED copy of an encrypted PDF (RC4 V1–V4, AES-128, AES-256) given password (user or owner; empty user password needs none). CAVEAT: the page tree is rebuilt — signatures and AcroForm are DROPPED. To merely READ an encrypted PDF pass password to inspect_pdf / extract_text / extract_attachments / read_form_fields instead. Never cached.

ParametersJSON Schema
NameRequiredDescriptionDefault
passwordNoPassword to open the encrypted source (user or owner). Omit only for documents with an empty user password.
pdfBase64YesBase64-encoded encrypted PDF to decrypt. NOTE: signatures and AcroForm are dropped (page-tree rebuild).
outputModeNo'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.7/5.0
Behavior5/5

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

Discloses non-obvious behavioral traits beyond the annotations: the page tree is rebuilt and signatures/AcroForm are DROPPED, plus "Never cached". Annotations only give the generic read/write/idempotency profile; the lossy-output caveat and the caching behavior are real added context. No contradiction with destructiveHint=false, since the source PDF is not modified.

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?

Three dense sentences with the core action first, the lossy caveat second, and the alternative-route guidance last. Every clause carries information; nothing is filler.

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

Completeness5/5

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

An output schema exists, so return values need no explanation. With algorithm support, password rules, output caveats and the read-only alternative all covered, an agent has everything needed to call this correctly.

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 100% and the schema already defines password eligibility, outputMode sandboxing and outputPath requirements. The description's "given `password` (user or owner; empty user password needs none)" largely restates the schema, so the baseline 3 applies rather than extra credit.

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 concrete verb+resource ("Emit an UNENCRYPTED copy of an encrypted PDF") and scopes it precisely with the supported cipher list (RC4 V1–V4, AES-128, AES-256). It is immediately distinguishable from encrypt_pdf and from the read-only siblings named later.

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

Usage Guidelines5/5

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

Explicitly routes the agent: "To merely READ an encrypted PDF pass `password` to inspect_pdf / extract_text / extract_attachments / read_form_fields instead." It also states when the password may be omitted (empty user password), so both use and non-use conditions are covered.

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

draft_governance_issueDraft a governance-compliant GitHub issue (HITL)A
Idempotent

Produce a LOCAL GitHub issue draft + compliance report for pdfnative / pdfnative-mcp and NEVER submit it — the agent drafts, a human reviews and files it under their own identity (Human-In-The-Loop contract, .github/AGENT_RULES.md). No GitHub write path exists. The draft is checked against the zero-dependency + reproduction policy; a violation (new runtime dependency, missing reproduction, duplicateSearchPerformed:false) throws GOVERNANCE_VIOLATION. Returns markdown inline (outputMode:'file' also writes a .md). Present the draft AND the report to the user, then STOP.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleYesConcise issue title (imperative, no trailing period).
summaryYesOne or two paragraphs describing the problem or proposal.
issueTypeYesIssue category: 'bug' | 'feature' | 'security' | 'docs' | 'performance'.
outputModeNo'inline' (default) returns the draft markdown in the response. 'file' additionally writes it to the sandbox (requires PDFNATIVE_MCP_OUTPUT_DIR); outputPath must be a relative .md path.inline
outputPathNoRelative .md path inside the sandbox (only when outputMode='file').
targetRepoNoDestination repository label for the draft (documentation only — the server never contacts it). Typically 'pdfnative-mcp' or 'pdfnative'.pdfnative-mcp
reproductionYesThe minimal, locally-executed reproduction that justifies this issue.
actualBehaviorNoWhat actually happened (defaults to the reproduction result when omitted).
affectedPackagesNoPackages impacted by this issue (e.g. ["pdfnative-mcp"], ["pdfnative"]).
expectedBehaviorYesWhat you expected to happen instead.
duplicateSearchPerformedYesMUST be true: confirms you searched open AND closed issues/PRs for duplicates before drafting.

Output Schema

ParametersJSON Schema
NameRequiredDescription
titleYes
filePathNoSandboxed absolute path (when outputMode='file').
warningsYes
issueTypeYes
sizeBytesYes
complianceYes
outputModeYes
targetRepoYes
draftMarkdownYesThe full draft, ready for a human to review and submit.

TDQS

A4.7/5.0
Behavior5/5

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

The description goes beyond the annotation set and provides crucial behavioral context: the draft is never submitted, a human files it, no GitHub write path exists, policy violations raise GOVERNANCE_VIOLATION, and the agent must present output and then STOP. This is exactly the kind of non-obvious behavior an autonomous agent needs.

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?

The description is compact yet information-dense. Critically, it front-loads the key constraints (LOCAL, NEVER submit, HITL) and includes the procedural end state ('present the draft AND the report to the user, then STOP') with no wasted words.

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

Completeness5/5

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

Given the 11 parameters, nested reproduction object, output schema, and annotations, this description still closes all important gaps: the governance policy, violation behavior, output modes, human review step, and stop condition. An agent has enough to invoke the tool and interpret its guidance correctly.

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?

Even though the input schema describes every parameter thoroughly, the description adds meaningful behavioral requirements: duplicateSearchPerformed:false triggers a GOVERNANCE_VIOLATION, and outputMode 'file' writes a .md file. These enrich the interpretation of the parameters beyond their simple schema definitions.

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?

The description clearly states the action ('Produce a LOCAL GitHub issue draft + compliance report'), the resource ('for pdfnative / pdfnative-mcp'), and the critical boundary ('NEVER submit it'). It is fully differentiated from the PDF-manipulation siblings by the explicit issue-drafting scope.

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?

It clearly establishes when to use the tool: when an issue draft is needed under the Human-In-The-Loop contract and must not be submitted. It also tells the agent it does not provide a GitHub write path, implying it should not be used for actual issue submission, though no explicit alternative tool is named.

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

embed_imageEmbed image in PDFA
Idempotent

PDF with one embedded JPEG or PNG (base64; PNG without alpha channel) plus optional caption and render width/height. Inside a longer document use an 'image' block of generate_basic_pdf instead. PDF/A, print, metadata and creationDate options as on every document tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
altNoAccessible description of the image (tagged /Figure /Alt). Provide it for non-decorative images under PDF/A or PDF/UA.
pdfANoPDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md.
pdfxNoPDF/X-4 print exchange (ISO 15930-7). REQUIRES outputIntent with the printer's ICC profile (device class 'prtr'; CMYK or Gray — none is bundled); needs embedFonts:true for a conformant file (PDFX_NO_FONT_ENTRIES otherwise, strict:true refuses). Exclusive with pdfA and encrypt; metadata.trapped must be 'True' or 'False'; TrimBox or ArtBox, not both. Links and form fields are reported (PDFX_ANNOTATIONS). Check with validate_pdf standard:'pdf-x-4'. See the print_ready prompt.
alignNoHorizontal placement of the image inside the content width.left
debugNoDraw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.
printNoPrint production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.
titleYesDocument title rendered at the top and used as PDF metadata title.
widthNoRender width in points. If omitted, the image is auto-sized to fit the page.
heightNoRender height in points. If omitted, aspect ratio is preserved.
strictNoFail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true.
captionNoOptional caption rendered below the image.
encryptNoEncrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.
marginsNoMargins in points, all four required (0–200). Default 45 / 36 / 35 / 36.
compressNoFlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.
metadataNo/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.
mimeTypeYesMIME type of the image. Must match the actual encoding of imageBase64 (magic bytes are checked).
pageSizeNoPortrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.
embedFontsNoEmbed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB.
outputModeNoEither 'base64' (returns the PDF inline) or 'file' (writes to a sandboxed path inside PDFNATIVE_MCP_OUTPUT_DIR).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf.
typographyNoFine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.
imageBase64YesBase64 image bytes. JPEG (baseline; 1, 3 or 4 components — CMYK raises PDFA_DEVICE_CMYK_IMAGE under PDF/A) or PNG (8-bit greyscale/RGB, non-interlaced; alpha-channel and palette PNGs are rejected with a remedy). No data: URI.
creationDateNoISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs.
outputIntentNoCustom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space.
footerTemplateNoRunning footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.
headerTemplateNoRunning header on every page (left / center / right zones); reserves 15 pt.
includeDiagnosticsNoReturn the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty).

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already carry the safety profile (readOnlyHint=false, idempotentHint=true, destructiveHint=false), so the bar is lower. The description adds real substance: PNG without an alpha channel, base64 input, and that PDF/A, print, metadata and creationDate options behave as on every other document tool — a useful cross-tool parity signal. It does not restate the deterministic/byte-identical behavior that creationDate pinning implies.

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 compact sentences, front-loaded with the artifact and its constraints before the routing rule. Every clause earns its place; the only slightly loose element is the trailing cross-reference to 'every document tool', which is terse but a bit hand-wavy about where those options are documented.

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 27-parameter tool with full schema coverage, an output schema and annotations, the description only needs to frame the artifact and route the agent, which it does. The complex regimes it inherits (PDF/A, PDF/X, print production, encryption, typography) are covered by the schema and sibling docs, so nothing essential for a correct call is missing.

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 the schema already documents all 27 properties in depth. The description's mentions of base64, PNG-without-alpha, caption and render width/height merely echo what the schema states, adding no syntax or format detail beyond it. Baseline 3 is correct when the schema does the heavy lifting.

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 ('PDF with one embedded JPEG or PNG') plus the optional caption and render width/height, so the output artifact is unambiguous. It also names the sibling to use instead ('image' block of generate_basic_pdf) for longer documents, letting an agent distinguish embed_image from generate_basic_pdf without opening either 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?

Explicit routing rule with condition: 'Inside a longer document use an "image" block of generate_basic_pdf instead.' This names the alternative and when to prefer it. It offers no other usage context (e.g. when PDF/A or print options matter for this tool), so it stops short of a full when/when-not map.

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

encrypt_pdfEncrypt / re-secure a PDFA

Encrypt an existing PDF with the Standard Security Handler: AES-128 (default) or AES-256; RC4 is never emitted. ownerPassword required; optional userPassword (open password), permissions { print, copy, modify, extractText }. Rotate the password of an already-encrypted source by passing its current password. CAVEAT: the page tree is rebuilt — signatures and AcroForm are DROPPED, only URI links kept; encrypt BEFORE signing. Never cached.

ParametersJSON Schema
NameRequiredDescriptionDefault
passwordNoCurrent password of an already-encrypted source (enables password rotation). Omit for an unencrypted source.
algorithmNoaes128 (V4/R4, widest compatibility) or aes256 (V5/R6).aes128
pdfBase64YesBase64-encoded source PDF to encrypt. NOTE: existing signatures and AcroForm are dropped (page-tree rebuild).
outputModeNo'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf.
permissionsNoPermission flags; each defaults to allowed.
userPasswordNoOpen password; omitted/empty = opens without a prompt.
ownerPasswordYesOwner password (full access).

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.6/5.0
Behavior5/5

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

Goes well beyond annotations by disclosing the destructive side-effects: signatures and AcroForm are DROPPED, only URI links kept, and results are never cached. These are exactly the consequences an agent must know before invoking, and they are not derivable from the readOnly/destructive/idempotent hints.

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?

Dense and front-loaded with the key outcome and CAVEAT clearly flagged. Semicolon-heavy phrasing packs a lot into two sentences; everything earns its place, though the first sentence is slightly run-on.

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

Completeness5/5

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

Covers algorithm choice, password roles, permissions, output modes, rotation, and the signature/AcroForm drop caveat. With an output schema present, return values need not be described, so nothing an agent needs is missing.

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 100%, so baseline is 3, but the description adds meaning beyond the schema by explaining the interplay: ownerPassword is required, userPassword is the open password, permissions map to the four flags (default allowed), and `password` enables rotation of an already-encrypted source.

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 (Encrypt) applied to a specific resource (an existing PDF) with the exact handler and algorithm set (AES-128/AES-256, RC4 never emitted). An agent can distinguish this from decrypt_pdf and sign_pdf without opening 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 situational guidance: rotate a password by passing the current `password`, and 'encrypt BEFORE signing' due to the page-tree rebuild. It does not explicitly name the alternative (decrypt_pdf) or state when not to use it, so it stops short of full when/when-not routing.

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

extract_attachmentsExtract embedded files from PDFA
Read-onlyIdempotent

Read-only extraction of embedded files (PDF/A-3, Factur-X, ZUGFeRD): name, mimeType, AFRelationship, description, sizeBytes and (by default) the payload as dataBase64. filename selects one file; includeData:false probes metadata only. Encrypted sources: pass password. Token-frugal: verbosity:'summary'.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsNoOptional dot-path projection applied to the structured result (e.g. ['attachments.name']). Composes after verbosity. Unknown paths are omitted.
filenameNoOptional exact attachment name to extract. When omitted, every embedded file is returned.
passwordNoPassword (user or owner) of an encrypted source. Never logged or echoed.
pdfBase64YesBase64-encoded PDF bytes to read embedded files from.
verbosityNoResponse verbosity. 'full' (default) returns the attachments[] array; 'summary' returns a token-frugal { attachmentCount } and drops the array.full
includeDataNoWhen true (default) each attachment carries its decoded payload as dataBase64. Set false for a metadata-only probe (names, sizes, relationships) with no payload bytes.

Output Schema

ParametersJSON Schema
NameRequiredDescription
attachmentsNo
attachmentCountNo

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint and idempotentHint, and the description reinforces this with 'Read-only extraction'. It adds valuable behavioral details beyond annotations: default payload inclusion, metadata-only probing, password handling, and token-frugal summary mode. These add meaningful context without contradicting the annotations.

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?

The description is three tightly-worded sentences with no fluff. The core action is front-loaded (read-only extraction), key formats are named in the first sentence, and the remaining sentences efficiently cover optional behaviors and parameter interactions.

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

Completeness5/5

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

Given the tool has a high-quality output schema, rich parameter descriptions, and complete annotations, the description covers the necessary behavioral context: file selection, payload vs metadata probing, encrypted sources, and response verbosity. Nothing appears missing for an agent to correctly invoke this tool.

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?

The schema already provides 100% parameter coverage with detailed descriptions, so the baseline is 3. The description adds concise semantic layer by explaining the practical intent of includeData:false as metadata-only probing and verbosity:'summary' as token-frugal. It also hints at the relationship between filename and single-file selection, complementing the schema.

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?

The description clearly identifies a specific verb-object pair ('Read-only extraction') targeting embedded files in PDFs, including recognizable formats like PDF/A-3 and ZUGFeRD. This distinguishes it from sibling tools such as add_attachment and extract_text without ambiguity.

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 provides clear usage context: extracting embedded files from a PDF, including how to select a single file, probe metadata only, handle encrypted sources, and save tokens. It stops short of explicitly naming alternative tools or stating when not to use this tool, but the context is strong enough for an agent to route correctly.

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

extract_pagesExtract pages into one PDFA
Idempotent

Keep an arbitrary pages[] subset (0-based, in the given order) in ONE fresh PDF. Same page-tree caveats as merge_pdfs (signatures/AcroForm/XMP dropped; boxes kept; URI links unless dropAnnotations). Encrypted sources: password; output unencrypted unless encrypt. Need several documents? Use split_pdf.

ParametersJSON Schema
NameRequiredDescriptionDefault
pagesYes0-based page indices to keep, in output order. Duplicates and out-of-range indices are rejected.
encryptNoRe-encrypt the output (Standard Security Handler; AES-128 default or AES-256; RC4 never emitted).
passwordNoPassword (user or owner) of an encrypted source. Never logged or echoed.
pdfBase64YesBase64-encoded source PDF. Pass `password` for an encrypted source.
outputModeNo'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..').
dropAnnotationsNoWhen true, drop ALL annotations. Default keeps self-contained URI link annotations.
maxOutputSizeBytesNoMaximum size, in bytes, of the produced PDF. Defaults to 268435456 (256 MiB).

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.6/5.0
Behavior5/5

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

Annotations only declare read/write/idempotency hints, but the description adds concrete lossy behavior: signatures, AcroForm, and XMP are dropped; boxes are kept; URI links are preserved unless dropAnnotations. It also discloses that output is unencrypted unless `encrypt` and that encrypted sources need `password`.

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?

Four compact clauses front-load the core behavior and bury constraints in parentheticals with minimal waste. It is dense but each sentence carries real information; slightly terse cross-references keep it from a full 5.

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

Completeness5/5

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

With an output schema present, return values need not be explained, and the description covers the mutation profile, source-encryption handling, output-encryption default, annotation retention, and the sibling alternative. Nothing needed to invoke it correctly is missing.

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 the schema already documents every parameter, and this is the baseline case. The description reiterates `pages`, `password`, `encrypt`, and `dropAnnotations` but adds little syntax or constraint detail beyond what the schema provides.

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?

The description states a specific verb+resource: keep a `pages[]` subset in ONE fresh PDF, with 0-based ordering semantics. It also discriminates from the sibling split_pdf by naming the multi-document case as its opposite, so the agent can distinguish it without opening either schema.

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

Usage Guidelines5/5

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

It explicitly routes the agent: 'Need several documents? Use split_pdf.' It also constrains input handling ('arbitrary pages[] subset') and references merge_pdfs for shared caveats, giving clear when-to-use context.

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

extract_textExtract plain text from PDFA
Read-onlyIdempotent

Plain-text extraction: decodes Tj/TJ operands through each font's /ToUnicode CMap, /Encoding /Differences or base encoding and returns pages[] + fullText (positioned runs with includeRuns:true; pages selects 0-based pages). extractable is false only when a page decoded ENTIRELY to U+FFFD (a font with no usable mapping — expected for some subset fonts, not an error; extractableReason explains). Tagged content carrying /ActualText (every pdfA document this server writes) returns that SOURCE text, in logical order; untagged right-to-left and Indic runs come back in the order their glyphs were drawn — generate with pdfA when faithful extraction of complex scripts matters. Encrypted sources: pass password (PASSWORD_REQUIRED / PASSWORD_INVALID otherwise). Token-frugal: verbosity:'summary', fields:[…].

ParametersJSON Schema
NameRequiredDescriptionDefault
pagesNoOptional 0-based page indices to extract. When omitted, every page is extracted.
fieldsNoOptional dot-path projection applied to the structured result (e.g. ['fullText'] or ['extractable']). Composes after verbosity. Unknown paths are omitted.
passwordNoPassword (user or owner) of an encrypted source. Never logged or echoed.
pdfBase64YesBase64-encoded PDF bytes.
verbosityNoResponse verbosity. 'full' (default) returns the per-page pages[] array and fullText; 'summary' returns a token-frugal { pageCount, extractedPageCount, extractable, charCount } and drops the text payloads.full
includeRunsNoWhen true, each page also carries `runs[]` — positioned text-showing operations `{ text, x, y, fontSize, fontName }` in device space (content-stream order). Useful for layout-aware extraction; larger responses.
maxTextLengthNoHard cap on total extracted characters across all pages (memory bound for adversarial input). Default 16000000. Exceeding it fails with OUTPUT_TOO_LARGE.

Output Schema

ParametersJSON Schema
NameRequiredDescription
pagesNo
fullTextNo
charCountNosummary only: length of fullText.
pageCountNo
extractableNoFalse when one or more requested pages produced text that is entirely U+FFFD replacement characters — a font with no usable /ToUnicode CMap or base encoding. Blank pages are still considered extractable.
extractableReasonNoPresent when extractable is false: why no text could be decoded.
extractedPageCountNo

TDQS

A4.6/5.0
Behavior5/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 goes well beyond them: `extractable` is false only on ENTIRE U+FFFD decoding with extractableReason, ActualText/tagged-content returns SOURCE text in logical order, untagged RTL/Indic returns glyph-draw order, encrypted sources yield PASSWORD_REQUIRED/PASSWORD_INVALID, and maxTextLength overflow fails with OUTPUT_TOO_LARGE. This is unusually rich behavioral disclosure.

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?

The purpose and core extraction semantics are front-loaded and no sentence is pure filler, but the paragraph is dense and heavily backticked, mixing contract-level guarantees (ActualText ordering, error codes) with implementation detail. Slightly over-stuffed for a single description, though nothing is wasted.

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

Completeness5/5

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

An output schema exists, so return shapes need not be re-explained, yet the description still clarifies the semantic meaning of `extractable`/`extractableReason`. With encryption handling, memory-bound behavior, and token-frugal options all covered, an agent has everything needed to call it correctly.

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 description coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema: the PASSWORD_REQUIRED/PASSWORD_INVALID error outcomes for `password`, the extractableReason semantics tied to extraction, and the interplay of verbosity:'summary' with the returned fields. It adds real inter-parameter behavior rather than restating field docs.

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 ('Plain-text extraction' returning pages[] + fullText) and implicitly distinguishes itself from siblings like extract_pages, extract_attachments and inspect_pdf by naming text extraction and its decoding mechanism (ToUnicode CMap, /Differences). An agent can identify what it does without opening 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 conditional guidance: pass `password` for encrypted sources, use includeRuns:true for positioned runs, verbosity:'summary' for token frugality, and prefer generating with pdfA when faithful extraction of complex scripts matters. It does not explicitly contrast with the closest sibling (extract_pages) or state when *not* to use it, so it stops short of full routing.

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

fill_formFill / flatten an existing AcroFormA
Idempotent

Fill and/or flatten the AcroForm of an EXISTING PDF (add_form creates one) as an incremental update — prior signatures stay valid for their revision. values: fully-qualified name → string (array for multi-select), boolean or export state for checkbox/radio. flatten:true stamps appearances and drops the interactive layer (with no values = pure flatten). Unknown names → FORM_FIELD_NOT_FOUND unless onUnknownField:'ignore'; signature fields cannot be filled (FORM_UNSUPPORTED). Encrypted sources: password.

ParametersJSON Schema
NameRequiredDescriptionDefault
valuesNoMap of fully-qualified field name → value. Text/choice: a string (array of strings for multi-select listboxes). Checkbox/radio: a boolean or the export-state string. Omit (or pass {}) with flatten:true for a pure flatten.
flattenNoWhen true, stamp appearances into page content and remove the interactive fields after filling.
passwordNoPassword (user or owner) of an encrypted source. Never logged or echoed.
pdfBase64YesBase64-encoded source PDF containing the AcroForm to fill. Use read_form_fields first to discover field names.
nonWinAnsiNoBehaviour when a value contains non-WinAnsi characters (appearance font is Helvetica/WinAnsi). 'throw' (default) rejects it; 'needAppearances' writes the value and sets /NeedAppearances so the viewer regenerates the appearance.throw
outputModeNo'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf.
onUnknownFieldNoBehaviour for a value key that matches no field. 'throw' (default) → FORM_FIELD_NOT_FOUND; 'ignore' skips it.throw

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.6/5.0
Behavior5/5

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

Goes well past the annotations by disclosing that writes are incremental so prior signatures stay valid for their revision, that flatten.drops the interactive layer, that unknown field names raise FORM_FIELD_NOT_FOUND unless onUnknownField:'ignore', that signature fields cannot be filled (FORM_UNSUPPORTED), and that encrypted sources need a password. These are exactly the behavioral traits an agent needs and none are derivable from readOnlyHint/idempotentHint.

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?

Effectively four dense sentences with no filler; the operation and its alternative are front-loaded and error behavior is packed into terse semicolon clauses. The telegraphic compression (backticked terms, arrow notation) costs a little readability, but nothing is wasted.

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

Completeness5/5

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

For an 8-parameter mutation tool with a nested values object and an output schema, the description covers scope, alternatives, mutation semantics, error codes, security (encryption) and the incremental-update guarantee. Return values need not be explained since an output schema exists.

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 100%, so baseline is 3, but the description adds real meaning: the values map semantics (fully-qualified name → string/array/boolean/export state), the pure-flatten shorthand, and the signature-field exclusion. It omits explaining outputMode/outputPath sandbox behavior, which lives only in the schema.

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 (fill and/or flatten) on a specific resource (the AcroForm of an EXISTING PDF) and explicitly contrasts with the sibling that creates one (add_form). An agent can distinguish this from add_form and read_form_fields 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?

Names add_form as the alternative for creating forms and states the selection condition ('EXISTING PDF'), plus clarifies that flatten with no values is a pure flatten. It does not explicitly route to read_form_fields for discovery in the description itself (though the schema does), so it stops just 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.

generate_basic_pdfGenerate basic PDFA
Idempotent

Multi-page PDF composed from ordered blocks: heading, paragraph, list, table, image (JPEG/PNG), link, toc (printed table of contents), barcode, svg, formField, chart, pageBreak, spacer — every block kind the engine offers, each sharing its body with the dedicated tool (add_table, embed_image, add_barcode, add_form, add_chart). DEFAULT for any document; use the dedicated tools only for a standalone artefact, add_attachment for embedded files and add_international_text for non-Latin scripts. pdfA + embedFonts:true for a valid PDF/A-1b/2b/2u/3b claim; outline / pageLabels / viewerPreferences / watermark for navigation and presentation; print, metadata, outputIntent, creationDate as on every document tool. The 'chart' block takes the same body as add_chart.

ParametersJSON Schema
NameRequiredDescriptionDefault
pdfANoPDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md.
pdfxNoPDF/X-4 print exchange (ISO 15930-7). REQUIRES outputIntent with the printer's ICC profile (device class 'prtr'; CMYK or Gray — none is bundled); needs embedFonts:true for a conformant file (PDFX_NO_FONT_ENTRIES otherwise, strict:true refuses). Exclusive with pdfA and encrypt; metadata.trapped must be 'True' or 'False'; TrimBox or ArtBox, not both. Links and form fields are reported (PDFX_ANNOTATIONS). Check with validate_pdf standard:'pdf-x-4'. See the print_ready prompt.
debugNoDraw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.
printNoPrint production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.
titleYesDocument title (rendered at top of page 1 and used as PDF metadata title).
blocksYesOrdered list of content blocks composing the document body.
strictNoFail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true.
encryptNoEncrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.
marginsNoMargins in points, all four required (0–200). Default 45 / 36 / 35 / 36.
outlineNoDocument outline (bookmarks panel). Either 'auto' (derive a flat outline from heading blocks) or an explicit nested bookmark tree.
compressNoFlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.
metadataNo/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.
pageSizeNoPortrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.
normalizeNoUnicode normalization before shaping ('NFC' recommended for glyph coverage; NFD/NFKC/NFKD accepted). Omit = none.
watermarkNoOptional semi-transparent watermark rendered centred on every page: `text` (e.g. 'DRAFT'), `image` (JPEG/PNG), or both combined. At least one of text / image is required. opacity < 1.0 (text or image, including the defaults) is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency).
embedFontsNoEmbed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB.
footerTextNoOptional footer text rendered at the bottom of every page.
outputModeNoEither 'base64' (returns the PDF inline as a base64 string) or 'file' (writes to a path inside the configured PDFNATIVE_MCP_OUTPUT_DIR sandbox).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf.
pageLabelsNoPage-label ranges (the visible page numbers in the viewer, e.g. roman front-matter then decimal body). startPage values must be unique and strictly increasing.
typographyNoFine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.
creationDateNoISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs.
outputIntentNoCustom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space.
footerTemplateNoRunning footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.
headerTemplateNoRunning header on every page (left / center / right zones); reserves 15 pt.
viewerPreferencesNoReader presentation hints (catalog /PageLayout, /PageMode, /ViewerPreferences). PDF/A-safe; all optional.
includeDiagnosticsNoReturn the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty).

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=true and openWorldHint=false, so the safety profile is largely covered. The description adds compliance-state consequences (what a valid PDF/A claim requires) and structural notes (block bodies mirror the dedicated tools), but says nothing about output mode behaviour (inline base64 vs sandboxed file write), the pdfA/encryption exclusivity, or the random-vs-deterministic output caveat — all material for a 27-parameter generator.

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?

Front-loaded with the block inventory, then the routing rule, then the option map — the three things an agent needs in priority order. Given the scope of the tool, every clause carries information; there is no filler or restated title.

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?

An output schema exists and the input schema is exhaustively documented, so return-value detail is unnecessary. The description covers routing and the major option families, and the block inventory matches the schema's oneOf variants; it stops short only on output delivery (outputMode/outputPath) and the pdfA/encrypt exclusivity, which matter for correct invocation.

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 description coverage is 100%, so the per-parameter text is already complete and the baseline is 3. The description earns above baseline by grouping the 27 parameters into functional clusters (compliance, navigation/presentation, print, metadata, determinism) and asserting cross-parameter pairings, which is orientation an agent does not get from reading 27 independent schema entries.

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?

The first sentence states a specific verb+resource (multi-page PDF) and enumerates exactly what can be composed from ordered blocks, naming every block kind. It explicitly positions itself against siblings: 'DEFAULT for any document; use the dedicated tools only for a standalone artefact', making it unmistakable that this is the general-purpose document builder rather than add_table/add_chart/embed_image.

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

Usage Guidelines5/5

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

Explicit routing guidance: default for any document, dedicated tools only for standalone artefacts, add_attachment for embedded files, add_international_text for non-Latin scripts. It also gives conditional guidance for compliance flags ('pdfA + embedFonts:true for a valid PDF/A-1b/2b/2u/3b claim') and for navigation/presentation options, which is when-to-use at the parameter level.

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

inspect_layoutInspect document layout (dry run)A
Read-onlyIdempotent

Pagination preview WITHOUT generating a PDF: page count and where every block lands (page, x, top, width, height in points). Same blocks as generate_basic_pdf plus every input that moves a block (title, footerText, pdfA, normalize, embedFonts, pageSize, margins, headerTemplate, footerTemplate): pass what you will give generate_basic_pdf and the page count matches — the dry run shares the pagination planner of the builder, toc blocks included. Read-only, deterministic. Token-frugal: verbosity:'summary', fields:['totalPages'].

ParametersJSON Schema
NameRequiredDescriptionDefault
pdfANoTagged (PDF/A) layout mode, as you would pass it to generate_basic_pdf. PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md.
titleYesDocument title — reserves the title band on page 1 exactly as generate_basic_pdf does.
blocksYesOrdered list of content blocks composing the document body.
fieldsNoOptional dot-path projection applied to the structured result (e.g. ['totalPages'] or ['pages.blocks.type']). Composes after verbosity. Unknown paths are omitted.
marginsNoMargins in points, all four required (0–200). Default 45 / 36 / 35 / 36.
pageSizeNoPortrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.
normalizeNoUnicode normalization before shaping ('NFC' recommended for glyph coverage; NFD/NFKC/NFKD accepted). Omit = none.
verbosityNo'full' (default) or 'summary' (scalars only: pageWidth, pageHeight, totalPages, blockCount; pages[] and margins dropped).full
embedFontsNoMeasure with the embedded Noto Sans Latin metrics instead of Helvetica — pass the same value you will give generate_basic_pdf. (Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB.)
footerTextNoFooter text as you would pass it to generate_basic_pdf (reserves the footer band).
typographyNoFine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.
footerTemplateNoRunning footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.
headerTemplateNoRunning header on every page (left / center / right zones); reserves 15 pt.

Output Schema

ParametersJSON Schema
NameRequiredDescription
pagesNoPer-page block placement, in render order. A table that spans pages appears once per slice.
marginsNoPage margins { top, right, bottom, left } in points.
pageWidthNoPage width in points (595.28 = A4).
blockCountNosummary only: number of placed blocks (table slices count once each).
pageHeightNoPage height in points (841.89 = A4).
totalPagesNoNumber of pages the blocks paginate into.

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already cover read-only/idempotent/non-destructive, so the description's 'Read-only, deterministic' is partly redundant. However it adds genuine behavioral value: the dry run shares the builder's pagination planner and includes toc blocks, guaranteeing page-count parity with generate_basic_pdf — non-obvious behavior beyond the annotations.

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 core purpose ('Pagination preview WITHOUT generating a PDF'), followed by output shape, parity guarantee, and a token-efficiency tip. Dense but every clause earns its place, though the em-dash-heavy run-on phrasing slightly hurts readability.

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

Completeness5/5

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

With an output schema present the description needn't explain return values, and the annotations cover the safety profile. Given the 13-param complexity, it still tells the agent what the tool is, when to reach for it, how its inputs mirror generate_basic_pdf, and how to keep calls cheap — nothing an agent needs is missing.

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 100%, so the baseline is 3, but the description adds real meaning: it enumerates which inputs move a block (title, footerText, pdfA, normalize, embedFonts, pageSize, margins, header/footerTemplate) and directs the agent to reuse generate_basic_pdf's arguments, plus a token-frugal recipe (verbosity:'summary', fields:['totalPages']).

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 precise verb+resource (pagination preview / inspect layout) and explicitly frames it as a dry run that does NOT generate a PDF, immediately distinguishing it from generate_basic_pdf. It also names the return shape (page count, block page/x/top/width/height in points), so an agent knows exactly what it produces.

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 usage context: pass the same inputs you would give generate_basic_pdf and the page count will match, because both share the pagination planner. The alternative (generate_basic_pdf) is implied rather than explicitly named as the non-preview path, and there are no explicit when-not-to-use exclusions, so it falls short of a 5.

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

inspect_pdfInspect PDF metadataA
Read-onlyIdempotent

Read-only facts about a PDF: version, pageCount, encryption, pdfA claim (the claim, not its validity — use veraPDF for that), signatureCount, hasSignaturePlaceholder, attachments[], info; presence-gated dss / docTimestampCount / trapped; signatures:true lists every field (subFilter, isDocTimestamp, isPlaceholder, byteRange, vriKey); pages:true adds per-page sizes and boxes. check:[…] turns it into a CI assertion ('pdfa','signed','encrypted','placeholder','attachments','dss','docTimestamp','trapped') → checks (requested keys only) + checksPassed. Encrypted sources: pass password. Token-frugal: verbosity:'summary', fields:[…].

ParametersJSON Schema
NameRequiredDescriptionDefault
checkNoCI assertions → checks (requested keys only) + checksPassed (all hold). 'signed' = a signature field with signed content exists (structural; validity is verify_pdf's job), 'placeholder' = an unsigned placeholder exists, 'dss' = /DSS present, 'docTimestamp' = a /DocTimeStamp exists, 'trapped' = /Info /Trapped set, 'annotations' = at least one page annotation exists, 'pdfx' = the XMP claims PDF/X (the claim, not its validity — validate_pdf standard:'pdf-x-4').
pagesNoWhen true, include per-page metadata in the response.
fieldsNoOptional dot-path projection applied to the structured result (e.g. ['pageCount','signatureCount']). Composes after verbosity. Unknown paths are omitted.
passwordNoPassword (user or owner) of an encrypted source. Never logged or echoed.
pdfBase64YesBase64-encoded PDF bytes to inspect.
verbosityNo'full' (default) or 'summary' (scalars only: version, pageCount, encryption, pdfA, signatureCount, hasSignaturePlaceholder, attachmentCount, + docTimestampCount / trapped / pdfX / checksPassed when present; arrays and dss dropped).full
signaturesNoWhen true, include a signatures[] array describing every signature field (field name, SubFilter, document-timestamp flag, placeholder flag, ByteRange, /Contents length, /VRI key). Off by default to keep responses compact.
annotationsNoWhen true, include an annotations[] array listing every page annotation (/Annots: links, text notes, highlights, shapes, widgets…) with its 0-based page, subtype, rect and, when present, contents (truncated to 200 chars), title, color, quadPoints and link url. Off by default to keep responses compact.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dssNoDocument Security Store summary (ISO 32000-2 §12.8.4.3), present only when the catalog has a /DSS.
infoNoDocument /Info dictionary entries decoded as strings.
pdfANoDetected PDF/A claim (e.g. '1B', '2B', '2U', '3B') from XMP metadata, or null when absent.
pdfXNoPDF/X claim from XMP (pdfxid:GTS_PDFXVersion, e.g. 'PDF/X-4'), present only when the document makes one. A claim, not a verdict: validate_pdf standard:'pdf-x-4' checks it.
checksNoOne boolean per REQUESTED check (keys = the check[] you passed, nothing else).
perPageNo
trappedNo/Info /Trapped flag, present only when the document carries one.
versionNoPDF version (e.g. "1.7").
pageCountNo
encryptionNo
pageLabelsNoLogical page-numbering ranges from the /PageLabels number tree (ISO 32000-1 §12.4.2), or absent when the document has none. Each range gives the 0-based first page, numbering style, optional prefix and start value.
signaturesNoSignature fields (opt-in via the `signatures` input). Document timestamps are listed inline with isDocTimestamp=true.
annotationsNoPage annotations (opt-in via the `annotations` input), in page order then /Annots order. Only the keys the annotation actually carries are emitted.
attachmentsNoEmbedded files exposed via /Names → /EmbeddedFiles (PDF/A-3, Factur-X).
checksPassedNoPresent when check[] was supplied: true when every requested check holds.
encryptionInfoNoPrecise Standard Security Handler details (pdfnative v1.6.0), present only when the document is encrypted and was opened successfully. Objects served by the reader are already decrypted.
signatureCountNo
annotationCountNoTotal number of page annotations (opt-in via the `annotations` input).
attachmentCountNosummary only: number of embedded files.
docTimestampCountNoNumber of /DocTimeStamp signature fields, present only when at least one exists.
hasSignaturePlaceholderNoTrue when at least one signature widget exists with empty /Contents — i.e. an unsigned placeholder awaiting `sign_pdf`.

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds genuinely non-obvious behavior: encrypted sources require a `password`, `check` returns only requested keys plus a `checksPassed` aggregate, and the tool is deliberately token-frugal via verbosity/fields. Nothing about failure modes or limits beyond that, hence not a 5.

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?

Dense but front-loaded: the core output shape comes first, optional flags next, encryption and token notes last. Backtick-heavy jargon makes it terse rather than skim-friendly, but every clause carries information.

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

Completeness5/5

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

For an 8-parameter inspection tool with an output schema, the description covers everything an agent needs: scope, field/claim distinction, CI-mode behavior, password handling and compactness controls. Return values are also briefly mapped even though the output schema carries them.

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% and the description largely restates what the schema already documents (check semantics, signatures/pages flags, verbosity contents). It adds little parameter meaning beyond the schema, though the 'composes after verbosity' projection ordering and token-frugal framing have some value.

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 precise verb+resource ('Read-only facts about a PDF') and enumerates exactly which facts are returned, then explicitly separates what it does NOT judge ('the claim, not its validity — use veraPDF for that'). This lets an agent distinguish it from validate_pdf and verify_pdf 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?

Clear about context: it routes validity questions to veraPDF/verify_pdf and frames the `check` option as a CI assertion workflow. It does not, however, give an explicit when-to-use-this-instead-of-verify_pdf/Sibling routing sentence for the common 'is this signed and valid?' question, which the schema partially covers.

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

merge_pdfsMerge PDFsA
Idempotent

Concatenate 2–50 PDFs (pdfsBase64[]) into one fresh, self-contained document. Page-tree rebuild: signatures and AcroForm are dropped, XMP (and thus a PDF/A claim) does not survive — re-declare PDF/A on the generating tools; page boxes and /UserUnit do survive; URI links kept unless dropAnnotations:true. Encrypted sources open with one password (PASSWORD_REQUIRED / PASSWORD_INVALID); output unencrypted unless encrypt. Guards: 256 MiB assembly (maxOutputSizeBytes), 50 MiB output (OUTPUT_TOO_LARGE).

ParametersJSON Schema
NameRequiredDescriptionDefault
encryptNoRe-encrypt the output (Standard Security Handler; AES-128 default or AES-256; RC4 never emitted).
passwordNoPassword applied to every encrypted source (pdfnative v1.6.0). Sources with an empty user password open without it. The merged output is unencrypted unless `encrypt` is set.
outputModeNo'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..').
pdfsBase64YesBase64-encoded source PDFs to concatenate, in order. 2–50 documents. Signatures and AcroForms are dropped (a page-tree edit invalidates them); encrypted PDFs are rejected.
dropAnnotationsNoWhen true, drop ALL annotations. Default (false) keeps self-contained URI link annotations and drops cross-document/widget annotations.
maxOutputSizeBytesNoIn-memory assembly guard (pdfnative maxOutputSize): the merge throws before materialising an object graph larger than this. Defaults to 268435456 (256 MiB). Note the emitted PDF is separately capped at 50 MiB by the output layer.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.6/5.0
Behavior5/5

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

Far exceeds the annotation bar: it discloses what is destroyed (signatures, AcroForm, XMP/PDF-A claim), what survives (page boxes, /UserUnit, URI links), error codes (PASSWORD_REQUIRED, PASSWORD_INVALID, OUTPUT_TOO_LARGE, SECURITY_VIOLATION) and two distinct size guards. Annotations only say it is not read-only and is idempotent, so the description carries the real behavioral load.

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?

Two sentences, front-loaded with the core operation before the caveats. Dense but every clause (what survives, error codes, guards) earns its place; the inline error-code tokens make it slightly less scannable than an ideal definition.

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

Completeness5/5

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

An output schema exists so return values need no explanation, and the description still covers encryption, annotation handling, sandboxed file output, and size limits — everything an agent needs to invoke this 7-parameter nested-object tool correctly.

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 100%, so the baseline is 3, but the description adds genuine meaning: `password` applies to every encrypted source, output is unencrypted unless `encrypt` is set, and it explains the layering of `maxOutputSizeBytes` (256 MiB assembly) against the separate 50 MiB output cap. Still, per-parameter syntax largely lives in the schema.

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 and resource plus scope: 'Concatenate 2–50 PDFs into one fresh, self-contained document.' That cleanly separates it from siblings like split_pdf, extract_pages, or validate_pdf.

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 operating conditions (encrypted sources need a password, output is unencrypted unless `encrypt`, page-tree rebuild side effects) and even routes PDF/A re-declaration to the generating tools. It stops short of naming a specific alternative sibling or stating explicit when-not-to-use cases.

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

prepare_signature_placeholderPrepare signature placeholderA
Idempotent

New PDF carrying an unsigned /Sig placeholder for a LATER sign_pdf call. OPTIONAL — sign_pdf auto-injects one. Use it to size the placeholder (placeholderBytes for > 4096-bit keys, reserveTimestamp for an RFC 3161 token), to pin the widget page (pageIndex), to choose subFilter 'ETSI.CAdES.detached' (PAdES), or to ship the placeholder separately. signerName/reason/location/contactInfo/signingTime are frozen into /Sig here — sign_pdf cannot rewrite them later. NOTE: the unsigned file is not yet a conformant PDF/A (empty /Contents); it becomes one once signed. PDF/A, print, metadata and creationDate options as on every document tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
pdfANoPDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md. The unsigned placeholder is NOT yet conformant (empty /Contents, ISO 19005-2 §6.4.3); it is once signed with sign_pdf profile:'pades'.
debugNoDraw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.
printNoPrint production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.
titleYesDocument title. Used as the PDF metadata title and rendered at the top of page 1.
blocksNoOptional document body blocks rendered before the signature field.
reasonNoReason for signing (e.g. "Approved", "I agree to the terms").
strictNoFail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true.
marginsNoMargins in points, all four required (0–200). Default 45 / 36 / 35 / 36.
compressNoFlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.
locationNoSigning location (city / country).
metadataNo/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.
pageSizeNoPortrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.
fieldNameNoOptional AcroForm field name for the signature widget (default 'Signature1').
pageIndexNoZero-based page index the (invisible) widget attaches to (default 0).
subFilterNoSignature SubFilter baked into the /Sig dictionary (frozen at placeholder time). Use 'ETSI.CAdES.detached' for PAdES baseline signatures (sign_pdf profile='pades'). Default 'adbe.pkcs7.detached'.
embedFontsNoEmbed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB.
outputModeNoEither 'base64' (returns the PDF inline) or 'file' (writes to a sandboxed path inside PDFNATIVE_MCP_OUTPUT_DIR).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf.
signerNameNoName of the intended signer, embedded in the /Sig dictionary.
typographyNoFine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.
contactInfoNoContact information for the signer.
signingTimeNo/Sig /M — the claimed signing instant (ISO-8601), frozen into the placeholder dictionary. Omitted: the wall clock at placeholder time. Pin it (with creationDate) for byte-identical output across calls.
creationDateNoISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs.
outputIntentNoCustom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space.
footerTemplateNoRunning footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.
headerTemplateNoRunning header on every page (left / center / right zones); reserves 15 pt.
placeholderBytesNoReserved bytes for the future CMS /Contents blob (default 16384; 24576 when reserveTimestamp=true). Increase only for >4096-bit RSA, long chains or large TSA tokens.
reserveTimestampNoReserve room for an RFC 3161 signature timestamp (sign_pdf timestamp=true): adds 8 KiB to the default placeholder size. Ignored when placeholderBytes is set explicitly.
includeDiagnosticsNoReturn the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty).

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only say readOnly=false, idempotent=true, destructive=false, so the description carries real weight: it discloses that signerName/reason/location/contactInfo/signingTime are frozen into /Sig at placeholder time and sign_pdf cannot rewrite them later, and that the unsigned output is not yet conformant PDF/A because /Contents is empty. These are non-obvious behavioral consequences not derivable from the annotations.

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?

The critical framing (what it is, that it is optional, that sign_pdf auto-injects) comes first, and the rest is a tight enumeration of reasons to use it. Sentences are dense and information-packed for a 29-parameter tool, though the parenthetical lists make it slightly harder to scan than an ideal definition.

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

Completeness5/5

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

With an output schema present, the description need not document return values, and with annotations covering the safety profile it mainly needs to convey the placeholder-specific semantics — freezing, nonconformance, and sizing. It does all of that, plus points to shared options, so an agent has everything needed to decide whether and how to call it.

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 description coverage is already 100%, so the baseline is 3, but the description adds genuine selection guidance beyond the schema: which situations justify placeholderBytes (large RSA keys, long chains), what reserveTimestamp is for, how pageIndex pins the widget, and the PAdES role of subFilter. It also forward-references cross-cutting options (PDF/A, print, metadata, creationDate) as shared document-tool conventions. It does not attempt to restate all 29 parameters, which is appropriate.

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 artifact: creates a new PDF carrying an unsigned /Sig placeholder explicitly intended for a LATER sign_pdf call. This clearly separates it from sign_pdf and from generate_basic_pdf, so the agent knows this is a preparatory step, not the signing step.

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

Usage Guidelines5/5

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

Explicitly declares itself OPTIONAL and names the alternative that makes it unnecessary ('sign_pdf auto-injects one'). It then enumerates the concrete reasons to use it anyway: sizing placeholderBytes for >4096-bit keys, reserveTimestamp for an RFC 3161 token, pinning pageIndex, choosing the PAdES subFilter, or shipping the placeholder separately. Both when-to-use and when-not-to-use are covered.

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

read_form_fieldsRead AcroForm fieldsA
Read-onlyIdempotent

Read-only list of an existing PDF's AcroForm fields: fully-qualified name, type (text | checkbox | radio | dropdown | listbox | button | signature | unknown), value, flags (readOnly / required / multiline), options, widget placements. Call it BEFORE fill_form to learn the names. Encrypted sources: password. Token-frugal: verbosity:'summary' → { fieldCount }.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsNoOptional dot-path projection applied to the structured result (e.g. ['fields.name','fields.type']). Composes after verbosity. Unknown paths are omitted.
passwordNoPassword (user or owner) of an encrypted source. Never logged or echoed.
pdfBase64YesBase64-encoded PDF bytes whose AcroForm fields should be enumerated.
verbosityNoResponse verbosity. 'full' (default) returns the fields[] array; 'summary' returns a token-frugal { fieldCount } and drops the array.full

Output Schema

ParametersJSON Schema
NameRequiredDescription
fieldsNo
fieldCountNo

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already mark it as read-only and idempotent, and the description adds useful behavior details: password handling for encrypted PDFs and a token-frugal 'summary' response mode that returns only fieldCount. It does not disclose every edge case, but the core behavioral traits are well covered by the annotations and description together.

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?

The purpose is front-loaded, and every sentence earns a place. The long first sentence packs critical output attributes efficiently, followed by short, actionable notes about fill_form, password, and verbosity. There is no excess filler or repetition.

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

Completeness5/5

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

Given the annotations, the rich parameter schema, and the presence of an output schema, the description covers the remaining necessary context. It tells the agent when to call it, how to handle encrypted files, and how to customise response size, which is complete for a read-only enumeration 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?

All four parameters already have thorough schema descriptions, so the baseline is met regardless. The description briefly mentions password and verbosity behavior, but those details are largely restating what is already in the schema. It adds little beyond what the input schema conveys.

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?

The description clearly states a read-only list of AcroForm fields and enumerates what is returned: name, type, value, flags, options, and widget placements. It also ties the operation to the sibling fill_form tool, so its role in the workflow is unmistakable.

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 explicitly says 'Call it BEFORE fill_form to learn the names,' giving the agent a concrete, actionable use case and emphasizing that this tool is a prerequisite for fill_form. It does not mention when not to use it or provide other alternative tools, so it lacks full exclusionary guidance.

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

sign_pdfSign PDF (RSA / ECDSA, PAdES)A

CMS / PAdES signature in ONE call: a missing /Sig placeholder is auto-injected (prepare_signature_placeholder is optional). Inputs: pdfBase64, algorithm (rsa-sha256/384/512, ecdsa-sha256 P-256), certDerBase64 (+ certChainDerBase64 intermediates) and the DER key (rsaKeyPkcs1DerBase64 for rsa-*, ecPrivateKeyDerBase64 or ecPrivateScalarHex for ECDSA; PEM is rejected with the openssl remedy). profile:'pades' (ETSI EN 319 142-1 baseline) is the right choice when add_ltv / timestamp_pdf follow; timestamp:true = PAdES B-T through the operator TSA (TSA_NOT_CONFIGURED otherwise, no network without it). signerName/reason/location/contactInfo/signingTime are baked into the placeholder THIS call injects (a pre-built placeholder keeps its own). Several unsigned placeholders → pass fieldName (PLACEHOLDER_AMBIGUOUS); allowMultiple:true + a new fieldName adds a further signature. Verify with verify_pdf.

ParametersJSON Schema
NameRequiredDescriptionDefault
reasonNo/Sig /Reason — baked into the placeholder when this call injects it.
profileNo'pkcs7' (default, adbe.pkcs7.detached) or 'pades' (ETSI EN 319 142-1 baseline; ETSI.CAdES.detached when the placeholder is injected here). Use 'pades' before timestamp / add_ltv / timestamp_pdf.pkcs7
locationNo/Sig /Location — baked into the placeholder when this call injects it.
algorithmYesSignature algorithm. 'rsa-sha384' / 'rsa-sha512' (pdfnative 1.7) upgrade the whole CMS digest chain. ECDSA only supports P-256 with SHA-256.
fieldNameNoName of the signature field to sign (required when several unsigned placeholders exist) and of the placeholder injected by this call.
pdfBase64YesBase64-encoded PDF bytes. When the PDF already contains an unsigned /Sig placeholder it is signed in place; otherwise the placeholder is auto-injected (set autoInjectPlaceholder=false to opt out).
timestampNoPAdES B-T: request an RFC 3161 signature timestamp from the operator-configured TSA (PDFNATIVE_MCP_TSA_URL). Fails with TSA_NOT_CONFIGURED when no TSA is configured — the server never contacts the network otherwise.
outputModeNo'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured).base64
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..').
signerNameNo/Sig /Name — baked into the placeholder when this call injects it.
contactInfoNo/Sig /ContactInfo — baked into the placeholder when this call injects it.
signingTimeNoISO-8601 signing instant → /Sig /M (only when THIS call injects the placeholder) and the CMS signing-time (pkcs7 profile). Default: now. Not trusted time — use timestamp:true for that.
allowMultipleNoAdd a NEW signature next to existing (already signed) fields instead of signing the first placeholder. Requires fieldName. Each signature is an incremental revision; earlier signatures stay valid.
certDerBase64YesBase64 of the signer X.509 certificate in DER form. Convert from PEM with: openssl x509 -in cert.pem -outform DER | openssl base64 -A
certChainDerBase64NoOptional intermediate CA certificates (DER base64) embedded in the CMS so verifiers and add_ltv can build the chain without fetching caIssuers.
ecPrivateScalarHexNoHex-encoded P-256 private scalar `d` (exactly 64 lowercase or uppercase hex chars, no 0x prefix). Mutually exclusive with ecPrivateKeyDerBase64; either is accepted for ECDSA.
rsaKeyPkcs1DerBase64NoBase64 of the RSA private key in DER form — PKCS#1 RSAPrivateKey (openssl rsa -in key.pem -outform DER -traditional | openssl base64 -A) or PKCS#8 PrivateKeyInfo (openssl pkey -in key.pem -outform DER | openssl base64 -A). NOT PEM. Required for the rsa-* algorithms.
autoInjectPlaceholderNoWhen true (default) and the input PDF has no /Sig widget, pdfnative.addSignaturePlaceholder is called before signing — enabling single-call signing of any PDF.
ecPrivateKeyDerBase64NoBase64 of an ECDSA P-256 private key in SEC1 (RFC 5915) or PKCS#8 (RFC 5208) DER form. Convert from PEM with: openssl pkey -in key.pem -outform DER | openssl base64 -A Mutually exclusive with ecPrivateScalarHex.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.6/5.0
Behavior4/5

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

Annotations cover the safety profile (readOnlyHint=false, openWorldHint=true, idempotentHint=false), and the description goes well beyond them: auto-injection of the /Sig placeholder, error codes (TSA_NOT_CONFIGURED, PLACEHOLDER_AMBIGUOUS), the no-network guarantee, PEM rejection, and the fact that each allowMultiple signature is an incremental revision keeping earlier signatures valid. It stops short of stating revertibility or output/return shape, so a 4 rather than 5.

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 one-call capability, then organized by input, profile choice, TSA behavior, placeholder metadata, and ambiguity handling. Extremely dense but no sentence is filler; the density slightly taxes readability, keeping it from a 5.

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

Completeness5/5

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

For a 19-parameter cryptographic signing tool with an output schema and rich annotations, the description covers what to call, which profile, when the TSA is needed, how placeholder metadata is applied, and how to handle ambiguity and multiple signatures. Nothing an agent needs to invoke it correctly is missing.

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 100%, so the baseline is 3, but the description supplies cross-parameter semantics the schema cannot: PEM is rejected with the openssl remedy, the placeholder-baking rule for signerName/reason/location/contactInfo/signingTime applies only when THIS call injects the placeholder, fieldName is required on ambiguity, and allowMultiple needs a new fieldName. That is real added meaning.

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+scope: 'CMS / PAdES signature in ONE call', and immediately clarifies the relationship to the sibling prepare_signature_placeholder (optional) and the verify step (verify_pdf). An agent can distinguish this from every other sibling in the list.

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

Usage Guidelines5/5

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

Explicit routing rules: profile:'pades' 'is the right choice when add_ltv / timestamp_pdf follow', timestamp:true for PAdES B-T, allowMultiple:true to add a further signature, and verify with verify_pdf. Names conditions and alternatives rather than leaving them to inference.

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

split_pdfSplit PDF into rangesA
Idempotent

Split one PDF into several documents, one per ranges[] entry ({ start, end? }, 0-based inclusive; end defaults to start). Multi-output result: base64 mode returns one embedded resource per part; file mode writes indexed siblings ('out.pdf' → 'out-1.pdf', 'out-2.pdf', …). Same page-tree caveats as merge_pdfs (signatures/AcroForm/XMP dropped; boxes kept). Encrypted sources: password. Need ONE document from a page subset? Use extract_pages.

ParametersJSON Schema
NameRequiredDescriptionDefault
rangesYesPage ranges to extract, one output PDF per range. 0-based, inclusive; `end` defaults to `start` (a single page).
encryptNoRe-encrypt the output (Standard Security Handler; AES-128 default or AES-256; RC4 never emitted). Applied to every produced range.
passwordNoPassword (user or owner) of an encrypted source. Never logged or echoed.
pdfBase64YesBase64-encoded source PDF. Pass `password` for an encrypted source.
outputModeNo'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured).base64
outputPathNoBase output path (file mode). Each PDF is written to an indexed sibling: 'out.pdf' → 'out-1.pdf', 'out-2.pdf', …
dropAnnotationsNoWhen true, drop ALL annotations. Default keeps self-contained URI link annotations.
maxOutputSizeBytesNoMaximum size, in bytes, of each produced PDF. Defaults to 268435456 (256 MiB).

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
countYes
partsYes
totalBytesYes

TDQS

A4.7/5.0
Behavior5/5

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

The description discloses multi-output behavior, output naming conventions in file mode, what happens in base64 mode, and important PDF caveats (signatures/AcroForm/XMP dropped; boxes kept). It also notes encrypted sources using password. These go beyond the annotations, which only describe readOnly/idemptency/destructive hints, and would meaningfully affect ai-agent expectations for the result.

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?

The description is compact and information-dense: four sentences that front-load the core operation, then deliver range semantics, output behavior, page-tree caveats, encrypted-source handling, and the sibling alternative. Every sentence earns its place and no extraneous content is present.

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

Completeness5/5

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

For a tool with 8 parameters, nested objects, and an output schema, the description covers the defining split behavior, the two output modes with concrete file naming, the main transformation caveats, and the canonical alternative. Given the rich schema and output schema, nothing essential is missing for selecting or invoking it correctly.

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 the input schema already documents every parameter including the zero-based inclusive nature of ranges, outputPath semantics, password behavior, and outputMode defaults. The description reinforces the central `ranges[]` semantics and output naming but does not add meaningful meaning beyond what the schema already provides.

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?

The description clearly states a specific verb and resource: 'Split one PDF into several documents, one per ranges[] entry'. It also distinguishes itself from extract_pages by explicitly naming the alternative for extracting a single document, so an agent can tell the tools apart at the description level.

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

Usage Guidelines5/5

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

Includes explicit routing guidance: 'Need ONE document from a page subset? Use extract_pages.' It also references merge_pdfs for shared page-tree caveats, helping the agent understand this tool is best when multiple ranges are wanted, and points to password handling for encrypted sources. Clear enough to select this tool over the alternatives.

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

timestamp_pdfAdd a document timestamp (PAdES B-LTA)A

PAdES B-LTA: append an RFC 3161 document timestamp (/DocTimeStamp, ETSI.RFC3161) over the whole document. Ladder step 4 after add_ltv; re-run before the TSA certificate expires. fieldName omitted → DocTimeStamp1, 2, …; a fieldName colliding with a signed field fails. Uses the OPERATOR TSA (PDFNATIVE_MCP_TSA_URL; TSA_NOT_CONFIGURED otherwise, no network without it). The token's status, imprint and nonce are checked before embedding (its own signature is verified by verify_pdf). Unencrypted PDFs only.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldNameNoSignature field name for the timestamp. Omit it to get 'DocTimeStamp1', 'DocTimeStamp2', … auto-suffixed on each re-timestamp; an explicit name that collides with an existing signed field fails.
pdfBase64YesBase64-encoded PDF (unencrypted). Typically already signed (+ add_ltv) — a document timestamp on an unsigned PDF is allowed but proves only existence at that time.
outputModeNo'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured).base64
outputPathNoRelative path inside PDFNATIVE_MCP_OUTPUT_DIR (required when outputMode='file').
placeholderBytesNoRoom reserved for the TimeStampToken (default 12288). Raise it for TSAs that return large certificate chains.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.4/5.0
Behavior5/5

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

Goes well beyond the annotations: discloses the OPERATOR TSA requirement, the TSA_NOT_CONFIGURED failure mode and absence of network without it, pre-embedding checks on status/imprint/nonce, fieldName collision failure, and re-run-before-expiry semantics that explain the non-idempotent annotation.

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?

Dense and front-loaded — the PAdES level and operation lead, with error modes and constraints following. Every sentence carries distinct information, though the single long block could be broken up for faster scanning.

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

Completeness5/5

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

An output schema exists so return values need no explanation; the description instead covers the prerequisites (operator TSA, unencrypted PDF), failure modes (TSA_NOT_CONFIGURED, field collision, SECURITY_VIOLATION), and ladder placement — everything an agent needs to call it correctly.

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 the schema already documents every parameter including fieldName auto-suffixing, outputMode sandbox errors, and placeholderBytes sizing. The description largely restates the fieldName rules rather than adding syntax or constraints beyond the schema, making the baseline 3 appropriate.

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 ('append an RFC 3161 document timestamp over the whole document') and locates itself precisely in the ladder ('step 4 after add_ltv'), distinguishing it from siblings add_ltv and verify_pdf 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?

Explicit sequencing guidance ('Ladder step 4 after add_ltv; re-run before the TSA certificate expires') and a hard exclusion ('Unencrypted PDFs only'). It stops short of naming when an agent should prefer verify_pdf or add_ltv instead, so it is clear context without full when-not routing.

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

update_metadataUpdate document metadataA

Rewrite /Info (title, author, subject, keywords) of an EXISTING PDF as an incremental update; XMP stays in sync on PDF/A documents; /ModDate is refreshed (pin modDate for reproducible bytes). Earlier revisions and signatures stay byte-identical — the new revision is unsigned (sign_pdf / timestamp_pdf again if needed). Encrypted sources → ENCRYPTED_SOURCE. For metadata at generation time use the metadata option of the document tools.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleNoNew /Info /Title (mirrored to XMP dc:title when the document carries XMP).
authorNoNew /Info /Author (XMP dc:creator).
modDateNoISO-8601 modification instant for /ModDate and xmp:ModifyDate. Defaults to now; pin it for reproducible output.
subjectNoNew /Info /Subject (XMP dc:description).
keywordsNoNew /Info /Keywords (XMP pdf:Keywords).
pdfBase64YesBase64-encoded PDF to update (unencrypted).
outputModeNo'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured).base64
outputPathNoRelative path inside PDFNATIVE_MCP_OUTPUT_DIR (required when outputMode='file').

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoEngine diagnostics (when includeDiagnostics=true).

TDQS

A4.9/5.0
Behavior5/5

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

Goes well beyond the annotations: it discloses incremental-update semantics, that earlier revisions and signatures stay byte-identical, that the new revision is unsigned, the ENCRYPTED_SOURCE failure for encrypted sources, XMP sync on PDF/A, and ModDate refresh/pinning for reproducibility. These are exactly the behavioral traits an agent needs that annotations (readOnly/idempotent/destructive hints) cannot convey.

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 dense sentences, front-loaded with the core action and followed by the behavioral caveats and the alternative. No filler or restated boilerplate; every sentence carries distinct information.

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

Completeness5/5

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

With an output schema and full annotation coverage already present, the description fills the remaining gaps: mutation semantics, signature invalidation, error codes, and alternative routing. Nothing an agent needs to invoke this correctly is missing.

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 100%, so the field-level semantics are already documented. The description still adds framing value by tying the fields to the /Info vs XMP dual-write behavior and to the ModDate pin for reproducible bytes, though it largely mirrors what the schema descriptions already say.

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 ('Rewrite /Info (title, author, subject, keywords) of an EXISTING PDF') scoped precisely to an incremental update of an existing file. It distinguishes itself from the generation-time siblings by naming the `metadata` option of the document tools, so an agent can route without opening a schema.

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

Usage Guidelines5/5

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

Explicitly names the alternative path ('For metadata at generation time use the `metadata` option of the document tools') and the condition that selects it. It also gives follow-up routing ('sign_pdf / timestamp_pdf again if needed'), so both when-to-use and what-to-do-next are covered.

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

validate_pdfValidate PDF structure (PDF/UA, PDF/X-4)A
Read-onlyIdempotent

Read-only structural gate; standard picks the rule set. 'pdf-ua-1' (default, ISO 14289-1) for Tagged PDF: /MarkInfo /Marked, /StructTreeRoot (+ /ParentTree), XMP /Metadata, /Lang, per-page MCID uniqueness — generate tagged input with pdfA (e.g. 'pdfa2u') first. 'pdf-x-4' (ISO 15930-7) for print exchange: /GTS_PDFX OutputIntent with a prtr ICC profile, TrimBox or ArtBox, every font embedded, no annotation / JavaScript / embedded file / transfer function — generate it with pdfx:'pdfx4'. Result { standard, valid, errors[], warnings[], summary } (+ caveats[] for PDF/X). Fast and structural only — NOT a reference validator or a certified preflight: fonts, colour and rendering are not checked (veraPDF for PDF/A and PDF/UA; callas pdfToolbox or Acrobat Preflight for PDF/X). Unparsable input → PDF_PARSE_FAILED.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsNoOptional dot-path projection applied to the structured result (e.g. ['valid']). Composes after verbosity. Unknown paths are omitted.
standardNoRule set. 'pdf-ua-1' (default): PDF/UA accessibility structure (ISO 14289-1). 'pdf-x-4': PDF/X-4 print exchange (ISO 15930-7) — OutputIntent + prtr ICC profile, TrimBox, embedded fonts, no annotations / JavaScript / embedded files; structural prerequisites only, not a certified preflight (see caveats[]).pdf-ua-1
pdfBase64YesBase64-encoded PDF bytes to validate for structural conformance.
verbosityNoResponse verbosity. 'full' (default) returns errors[] and warnings[]; 'summary' returns a token-frugal verdict { standard, valid, errorCount, warningCount, summary } and drops the message arrays.full

Output Schema

ParametersJSON Schema
NameRequiredDescription
validNoTrue when no blocking structural violations were found.
errorsNoBlocking conformance violations. Empty when valid is true.
caveatsNostandard 'pdf-x-4' only: what a valid verdict does NOT establish.
summaryNoHuman-readable one-line summary of the result.
standardNoConformance standard checked (ISO 14289-1 or ISO 15930-7).
warningsNoNon-blocking best-practice recommendations.
errorCountNosummary only: number of errors.
warningCountNosummary only: number of warnings.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already cover read-only/idempotent/non-destructive, but the description adds substantial behavior beyond them: what is deliberately not checked (fonts, colour, rendering), the caveats[] return for PDF/X, and the concrete failure mode 'PDF_PARSE_FAILED' for unparsable input.

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?

Dense but front-loaded: the core role and the standard switch come first, followed by per-standard detail, result shape, and limitations. Every clause carries information, though the single block is heavy enough that some trimming or line breaks would improve scanability.

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

Completeness5/5

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

Given an output schema exists, the description need not explain returns, yet it still summarizes the result shape and caveats[]. Combined with coverage of both standards, generation prerequisites, limitations, and the parse-failure code, an agent has everything needed to call it correctly.

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 100%, so baseline is 3, but the description still adds value by spelling out the ISO numbers and the exact rule contents behind each 'standard' enum value, plus the default. It does not add much beyond the schema for 'fields' or 'verbosity', keeping it at a 4.

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 ('structural gate') and enumerates exactly what each standard validates (PDF/UA tags, PDF/X-4 OutputIntent/fonts/annotations). It is clearly distinguishable from siblings like inspect_pdf or verify_pdf, which are not described in these structural-conformance terms.

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

Usage Guidelines5/5

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

States when to pick each standard, that input should be generated first with the pdfA/pdfx tools (e.g. 'pdfa2u', 'pdfx4'), and explicitly routes agents needing deeper validation to veraPDF/callas/Acrobat. It also bounds scope with 'NOT a reference validator or a certified preflight'.

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

verify_pdfVerify PDF signaturesA
Read-onlyIdempotent

Read-only verification of every signature: ByteRange digest vs CMS messageDigest (integrity), CMS signatureValue vs the embedded signer certificate (RSA-SHA256/384/512, ECDSA P-256), chain trust when trustedRootsDerBase64 is given ('self-signed' | 'unverified' | 'trusted' otherwise). /DocTimeStamp entries are verified as RFC 3161 tokens and count in allValid like any signature. Result: { allValid, signatureCount, summary, signatures:[{ valid, integrity, signerSubject, signingTime, chainTrust, errors[] }] }. ltv:true adds the PAdES view: per-signature profile, timestamp, revocation (read from embedded /DSS only — responder signatures are not re-verified) and ltvLevel B-B / B-T / B-LT / B-LTA with explicit caveats. Token-frugal: verbosity:'summary', fields:['allValid'].

ParametersJSON Schema
NameRequiredDescriptionDefault
ltvNoAdd the PAdES view: per signature profile, timestamp, revocation (embedded /DSS only), ltvLevel (B-B / B-T / B-LT / B-LTA); document-level dss, ltvLevel, caveats.
fieldsNoOptional dot-path projection applied to the structured result (e.g. ['allValid'] or ['signatures.valid']). Composes after verbosity. Unknown paths are omitted.
passwordNoPassword (user or owner) of an encrypted source. Never logged or echoed.
pdfBase64YesBase64-encoded PDF bytes to verify.
verbosityNoResponse verbosity. 'full' (default) returns the per-signature signatures[] array; 'summary' returns a token-frugal verdict { signatureCount, allValid, invalid, summary } (+ ltvLevel when ltv:true) and drops signatures[], dss and caveats.full
trustedRootsDerBase64NoOptional list of base64-encoded X.509 root certificates (DER). When supplied, each signer certificate is validated against these roots; otherwise chainTrust is reported as self-signed or unverified.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dssNoltv only. Document Security Store summary, or null when the catalog has no /DSS.
caveatsNoltv only. Fixed statements about what the LTV evaluation does not cover.
invalidNosummary only: number of invalid signatures.
summaryNo
allValidNotrue when the document carries at least one signature and every entry of signatures[] — CMS signatures and /DocTimeStamp tokens alike — is valid (integrity + signature check + chain trust when trustedRootsDerBase64 is given). A tampered document timestamp fails the verdict; a sound one never does.
ltvLevelNoltv only. Minimum level across non-timestamp signatures ('B-B' when there are none).
signaturesNo
signatureCountNo

TDQS

A4.5/5.0
Behavior5/5

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

The description goes beyond the readOnlyHint and idempotentHint annotations by explaining exactly what is verified, how chainTrust is determined, how /DocTimeStamp is treated, and what ltv:true does. It also includes important caveats such as embedded /DSS-only revocation data and the fact that responder signatures are not re-verified. This gives the agent a strong model of the tool's behavior before invoking it.

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?

The description is dense but well structured, front-loading the core verification purpose and then layering optional modes. Every sentence adds meaningful information, and the structured result shape and token-frugal guidance are presented in compact, scannable form.

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

Completeness5/5

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

Given the tool's complexity, the input schema, annotations, and output schema, the description covers the essential semantic, behavioral, and output-critical details. It explains verification scope, trust behavior, timestamp handling, LTV caveats, and result shapes well enough for an agent to decide whether to call it and what to expect.

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?

The schema already documents all six parameters with high coverage, so the baseline is solid. The description adds genuine semantic value by explaining the effect of trustedRootsDerBase64, the LTV behavior tied to ltv:true, and the token-frugal interaction between verbosity and fields.

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?

The description states a precise operation: read-only verification of every PDF signature, including integrity, signature value, chain trust, timestamps, and PAdES LTV behavior. It clearly distinguishes the tool's scope from generic PDF validation by enumerating specific verification mechanics and output fields.

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

Usage Guidelines3/5

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

The description makes the tool's purpose and behavior easy to infer: it is for signature-specific verification, with optional LTV analysis. However, it does not explicitly tell the agent when to choose verify_pdf over sibling tools like validate_pdf or inspect_pdf, nor does it state any exclusions. Usage context is implied rather than directly described.

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. 22 tool updatesv1.6.2
    • Changedadd_attachment23 fields changed
      • changedInput schema / properties / creationDate / description
        Previous value: -"ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs."New value: +"ISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs."
      • changedInput schema / properties / embedFonts / description
        Previous value: -"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB."New value: +"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB."
      • changedInput schema / properties / footerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / footerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / footerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / footerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / footerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / footerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / footerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / headerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / headerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / headerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / headerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / headerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / includeDiagnostics / description
        Previous value: -"Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty)."New value: +"Return the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty)."
      • changedInput schema / properties / outputIntent / description
        Previous value: -"Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected)."New value: +"Custom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space."
      • changedInput schema / properties / outputIntent / properties / iccProfileBase64 / description
        Previous value: -"ICC profile bytes, base64 (RGB, ≤ 8 MiB)."New value: +"ICC profile bytes, base64 (RGB, CMYK or Gray; ≤ 8 MiB)."
      • changedInput schema / properties / print / properties / marks / oneOf
        Previous value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "crop": {
        -        "description": "Corner crop (trim) marks. Default true.",
        -        "type": "boolean"
        -      },
        -      "length": {
        -        "description": "Mark length in points. Default 14.",
        -        "maximum": 100,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "offset": {
        -        "description": "Gap between TrimBox and marks in points. Default 5.",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "registration": {
        -        "description": "Edge-midpoint registration targets. Default true.",
        -        "type": "boolean"
        -      },
        -      "weight": {
        -        "description": "Stroke width in points. Default 0.25.",
        -        "maximum": 5,
        -        "minimum": 0.05,
        -        "type": "number"
        -      }
        -    },
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "colourBars": {
        +        "anyOf": [
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "additionalProperties": false,
        +            "properties": {
        +              "size": {
        +                "description": "Patch size in points. Default 12.",
        +                "maximum": 72,
        +                "minimum": 4,
        +                "type": "number"
        +              },
        +              "tints": {
        +                "description": "Add the four 50 % tint patches. Default true.",
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          }
        +        ],
        +        "description": "Colour control strip in the bleed (C M Y K solids + their 50 % tints): true for defaults. Off by default; needs a bleed of about 5 mm (14.17 pt) and is skipped when the strip would not fit."
        +      },
        +      "crop": {
        +        "description": "Corner crop (trim) marks. Default true.",
        +        "type": "boolean"
        +      },
        +      "length": {
        +        "description": "Mark length in points. Default 14.",
        +        "maximum": 100,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "offset": {
        +        "description": "Gap between TrimBox and marks in points. Default 5.",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "registration": {
        +        "description": "Edge-midpoint registration targets. Default true.",
        +        "type": "boolean"
        +      },
        +      "weight": {
        +        "description": "Stroke width in points. Default 0.25.",
        +        "maximum": 5,
        +        "minimum": 0.05,
        +        "type": "number"
        +      }
        +    },
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / strict / description
        Previous value: -"Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true."New value: +"Fail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true."
      • addedInput schema / properties / typography
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Fine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.",
        +  "properties": {
        +    "bindShortWords": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "maxLength": {
        +              "maximum": 3,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "words": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never end a line on a short word: up to maxLength letters (default 1), or exactly the listed words."
        +    },
        +    "fontFeatures": {
        +      "description": "OpenType features, later wins. tnum / lnum are no-ops on Noto Sans (TYPOGRAPHY_FEATURE_INEFFECTIVE).",
        +      "items": {
        +        "enum": [
        +          "tnum",
        +          "pnum",
        +          "lnum",
        +          "onum",
        +          "zero",
        +          "ordn",
        +          "sups",
        +          "subs",
        +          "smcp",
        +          "c2sc",
        +          "case"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 11,
        +      "type": "array",
        +      "uniqueItems": true
        +    },
        +    "hyphenationLanguage": {
        +      "description": "BCP 47 tag; no effect here (no hyphenation provider installed).",
        +      "maxLength": 35,
        +      "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
        +      "type": "string"
        +    },
        +    "keepHeadingsWithNext": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "minLines": {
        +              "maximum": 10,
        +              "minimum": 1,
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never strand a heading at a page foot. true = { minLines: 2 }."
        +    },
        +    "kerning": {
        +      "description": "Pair kerning (GPOS).",
        +      "type": "boolean"
        +    },
        +    "metrics": {
        +      "description": "Base-14 text: 'exact' uses the AFM widths (different wraps). Default 'approximate'.",
        +      "enum": [
        +        "approximate",
        +        "exact"
        +      ],
        +      "type": "string"
        +    },
        +    "opticalMargins": {
        +      "description": "Hang punctuation into the margin of align:'justify' text.",
        +      "type": "boolean"
        +    },
        +    "orphans": {
        +      "description": "Min lines left at a page foot (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "punctuationSpacing": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "fr",
        +            "fr-CA"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "char": {
        +                "maxLength": 2,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "side": {
        +                "enum": [
        +                  "before",
        +                  "after"
        +                ],
        +                "type": "string"
        +              },
        +              "space": {
        +                "description": "U+00A0 / U+202F (narrow needs embedFonts).",
        +                "enum": [
        +                  "nbsp",
        +                  "narrow"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "char",
        +              "side",
        +              "space"
        +            ],
        +            "type": "object"
        +          },
        +          "maxItems": 32,
        +          "type": "array"
        +        }
        +      ],
        +      "description": "No-break spaces next to punctuation (existing spaces only). 'fr': narrow before ; ! ?, no-break before ':' and inside « ». 'fr-CA': ':' and « » only. Or explicit rules."
        +    },
        +    "splitParagraphs": {
        +      "description": "Paragraphs may break across pages at a line boundary (default: atomic).",
        +      "type": "boolean"
        +    },
        +    "unitBinding": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "units": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "No-break space between a number and its unit ('150 €', '12 kg'); units replaces the built-in list."
        +    },
        +    "widows": {
        +      "description": "Min lines carried over (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedadd_barcode24 fields changed
      • changedInput schema / properties / creationDate / description
        Previous value: -"ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs."New value: +"ISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs."
      • changedInput schema / properties / embedFonts / description
        Previous value: -"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB."New value: +"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB."
      • changedInput schema / properties / footerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / footerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / footerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / footerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / footerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / footerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / footerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / headerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / headerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / headerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / headerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / headerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / includeDiagnostics / description
        Previous value: -"Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty)."New value: +"Return the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty)."
      • changedInput schema / properties / outputIntent / description
        Previous value: -"Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected)."New value: +"Custom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space."
      • changedInput schema / properties / outputIntent / properties / iccProfileBase64 / description
        Previous value: -"ICC profile bytes, base64 (RGB, ≤ 8 MiB)."New value: +"ICC profile bytes, base64 (RGB, CMYK or Gray; ≤ 8 MiB)."
      • addedInput schema / properties / pdfx
        Added value: +{
        +  "description": "PDF/X-4 print exchange (ISO 15930-7). REQUIRES outputIntent with the printer's ICC profile (device class 'prtr'; CMYK or Gray — none is bundled); needs embedFonts:true for a conformant file (PDFX_NO_FONT_ENTRIES otherwise, strict:true refuses). Exclusive with pdfA and encrypt; metadata.trapped must be 'True' or 'False'; TrimBox or ArtBox, not both. Links and form fields are reported (PDFX_ANNOTATIONS). Check with validate_pdf standard:'pdf-x-4'. See the print_ready prompt.",
        +  "enum": [
        +    "pdfx4"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / print / properties / marks / oneOf
        Previous value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "crop": {
        -        "description": "Corner crop (trim) marks. Default true.",
        -        "type": "boolean"
        -      },
        -      "length": {
        -        "description": "Mark length in points. Default 14.",
        -        "maximum": 100,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "offset": {
        -        "description": "Gap between TrimBox and marks in points. Default 5.",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "registration": {
        -        "description": "Edge-midpoint registration targets. Default true.",
        -        "type": "boolean"
        -      },
        -      "weight": {
        -        "description": "Stroke width in points. Default 0.25.",
        -        "maximum": 5,
        -        "minimum": 0.05,
        -        "type": "number"
        -      }
        -    },
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "colourBars": {
        +        "anyOf": [
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "additionalProperties": false,
        +            "properties": {
        +              "size": {
        +                "description": "Patch size in points. Default 12.",
        +                "maximum": 72,
        +                "minimum": 4,
        +                "type": "number"
        +              },
        +              "tints": {
        +                "description": "Add the four 50 % tint patches. Default true.",
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          }
        +        ],
        +        "description": "Colour control strip in the bleed (C M Y K solids + their 50 % tints): true for defaults. Off by default; needs a bleed of about 5 mm (14.17 pt) and is skipped when the strip would not fit."
        +      },
        +      "crop": {
        +        "description": "Corner crop (trim) marks. Default true.",
        +        "type": "boolean"
        +      },
        +      "length": {
        +        "description": "Mark length in points. Default 14.",
        +        "maximum": 100,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "offset": {
        +        "description": "Gap between TrimBox and marks in points. Default 5.",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "registration": {
        +        "description": "Edge-midpoint registration targets. Default true.",
        +        "type": "boolean"
        +      },
        +      "weight": {
        +        "description": "Stroke width in points. Default 0.25.",
        +        "maximum": 5,
        +        "minimum": 0.05,
        +        "type": "number"
        +      }
        +    },
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / strict / description
        Previous value: -"Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true."New value: +"Fail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true."
      • addedInput schema / properties / typography
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Fine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.",
        +  "properties": {
        +    "bindShortWords": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "maxLength": {
        +              "maximum": 3,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "words": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never end a line on a short word: up to maxLength letters (default 1), or exactly the listed words."
        +    },
        +    "fontFeatures": {
        +      "description": "OpenType features, later wins. tnum / lnum are no-ops on Noto Sans (TYPOGRAPHY_FEATURE_INEFFECTIVE).",
        +      "items": {
        +        "enum": [
        +          "tnum",
        +          "pnum",
        +          "lnum",
        +          "onum",
        +          "zero",
        +          "ordn",
        +          "sups",
        +          "subs",
        +          "smcp",
        +          "c2sc",
        +          "case"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 11,
        +      "type": "array",
        +      "uniqueItems": true
        +    },
        +    "hyphenationLanguage": {
        +      "description": "BCP 47 tag; no effect here (no hyphenation provider installed).",
        +      "maxLength": 35,
        +      "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
        +      "type": "string"
        +    },
        +    "keepHeadingsWithNext": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "minLines": {
        +              "maximum": 10,
        +              "minimum": 1,
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never strand a heading at a page foot. true = { minLines: 2 }."
        +    },
        +    "kerning": {
        +      "description": "Pair kerning (GPOS).",
        +      "type": "boolean"
        +    },
        +    "metrics": {
        +      "description": "Base-14 text: 'exact' uses the AFM widths (different wraps). Default 'approximate'.",
        +      "enum": [
        +        "approximate",
        +        "exact"
        +      ],
        +      "type": "string"
        +    },
        +    "opticalMargins": {
        +      "description": "Hang punctuation into the margin of align:'justify' text.",
        +      "type": "boolean"
        +    },
        +    "orphans": {
        +      "description": "Min lines left at a page foot (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "punctuationSpacing": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "fr",
        +            "fr-CA"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "char": {
        +                "maxLength": 2,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "side": {
        +                "enum": [
        +                  "before",
        +                  "after"
        +                ],
        +                "type": "string"
        +              },
        +              "space": {
        +                "description": "U+00A0 / U+202F (narrow needs embedFonts).",
        +                "enum": [
        +                  "nbsp",
        +                  "narrow"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "char",
        +              "side",
        +              "space"
        +            ],
        +            "type": "object"
        +          },
        +          "maxItems": 32,
        +          "type": "array"
        +        }
        +      ],
        +      "description": "No-break spaces next to punctuation (existing spaces only). 'fr': narrow before ; ! ?, no-break before ':' and inside « ». 'fr-CA': ':' and « » only. Or explicit rules."
        +    },
        +    "splitParagraphs": {
        +      "description": "Paragraphs may break across pages at a line boundary (default: atomic).",
        +      "type": "boolean"
        +    },
        +    "unitBinding": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "units": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "No-break space between a number and its unit ('150 €', '12 kg'); units replaces the built-in list."
        +    },
        +    "widows": {
        +      "description": "Min lines carried over (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedadd_chart30 fields changed
      • addedInput schema / properties / colors / items / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#?[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • removedInput schema / properties / colors / items / pattern
        Removed value: -"^#?[0-9a-fA-F]{6}$"
      • removedInput schema / properties / colors / items / type
        Removed value: -"string"
      • changedInput schema / properties / creationDate / description
        Previous value: -"ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs."New value: +"ISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs."
      • changedInput schema / properties / embedFonts / description
        Previous value: -"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB."New value: +"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB."
      • changedInput schema / properties / footerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / footerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / footerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / footerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / footerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / footerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / footerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / headerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / headerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / headerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / headerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / headerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / includeDiagnostics / description
        Previous value: -"Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty)."New value: +"Return the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty)."
      • changedInput schema / properties / outputIntent / description
        Previous value: -"Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected)."New value: +"Custom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space."
      • changedInput schema / properties / outputIntent / properties / iccProfileBase64 / description
        Previous value: -"ICC profile bytes, base64 (RGB, ≤ 8 MiB)."New value: +"ICC profile bytes, base64 (RGB, CMYK or Gray; ≤ 8 MiB)."
      • addedInput schema / properties / pdfx
        Added value: +{
        +  "description": "PDF/X-4 print exchange (ISO 15930-7). REQUIRES outputIntent with the printer's ICC profile (device class 'prtr'; CMYK or Gray — none is bundled); needs embedFonts:true for a conformant file (PDFX_NO_FONT_ENTRIES otherwise, strict:true refuses). Exclusive with pdfA and encrypt; metadata.trapped must be 'True' or 'False'; TrimBox or ArtBox, not both. Links and form fields are reported (PDFX_ANNOTATIONS). Check with validate_pdf standard:'pdf-x-4'. See the print_ready prompt.",
        +  "enum": [
        +    "pdfx4"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / print / properties / marks / oneOf
        Previous value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "crop": {
        -        "description": "Corner crop (trim) marks. Default true.",
        -        "type": "boolean"
        -      },
        -      "length": {
        -        "description": "Mark length in points. Default 14.",
        -        "maximum": 100,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "offset": {
        -        "description": "Gap between TrimBox and marks in points. Default 5.",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "registration": {
        -        "description": "Edge-midpoint registration targets. Default true.",
        -        "type": "boolean"
        -      },
        -      "weight": {
        -        "description": "Stroke width in points. Default 0.25.",
        -        "maximum": 5,
        -        "minimum": 0.05,
        -        "type": "number"
        -      }
        -    },
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "colourBars": {
        +        "anyOf": [
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "additionalProperties": false,
        +            "properties": {
        +              "size": {
        +                "description": "Patch size in points. Default 12.",
        +                "maximum": 72,
        +                "minimum": 4,
        +                "type": "number"
        +              },
        +              "tints": {
        +                "description": "Add the four 50 % tint patches. Default true.",
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          }
        +        ],
        +        "description": "Colour control strip in the bleed (C M Y K solids + their 50 % tints): true for defaults. Off by default; needs a bleed of about 5 mm (14.17 pt) and is skipped when the strip would not fit."
        +      },
        +      "crop": {
        +        "description": "Corner crop (trim) marks. Default true.",
        +        "type": "boolean"
        +      },
        +      "length": {
        +        "description": "Mark length in points. Default 14.",
        +        "maximum": 100,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "offset": {
        +        "description": "Gap between TrimBox and marks in points. Default 5.",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "registration": {
        +        "description": "Edge-midpoint registration targets. Default true.",
        +        "type": "boolean"
        +      },
        +      "weight": {
        +        "description": "Stroke width in points. Default 0.25.",
        +        "maximum": 5,
        +        "minimum": 0.05,
        +        "type": "number"
        +      }
        +    },
        +    "type": "object"
        +  }
        +]
      • addedInput schema / properties / series / items / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#?[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • removedInput schema / properties / series / items / properties / color / pattern
        Removed value: -"^#?[0-9a-fA-F]{6}$"
      • removedInput schema / properties / series / items / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / strict / description
        Previous value: -"Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true."New value: +"Fail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true."
      • addedInput schema / properties / typography
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Fine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.",
        +  "properties": {
        +    "bindShortWords": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "maxLength": {
        +              "maximum": 3,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "words": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never end a line on a short word: up to maxLength letters (default 1), or exactly the listed words."
        +    },
        +    "fontFeatures": {
        +      "description": "OpenType features, later wins. tnum / lnum are no-ops on Noto Sans (TYPOGRAPHY_FEATURE_INEFFECTIVE).",
        +      "items": {
        +        "enum": [
        +          "tnum",
        +          "pnum",
        +          "lnum",
        +          "onum",
        +          "zero",
        +          "ordn",
        +          "sups",
        +          "subs",
        +          "smcp",
        +          "c2sc",
        +          "case"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 11,
        +      "type": "array",
        +      "uniqueItems": true
        +    },
        +    "hyphenationLanguage": {
        +      "description": "BCP 47 tag; no effect here (no hyphenation provider installed).",
        +      "maxLength": 35,
        +      "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
        +      "type": "string"
        +    },
        +    "keepHeadingsWithNext": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "minLines": {
        +              "maximum": 10,
        +              "minimum": 1,
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never strand a heading at a page foot. true = { minLines: 2 }."
        +    },
        +    "kerning": {
        +      "description": "Pair kerning (GPOS).",
        +      "type": "boolean"
        +    },
        +    "metrics": {
        +      "description": "Base-14 text: 'exact' uses the AFM widths (different wraps). Default 'approximate'.",
        +      "enum": [
        +        "approximate",
        +        "exact"
        +      ],
        +      "type": "string"
        +    },
        +    "opticalMargins": {
        +      "description": "Hang punctuation into the margin of align:'justify' text.",
        +      "type": "boolean"
        +    },
        +    "orphans": {
        +      "description": "Min lines left at a page foot (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "punctuationSpacing": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "fr",
        +            "fr-CA"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "char": {
        +                "maxLength": 2,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "side": {
        +                "enum": [
        +                  "before",
        +                  "after"
        +                ],
        +                "type": "string"
        +              },
        +              "space": {
        +                "description": "U+00A0 / U+202F (narrow needs embedFonts).",
        +                "enum": [
        +                  "nbsp",
        +                  "narrow"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "char",
        +              "side",
        +              "space"
        +            ],
        +            "type": "object"
        +          },
        +          "maxItems": 32,
        +          "type": "array"
        +        }
        +      ],
        +      "description": "No-break spaces next to punctuation (existing spaces only). 'fr': narrow before ; ! ?, no-break before ':' and inside « ». 'fr-CA': ':' and « » only. Or explicit rules."
        +    },
        +    "splitParagraphs": {
        +      "description": "Paragraphs may break across pages at a line boundary (default: atomic).",
        +      "type": "boolean"
        +    },
        +    "unitBinding": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "units": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "No-break space between a number and its unit ('150 €', '12 kg'); units replaces the built-in list."
        +    },
        +    "widows": {
        +      "description": "Min lines carried over (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedadd_form24 fields changed
      • changedInput schema / properties / creationDate / description
        Previous value: -"ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs."New value: +"ISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs."
      • changedInput schema / properties / embedFonts / description
        Previous value: -"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB."New value: +"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB."
      • changedInput schema / properties / fields / items / properties / value / description
        Previous value: -"Default value pre-filled in the field."New value: +"Pre-filled value. The key is 'value' (there is no defaultValue)."
      • changedInput schema / properties / footerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / footerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / footerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / footerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / footerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / footerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / footerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / headerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / headerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / headerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / headerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / headerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / includeDiagnostics / description
        Previous value: -"Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty)."New value: +"Return the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty)."
      • changedInput schema / properties / outputIntent / description
        Previous value: -"Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected)."New value: +"Custom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space."
      • changedInput schema / properties / outputIntent / properties / iccProfileBase64 / description
        Previous value: -"ICC profile bytes, base64 (RGB, ≤ 8 MiB)."New value: +"ICC profile bytes, base64 (RGB, CMYK or Gray; ≤ 8 MiB)."
      • changedInput schema / properties / print / properties / marks / oneOf
        Previous value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "crop": {
        -        "description": "Corner crop (trim) marks. Default true.",
        -        "type": "boolean"
        -      },
        -      "length": {
        -        "description": "Mark length in points. Default 14.",
        -        "maximum": 100,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "offset": {
        -        "description": "Gap between TrimBox and marks in points. Default 5.",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "registration": {
        -        "description": "Edge-midpoint registration targets. Default true.",
        -        "type": "boolean"
        -      },
        -      "weight": {
        -        "description": "Stroke width in points. Default 0.25.",
        -        "maximum": 5,
        -        "minimum": 0.05,
        -        "type": "number"
        -      }
        -    },
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "colourBars": {
        +        "anyOf": [
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "additionalProperties": false,
        +            "properties": {
        +              "size": {
        +                "description": "Patch size in points. Default 12.",
        +                "maximum": 72,
        +                "minimum": 4,
        +                "type": "number"
        +              },
        +              "tints": {
        +                "description": "Add the four 50 % tint patches. Default true.",
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          }
        +        ],
        +        "description": "Colour control strip in the bleed (C M Y K solids + their 50 % tints): true for defaults. Off by default; needs a bleed of about 5 mm (14.17 pt) and is skipped when the strip would not fit."
        +      },
        +      "crop": {
        +        "description": "Corner crop (trim) marks. Default true.",
        +        "type": "boolean"
        +      },
        +      "length": {
        +        "description": "Mark length in points. Default 14.",
        +        "maximum": 100,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "offset": {
        +        "description": "Gap between TrimBox and marks in points. Default 5.",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "registration": {
        +        "description": "Edge-midpoint registration targets. Default true.",
        +        "type": "boolean"
        +      },
        +      "weight": {
        +        "description": "Stroke width in points. Default 0.25.",
        +        "maximum": 5,
        +        "minimum": 0.05,
        +        "type": "number"
        +      }
        +    },
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / strict / description
        Previous value: -"Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true."New value: +"Fail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true."
      • addedInput schema / properties / typography
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Fine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.",
        +  "properties": {
        +    "bindShortWords": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "maxLength": {
        +              "maximum": 3,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "words": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never end a line on a short word: up to maxLength letters (default 1), or exactly the listed words."
        +    },
        +    "fontFeatures": {
        +      "description": "OpenType features, later wins. tnum / lnum are no-ops on Noto Sans (TYPOGRAPHY_FEATURE_INEFFECTIVE).",
        +      "items": {
        +        "enum": [
        +          "tnum",
        +          "pnum",
        +          "lnum",
        +          "onum",
        +          "zero",
        +          "ordn",
        +          "sups",
        +          "subs",
        +          "smcp",
        +          "c2sc",
        +          "case"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 11,
        +      "type": "array",
        +      "uniqueItems": true
        +    },
        +    "hyphenationLanguage": {
        +      "description": "BCP 47 tag; no effect here (no hyphenation provider installed).",
        +      "maxLength": 35,
        +      "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
        +      "type": "string"
        +    },
        +    "keepHeadingsWithNext": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "minLines": {
        +              "maximum": 10,
        +              "minimum": 1,
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never strand a heading at a page foot. true = { minLines: 2 }."
        +    },
        +    "kerning": {
        +      "description": "Pair kerning (GPOS).",
        +      "type": "boolean"
        +    },
        +    "metrics": {
        +      "description": "Base-14 text: 'exact' uses the AFM widths (different wraps). Default 'approximate'.",
        +      "enum": [
        +        "approximate",
        +        "exact"
        +      ],
        +      "type": "string"
        +    },
        +    "opticalMargins": {
        +      "description": "Hang punctuation into the margin of align:'justify' text.",
        +      "type": "boolean"
        +    },
        +    "orphans": {
        +      "description": "Min lines left at a page foot (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "punctuationSpacing": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "fr",
        +            "fr-CA"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "char": {
        +                "maxLength": 2,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "side": {
        +                "enum": [
        +                  "before",
        +                  "after"
        +                ],
        +                "type": "string"
        +              },
        +              "space": {
        +                "description": "U+00A0 / U+202F (narrow needs embedFonts).",
        +                "enum": [
        +                  "nbsp",
        +                  "narrow"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "char",
        +              "side",
        +              "space"
        +            ],
        +            "type": "object"
        +          },
        +          "maxItems": 32,
        +          "type": "array"
        +        }
        +      ],
        +      "description": "No-break spaces next to punctuation (existing spaces only). 'fr': narrow before ; ! ?, no-break before ':' and inside « ». 'fr-CA': ':' and « » only. Or explicit rules."
        +    },
        +    "splitParagraphs": {
        +      "description": "Paragraphs may break across pages at a line boundary (default: atomic).",
        +      "type": "boolean"
        +    },
        +    "unitBinding": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "units": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "No-break space between a number and its unit ('150 €', '12 kg'); units replaces the built-in list."
        +    },
        +    "widows": {
        +      "description": "Min lines carried over (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedadd_international_text25 fields changed
      • changedInput schema / properties / creationDate / description
        Previous value: -"ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs."New value: +"ISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs."
      • changedInput schema / properties / footerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / footerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / footerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / footerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / footerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / footerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / footerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / headerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / headerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / headerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / headerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / headerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / includeDiagnostics / description
        Previous value: -"Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty)."New value: +"Return the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty)."
      • changedInput schema / properties / lang / anyOf
        Previous value: -[
        -  {
        -    "enum": [
        -      "ar",
        -      "he",
        -      "th",
        -      "ja",
        -      "zh",
        -      "ko",
        -      "el",
        -      "hi",
        -      "bn",
        -      "ta",
        -      "ru",
        -      "ka",
        -      "hy",
        -      "tr",
        -      "pl",
        -      "vi",
        -      "latin",
        -      "te",
        -      "si",
        -      "bo",
        -      "km",
        -      "my",
        -      "am",
        -      "emoji",
        -      "math"
        -    ],
        -    "type": "string"
        -  },
        -  {
        -    "items": {
        -      "enum": [
        -        "ar",
        -        "he",
        -        "th",
        -        "ja",
        -        "zh",
        -        "ko",
        -        "el",
        -        "hi",
        -        "bn",
        -        "ta",
        -        "ru",
        -        "ka",
        -        "hy",
        -        "tr",
        -        "pl",
        -        "vi",
        -        "latin",
        -        "te",
        -        "si",
        -        "bo",
        -        "km",
        -        "my",
        -        "am",
        -        "emoji",
        -        "math"
        -      ],
        -      "type": "string"
        -    },
        -    "maxItems": 25,
        -    "minItems": 1,
        -    "type": "array"
        -  },
        -  {
        -    "description": "Comma-separated list of supported codes.",
        -    "maxLength": 80,
        -    "minLength": 2,
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "enum": [
        +      "ar",
        +      "he",
        +      "th",
        +      "ja",
        +      "zh",
        +      "ko",
        +      "el",
        +      "hi",
        +      "bn",
        +      "ta",
        +      "ru",
        +      "ka",
        +      "hy",
        +      "tr",
        +      "pl",
        +      "vi",
        +      "latin",
        +      "te",
        +      "si",
        +      "bo",
        +      "km",
        +      "my",
        +      "am",
        +      "emoji",
        +      "math",
        +      "lo",
        +      "nod",
        +      "khb",
        +      "tdd",
        +      "cjm",
        +      "ha",
        +      "yo",
        +      "ig",
        +      "sw"
        +    ],
        +    "type": "string"
        +  },
        +  {
        +    "items": {
        +      "enum": [
        +        "ar",
        +        "he",
        +        "th",
        +        "ja",
        +        "zh",
        +        "ko",
        +        "el",
        +        "hi",
        +        "bn",
        +        "ta",
        +        "ru",
        +        "ka",
        +        "hy",
        +        "tr",
        +        "pl",
        +        "vi",
        +        "latin",
        +        "te",
        +        "si",
        +        "bo",
        +        "km",
        +        "my",
        +        "am",
        +        "emoji",
        +        "math",
        +        "lo",
        +        "nod",
        +        "khb",
        +        "tdd",
        +        "cjm",
        +        "ha",
        +        "yo",
        +        "ig",
        +        "sw"
        +      ],
        +      "type": "string"
        +    },
        +    "maxItems": 34,
        +    "minItems": 1,
        +    "type": "array"
        +  },
        +  {
        +    "description": "Comma-separated list of supported codes.",
        +    "maxLength": 80,
        +    "minLength": 2,
        +    "type": "string"
        +  }
        +]
      • changedInput schema / properties / lang / description
        Previous value: -"Language / script identifier. Either a single code (e.g. 'ar'), a comma-separated list ('ar,emoji'), or an array (['ar','emoji']). Multiple codes enable multi-font run splitting (script + emoji + Latin fallback)."New value: +"Language / script identifier. Either a single code (e.g. 'ar'), a comma-separated list ('ar,emoji'), or an array (['ar','emoji']). Multiple codes enable multi-font run splitting (script + emoji + Latin fallback). 27 scripts; ha / yo / ig / sw (Hausa, Yoruba, Igbo, Swahili) are aliases of latin, whose combining marks are anchored."
      • changedInput schema / properties / outputIntent / description
        Previous value: -"Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected)."New value: +"Custom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space."
      • changedInput schema / properties / outputIntent / properties / iccProfileBase64 / description
        Previous value: -"ICC profile bytes, base64 (RGB, ≤ 8 MiB)."New value: +"ICC profile bytes, base64 (RGB, CMYK or Gray; ≤ 8 MiB)."
      • addedInput schema / properties / pdfx
        Added value: +{
        +  "description": "PDF/X-4 print exchange (ISO 15930-7). REQUIRES outputIntent with the printer's ICC profile (device class 'prtr'; CMYK or Gray — none is bundled); needs embedFonts:true for a conformant file (PDFX_NO_FONT_ENTRIES otherwise, strict:true refuses). Exclusive with pdfA and encrypt; metadata.trapped must be 'True' or 'False'; TrimBox or ArtBox, not both. Links and form fields are reported (PDFX_ANNOTATIONS). Check with validate_pdf standard:'pdf-x-4'. See the print_ready prompt.",
        +  "enum": [
        +    "pdfx4"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / print / properties / marks / oneOf
        Previous value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "crop": {
        -        "description": "Corner crop (trim) marks. Default true.",
        -        "type": "boolean"
        -      },
        -      "length": {
        -        "description": "Mark length in points. Default 14.",
        -        "maximum": 100,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "offset": {
        -        "description": "Gap between TrimBox and marks in points. Default 5.",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "registration": {
        -        "description": "Edge-midpoint registration targets. Default true.",
        -        "type": "boolean"
        -      },
        -      "weight": {
        -        "description": "Stroke width in points. Default 0.25.",
        -        "maximum": 5,
        -        "minimum": 0.05,
        -        "type": "number"
        -      }
        -    },
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "colourBars": {
        +        "anyOf": [
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "additionalProperties": false,
        +            "properties": {
        +              "size": {
        +                "description": "Patch size in points. Default 12.",
        +                "maximum": 72,
        +                "minimum": 4,
        +                "type": "number"
        +              },
        +              "tints": {
        +                "description": "Add the four 50 % tint patches. Default true.",
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          }
        +        ],
        +        "description": "Colour control strip in the bleed (C M Y K solids + their 50 % tints): true for defaults. Off by default; needs a bleed of about 5 mm (14.17 pt) and is skipped when the strip would not fit."
        +      },
        +      "crop": {
        +        "description": "Corner crop (trim) marks. Default true.",
        +        "type": "boolean"
        +      },
        +      "length": {
        +        "description": "Mark length in points. Default 14.",
        +        "maximum": 100,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "offset": {
        +        "description": "Gap between TrimBox and marks in points. Default 5.",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "registration": {
        +        "description": "Edge-midpoint registration targets. Default true.",
        +        "type": "boolean"
        +      },
        +      "weight": {
        +        "description": "Stroke width in points. Default 0.25.",
        +        "maximum": 5,
        +        "minimum": 0.05,
        +        "type": "number"
        +      }
        +    },
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / strict / description
        Previous value: -"Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true."New value: +"Fail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true."
      • addedInput schema / properties / typography
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Fine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.",
        +  "properties": {
        +    "bindShortWords": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "maxLength": {
        +              "maximum": 3,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "words": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never end a line on a short word: up to maxLength letters (default 1), or exactly the listed words."
        +    },
        +    "fontFeatures": {
        +      "description": "OpenType features, later wins. tnum / lnum are no-ops on Noto Sans (TYPOGRAPHY_FEATURE_INEFFECTIVE).",
        +      "items": {
        +        "enum": [
        +          "tnum",
        +          "pnum",
        +          "lnum",
        +          "onum",
        +          "zero",
        +          "ordn",
        +          "sups",
        +          "subs",
        +          "smcp",
        +          "c2sc",
        +          "case"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 11,
        +      "type": "array",
        +      "uniqueItems": true
        +    },
        +    "hyphenationLanguage": {
        +      "description": "BCP 47 tag; no effect here (no hyphenation provider installed).",
        +      "maxLength": 35,
        +      "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
        +      "type": "string"
        +    },
        +    "keepHeadingsWithNext": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "minLines": {
        +              "maximum": 10,
        +              "minimum": 1,
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never strand a heading at a page foot. true = { minLines: 2 }."
        +    },
        +    "kerning": {
        +      "description": "Pair kerning (GPOS).",
        +      "type": "boolean"
        +    },
        +    "metrics": {
        +      "description": "Base-14 text: 'exact' uses the AFM widths (different wraps). Default 'approximate'.",
        +      "enum": [
        +        "approximate",
        +        "exact"
        +      ],
        +      "type": "string"
        +    },
        +    "opticalMargins": {
        +      "description": "Hang punctuation into the margin of align:'justify' text.",
        +      "type": "boolean"
        +    },
        +    "orphans": {
        +      "description": "Min lines left at a page foot (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "punctuationSpacing": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "fr",
        +            "fr-CA"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "char": {
        +                "maxLength": 2,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "side": {
        +                "enum": [
        +                  "before",
        +                  "after"
        +                ],
        +                "type": "string"
        +              },
        +              "space": {
        +                "description": "U+00A0 / U+202F (narrow needs embedFonts).",
        +                "enum": [
        +                  "nbsp",
        +                  "narrow"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "char",
        +              "side",
        +              "space"
        +            ],
        +            "type": "object"
        +          },
        +          "maxItems": 32,
        +          "type": "array"
        +        }
        +      ],
        +      "description": "No-break spaces next to punctuation (existing spaces only). 'fr': narrow before ; ! ?, no-break before ':' and inside « ». 'fr-CA': ':' and « » only. Or explicit rules."
        +    },
        +    "splitParagraphs": {
        +      "description": "Paragraphs may break across pages at a line boundary (default: atomic).",
        +      "type": "boolean"
        +    },
        +    "unitBinding": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "units": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "No-break space between a number and its unit ('150 €', '12 kg'); units replaces the built-in list."
        +    },
        +    "widows": {
        +      "description": "Min lines carried over (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedadd_ltv1 field changed
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedadd_table32 fields changed
      • addedInput schema / properties / cellBorders / properties / color / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • removedInput schema / properties / cellBorders / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / creationDate / description
        Previous value: -"ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs."New value: +"ISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs."
      • changedInput schema / properties / embedFonts / description
        Previous value: -"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB."New value: +"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB."
      • changedInput schema / properties / footerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / footerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / footerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / footerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / footerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / footerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / footerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / headerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / headerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / headerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / headerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / headerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / includeDiagnostics / description
        Previous value: -"Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty)."New value: +"Return the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty)."
      • changedInput schema / properties / outputIntent / description
        Previous value: -"Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected)."New value: +"Custom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space."
      • changedInput schema / properties / outputIntent / properties / iccProfileBase64 / description
        Previous value: -"ICC profile bytes, base64 (RGB, ≤ 8 MiB)."New value: +"ICC profile bytes, base64 (RGB, CMYK or Gray; ≤ 8 MiB)."
      • addedInput schema / properties / pdfx
        Added value: +{
        +  "description": "PDF/X-4 print exchange (ISO 15930-7). REQUIRES outputIntent with the printer's ICC profile (device class 'prtr'; CMYK or Gray — none is bundled); needs embedFonts:true for a conformant file (PDFX_NO_FONT_ENTRIES otherwise, strict:true refuses). Exclusive with pdfA and encrypt; metadata.trapped must be 'True' or 'False'; TrimBox or ArtBox, not both. Links and form fields are reported (PDFX_ANNOTATIONS). Check with validate_pdf standard:'pdf-x-4'. See the print_ready prompt.",
        +  "enum": [
        +    "pdfx4"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / print / properties / marks / oneOf
        Previous value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "crop": {
        -        "description": "Corner crop (trim) marks. Default true.",
        -        "type": "boolean"
        -      },
        -      "length": {
        -        "description": "Mark length in points. Default 14.",
        -        "maximum": 100,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "offset": {
        -        "description": "Gap between TrimBox and marks in points. Default 5.",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "registration": {
        -        "description": "Edge-midpoint registration targets. Default true.",
        -        "type": "boolean"
        -      },
        -      "weight": {
        -        "description": "Stroke width in points. Default 0.25.",
        -        "maximum": 5,
        -        "minimum": 0.05,
        -        "type": "number"
        -      }
        -    },
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "colourBars": {
        +        "anyOf": [
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "additionalProperties": false,
        +            "properties": {
        +              "size": {
        +                "description": "Patch size in points. Default 12.",
        +                "maximum": 72,
        +                "minimum": 4,
        +                "type": "number"
        +              },
        +              "tints": {
        +                "description": "Add the four 50 % tint patches. Default true.",
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          }
        +        ],
        +        "description": "Colour control strip in the bleed (C M Y K solids + their 50 % tints): true for defaults. Off by default; needs a bleed of about 5 mm (14.17 pt) and is skipped when the strip would not fit."
        +      },
        +      "crop": {
        +        "description": "Corner crop (trim) marks. Default true.",
        +        "type": "boolean"
        +      },
        +      "length": {
        +        "description": "Mark length in points. Default 14.",
        +        "maximum": 100,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "offset": {
        +        "description": "Gap between TrimBox and marks in points. Default 5.",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "registration": {
        +        "description": "Edge-midpoint registration targets. Default true.",
        +        "type": "boolean"
        +      },
        +      "weight": {
        +        "description": "Stroke width in points. Default 0.25.",
        +        "maximum": 5,
        +        "minimum": 0.05,
        +        "type": "number"
        +      }
        +    },
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / strict / description
        Previous value: -"Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true."New value: +"Fail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true."
      • addedInput schema / properties / typography
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Fine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.",
        +  "properties": {
        +    "bindShortWords": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "maxLength": {
        +              "maximum": 3,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "words": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never end a line on a short word: up to maxLength letters (default 1), or exactly the listed words."
        +    },
        +    "fontFeatures": {
        +      "description": "OpenType features, later wins. tnum / lnum are no-ops on Noto Sans (TYPOGRAPHY_FEATURE_INEFFECTIVE).",
        +      "items": {
        +        "enum": [
        +          "tnum",
        +          "pnum",
        +          "lnum",
        +          "onum",
        +          "zero",
        +          "ordn",
        +          "sups",
        +          "subs",
        +          "smcp",
        +          "c2sc",
        +          "case"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 11,
        +      "type": "array",
        +      "uniqueItems": true
        +    },
        +    "hyphenationLanguage": {
        +      "description": "BCP 47 tag; no effect here (no hyphenation provider installed).",
        +      "maxLength": 35,
        +      "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
        +      "type": "string"
        +    },
        +    "keepHeadingsWithNext": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "minLines": {
        +              "maximum": 10,
        +              "minimum": 1,
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never strand a heading at a page foot. true = { minLines: 2 }."
        +    },
        +    "kerning": {
        +      "description": "Pair kerning (GPOS).",
        +      "type": "boolean"
        +    },
        +    "metrics": {
        +      "description": "Base-14 text: 'exact' uses the AFM widths (different wraps). Default 'approximate'.",
        +      "enum": [
        +        "approximate",
        +        "exact"
        +      ],
        +      "type": "string"
        +    },
        +    "opticalMargins": {
        +      "description": "Hang punctuation into the margin of align:'justify' text.",
        +      "type": "boolean"
        +    },
        +    "orphans": {
        +      "description": "Min lines left at a page foot (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "punctuationSpacing": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "fr",
        +            "fr-CA"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "char": {
        +                "maxLength": 2,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "side": {
        +                "enum": [
        +                  "before",
        +                  "after"
        +                ],
        +                "type": "string"
        +              },
        +              "space": {
        +                "description": "U+00A0 / U+202F (narrow needs embedFonts).",
        +                "enum": [
        +                  "nbsp",
        +                  "narrow"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "char",
        +              "side",
        +              "space"
        +            ],
        +            "type": "object"
        +          },
        +          "maxItems": 32,
        +          "type": "array"
        +        }
        +      ],
        +      "description": "No-break spaces next to punctuation (existing spaces only). 'fr': narrow before ; ! ?, no-break before ':' and inside « ». 'fr-CA': ':' and « » only. Or explicit rules."
        +    },
        +    "splitParagraphs": {
        +      "description": "Paragraphs may break across pages at a line boundary (default: atomic).",
        +      "type": "boolean"
        +    },
        +    "unitBinding": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "units": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "No-break space between a number and its unit ('150 €', '12 kg'); units replaces the built-in list."
        +    },
        +    "widows": {
        +      "description": "Min lines carried over (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / watermark / properties / color / anyOf
        Added value: +[
        +  {
        +    "items": {
        +      "maximum": 1,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 3,
        +    "minItems": 3,
        +    "type": "array"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / watermark / properties / color / description
        Previous value: -"Text RGB colour as a [r, g, b] triple in the 0.0–1.0 range. Default light gray [0.75, 0.75, 0.75]."New value: +"Text colour. RGB as a [r, g, b] triple in the 0.0–1.0 range; default light gray [0.75, 0.75, 0.75]."
      • removedInput schema / properties / watermark / properties / color / items
        Removed value: -{
        -  "maximum": 1,
        -  "minimum": 0,
        -  "type": "number"
        -}
      • removedInput schema / properties / watermark / properties / color / maxItems
        Removed value: -3
      • removedInput schema / properties / watermark / properties / color / minItems
        Removed value: -3
      • removedInput schema / properties / watermark / properties / color / type
        Removed value: -"array"
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedannotate_pdf3 fields changed
      • changedInput schema / properties / annotations / items / properties / color / oneOf
        Previous value: -[
        -  {
        -    "description": "Hex (e.g. \"#ffcc00\") or PDF operator string (\"R G B\").",
        -    "type": "string"
        -  },
        -  {
        -    "description": "RGB tuple, 0.0–1.0.",
        -    "items": {
        -      "type": "number"
        -    },
        -    "maxItems": 3,
        -    "minItems": 3,
        -    "type": "array"
        -  }
        -]New value: +[
        +  {
        +    "description": "Hex (e.g. \"#ffcc00\") or PDF operator string (\"R G B\", or \"C M Y K\" for DeviceCMYK), each operand 0.0–1.0.",
        +    "type": "string"
        +  },
        +  {
        +    "description": "RGB tuple, 0.0–1.0.",
        +    "items": {
        +      "type": "number"
        +    },
        +    "maxItems": 3,
        +    "minItems": 3,
        +    "type": "array"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / annotations / items / properties / interiorColor / oneOf
        Previous value: -[
        -  {
        -    "description": "Hex (e.g. \"#ffcc00\") or PDF operator string (\"R G B\").",
        -    "type": "string"
        -  },
        -  {
        -    "description": "RGB tuple, 0.0–1.0.",
        -    "items": {
        -      "type": "number"
        -    },
        -    "maxItems": 3,
        -    "minItems": 3,
        -    "type": "array"
        -  }
        -]New value: +[
        +  {
        +    "description": "Hex (e.g. \"#ffcc00\") or PDF operator string (\"R G B\", or \"C M Y K\" for DeviceCMYK), each operand 0.0–1.0.",
        +    "type": "string"
        +  },
        +  {
        +    "description": "RGB tuple, 0.0–1.0.",
        +    "items": {
        +      "type": "number"
        +    },
        +    "maxItems": 3,
        +    "minItems": 3,
        +    "type": "array"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changeddecrypt_pdf1 field changed
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedembed_image24 fields changed
      • changedInput schema / properties / creationDate / description
        Previous value: -"ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs."New value: +"ISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs."
      • changedInput schema / properties / embedFonts / description
        Previous value: -"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB."New value: +"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB."
      • changedInput schema / properties / footerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / footerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / footerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / footerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / footerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / footerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / footerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / headerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / headerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / headerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / headerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / headerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / includeDiagnostics / description
        Previous value: -"Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty)."New value: +"Return the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty)."
      • changedInput schema / properties / outputIntent / description
        Previous value: -"Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected)."New value: +"Custom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space."
      • changedInput schema / properties / outputIntent / properties / iccProfileBase64 / description
        Previous value: -"ICC profile bytes, base64 (RGB, ≤ 8 MiB)."New value: +"ICC profile bytes, base64 (RGB, CMYK or Gray; ≤ 8 MiB)."
      • addedInput schema / properties / pdfx
        Added value: +{
        +  "description": "PDF/X-4 print exchange (ISO 15930-7). REQUIRES outputIntent with the printer's ICC profile (device class 'prtr'; CMYK or Gray — none is bundled); needs embedFonts:true for a conformant file (PDFX_NO_FONT_ENTRIES otherwise, strict:true refuses). Exclusive with pdfA and encrypt; metadata.trapped must be 'True' or 'False'; TrimBox or ArtBox, not both. Links and form fields are reported (PDFX_ANNOTATIONS). Check with validate_pdf standard:'pdf-x-4'. See the print_ready prompt.",
        +  "enum": [
        +    "pdfx4"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / print / properties / marks / oneOf
        Previous value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "crop": {
        -        "description": "Corner crop (trim) marks. Default true.",
        -        "type": "boolean"
        -      },
        -      "length": {
        -        "description": "Mark length in points. Default 14.",
        -        "maximum": 100,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "offset": {
        -        "description": "Gap between TrimBox and marks in points. Default 5.",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "registration": {
        -        "description": "Edge-midpoint registration targets. Default true.",
        -        "type": "boolean"
        -      },
        -      "weight": {
        -        "description": "Stroke width in points. Default 0.25.",
        -        "maximum": 5,
        -        "minimum": 0.05,
        -        "type": "number"
        -      }
        -    },
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "colourBars": {
        +        "anyOf": [
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "additionalProperties": false,
        +            "properties": {
        +              "size": {
        +                "description": "Patch size in points. Default 12.",
        +                "maximum": 72,
        +                "minimum": 4,
        +                "type": "number"
        +              },
        +              "tints": {
        +                "description": "Add the four 50 % tint patches. Default true.",
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          }
        +        ],
        +        "description": "Colour control strip in the bleed (C M Y K solids + their 50 % tints): true for defaults. Off by default; needs a bleed of about 5 mm (14.17 pt) and is skipped when the strip would not fit."
        +      },
        +      "crop": {
        +        "description": "Corner crop (trim) marks. Default true.",
        +        "type": "boolean"
        +      },
        +      "length": {
        +        "description": "Mark length in points. Default 14.",
        +        "maximum": 100,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "offset": {
        +        "description": "Gap between TrimBox and marks in points. Default 5.",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "registration": {
        +        "description": "Edge-midpoint registration targets. Default true.",
        +        "type": "boolean"
        +      },
        +      "weight": {
        +        "description": "Stroke width in points. Default 0.25.",
        +        "maximum": 5,
        +        "minimum": 0.05,
        +        "type": "number"
        +      }
        +    },
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / strict / description
        Previous value: -"Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true."New value: +"Fail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true."
      • addedInput schema / properties / typography
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Fine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.",
        +  "properties": {
        +    "bindShortWords": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "maxLength": {
        +              "maximum": 3,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "words": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never end a line on a short word: up to maxLength letters (default 1), or exactly the listed words."
        +    },
        +    "fontFeatures": {
        +      "description": "OpenType features, later wins. tnum / lnum are no-ops on Noto Sans (TYPOGRAPHY_FEATURE_INEFFECTIVE).",
        +      "items": {
        +        "enum": [
        +          "tnum",
        +          "pnum",
        +          "lnum",
        +          "onum",
        +          "zero",
        +          "ordn",
        +          "sups",
        +          "subs",
        +          "smcp",
        +          "c2sc",
        +          "case"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 11,
        +      "type": "array",
        +      "uniqueItems": true
        +    },
        +    "hyphenationLanguage": {
        +      "description": "BCP 47 tag; no effect here (no hyphenation provider installed).",
        +      "maxLength": 35,
        +      "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
        +      "type": "string"
        +    },
        +    "keepHeadingsWithNext": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "minLines": {
        +              "maximum": 10,
        +              "minimum": 1,
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never strand a heading at a page foot. true = { minLines: 2 }."
        +    },
        +    "kerning": {
        +      "description": "Pair kerning (GPOS).",
        +      "type": "boolean"
        +    },
        +    "metrics": {
        +      "description": "Base-14 text: 'exact' uses the AFM widths (different wraps). Default 'approximate'.",
        +      "enum": [
        +        "approximate",
        +        "exact"
        +      ],
        +      "type": "string"
        +    },
        +    "opticalMargins": {
        +      "description": "Hang punctuation into the margin of align:'justify' text.",
        +      "type": "boolean"
        +    },
        +    "orphans": {
        +      "description": "Min lines left at a page foot (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "punctuationSpacing": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "fr",
        +            "fr-CA"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "char": {
        +                "maxLength": 2,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "side": {
        +                "enum": [
        +                  "before",
        +                  "after"
        +                ],
        +                "type": "string"
        +              },
        +              "space": {
        +                "description": "U+00A0 / U+202F (narrow needs embedFonts).",
        +                "enum": [
        +                  "nbsp",
        +                  "narrow"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "char",
        +              "side",
        +              "space"
        +            ],
        +            "type": "object"
        +          },
        +          "maxItems": 32,
        +          "type": "array"
        +        }
        +      ],
        +      "description": "No-break spaces next to punctuation (existing spaces only). 'fr': narrow before ; ! ?, no-break before ':' and inside « ». 'fr-CA': ':' and « » only. Or explicit rules."
        +    },
        +    "splitParagraphs": {
        +      "description": "Paragraphs may break across pages at a line boundary (default: atomic).",
        +      "type": "boolean"
        +    },
        +    "unitBinding": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "units": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "No-break space between a number and its unit ('150 €', '12 kg'); units replaces the built-in list."
        +    },
        +    "widows": {
        +      "description": "Min lines carried over (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedencrypt_pdf1 field changed
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedextract_pages1 field changed
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedfill_form1 field changed
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedgenerate_basic_pdf32 fields changed
      • changedInput schema / properties / blocks / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "level": {
        -        "enum": [
        -          1,
        -          2,
        -          3
        -        ],
        -        "type": "integer"
        -      },
        -      "text": {
        -        "maxLength": 500,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "heading"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text",
        -      "level"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "text": {
        -        "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.",
        -        "maxLength": 50000,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "paragraph"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "items": {
        -        "description": "List items. A string is a leaf; an object { text, items } nests a sub-list (bullets/numbers indent; numbered sub-lists restart at 1).",
        -        "items": {
        -          "oneOf": [
        -            {
        -              "maxLength": 1000,
        -              "minLength": 1,
        -              "type": "string"
        -            },
        -            {
        -              "additionalProperties": false,
        -              "properties": {
        -                "items": {
        -                  "items": {
        -                    "oneOf": [
        -                      {
        -                        "maxLength": 1000,
        -                        "minLength": 1,
        -                        "type": "string"
        -                      },
        -                      {
        -                        "additionalProperties": false,
        -                        "properties": {
        -                          "items": {
        -                            "items": {
        -                              "oneOf": [
        -                                {
        -                                  "maxLength": 1000,
        -                                  "minLength": 1,
        -                                  "type": "string"
        -                                },
        -                                {
        -                                  "additionalProperties": false,
        -                                  "properties": {
        -                                    "items": {
        -                                      "items": {
        -                                        "oneOf": [
        -                                          {
        -                                            "maxLength": 1000,
        -                                            "minLength": 1,
        -                                            "type": "string"
        -                                          },
        -                                          {
        -                                            "additionalProperties": false,
        -                                            "properties": {
        -                                              "items": {
        -                                                "items": {
        -                                                  "oneOf": [
        -                                                    {
        -                                                      "maxLength": 1000,
        -                                                      "minLength": 1,
        -                                                      "type": "string"
        -                                                    },
        -                                                    {
        -                                                      "additionalProperties": false,
        -                                                      "properties": {
        -                                                        "items": {
        -                                                          "items": {
        -                                                            "oneOf": [
        -                                                              {
        -                                                                "maxLength": 1000,
        -                                                                "minLength": 1,
        -                                                                "type": "string"
        -                                                              },
        -                                                              {
        -                                                                "additionalProperties": false,
        -                                                                "properties": {
        -                                                                  "text": {
        -                                                                    "maxLength": 1000,
        -                                                                    "minLength": 1,
        -                                                                    "type": "string"
        -                                                                  }
        -                                                                },
        -                                                                "required": [
        -                                                                  "text"
        -                                                                ],
        -                                                                "type": "object"
        -                                                              }
        -                                                            ]
        -                                                          },
        -                                                          "maxItems": 1000,
        -                                                          "minItems": 1,
        -                                                          "type": "array"
        -                                                        },
        -                                                        "text": {
        -                                                          "maxLength": 1000,
        -                                                          "minLength": 1,
        -                                                          "type": "string"
        -                                                        }
        -                                                      },
        -                                                      "required": [
        -                                                        "text"
        -                                                      ],
        -                                                      "type": "object"
        -                                                    }
        -                                                  ]
        -                                                },
        -                                                "maxItems": 1000,
        -                                                "minItems": 1,
        -                                                "type": "array"
        -                                              },
        -                                              "text": {
        -                                                "maxLength": 1000,
        -                                                "minLength": 1,
        -                                                "type": "string"
        -                                              }
        -                                            },
        -                                            "required": [
        -                                              "text"
        -                                            ],
        -                                            "type": "object"
        -                                          }
        -                                        ]
        -                                      },
        -                                      "maxItems": 1000,
        -                                      "minItems": 1,
        -                                      "type": "array"
        -                                    },
        -                                    "text": {
        -                                      "maxLength": 1000,
        -                                      "minLength": 1,
        -                                      "type": "string"
        -                                    }
        -                                  },
        -                                  "required": [
        -                                    "text"
        -                                  ],
        -                                  "type": "object"
        -                                }
        -                              ]
        -                            },
        -                            "maxItems": 1000,
        -                            "minItems": 1,
        -                            "type": "array"
        -                          },
        -                          "text": {
        -                            "maxLength": 1000,
        -                            "minLength": 1,
        -                            "type": "string"
        -                          }
        -                        },
        -                        "required": [
        -                          "text"
        -                        ],
        -                        "type": "object"
        -                      }
        -                    ]
        -                  },
        -                  "maxItems": 1000,
        -                  "minItems": 1,
        -                  "type": "array"
        -                },
        -                "text": {
        -                  "maxLength": 1000,
        -                  "minLength": 1,
        -                  "type": "string"
        -                }
        -              },
        -              "required": [
        -                "text"
        -              ],
        -              "type": "object"
        -            }
        -          ]
        -        },
        -        "maxItems": 1000,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "style": {
        -        "default": "bullet",
        -        "enum": [
        -          "bullet",
        -          "numbered"
        -        ],
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "list"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "items"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "type": {
        -        "const": "pageBreak"
        -      }
        -    },
        -    "required": [
        -      "type"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "height": {
        -        "maximum": 500,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "type": {
        -        "const": "spacer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "height"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Native vector chart rendered as pure PDF path operators — bar / horizontal-bar / stacked-bar / line / area / scatter / pie / donut (pdfnative 1.7 charts v2: time and log axes, data labels, secondary axis, legends). Same body as add_chart.",
        -    "properties": {
        -      "align": {
        -        "description": "Horizontal alignment within the content width. Default 'left'.",
        -        "enum": [
        -          "left",
        -          "center",
        -          "right"
        -        ],
        -        "type": "string"
        -      },
        -      "altText": {
        -        "description": "Alt text for the tagged-PDF /Figure /Alt. Auto-generated when omitted.",
        -        "maxLength": 500,
        -        "type": "string"
        -      },
        -      "axis": {
        -        "additionalProperties": false,
        -        "description": "Value-axis options (bar/line only).",
        -        "properties": {
        -          "grid": {
        -            "description": "Draw horizontal gridlines.",
        -            "type": "boolean"
        -          },
        -          "scale": {
        -            "description": "Value-axis scale. 'log' requires strictly positive values and is not available for stacked charts.",
        -            "enum": [
        -              "linear",
        -              "log"
        -            ],
        -            "type": "string"
        -          },
        -          "ticks": {
        -            "description": "Target tick count (nice 1/2/5×10ⁿ steps).",
        -            "maximum": 20,
        -            "minimum": 2,
        -            "type": "integer"
        -          },
        -          "yMax": {
        -            "description": "Force the axis maximum (values are clamped to the plot band).",
        -            "type": "number"
        -          },
        -          "yMin": {
        -            "description": "Force the axis minimum (values are clamped to the plot band).",
        -            "type": "number"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "axis2": {
        -        "additionalProperties": false,
        -        "description": "Secondary RIGHT value axis (drawn only when a series sets yAxis:'right').",
        -        "properties": {
        -          "scale": {
        -            "enum": [
        -              "linear",
        -              "log"
        -            ],
        -            "type": "string"
        -          },
        -          "ticks": {
        -            "maximum": 20,
        -            "minimum": 2,
        -            "type": "integer"
        -          },
        -          "yMax": {
        -            "type": "number"
        -          },
        -          "yMin": {
        -            "type": "number"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "categories": {
        -        "description": "Category / slice labels (x-axis). Defaults to 1-based indices when omitted.",
        -        "items": {
        -          "maxLength": 200,
        -          "type": "string"
        -        },
        -        "maxItems": 1000,
        -        "type": "array"
        -      },
        -      "chartType": {
        -        "description": "Chart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'stackedBar'/'stackedBarH'/'line'/'area'/'scatter' support multiple series. 'scatter' requires xValues on every series and a positional xAxis.type ('linear' or 'time').",
        -        "enum": [
        -          "bar",
        -          "barH",
        -          "stackedBar",
        -          "stackedBarH",
        -          "line",
        -          "area",
        -          "scatter",
        -          "pie",
        -          "donut"
        -        ],
        -        "type": "string"
        -      },
        -      "colors": {
        -        "description": "Palette override (per-series for bar/line, per-slice for pie/donut).",
        -        "items": {
        -          "description": "CSS-style hex colour, e.g. \"#3366cc\".",
        -          "pattern": "^#?[0-9a-fA-F]{6}$",
        -          "type": "string"
        -        },
        -        "maxItems": 50,
        -        "type": "array"
        -      },
        -      "dataLabels": {
        -        "description": "Per-point value labels: true for defaults, or an object to format them.",
        -        "oneOf": [
        -          {
        -            "type": "boolean"
        -          },
        -          {
        -            "additionalProperties": false,
        -            "properties": {
        -              "decimals": {
        -                "maximum": 6,
        -                "minimum": 0,
        -                "type": "integer"
        -              },
        -              "prefix": {
        -                "maxLength": 16,
        -                "type": "string"
        -              },
        -              "suffix": {
        -                "maxLength": 16,
        -                "type": "string"
        -              }
        -            },
        -            "type": "object"
        -          }
        -        ]
        -      },
        -      "height": {
        -        "description": "Plot-area height in points. Default 240.",
        -        "maximum": 2000,
        -        "minimum": 50,
        -        "type": "number"
        -      },
        -      "labelRotation": {
        -        "description": "Rotate category labels counter-clockwise by this many degrees (disables the automatic stride).",
        -        "maximum": 90,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "labelStride": {
        -        "description": "Draw every Nth category label. Default: automatic (measured non-overlap); 1 draws every label.",
        -        "maximum": 1000,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "legend": {
        -        "description": "Legend placement. Defaults to 'bottom' for multi-series/pie, else 'none'.",
        -        "enum": [
        -          "bottom",
        -          "none"
        -        ],
        -        "type": "string"
        -      },
        -      "markers": {
        -        "description": "Draw point markers on line series. Default false.",
        -        "type": "boolean"
        -      },
        -      "series": {
        -        "description": "Data series. Pie/donut charts use exactly one series (each value becomes a slice).",
        -        "items": {
        -          "additionalProperties": false,
        -          "properties": {
        -            "color": {
        -              "description": "CSS-style hex colour, e.g. \"#3366cc\".",
        -              "pattern": "^#?[0-9a-fA-F]{6}$",
        -              "type": "string"
        -            },
        -            "label": {
        -              "description": "Series label (shown in the legend).",
        -              "maxLength": 200,
        -              "minLength": 1,
        -              "type": "string"
        -            },
        -            "values": {
        -              "description": "Numeric values, one per category. Negative values are supported for bar/line.",
        -              "items": {
        -                "type": "number"
        -              },
        -              "maxItems": 1000,
        -              "minItems": 1,
        -              "type": "array"
        -            },
        -            "xValues": {
        -              "description": "Per-point x positions (same length as values) for scatter charts and for line/area charts with xAxis.type 'linear' or 'time'.",
        -              "items": {
        -                "description": "Positional x value: a number (linear axis) or an ISO-8601 date / epoch milliseconds (time axis).",
        -                "maxLength": 64,
        -                "type": [
        -                  "number",
        -                  "string"
        -                ]
        -              },
        -              "maxItems": 1000,
        -              "minItems": 1,
        -              "type": "array"
        -            },
        -            "yAxis": {
        -              "description": "Bind the series to the left (default) or the secondary right value axis (cartesian charts only; configure its range with 'axis2').",
        -              "enum": [
        -                "left",
        -                "right"
        -              ],
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "label",
        -            "values"
        -          ],
        -          "type": "object"
        -        },
        -        "maxItems": 50,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "title": {
        -        "description": "Chart title rendered above the plot.",
        -        "maxLength": 200,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "chart"
        -      },
        -      "width": {
        -        "description": "Plot width in points (clamped to content width). Default 460.",
        -        "maximum": 2000,
        -        "minimum": 50,
        -        "type": "number"
        -      },
        -      "xAxis": {
        -        "additionalProperties": false,
        -        "description": "Horizontal axis. 'category' (default) positions points by index; 'linear' / 'time' position them by series xValues (line/area/scatter only). Time ticks are UTC-deterministic.",
        -        "properties": {
        -          "grid": {
        -            "description": "Draw vertical gridlines.",
        -            "type": "boolean"
        -          },
        -          "max": {
        -            "description": "Axis maximum (number, or ISO-8601 / epoch ms for time axes).",
        -            "maxLength": 64,
        -            "type": [
        -              "number",
        -              "string"
        -            ]
        -          },
        -          "min": {
        -            "description": "Axis minimum (number, or ISO-8601 / epoch ms for time axes).",
        -            "maxLength": 64,
        -            "type": [
        -              "number",
        -              "string"
        -            ]
        -          },
        -          "ticks": {
        -            "maximum": 20,
        -            "minimum": 2,
        -            "type": "integer"
        -          },
        -          "type": {
        -            "enum": [
        -              "category",
        -              "linear",
        -              "time"
        -            ],
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "chartType",
        -      "series"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Inline smart table — same body as add_table (every row must have exactly as many cells as headers).",
        -    "properties": {
        -      "autoFitColumns": {
        -        "description": "Auto-fit column widths to content. Output bytes then depend on text metrics (not byte-deterministic across content changes).",
        -        "type": "boolean"
        -      },
        -      "caption": {
        -        "description": "Caption rendered above the table (tagged as /Caption under PDF/A).",
        -        "maxLength": 200,
        -        "type": "string"
        -      },
        -      "cellBorders": {
        -        "additionalProperties": false,
        -        "description": "Per-cell vector borders (pure strokes, PDF/A-safe). Choose individual sides or `all`.",
        -        "properties": {
        -          "all": {
        -            "description": "Draw all four edges (overrides the individual side flags).",
        -            "type": "boolean"
        -          },
        -          "bottom": {
        -            "type": "boolean"
        -          },
        -          "color": {
        -            "description": "Stroke colour as a PDF operator string ('0.8 0.8 0.8') or hex. Default light grey.",
        -            "type": "string"
        -          },
        -          "left": {
        -            "type": "boolean"
        -          },
        -          "right": {
        -            "type": "boolean"
        -          },
        -          "style": {
        -            "description": "Stroke style (default 'solid').",
        -            "enum": [
        -              "solid",
        -              "dashed",
        -              "dotted"
        -            ],
        -            "type": "string"
        -          },
        -          "top": {
        -            "type": "boolean"
        -          },
        -          "width": {
        -            "description": "Stroke width in points (default 0.5).",
        -            "maximum": 10,
        -            "minimum": 0,
        -            "type": "number"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "cellPadding": {
        -        "description": "Horizontal cell padding in points (default 3).",
        -        "maximum": 50,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "cellVAlign": {
        -        "description": "Vertical alignment of cell content.",
        -        "enum": [
        -          "top",
        -          "middle",
        -          "bottom"
        -        ],
        -        "type": "string"
        -      },
        -      "clipCells": {
        -        "description": "Clip cell contents to the column bounds (PDF clip operators). Recommended for PDF/A and visual safety.",
        -        "type": "boolean"
        -      },
        -      "headers": {
        -        "description": "Column header labels. Must have the same length as each row in `rows`.",
        -        "items": {
        -          "maxLength": 200,
        -          "minLength": 1,
        -          "type": "string"
        -        },
        -        "maxItems": 50,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "minRowHeight": {
        -        "description": "Minimum row height in points (default 12).",
        -        "maximum": 200,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "repeatHeader": {
        -        "description": "Repeat the header row on every continuation page (default true).",
        -        "type": "boolean"
        -      },
        -      "rows": {
        -        "description": "Data rows. Each row is an array of cell strings with the same length as `headers`.",
        -        "items": {
        -          "items": {
        -            "maxLength": 500,
        -            "type": "string"
        -          },
        -          "maxItems": 50,
        -          "minItems": 1,
        -          "type": "array"
        -        },
        -        "maxItems": 5000,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "type": {
        -        "const": "table"
        -      },
        -      "wrap": {
        -        "description": "Cell wrap policy: 'auto' (default) wraps only overflowing cells; 'always' wraps every cell; 'never' truncates.",
        -        "enum": [
        -          "auto",
        -          "always",
        -          "never"
        -        ],
        -        "type": "string"
        -      },
        -      "zebra": {
        -        "description": "Alternate-row light tint (static fill, PDF/A-1b safe).",
        -        "type": "boolean"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "headers",
        -      "rows"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Inline JPEG/PNG image. Without width/height the pixel size is used as points and clamped to the content width; with one dimension the aspect ratio is kept. The decoded bytes of all image blocks in one call are capped at 24 MiB (a watermark image has its own 8 MiB cap).",
        -    "properties": {
        -      "align": {
        -        "default": "left",
        -        "description": "Horizontal placement inside the content width.",
        -        "enum": [
        -          "left",
        -          "center",
        -          "right"
        -        ],
        -        "type": "string"
        -      },
        -      "alt": {
        -        "description": "Accessible description (tagged /Figure /Alt). Always provide it for non-decorative content under PDF/A or PDF/UA.",
        -        "maxLength": 500,
        -        "type": "string"
        -      },
        -      "height": {
        -        "description": "Render height in points.",
        -        "maximum": 1000,
        -        "minimum": 10,
        -        "type": "number"
        -      },
        -      "imageBase64": {
        -        "description": "Base64 image bytes. JPEG (baseline; 1, 3 or 4 components — CMYK raises PDFA_DEVICE_CMYK_IMAGE under PDF/A) or PNG (8-bit greyscale/RGB, non-interlaced; alpha-channel and palette PNGs are rejected with a remedy). No data: URI.",
        -        "maxLength": 12000000,
        -        "minLength": 4,
        -        "type": "string"
        -      },
        -      "mimeType": {
        -        "description": "MIME type of the image. Must match the actual encoding of imageBase64 (magic bytes are checked).",
        -        "enum": [
        -          "image/jpeg",
        -          "image/png"
        -        ],
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "image"
        -      },
        -      "width": {
        -        "description": "Render width in points.",
        -        "maximum": 800,
        -        "minimum": 10,
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "imageBase64",
        -      "mimeType"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Clickable external link (/URI action). Only http:, https: and mailto: URLs are accepted.",
        -    "properties": {
        -      "color": {
        -        "description": "Hex colour (#RGB or #RRGGBB).",
        -        "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$",
        -        "type": "string"
        -      },
        -      "fontSize": {
        -        "description": "Default 10.",
        -        "maximum": 48,
        -        "minimum": 6,
        -        "type": "number"
        -      },
        -      "text": {
        -        "maxLength": 500,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "link"
        -      },
        -      "url": {
        -        "description": "http(s):// or mailto: URL.",
        -        "maxLength": 2048,
        -        "minLength": 1,
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text",
        -      "url"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Printed table of contents generated from the document's heading blocks (internal /GoTo links with dot leaders). Pairs with outline:'auto' for the bookmark pane.",
        -    "properties": {
        -      "fontSize": {
        -        "description": "Default 10.",
        -        "maximum": 24,
        -        "minimum": 6,
        -        "type": "number"
        -      },
        -      "indent": {
        -        "description": "Points of indent per heading level (default 15).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "maxLevel": {
        -        "description": "Deepest heading level listed (default 3).",
        -        "enum": [
        -          1,
        -          2,
        -          3
        -        ],
        -        "type": "integer"
        -      },
        -      "title": {
        -        "description": "Default 'Table of Contents'.",
        -        "maxLength": 200,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "toc"
        -      }
        -    },
        -    "required": [
        -      "type"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Inline barcode — same body as add_barcode (pure vector, no /Alt available in the engine).",
        -    "properties": {
        -      "align": {
        -        "default": "left",
        -        "description": "Horizontal placement inside the content width.",
        -        "enum": [
        -          "left",
        -          "center",
        -          "right"
        -        ],
        -        "type": "string"
        -      },
        -      "data": {
        -        "description": "Raw payload to encode — do NOT URL-encode. For QR/URL pass e.g. \"https://example.com\" verbatim. EAN-13 must be 12 or 13 digits (13th is auto-computed). Code 128 accepts ASCII alphanumerics.",
        -        "maxLength": 4296,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "ecLevel": {
        -        "default": "M",
        -        "description": "QR ONLY. Error correction level (L=7%, M=15%, Q=25%, H=30%). Ignored for code128/ean13/datamatrix/pdf417. Use H for printed media that may get smudged or partially covered (e.g. logo overlay).",
        -        "enum": [
        -          "L",
        -          "M",
        -          "Q",
        -          "H"
        -        ],
        -        "type": "string"
        -      },
        -      "format": {
        -        "description": "Barcode symbology to render.",
        -        "enum": [
        -          "qr",
        -          "code128",
        -          "ean13",
        -          "datamatrix",
        -          "pdf417"
        -        ],
        -        "type": "string"
        -      },
        -      "height": {
        -        "default": 200,
        -        "description": "Barcode height in PDF points (ignored for square symbologies like QR/Data Matrix).",
        -        "maximum": 500,
        -        "minimum": 30,
        -        "type": "number"
        -      },
        -      "type": {
        -        "const": "barcode"
        -      },
        -      "width": {
        -        "default": 200,
        -        "description": "Barcode width in PDF points.",
        -        "maximum": 500,
        -        "minimum": 30,
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "format",
        -      "data"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Vector drawing from an SVG path `d` string or SVG markup. Supported: <path> <rect> (rx/ry) <circle> <ellipse> <line> <polyline> <polygon> and <text>/<tspan> (x, y, font-size, fill, text-anchor, dx/dy); fill / stroke / stroke-width attributes; double-quoted attributes only. NOT supported (silently ignored): transform, <g>, <use>, <image>, <defs>/<clipPath>, gradients, opacity, CSS/style, dash patterns, text word-wrap. No external reference is ever fetched (no XML parser: entities other than &amp; &lt; &gt; &quot; &apos; &nbsp; &#n; are dropped). Pure path operators — PDF/A-safe at every level.",
        -    "properties": {
        -      "align": {
        -        "default": "left",
        -        "description": "Horizontal placement inside the content width.",
        -        "enum": [
        -          "left",
        -          "center",
        -          "right"
        -        ],
        -        "type": "string"
        -      },
        -      "alt": {
        -        "description": "Accessible description (tagged /Figure /Alt). Always provide it for non-decorative content under PDF/A or PDF/UA.",
        -        "maxLength": 500,
        -        "type": "string"
        -      },
        -      "data": {
        -        "description": "Path `d` string or SVG markup (≤ 100 000 characters).",
        -        "maxLength": 100000,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "fill": {
        -        "description": "Hex colour or 'none' (default black).",
        -        "pattern": "^(?:none|#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}))$",
        -        "type": "string"
        -      },
        -      "height": {
        -        "description": "Render height in points (default 200).",
        -        "maximum": 1000,
        -        "minimum": 10,
        -        "type": "number"
        -      },
        -      "stroke": {
        -        "description": "Hex colour or 'none' (default none).",
        -        "pattern": "^(?:none|#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}))$",
        -        "type": "string"
        -      },
        -      "strokeWidth": {
        -        "description": "Stroke width in SVG user units (default 1).",
        -        "maximum": 50,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "type": {
        -        "const": "svg"
        -      },
        -      "viewBox": {
        -        "description": "[minX, minY, width, height] — overrides the viewBox of the markup; required for a bare path string that is not 0-based.",
        -        "items": {
        -          "type": "number"
        -        },
        -        "maxItems": 4,
        -        "minItems": 4,
        -        "type": "array"
        -      },
        -      "width": {
        -        "description": "Render width in points (default 200).",
        -        "maximum": 800,
        -        "minimum": 10,
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "data"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Inline AcroForm field — same body as an add_form field. Under a PDF/A claim the widget appearance font is not embedded (PDFA_UNEMBEDDED_FORM_FONT; strict:true fails the call).",
        -    "properties": {
        -      "checked": {
        -        "description": "Initial checked state for checkbox / radio fields.",
        -        "type": "boolean"
        -      },
        -      "fieldType": {
        -        "description": "Type of form control to render. Radio fields sharing a name form one radio group.",
        -        "enum": [
        -          "text",
        -          "textarea",
        -          "checkbox",
        -          "radio",
        -          "dropdown",
        -          "listbox"
        -        ],
        -        "type": "string"
        -      },
        -      "fontSize": {
        -        "description": "Font size for text rendering inside the field.",
        -        "maximum": 48,
        -        "minimum": 6,
        -        "type": "number"
        -      },
        -      "height": {
        -        "description": "Field height in points (default depends on the type).",
        -        "maximum": 300,
        -        "minimum": 10,
        -        "type": "number"
        -      },
        -      "label": {
        -        "description": "Human-readable label shown above the field.",
        -        "maxLength": 200,
        -        "type": "string"
        -      },
        -      "maxLength": {
        -        "description": "Maximum character length for text/textarea fields.",
        -        "maximum": 32767,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "name": {
        -        "description": "Unique field name used as the PDF annotation identifier (/T).",
        -        "maxLength": 100,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "options": {
        -        "description": "Choices for dropdown, listbox or radio fields.",
        -        "items": {
        -          "maxLength": 200,
        -          "type": "string"
        -        },
        -        "maxItems": 100,
        -        "type": "array"
        -      },
        -      "placeholder": {
        -        "description": "Hint text shown while the field is empty.",
        -        "maxLength": 200,
        -        "type": "string"
        -      },
        -      "readOnly": {
        -        "description": "Prevent editing of this field.",
        -        "type": "boolean"
        -      },
        -      "required": {
        -        "description": "Mark field as required.",
        -        "type": "boolean"
        -      },
        -      "type": {
        -        "const": "formField"
        -      },
        -      "value": {
        -        "description": "Default value pre-filled in the field.",
        -        "maxLength": 2000,
        -        "type": "string"
        -      },
        -      "width": {
        -        "description": "Field width in points (default: full content width).",
        -        "maximum": 500,
        -        "minimum": 10,
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "fieldType",
        -      "name"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "keepWithNext": {
        +        "description": "Keep this heading on the same page as the block that follows. Overrides typography.keepHeadingsWithNext for this block, either way.",
        +        "type": "boolean"
        +      },
        +      "level": {
        +        "enum": [
        +          1,
        +          2,
        +          3
        +        ],
        +        "type": "integer"
        +      },
        +      "text": {
        +        "maxLength": 500,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "heading"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text",
        +      "level"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "align": {
        +        "description": "Text alignment (default left). 'justify' spans every line but the last across the measure; pair it with typography.opticalMargins.",
        +        "enum": [
        +          "left",
        +          "right",
        +          "center",
        +          "justify"
        +        ],
        +        "type": "string"
        +      },
        +      "keepWithNext": {
        +        "description": "Keep this paragraph on the same page as the block that follows (a lead-in line before a table or figure). Default false.",
        +        "type": "boolean"
        +      },
        +      "splittable": {
        +        "description": "Allow / forbid this paragraph breaking across pages, overriding typography.splitParagraphs for this block.",
        +        "type": "boolean"
        +      },
        +      "text": {
        +        "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.",
        +        "maxLength": 50000,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "paragraph"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "items": {
        +        "description": "List items. A string is a leaf; an object { text, items } nests a sub-list (bullets/numbers indent; numbered sub-lists restart at 1).",
        +        "items": {
        +          "oneOf": [
        +            {
        +              "maxLength": 1000,
        +              "minLength": 1,
        +              "type": "string"
        +            },
        +            {
        +              "additionalProperties": false,
        +              "properties": {
        +                "items": {
        +                  "items": {
        +                    "oneOf": [
        +                      {
        +                        "maxLength": 1000,
        +                        "minLength": 1,
        +                        "type": "string"
        +                      },
        +                      {
        +                        "additionalProperties": false,
        +                        "properties": {
        +                          "items": {
        +                            "items": {
        +                              "oneOf": [
        +                                {
        +                                  "maxLength": 1000,
        +                                  "minLength": 1,
        +                                  "type": "string"
        +                                },
        +                                {
        +                                  "additionalProperties": false,
        +                                  "properties": {
        +                                    "items": {
        +                                      "items": {
        +                                        "oneOf": [
        +                                          {
        +                                            "maxLength": 1000,
        +                                            "minLength": 1,
        +                                            "type": "string"
        +                                          },
        +                                          {
        +                                            "additionalProperties": false,
        +                                            "properties": {
        +                                              "items": {
        +                                                "items": {
        +                                                  "oneOf": [
        +                                                    {
        +                                                      "maxLength": 1000,
        +                                                      "minLength": 1,
        +                                                      "type": "string"
        +                                                    },
        +                                                    {
        +                                                      "additionalProperties": false,
        +                                                      "properties": {
        +                                                        "items": {
        +                                                          "items": {
        +                                                            "oneOf": [
        +                                                              {
        +                                                                "maxLength": 1000,
        +                                                                "minLength": 1,
        +                                                                "type": "string"
        +                                                              },
        +                                                              {
        +                                                                "additionalProperties": false,
        +                                                                "properties": {
        +                                                                  "text": {
        +                                                                    "maxLength": 1000,
        +                                                                    "minLength": 1,
        +                                                                    "type": "string"
        +                                                                  }
        +                                                                },
        +                                                                "required": [
        +                                                                  "text"
        +                                                                ],
        +                                                                "type": "object"
        +                                                              }
        +                                                            ]
        +                                                          },
        +                                                          "maxItems": 1000,
        +                                                          "minItems": 1,
        +                                                          "type": "array"
        +                                                        },
        +                                                        "text": {
        +                                                          "maxLength": 1000,
        +                                                          "minLength": 1,
        +                                                          "type": "string"
        +                                                        }
        +                                                      },
        +                                                      "required": [
        +                                                        "text"
        +                                                      ],
        +                                                      "type": "object"
        +                                                    }
        +                                                  ]
        +                                                },
        +                                                "maxItems": 1000,
        +                                                "minItems": 1,
        +                                                "type": "array"
        +                                              },
        +                                              "text": {
        +                                                "maxLength": 1000,
        +                                                "minLength": 1,
        +                                                "type": "string"
        +                                              }
        +                                            },
        +                                            "required": [
        +                                              "text"
        +                                            ],
        +                                            "type": "object"
        +                                          }
        +                                        ]
        +                                      },
        +                                      "maxItems": 1000,
        +                                      "minItems": 1,
        +                                      "type": "array"
        +                                    },
        +                                    "text": {
        +                                      "maxLength": 1000,
        +                                      "minLength": 1,
        +                                      "type": "string"
        +                                    }
        +                                  },
        +                                  "required": [
        +                                    "text"
        +                                  ],
        +                                  "type": "object"
        +                                }
        +                              ]
        +                            },
        +                            "maxItems": 1000,
        +                            "minItems": 1,
        +                            "type": "array"
        +                          },
        +                          "text": {
        +                            "maxLength": 1000,
        +                            "minLength": 1,
        +                            "type": "string"
        +                          }
        +                        },
        +                        "required": [
        +                          "text"
        +                        ],
        +                        "type": "object"
        +                      }
        +                    ]
        +                  },
        +                  "maxItems": 1000,
        +                  "minItems": 1,
        +                  "type": "array"
        +                },
        +                "text": {
        +                  "maxLength": 1000,
        +                  "minLength": 1,
        +                  "type": "string"
        +                }
        +              },
        +              "required": [
        +                "text"
        +              ],
        +              "type": "object"
        +            }
        +          ]
        +        },
        +        "maxItems": 1000,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "style": {
        +        "default": "bullet",
        +        "enum": [
        +          "bullet",
        +          "numbered"
        +        ],
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "list"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "items"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "type": {
        +        "const": "pageBreak"
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "height": {
        +        "maximum": 500,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "type": {
        +        "const": "spacer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "height"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Native vector chart rendered as pure PDF path operators — bar / horizontal-bar / stacked-bar / line / area / scatter / pie / donut (pdfnative 1.7 charts v2: time and log axes, data labels, secondary axis, legends). Same body as add_chart.",
        +    "properties": {
        +      "align": {
        +        "description": "Horizontal alignment within the content width. Default 'left'.",
        +        "enum": [
        +          "left",
        +          "center",
        +          "right"
        +        ],
        +        "type": "string"
        +      },
        +      "altText": {
        +        "description": "Alt text for the tagged-PDF /Figure /Alt. Auto-generated when omitted.",
        +        "maxLength": 500,
        +        "type": "string"
        +      },
        +      "axis": {
        +        "additionalProperties": false,
        +        "description": "Value-axis options (bar/line only).",
        +        "properties": {
        +          "grid": {
        +            "description": "Draw horizontal gridlines.",
        +            "type": "boolean"
        +          },
        +          "scale": {
        +            "description": "Value-axis scale. 'log' requires strictly positive values and is not available for stacked charts.",
        +            "enum": [
        +              "linear",
        +              "log"
        +            ],
        +            "type": "string"
        +          },
        +          "ticks": {
        +            "description": "Target tick count (nice 1/2/5×10ⁿ steps).",
        +            "maximum": 20,
        +            "minimum": 2,
        +            "type": "integer"
        +          },
        +          "yMax": {
        +            "description": "Force the axis maximum (values are clamped to the plot band).",
        +            "type": "number"
        +          },
        +          "yMin": {
        +            "description": "Force the axis minimum (values are clamped to the plot band).",
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "axis2": {
        +        "additionalProperties": false,
        +        "description": "Secondary RIGHT value axis (drawn only when a series sets yAxis:'right').",
        +        "properties": {
        +          "scale": {
        +            "enum": [
        +              "linear",
        +              "log"
        +            ],
        +            "type": "string"
        +          },
        +          "ticks": {
        +            "maximum": 20,
        +            "minimum": 2,
        +            "type": "integer"
        +          },
        +          "yMax": {
        +            "type": "number"
        +          },
        +          "yMin": {
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "categories": {
        +        "description": "Category / slice labels (x-axis). Defaults to 1-based indices when omitted.",
        +        "items": {
        +          "maxLength": 200,
        +          "type": "string"
        +        },
        +        "maxItems": 1000,
        +        "type": "array"
        +      },
        +      "chartType": {
        +        "description": "Chart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'stackedBar'/'stackedBarH'/'line'/'area'/'scatter' support multiple series. 'scatter' requires xValues on every series and a positional xAxis.type ('linear' or 'time').",
        +        "enum": [
        +          "bar",
        +          "barH",
        +          "stackedBar",
        +          "stackedBarH",
        +          "line",
        +          "area",
        +          "scatter",
        +          "pie",
        +          "donut"
        +        ],
        +        "type": "string"
        +      },
        +      "colors": {
        +        "description": "Palette override (per-series for bar/line, per-slice for pie/donut).",
        +        "items": {
        +          "anyOf": [
        +            {
        +              "pattern": "^#?[0-9a-fA-F]{6}$",
        +              "type": "string"
        +            },
        +            {
        +              "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +              "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +              "type": "string"
        +            },
        +            {
        +              "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +              "items": {
        +                "maximum": 100,
        +                "minimum": 0,
        +                "type": "number"
        +              },
        +              "maxItems": 4,
        +              "minItems": 4,
        +              "type": "array"
        +            }
        +          ],
        +          "description": "CSS-style hex colour, e.g. \"#3366cc\"."
        +        },
        +        "maxItems": 50,
        +        "type": "array"
        +      },
        +      "dataLabels": {
        +        "description": "Per-point value labels: true for defaults, or an object to format them.",
        +        "oneOf": [
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "additionalProperties": false,
        +            "properties": {
        +              "decimals": {
        +                "maximum": 6,
        +                "minimum": 0,
        +                "type": "integer"
        +              },
        +              "prefix": {
        +                "maxLength": 16,
        +                "type": "string"
        +              },
        +              "suffix": {
        +                "maxLength": 16,
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          }
        +        ]
        +      },
        +      "height": {
        +        "description": "Plot-area height in points. Default 240.",
        +        "maximum": 2000,
        +        "minimum": 50,
        +        "type": "number"
        +      },
        +      "labelRotation": {
        +        "description": "Rotate category labels counter-clockwise by this many degrees (disables the automatic stride).",
        +        "maximum": 90,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "labelStride": {
        +        "description": "Draw every Nth category label. Default: automatic (measured non-overlap); 1 draws every label.",
        +        "maximum": 1000,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "legend": {
        +        "description": "Legend placement. Defaults to 'bottom' for multi-series/pie, else 'none'.",
        +        "enum": [
        +          "bottom",
        +          "none"
        +        ],
        +        "type": "string"
        +      },
        +      "markers": {
        +        "description": "Draw point markers on line series. Default false.",
        +        "type": "boolean"
        +      },
        +      "series": {
        +        "description": "Data series. Pie/donut charts use exactly one series (each value becomes a slice).",
        +        "items": {
        +          "additionalProperties": false,
        +          "properties": {
        +            "color": {
        +              "anyOf": [
        +                {
        +                  "pattern": "^#?[0-9a-fA-F]{6}$",
        +                  "type": "string"
        +                },
        +                {
        +                  "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +                  "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +                  "type": "string"
        +                },
        +                {
        +                  "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +                  "items": {
        +                    "maximum": 100,
        +                    "minimum": 0,
        +                    "type": "number"
        +                  },
        +                  "maxItems": 4,
        +                  "minItems": 4,
        +                  "type": "array"
        +                }
        +              ],
        +              "description": "CSS-style hex colour, e.g. \"#3366cc\"."
        +            },
        +            "label": {
        +              "description": "Series label (shown in the legend).",
        +              "maxLength": 200,
        +              "minLength": 1,
        +              "type": "string"
        +            },
        +            "values": {
        +              "description": "Numeric values, one per category. Negative values are supported for bar/line.",
        +              "items": {
        +                "type": "number"
        +              },
        +              "maxItems": 1000,
        +              "minItems": 1,
        +              "type": "array"
        +            },
        +            "xValues": {
        +              "description": "Per-point x positions (same length as values) for scatter charts and for line/area charts with xAxis.type 'linear' or 'time'.",
        +              "items": {
        +                "description": "Positional x value: a number (linear axis) or an ISO-8601 date / epoch milliseconds (time axis).",
        +                "maxLength": 64,
        +                "type": [
        +                  "number",
        +                  "string"
        +                ]
        +              },
        +              "maxItems": 1000,
        +              "minItems": 1,
        +              "type": "array"
        +            },
        +            "yAxis": {
        +              "description": "Bind the series to the left (default) or the secondary right value axis (cartesian charts only; configure its range with 'axis2').",
        +              "enum": [
        +                "left",
        +                "right"
        +              ],
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "label",
        +            "values"
        +          ],
        +          "type": "object"
        +        },
        +        "maxItems": 50,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "title": {
        +        "description": "Chart title rendered above the plot.",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "chart"
        +      },
        +      "width": {
        +        "description": "Plot width in points (clamped to content width). Default 460.",
        +        "maximum": 2000,
        +        "minimum": 50,
        +        "type": "number"
        +      },
        +      "xAxis": {
        +        "additionalProperties": false,
        +        "description": "Horizontal axis. 'category' (default) positions points by index; 'linear' / 'time' position them by series xValues (line/area/scatter only). Time ticks are UTC-deterministic.",
        +        "properties": {
        +          "grid": {
        +            "description": "Draw vertical gridlines.",
        +            "type": "boolean"
        +          },
        +          "max": {
        +            "description": "Axis maximum (number, or ISO-8601 / epoch ms for time axes).",
        +            "maxLength": 64,
        +            "type": [
        +              "number",
        +              "string"
        +            ]
        +          },
        +          "min": {
        +            "description": "Axis minimum (number, or ISO-8601 / epoch ms for time axes).",
        +            "maxLength": 64,
        +            "type": [
        +              "number",
        +              "string"
        +            ]
        +          },
        +          "ticks": {
        +            "maximum": 20,
        +            "minimum": 2,
        +            "type": "integer"
        +          },
        +          "type": {
        +            "enum": [
        +              "category",
        +              "linear",
        +              "time"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "chartType",
        +      "series"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Inline smart table — same body as add_table (every row must have exactly as many cells as headers).",
        +    "properties": {
        +      "autoFitColumns": {
        +        "description": "Auto-fit column widths to content. Output bytes then depend on text metrics (not byte-deterministic across content changes).",
        +        "type": "boolean"
        +      },
        +      "caption": {
        +        "description": "Caption rendered above the table (tagged as /Caption under PDF/A).",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "cellBorders": {
        +        "additionalProperties": false,
        +        "description": "Per-cell vector borders (pure strokes, PDF/A-safe). Choose individual sides or `all`.",
        +        "properties": {
        +          "all": {
        +            "description": "Draw all four edges (overrides the individual side flags).",
        +            "type": "boolean"
        +          },
        +          "bottom": {
        +            "type": "boolean"
        +          },
        +          "color": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +                "items": {
        +                  "maximum": 100,
        +                  "minimum": 0,
        +                  "type": "number"
        +                },
        +                "maxItems": 4,
        +                "minItems": 4,
        +                "type": "array"
        +              }
        +            ],
        +            "description": "Stroke colour as a PDF operator string ('0.8 0.8 0.8') or hex. Default light grey."
        +          },
        +          "left": {
        +            "type": "boolean"
        +          },
        +          "right": {
        +            "type": "boolean"
        +          },
        +          "style": {
        +            "description": "Stroke style (default 'solid').",
        +            "enum": [
        +              "solid",
        +              "dashed",
        +              "dotted"
        +            ],
        +            "type": "string"
        +          },
        +          "top": {
        +            "type": "boolean"
        +          },
        +          "width": {
        +            "description": "Stroke width in points (default 0.5).",
        +            "maximum": 10,
        +            "minimum": 0,
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "cellPadding": {
        +        "description": "Horizontal cell padding in points (default 3).",
        +        "maximum": 50,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "cellVAlign": {
        +        "description": "Vertical alignment of cell content.",
        +        "enum": [
        +          "top",
        +          "middle",
        +          "bottom"
        +        ],
        +        "type": "string"
        +      },
        +      "clipCells": {
        +        "description": "Clip cell contents to the column bounds (PDF clip operators). Recommended for PDF/A and visual safety.",
        +        "type": "boolean"
        +      },
        +      "headers": {
        +        "description": "Column header labels. Must have the same length as each row in `rows`.",
        +        "items": {
        +          "maxLength": 200,
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "maxItems": 50,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "minRowHeight": {
        +        "description": "Minimum row height in points (default 12).",
        +        "maximum": 200,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "repeatHeader": {
        +        "description": "Repeat the header row on every continuation page (default true).",
        +        "type": "boolean"
        +      },
        +      "rows": {
        +        "description": "Data rows. Each row is an array of cell strings with the same length as `headers`.",
        +        "items": {
        +          "items": {
        +            "maxLength": 500,
        +            "type": "string"
        +          },
        +          "maxItems": 50,
        +          "minItems": 1,
        +          "type": "array"
        +        },
        +        "maxItems": 5000,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "type": {
        +        "const": "table"
        +      },
        +      "wrap": {
        +        "description": "Cell wrap policy: 'auto' (default) wraps only overflowing cells; 'always' wraps every cell; 'never' truncates.",
        +        "enum": [
        +          "auto",
        +          "always",
        +          "never"
        +        ],
        +        "type": "string"
        +      },
        +      "zebra": {
        +        "description": "Alternate-row light tint (static fill, PDF/A-1b safe).",
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "headers",
        +      "rows"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Inline JPEG/PNG image. Without width/height the pixel size is used as points and clamped to the content width; with one dimension the aspect ratio is kept. The decoded bytes of all image blocks in one call are capped at 24 MiB (a watermark image has its own 8 MiB cap).",
        +    "properties": {
        +      "align": {
        +        "default": "left",
        +        "description": "Horizontal placement inside the content width.",
        +        "enum": [
        +          "left",
        +          "center",
        +          "right"
        +        ],
        +        "type": "string"
        +      },
        +      "alt": {
        +        "description": "Accessible description (tagged /Figure /Alt). Always provide it for non-decorative content under PDF/A or PDF/UA.",
        +        "maxLength": 500,
        +        "type": "string"
        +      },
        +      "height": {
        +        "description": "Render height in points.",
        +        "maximum": 1000,
        +        "minimum": 10,
        +        "type": "number"
        +      },
        +      "imageBase64": {
        +        "description": "Base64 image bytes. JPEG (baseline; 1, 3 or 4 components — CMYK raises PDFA_DEVICE_CMYK_IMAGE under PDF/A) or PNG (8-bit greyscale/RGB, non-interlaced; alpha-channel and palette PNGs are rejected with a remedy). No data: URI.",
        +        "maxLength": 12000000,
        +        "minLength": 4,
        +        "type": "string"
        +      },
        +      "mimeType": {
        +        "description": "MIME type of the image. Must match the actual encoding of imageBase64 (magic bytes are checked).",
        +        "enum": [
        +          "image/jpeg",
        +          "image/png"
        +        ],
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "image"
        +      },
        +      "width": {
        +        "description": "Render width in points.",
        +        "maximum": 800,
        +        "minimum": 10,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "imageBase64",
        +      "mimeType"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Clickable external link (/URI action). Only http:, https: and mailto: URLs are accepted.",
        +    "properties": {
        +      "color": {
        +        "anyOf": [
        +          {
        +            "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$",
        +            "type": "string"
        +          },
        +          {
        +            "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +            "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +            "type": "string"
        +          },
        +          {
        +            "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +            "items": {
        +              "maximum": 100,
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "maxItems": 4,
        +            "minItems": 4,
        +            "type": "array"
        +          }
        +        ],
        +        "description": "Hex colour (#RGB or #RRGGBB)."
        +      },
        +      "fontSize": {
        +        "description": "Default 10.",
        +        "maximum": 48,
        +        "minimum": 6,
        +        "type": "number"
        +      },
        +      "text": {
        +        "maxLength": 500,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "link"
        +      },
        +      "url": {
        +        "description": "http(s):// or mailto: URL.",
        +        "maxLength": 2048,
        +        "minLength": 1,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text",
        +      "url"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Printed table of contents generated from the document's heading blocks (internal /GoTo links with dot leaders). Pairs with outline:'auto' for the bookmark pane.",
        +    "properties": {
        +      "fontSize": {
        +        "description": "Default 10.",
        +        "maximum": 24,
        +        "minimum": 6,
        +        "type": "number"
        +      },
        +      "indent": {
        +        "description": "Points of indent per heading level (default 15).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "maxLevel": {
        +        "description": "Deepest heading level listed (default 3).",
        +        "enum": [
        +          1,
        +          2,
        +          3
        +        ],
        +        "type": "integer"
        +      },
        +      "title": {
        +        "description": "Default 'Table of Contents'.",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "toc"
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Inline barcode — same body as add_barcode (pure vector, no /Alt available in the engine).",
        +    "properties": {
        +      "align": {
        +        "default": "left",
        +        "description": "Horizontal placement inside the content width.",
        +        "enum": [
        +          "left",
        +          "center",
        +          "right"
        +        ],
        +        "type": "string"
        +      },
        +      "data": {
        +        "description": "Raw payload to encode — do NOT URL-encode. For QR/URL pass e.g. \"https://example.com\" verbatim. EAN-13 must be 12 or 13 digits (13th is auto-computed). Code 128 accepts ASCII alphanumerics.",
        +        "maxLength": 4296,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "ecLevel": {
        +        "default": "M",
        +        "description": "QR ONLY. Error correction level (L=7%, M=15%, Q=25%, H=30%). Ignored for code128/ean13/datamatrix/pdf417. Use H for printed media that may get smudged or partially covered (e.g. logo overlay).",
        +        "enum": [
        +          "L",
        +          "M",
        +          "Q",
        +          "H"
        +        ],
        +        "type": "string"
        +      },
        +      "format": {
        +        "description": "Barcode symbology to render.",
        +        "enum": [
        +          "qr",
        +          "code128",
        +          "ean13",
        +          "datamatrix",
        +          "pdf417"
        +        ],
        +        "type": "string"
        +      },
        +      "height": {
        +        "default": 200,
        +        "description": "Barcode height in PDF points (ignored for square symbologies like QR/Data Matrix).",
        +        "maximum": 500,
        +        "minimum": 30,
        +        "type": "number"
        +      },
        +      "type": {
        +        "const": "barcode"
        +      },
        +      "width": {
        +        "default": 200,
        +        "description": "Barcode width in PDF points.",
        +        "maximum": 500,
        +        "minimum": 30,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "format",
        +      "data"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Vector drawing from an SVG path `d` string or SVG markup. Supported: <path> <rect> (rx/ry) <circle> <ellipse> <line> <polyline> <polygon> and <text>/<tspan> (x, y, font-size, fill, text-anchor, dx/dy); fill / stroke / stroke-width attributes; double-quoted attributes only. NOT supported (silently ignored): transform, <g>, <use>, <image>, <defs>/<clipPath>, gradients, opacity, CSS/style, dash patterns, text word-wrap. No external reference is ever fetched (no XML parser: entities other than &amp; &lt; &gt; &quot; &apos; &nbsp; &#n; are dropped). Pure path operators — PDF/A-safe at every level.",
        +    "properties": {
        +      "align": {
        +        "default": "left",
        +        "description": "Horizontal placement inside the content width.",
        +        "enum": [
        +          "left",
        +          "center",
        +          "right"
        +        ],
        +        "type": "string"
        +      },
        +      "alt": {
        +        "description": "Accessible description (tagged /Figure /Alt). Always provide it for non-decorative content under PDF/A or PDF/UA.",
        +        "maxLength": 500,
        +        "type": "string"
        +      },
        +      "data": {
        +        "description": "Path `d` string or SVG markup (≤ 100 000 characters).",
        +        "maxLength": 100000,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "fill": {
        +        "anyOf": [
        +          {
        +            "pattern": "^(?:none|#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}))$",
        +            "type": "string"
        +          },
        +          {
        +            "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +            "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +            "type": "string"
        +          },
        +          {
        +            "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +            "items": {
        +              "maximum": 100,
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "maxItems": 4,
        +            "minItems": 4,
        +            "type": "array"
        +          }
        +        ],
        +        "description": "Hex colour or 'none' (default black)."
        +      },
        +      "height": {
        +        "description": "Render height in points (default 200).",
        +        "maximum": 1000,
        +        "minimum": 10,
        +        "type": "number"
        +      },
        +      "stroke": {
        +        "anyOf": [
        +          {
        +            "pattern": "^(?:none|#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}))$",
        +            "type": "string"
        +          },
        +          {
        +            "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +            "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +            "type": "string"
        +          },
        +          {
        +            "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +            "items": {
        +              "maximum": 100,
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "maxItems": 4,
        +            "minItems": 4,
        +            "type": "array"
        +          }
        +        ],
        +        "description": "Hex colour or 'none' (default none)."
        +      },
        +      "strokeWidth": {
        +        "description": "Stroke width in SVG user units (default 1).",
        +        "maximum": 50,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "type": {
        +        "const": "svg"
        +      },
        +      "viewBox": {
        +        "description": "[minX, minY, width, height] — overrides the viewBox of the markup; required for a bare path string that is not 0-based.",
        +        "items": {
        +          "type": "number"
        +        },
        +        "maxItems": 4,
        +        "minItems": 4,
        +        "type": "array"
        +      },
        +      "width": {
        +        "description": "Render width in points (default 200).",
        +        "maximum": 800,
        +        "minimum": 10,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "data"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Inline AcroForm field — same body as an add_form field. Under a PDF/A claim pass embedFonts:true so the field font is embedded too (PDFA_UNEMBEDDED_FORM_FONT otherwise; strict:true then fails the call).",
        +    "properties": {
        +      "checked": {
        +        "description": "Initial checked state for checkbox / radio fields.",
        +        "type": "boolean"
        +      },
        +      "fieldType": {
        +        "description": "Type of form control to render. Radio fields sharing a name form one radio group.",
        +        "enum": [
        +          "text",
        +          "textarea",
        +          "checkbox",
        +          "radio",
        +          "dropdown",
        +          "listbox"
        +        ],
        +        "type": "string"
        +      },
        +      "fontSize": {
        +        "description": "Font size for text rendering inside the field.",
        +        "maximum": 48,
        +        "minimum": 6,
        +        "type": "number"
        +      },
        +      "height": {
        +        "description": "Field height in points (default depends on the type).",
        +        "maximum": 300,
        +        "minimum": 10,
        +        "type": "number"
        +      },
        +      "label": {
        +        "description": "Human-readable label shown above the field.",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "maxLength": {
        +        "description": "Maximum character length for text/textarea fields.",
        +        "maximum": 32767,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "name": {
        +        "description": "Unique field name used as the PDF annotation identifier (/T).",
        +        "maxLength": 100,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "options": {
        +        "description": "Choices for dropdown, listbox or radio fields.",
        +        "items": {
        +          "maxLength": 200,
        +          "type": "string"
        +        },
        +        "maxItems": 100,
        +        "type": "array"
        +      },
        +      "placeholder": {
        +        "description": "Hint text shown while the field is empty.",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "readOnly": {
        +        "description": "Prevent editing of this field.",
        +        "type": "boolean"
        +      },
        +      "required": {
        +        "description": "Mark field as required.",
        +        "type": "boolean"
        +      },
        +      "type": {
        +        "const": "formField"
        +      },
        +      "value": {
        +        "description": "Pre-filled value. The key is 'value' (there is no defaultValue).",
        +        "maxLength": 2000,
        +        "type": "string"
        +      },
        +      "width": {
        +        "description": "Field width in points (default: full content width).",
        +        "maximum": 500,
        +        "minimum": 10,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "fieldType",
        +      "name"
        +    ],
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / creationDate / description
        Previous value: -"ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs."New value: +"ISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs."
      • changedInput schema / properties / embedFonts / description
        Previous value: -"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB."New value: +"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB."
      • changedInput schema / properties / footerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / footerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / footerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / footerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / footerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / footerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / footerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / headerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / headerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / headerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / headerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / headerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / includeDiagnostics / description
        Previous value: -"Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty)."New value: +"Return the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty)."
      • changedInput schema / properties / outline / oneOf
        Previous value: -[
        -  {
        -    "enum": [
        -      "auto"
        -    ],
        -    "type": "string"
        -  },
        -  {
        -    "items": {
        -      "additionalProperties": false,
        -      "properties": {
        -        "bold": {
        -          "type": "boolean"
        -        },
        -        "children": {
        -          "items": {
        -            "additionalProperties": false,
        -            "properties": {
        -              "bold": {
        -                "type": "boolean"
        -              },
        -              "children": {
        -                "items": {
        -                  "additionalProperties": false,
        -                  "properties": {
        -                    "bold": {
        -                      "type": "boolean"
        -                    },
        -                    "children": {
        -                      "items": {
        -                        "additionalProperties": false,
        -                        "properties": {
        -                          "bold": {
        -                            "type": "boolean"
        -                          },
        -                          "children": {
        -                            "items": {
        -                              "additionalProperties": false,
        -                              "properties": {
        -                                "bold": {
        -                                  "type": "boolean"
        -                                },
        -                                "children": {
        -                                  "items": {
        -                                    "additionalProperties": false,
        -                                    "properties": {
        -                                      "bold": {
        -                                        "type": "boolean"
        -                                      },
        -                                      "color": {
        -                                        "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').",
        -                                        "type": "string"
        -                                      },
        -                                      "italic": {
        -                                        "type": "boolean"
        -                                      },
        -                                      "open": {
        -                                        "description": "Initial expansion state (default true). false renders the branch collapsed.",
        -                                        "type": "boolean"
        -                                      },
        -                                      "pageIndex": {
        -                                        "description": "0-based destination page index.",
        -                                        "minimum": 0,
        -                                        "type": "integer"
        -                                      },
        -                                      "title": {
        -                                        "description": "Bookmark label.",
        -                                        "maxLength": 500,
        -                                        "minLength": 1,
        -                                        "type": "string"
        -                                      },
        -                                      "y": {
        -                                        "description": "Destination Y coordinate in points (default: top of page).",
        -                                        "type": "number"
        -                                      }
        -                                    },
        -                                    "required": [
        -                                      "title",
        -                                      "pageIndex"
        -                                    ],
        -                                    "type": "object"
        -                                  },
        -                                  "maxItems": 1000,
        -                                  "type": "array"
        -                                },
        -                                "color": {
        -                                  "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').",
        -                                  "type": "string"
        -                                },
        -                                "italic": {
        -                                  "type": "boolean"
        -                                },
        -                                "open": {
        -                                  "description": "Initial expansion state (default true). false renders the branch collapsed.",
        -                                  "type": "boolean"
        -                                },
        -                                "pageIndex": {
        -                                  "description": "0-based destination page index.",
        -                                  "minimum": 0,
        -                                  "type": "integer"
        -                                },
        -                                "title": {
        -                                  "description": "Bookmark label.",
        -                                  "maxLength": 500,
        -                                  "minLength": 1,
        -                                  "type": "string"
        -                                },
        -                                "y": {
        -                                  "description": "Destination Y coordinate in points (default: top of page).",
        -                                  "type": "number"
        -                                }
        -                              },
        -                              "required": [
        -                                "title",
        -                                "pageIndex"
        -                              ],
        -                              "type": "object"
        -                            },
        -                            "maxItems": 1000,
        -                            "type": "array"
        -                          },
        -                          "color": {
        -                            "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').",
        -                            "type": "string"
        -                          },
        -                          "italic": {
        -                            "type": "boolean"
        -                          },
        -                          "open": {
        -                            "description": "Initial expansion state (default true). false renders the branch collapsed.",
        -                            "type": "boolean"
        -                          },
        -                          "pageIndex": {
        -                            "description": "0-based destination page index.",
        -                            "minimum": 0,
        -                            "type": "integer"
        -                          },
        -                          "title": {
        -                            "description": "Bookmark label.",
        -                            "maxLength": 500,
        -                            "minLength": 1,
        -                            "type": "string"
        -                          },
        -                          "y": {
        -                            "description": "Destination Y coordinate in points (default: top of page).",
        -                            "type": "number"
        -                          }
        -                        },
        -                        "required": [
        -                          "title",
        -                          "pageIndex"
        -                        ],
        -                        "type": "object"
        -                      },
        -                      "maxItems": 1000,
        -                      "type": "array"
        -                    },
        -                    "color": {
        -                      "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').",
        -                      "type": "string"
        -                    },
        -                    "italic": {
        -                      "type": "boolean"
        -                    },
        -                    "open": {
        -                      "description": "Initial expansion state (default true). false renders the branch collapsed.",
        -                      "type": "boolean"
        -                    },
        -                    "pageIndex": {
        -                      "description": "0-based destination page index.",
        -                      "minimum": 0,
        -                      "type": "integer"
        -                    },
        -                    "title": {
        -                      "description": "Bookmark label.",
        -                      "maxLength": 500,
        -                      "minLength": 1,
        -                      "type": "string"
        -                    },
        -                    "y": {
        -                      "description": "Destination Y coordinate in points (default: top of page).",
        -                      "type": "number"
        -                    }
        -                  },
        -                  "required": [
        -                    "title",
        -                    "pageIndex"
        -                  ],
        -                  "type": "object"
        -                },
        -                "maxItems": 1000,
        -                "type": "array"
        -              },
        -              "color": {
        -                "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').",
        -                "type": "string"
        -              },
        -              "italic": {
        -                "type": "boolean"
        -              },
        -              "open": {
        -                "description": "Initial expansion state (default true). false renders the branch collapsed.",
        -                "type": "boolean"
        -              },
        -              "pageIndex": {
        -                "description": "0-based destination page index.",
        -                "minimum": 0,
        -                "type": "integer"
        -              },
        -              "title": {
        -                "description": "Bookmark label.",
        -                "maxLength": 500,
        -                "minLength": 1,
        -                "type": "string"
        -              },
        -              "y": {
        -                "description": "Destination Y coordinate in points (default: top of page).",
        -                "type": "number"
        -              }
        -            },
        -            "required": [
        -              "title",
        -              "pageIndex"
        -            ],
        -            "type": "object"
        -          },
        -          "maxItems": 1000,
        -          "type": "array"
        -        },
        -        "color": {
        -          "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').",
        -          "type": "string"
        -        },
        -        "italic": {
        -          "type": "boolean"
        -        },
        -        "open": {
        -          "description": "Initial expansion state (default true). false renders the branch collapsed.",
        -          "type": "boolean"
        -        },
        -        "pageIndex": {
        -          "description": "0-based destination page index.",
        -          "minimum": 0,
        -          "type": "integer"
        -        },
        -        "title": {
        -          "description": "Bookmark label.",
        -          "maxLength": 500,
        -          "minLength": 1,
        -          "type": "string"
        -        },
        -        "y": {
        -          "description": "Destination Y coordinate in points (default: top of page).",
        -          "type": "number"
        -        }
        -      },
        -      "required": [
        -        "title",
        -        "pageIndex"
        -      ],
        -      "type": "object"
        -    },
        -    "maxItems": 1000,
        -    "minItems": 1,
        -    "type": "array"
        -  }
        -]New value: +[
        +  {
        +    "enum": [
        +      "auto"
        +    ],
        +    "type": "string"
        +  },
        +  {
        +    "items": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "bold": {
        +          "type": "boolean"
        +        },
        +        "children": {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "bold": {
        +                "type": "boolean"
        +              },
        +              "children": {
        +                "items": {
        +                  "additionalProperties": false,
        +                  "properties": {
        +                    "bold": {
        +                      "type": "boolean"
        +                    },
        +                    "children": {
        +                      "items": {
        +                        "additionalProperties": false,
        +                        "properties": {
        +                          "bold": {
        +                            "type": "boolean"
        +                          },
        +                          "children": {
        +                            "items": {
        +                              "additionalProperties": false,
        +                              "properties": {
        +                                "bold": {
        +                                  "type": "boolean"
        +                                },
        +                                "children": {
        +                                  "items": {
        +                                    "additionalProperties": false,
        +                                    "properties": {
        +                                      "bold": {
        +                                        "type": "boolean"
        +                                      },
        +                                      "color": {
        +                                        "anyOf": [
        +                                          {
        +                                            "type": "string"
        +                                          },
        +                                          {
        +                                            "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +                                            "items": {
        +                                              "maximum": 100,
        +                                              "minimum": 0,
        +                                              "type": "number"
        +                                            },
        +                                            "maxItems": 4,
        +                                            "minItems": 4,
        +                                            "type": "array"
        +                                          }
        +                                        ],
        +                                        "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1'). An outline label is RGB by definition (/C): a CMYK value is converted for on-screen display."
        +                                      },
        +                                      "italic": {
        +                                        "type": "boolean"
        +                                      },
        +                                      "open": {
        +                                        "description": "Initial expansion state (default true). false renders the branch collapsed.",
        +                                        "type": "boolean"
        +                                      },
        +                                      "pageIndex": {
        +                                        "description": "0-based destination page index.",
        +                                        "minimum": 0,
        +                                        "type": "integer"
        +                                      },
        +                                      "title": {
        +                                        "description": "Bookmark label.",
        +                                        "maxLength": 500,
        +                                        "minLength": 1,
        +                                        "type": "string"
        +                                      },
        +                                      "y": {
        +                                        "description": "Destination Y coordinate in points (default: top of page).",
        +                                        "type": "number"
        +                                      }
        +                                    },
        +                                    "required": [
        +                                      "title",
        +                                      "pageIndex"
        +                                    ],
        +                                    "type": "object"
        +                                  },
        +                                  "maxItems": 1000,
        +                                  "type": "array"
        +                                },
        +                                "color": {
        +                                  "anyOf": [
        +                                    {
        +                                      "type": "string"
        +                                    },
        +                                    {
        +                                      "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +                                      "items": {
        +                                        "maximum": 100,
        +                                        "minimum": 0,
        +                                        "type": "number"
        +                                      },
        +                                      "maxItems": 4,
        +                                      "minItems": 4,
        +                                      "type": "array"
        +                                    }
        +                                  ],
        +                                  "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1'). An outline label is RGB by definition (/C): a CMYK value is converted for on-screen display."
        +                                },
        +                                "italic": {
        +                                  "type": "boolean"
        +                                },
        +                                "open": {
        +                                  "description": "Initial expansion state (default true). false renders the branch collapsed.",
        +                                  "type": "boolean"
        +                                },
        +                                "pageIndex": {
        +                                  "description": "0-based destination page index.",
        +                                  "minimum": 0,
        +                                  "type": "integer"
        +                                },
        +                                "title": {
        +                                  "description": "Bookmark label.",
        +                                  "maxLength": 500,
        +                                  "minLength": 1,
        +                                  "type": "string"
        +                                },
        +                                "y": {
        +                                  "description": "Destination Y coordinate in points (default: top of page).",
        +                                  "type": "number"
        +                                }
        +                              },
        +                              "required": [
        +                                "title",
        +                                "pageIndex"
        +                              ],
        +                              "type": "object"
        +                            },
        +                            "maxItems": 1000,
        +                            "type": "array"
        +                          },
        +                          "color": {
        +                            "anyOf": [
        +                              {
        +                                "type": "string"
        +                              },
        +                              {
        +                                "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +                                "items": {
        +                                  "maximum": 100,
        +                                  "minimum": 0,
        +                                  "type": "number"
        +                                },
        +                                "maxItems": 4,
        +                                "minItems": 4,
        +                                "type": "array"
        +                              }
        +                            ],
        +                            "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1'). An outline label is RGB by definition (/C): a CMYK value is converted for on-screen display."
        +                          },
        +                          "italic": {
        +                            "type": "boolean"
        +                          },
        +                          "open": {
        +                            "description": "Initial expansion state (default true). false renders the branch collapsed.",
        +                            "type": "boolean"
        +                          },
        +                          "pageIndex": {
        +                            "description": "0-based destination page index.",
        +                            "minimum": 0,
        +                            "type": "integer"
        +                          },
        +                          "title": {
        +                            "description": "Bookmark label.",
        +                            "maxLength": 500,
        +                            "minLength": 1,
        +                            "type": "string"
        +                          },
        +                          "y": {
        +                            "description": "Destination Y coordinate in points (default: top of page).",
        +                            "type": "number"
        +                          }
        +                        },
        +                        "required": [
        +                          "title",
        +                          "pageIndex"
        +                        ],
        +                        "type": "object"
        +                      },
        +                      "maxItems": 1000,
        +                      "type": "array"
        +                    },
        +                    "color": {
        +                      "anyOf": [
        +                        {
        +                          "type": "string"
        +                        },
        +                        {
        +                          "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +                          "items": {
        +                            "maximum": 100,
        +                            "minimum": 0,
        +                            "type": "number"
        +                          },
        +                          "maxItems": 4,
        +                          "minItems": 4,
        +                          "type": "array"
        +                        }
        +                      ],
        +                      "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1'). An outline label is RGB by definition (/C): a CMYK value is converted for on-screen display."
        +                    },
        +                    "italic": {
        +                      "type": "boolean"
        +                    },
        +                    "open": {
        +                      "description": "Initial expansion state (default true). false renders the branch collapsed.",
        +                      "type": "boolean"
        +                    },
        +                    "pageIndex": {
        +                      "description": "0-based destination page index.",
        +                      "minimum": 0,
        +                      "type": "integer"
        +                    },
        +                    "title": {
        +                      "description": "Bookmark label.",
        +                      "maxLength": 500,
        +                      "minLength": 1,
        +                      "type": "string"
        +                    },
        +                    "y": {
        +                      "description": "Destination Y coordinate in points (default: top of page).",
        +                      "type": "number"
        +                    }
        +                  },
        +                  "required": [
        +                    "title",
        +                    "pageIndex"
        +                  ],
        +                  "type": "object"
        +                },
        +                "maxItems": 1000,
        +                "type": "array"
        +              },
        +              "color": {
        +                "anyOf": [
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +                    "items": {
        +                      "maximum": 100,
        +                      "minimum": 0,
        +                      "type": "number"
        +                    },
        +                    "maxItems": 4,
        +                    "minItems": 4,
        +                    "type": "array"
        +                  }
        +                ],
        +                "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1'). An outline label is RGB by definition (/C): a CMYK value is converted for on-screen display."
        +              },
        +              "italic": {
        +                "type": "boolean"
        +              },
        +              "open": {
        +                "description": "Initial expansion state (default true). false renders the branch collapsed.",
        +                "type": "boolean"
        +              },
        +              "pageIndex": {
        +                "description": "0-based destination page index.",
        +                "minimum": 0,
        +                "type": "integer"
        +              },
        +              "title": {
        +                "description": "Bookmark label.",
        +                "maxLength": 500,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "y": {
        +                "description": "Destination Y coordinate in points (default: top of page).",
        +                "type": "number"
        +              }
        +            },
        +            "required": [
        +              "title",
        +              "pageIndex"
        +            ],
        +            "type": "object"
        +          },
        +          "maxItems": 1000,
        +          "type": "array"
        +        },
        +        "color": {
        +          "anyOf": [
        +            {
        +              "type": "string"
        +            },
        +            {
        +              "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +              "items": {
        +                "maximum": 100,
        +                "minimum": 0,
        +                "type": "number"
        +              },
        +              "maxItems": 4,
        +              "minItems": 4,
        +              "type": "array"
        +            }
        +          ],
        +          "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1'). An outline label is RGB by definition (/C): a CMYK value is converted for on-screen display."
        +        },
        +        "italic": {
        +          "type": "boolean"
        +        },
        +        "open": {
        +          "description": "Initial expansion state (default true). false renders the branch collapsed.",
        +          "type": "boolean"
        +        },
        +        "pageIndex": {
        +          "description": "0-based destination page index.",
        +          "minimum": 0,
        +          "type": "integer"
        +        },
        +        "title": {
        +          "description": "Bookmark label.",
        +          "maxLength": 500,
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "y": {
        +          "description": "Destination Y coordinate in points (default: top of page).",
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "title",
        +        "pageIndex"
        +      ],
        +      "type": "object"
        +    },
        +    "maxItems": 1000,
        +    "minItems": 1,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / outputIntent / description
        Previous value: -"Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected)."New value: +"Custom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space."
      • changedInput schema / properties / outputIntent / properties / iccProfileBase64 / description
        Previous value: -"ICC profile bytes, base64 (RGB, ≤ 8 MiB)."New value: +"ICC profile bytes, base64 (RGB, CMYK or Gray; ≤ 8 MiB)."
      • addedInput schema / properties / pdfx
        Added value: +{
        +  "description": "PDF/X-4 print exchange (ISO 15930-7). REQUIRES outputIntent with the printer's ICC profile (device class 'prtr'; CMYK or Gray — none is bundled); needs embedFonts:true for a conformant file (PDFX_NO_FONT_ENTRIES otherwise, strict:true refuses). Exclusive with pdfA and encrypt; metadata.trapped must be 'True' or 'False'; TrimBox or ArtBox, not both. Links and form fields are reported (PDFX_ANNOTATIONS). Check with validate_pdf standard:'pdf-x-4'. See the print_ready prompt.",
        +  "enum": [
        +    "pdfx4"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / print / properties / marks / oneOf
        Previous value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "crop": {
        -        "description": "Corner crop (trim) marks. Default true.",
        -        "type": "boolean"
        -      },
        -      "length": {
        -        "description": "Mark length in points. Default 14.",
        -        "maximum": 100,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "offset": {
        -        "description": "Gap between TrimBox and marks in points. Default 5.",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "registration": {
        -        "description": "Edge-midpoint registration targets. Default true.",
        -        "type": "boolean"
        -      },
        -      "weight": {
        -        "description": "Stroke width in points. Default 0.25.",
        -        "maximum": 5,
        -        "minimum": 0.05,
        -        "type": "number"
        -      }
        -    },
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "colourBars": {
        +        "anyOf": [
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "additionalProperties": false,
        +            "properties": {
        +              "size": {
        +                "description": "Patch size in points. Default 12.",
        +                "maximum": 72,
        +                "minimum": 4,
        +                "type": "number"
        +              },
        +              "tints": {
        +                "description": "Add the four 50 % tint patches. Default true.",
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          }
        +        ],
        +        "description": "Colour control strip in the bleed (C M Y K solids + their 50 % tints): true for defaults. Off by default; needs a bleed of about 5 mm (14.17 pt) and is skipped when the strip would not fit."
        +      },
        +      "crop": {
        +        "description": "Corner crop (trim) marks. Default true.",
        +        "type": "boolean"
        +      },
        +      "length": {
        +        "description": "Mark length in points. Default 14.",
        +        "maximum": 100,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "offset": {
        +        "description": "Gap between TrimBox and marks in points. Default 5.",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "registration": {
        +        "description": "Edge-midpoint registration targets. Default true.",
        +        "type": "boolean"
        +      },
        +      "weight": {
        +        "description": "Stroke width in points. Default 0.25.",
        +        "maximum": 5,
        +        "minimum": 0.05,
        +        "type": "number"
        +      }
        +    },
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / strict / description
        Previous value: -"Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true."New value: +"Fail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true."
      • addedInput schema / properties / typography
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Fine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.",
        +  "properties": {
        +    "bindShortWords": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "maxLength": {
        +              "maximum": 3,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "words": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never end a line on a short word: up to maxLength letters (default 1), or exactly the listed words."
        +    },
        +    "fontFeatures": {
        +      "description": "OpenType features, later wins. tnum / lnum are no-ops on Noto Sans (TYPOGRAPHY_FEATURE_INEFFECTIVE).",
        +      "items": {
        +        "enum": [
        +          "tnum",
        +          "pnum",
        +          "lnum",
        +          "onum",
        +          "zero",
        +          "ordn",
        +          "sups",
        +          "subs",
        +          "smcp",
        +          "c2sc",
        +          "case"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 11,
        +      "type": "array",
        +      "uniqueItems": true
        +    },
        +    "hyphenationLanguage": {
        +      "description": "BCP 47 tag; no effect here (no hyphenation provider installed).",
        +      "maxLength": 35,
        +      "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
        +      "type": "string"
        +    },
        +    "keepHeadingsWithNext": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "minLines": {
        +              "maximum": 10,
        +              "minimum": 1,
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never strand a heading at a page foot. true = { minLines: 2 }."
        +    },
        +    "kerning": {
        +      "description": "Pair kerning (GPOS).",
        +      "type": "boolean"
        +    },
        +    "metrics": {
        +      "description": "Base-14 text: 'exact' uses the AFM widths (different wraps). Default 'approximate'.",
        +      "enum": [
        +        "approximate",
        +        "exact"
        +      ],
        +      "type": "string"
        +    },
        +    "opticalMargins": {
        +      "description": "Hang punctuation into the margin of align:'justify' text.",
        +      "type": "boolean"
        +    },
        +    "orphans": {
        +      "description": "Min lines left at a page foot (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "punctuationSpacing": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "fr",
        +            "fr-CA"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "char": {
        +                "maxLength": 2,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "side": {
        +                "enum": [
        +                  "before",
        +                  "after"
        +                ],
        +                "type": "string"
        +              },
        +              "space": {
        +                "description": "U+00A0 / U+202F (narrow needs embedFonts).",
        +                "enum": [
        +                  "nbsp",
        +                  "narrow"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "char",
        +              "side",
        +              "space"
        +            ],
        +            "type": "object"
        +          },
        +          "maxItems": 32,
        +          "type": "array"
        +        }
        +      ],
        +      "description": "No-break spaces next to punctuation (existing spaces only). 'fr': narrow before ; ! ?, no-break before ':' and inside « ». 'fr-CA': ':' and « » only. Or explicit rules."
        +    },
        +    "splitParagraphs": {
        +      "description": "Paragraphs may break across pages at a line boundary (default: atomic).",
        +      "type": "boolean"
        +    },
        +    "unitBinding": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "units": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "No-break space between a number and its unit ('150 €', '12 kg'); units replaces the built-in list."
        +    },
        +    "widows": {
        +      "description": "Min lines carried over (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / watermark / properties / color / anyOf
        Added value: +[
        +  {
        +    "items": {
        +      "maximum": 1,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 3,
        +    "minItems": 3,
        +    "type": "array"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / watermark / properties / color / description
        Previous value: -"Text RGB colour as a [r, g, b] triple in the 0.0–1.0 range. Default light gray [0.75, 0.75, 0.75]."New value: +"Text colour. RGB as a [r, g, b] triple in the 0.0–1.0 range; default light gray [0.75, 0.75, 0.75]."
      • removedInput schema / properties / watermark / properties / color / items
        Removed value: -{
        -  "maximum": 1,
        -  "minimum": 0,
        -  "type": "number"
        -}
      • removedInput schema / properties / watermark / properties / color / maxItems
        Removed value: -3
      • removedInput schema / properties / watermark / properties / color / minItems
        Removed value: -3
      • removedInput schema / properties / watermark / properties / color / type
        Removed value: -"array"
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedinspect_layout17 fields changed
      • changedInput schema / properties / blocks / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "level": {
        -        "enum": [
        -          1,
        -          2,
        -          3
        -        ],
        -        "type": "integer"
        -      },
        -      "text": {
        -        "maxLength": 500,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "heading"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text",
        -      "level"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "text": {
        -        "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.",
        -        "maxLength": 50000,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "paragraph"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "items": {
        -        "description": "List items. A string is a leaf; an object { text, items } nests a sub-list (bullets/numbers indent; numbered sub-lists restart at 1).",
        -        "items": {
        -          "oneOf": [
        -            {
        -              "maxLength": 1000,
        -              "minLength": 1,
        -              "type": "string"
        -            },
        -            {
        -              "additionalProperties": false,
        -              "properties": {
        -                "items": {
        -                  "items": {
        -                    "oneOf": [
        -                      {
        -                        "maxLength": 1000,
        -                        "minLength": 1,
        -                        "type": "string"
        -                      },
        -                      {
        -                        "additionalProperties": false,
        -                        "properties": {
        -                          "items": {
        -                            "items": {
        -                              "oneOf": [
        -                                {
        -                                  "maxLength": 1000,
        -                                  "minLength": 1,
        -                                  "type": "string"
        -                                },
        -                                {
        -                                  "additionalProperties": false,
        -                                  "properties": {
        -                                    "items": {
        -                                      "items": {
        -                                        "oneOf": [
        -                                          {
        -                                            "maxLength": 1000,
        -                                            "minLength": 1,
        -                                            "type": "string"
        -                                          },
        -                                          {
        -                                            "additionalProperties": false,
        -                                            "properties": {
        -                                              "items": {
        -                                                "items": {
        -                                                  "oneOf": [
        -                                                    {
        -                                                      "maxLength": 1000,
        -                                                      "minLength": 1,
        -                                                      "type": "string"
        -                                                    },
        -                                                    {
        -                                                      "additionalProperties": false,
        -                                                      "properties": {
        -                                                        "items": {
        -                                                          "items": {
        -                                                            "oneOf": [
        -                                                              {
        -                                                                "maxLength": 1000,
        -                                                                "minLength": 1,
        -                                                                "type": "string"
        -                                                              },
        -                                                              {
        -                                                                "additionalProperties": false,
        -                                                                "properties": {
        -                                                                  "text": {
        -                                                                    "maxLength": 1000,
        -                                                                    "minLength": 1,
        -                                                                    "type": "string"
        -                                                                  }
        -                                                                },
        -                                                                "required": [
        -                                                                  "text"
        -                                                                ],
        -                                                                "type": "object"
        -                                                              }
        -                                                            ]
        -                                                          },
        -                                                          "maxItems": 1000,
        -                                                          "minItems": 1,
        -                                                          "type": "array"
        -                                                        },
        -                                                        "text": {
        -                                                          "maxLength": 1000,
        -                                                          "minLength": 1,
        -                                                          "type": "string"
        -                                                        }
        -                                                      },
        -                                                      "required": [
        -                                                        "text"
        -                                                      ],
        -                                                      "type": "object"
        -                                                    }
        -                                                  ]
        -                                                },
        -                                                "maxItems": 1000,
        -                                                "minItems": 1,
        -                                                "type": "array"
        -                                              },
        -                                              "text": {
        -                                                "maxLength": 1000,
        -                                                "minLength": 1,
        -                                                "type": "string"
        -                                              }
        -                                            },
        -                                            "required": [
        -                                              "text"
        -                                            ],
        -                                            "type": "object"
        -                                          }
        -                                        ]
        -                                      },
        -                                      "maxItems": 1000,
        -                                      "minItems": 1,
        -                                      "type": "array"
        -                                    },
        -                                    "text": {
        -                                      "maxLength": 1000,
        -                                      "minLength": 1,
        -                                      "type": "string"
        -                                    }
        -                                  },
        -                                  "required": [
        -                                    "text"
        -                                  ],
        -                                  "type": "object"
        -                                }
        -                              ]
        -                            },
        -                            "maxItems": 1000,
        -                            "minItems": 1,
        -                            "type": "array"
        -                          },
        -                          "text": {
        -                            "maxLength": 1000,
        -                            "minLength": 1,
        -                            "type": "string"
        -                          }
        -                        },
        -                        "required": [
        -                          "text"
        -                        ],
        -                        "type": "object"
        -                      }
        -                    ]
        -                  },
        -                  "maxItems": 1000,
        -                  "minItems": 1,
        -                  "type": "array"
        -                },
        -                "text": {
        -                  "maxLength": 1000,
        -                  "minLength": 1,
        -                  "type": "string"
        -                }
        -              },
        -              "required": [
        -                "text"
        -              ],
        -              "type": "object"
        -            }
        -          ]
        -        },
        -        "maxItems": 1000,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "style": {
        -        "default": "bullet",
        -        "enum": [
        -          "bullet",
        -          "numbered"
        -        ],
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "list"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "items"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "type": {
        -        "const": "pageBreak"
        -      }
        -    },
        -    "required": [
        -      "type"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "height": {
        -        "maximum": 500,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "type": {
        -        "const": "spacer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "height"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Native vector chart rendered as pure PDF path operators — bar / horizontal-bar / stacked-bar / line / area / scatter / pie / donut (pdfnative 1.7 charts v2: time and log axes, data labels, secondary axis, legends). Same body as add_chart.",
        -    "properties": {
        -      "align": {
        -        "description": "Horizontal alignment within the content width. Default 'left'.",
        -        "enum": [
        -          "left",
        -          "center",
        -          "right"
        -        ],
        -        "type": "string"
        -      },
        -      "altText": {
        -        "description": "Alt text for the tagged-PDF /Figure /Alt. Auto-generated when omitted.",
        -        "maxLength": 500,
        -        "type": "string"
        -      },
        -      "axis": {
        -        "additionalProperties": false,
        -        "description": "Value-axis options (bar/line only).",
        -        "properties": {
        -          "grid": {
        -            "description": "Draw horizontal gridlines.",
        -            "type": "boolean"
        -          },
        -          "scale": {
        -            "description": "Value-axis scale. 'log' requires strictly positive values and is not available for stacked charts.",
        -            "enum": [
        -              "linear",
        -              "log"
        -            ],
        -            "type": "string"
        -          },
        -          "ticks": {
        -            "description": "Target tick count (nice 1/2/5×10ⁿ steps).",
        -            "maximum": 20,
        -            "minimum": 2,
        -            "type": "integer"
        -          },
        -          "yMax": {
        -            "description": "Force the axis maximum (values are clamped to the plot band).",
        -            "type": "number"
        -          },
        -          "yMin": {
        -            "description": "Force the axis minimum (values are clamped to the plot band).",
        -            "type": "number"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "axis2": {
        -        "additionalProperties": false,
        -        "description": "Secondary RIGHT value axis (drawn only when a series sets yAxis:'right').",
        -        "properties": {
        -          "scale": {
        -            "enum": [
        -              "linear",
        -              "log"
        -            ],
        -            "type": "string"
        -          },
        -          "ticks": {
        -            "maximum": 20,
        -            "minimum": 2,
        -            "type": "integer"
        -          },
        -          "yMax": {
        -            "type": "number"
        -          },
        -          "yMin": {
        -            "type": "number"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "categories": {
        -        "description": "Category / slice labels (x-axis). Defaults to 1-based indices when omitted.",
        -        "items": {
        -          "maxLength": 200,
        -          "type": "string"
        -        },
        -        "maxItems": 1000,
        -        "type": "array"
        -      },
        -      "chartType": {
        -        "description": "Chart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'stackedBar'/'stackedBarH'/'line'/'area'/'scatter' support multiple series. 'scatter' requires xValues on every series and a positional xAxis.type ('linear' or 'time').",
        -        "enum": [
        -          "bar",
        -          "barH",
        -          "stackedBar",
        -          "stackedBarH",
        -          "line",
        -          "area",
        -          "scatter",
        -          "pie",
        -          "donut"
        -        ],
        -        "type": "string"
        -      },
        -      "colors": {
        -        "description": "Palette override (per-series for bar/line, per-slice for pie/donut).",
        -        "items": {
        -          "description": "CSS-style hex colour, e.g. \"#3366cc\".",
        -          "pattern": "^#?[0-9a-fA-F]{6}$",
        -          "type": "string"
        -        },
        -        "maxItems": 50,
        -        "type": "array"
        -      },
        -      "dataLabels": {
        -        "description": "Per-point value labels: true for defaults, or an object to format them.",
        -        "oneOf": [
        -          {
        -            "type": "boolean"
        -          },
        -          {
        -            "additionalProperties": false,
        -            "properties": {
        -              "decimals": {
        -                "maximum": 6,
        -                "minimum": 0,
        -                "type": "integer"
        -              },
        -              "prefix": {
        -                "maxLength": 16,
        -                "type": "string"
        -              },
        -              "suffix": {
        -                "maxLength": 16,
        -                "type": "string"
        -              }
        -            },
        -            "type": "object"
        -          }
        -        ]
        -      },
        -      "height": {
        -        "description": "Plot-area height in points. Default 240.",
        -        "maximum": 2000,
        -        "minimum": 50,
        -        "type": "number"
        -      },
        -      "labelRotation": {
        -        "description": "Rotate category labels counter-clockwise by this many degrees (disables the automatic stride).",
        -        "maximum": 90,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "labelStride": {
        -        "description": "Draw every Nth category label. Default: automatic (measured non-overlap); 1 draws every label.",
        -        "maximum": 1000,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "legend": {
        -        "description": "Legend placement. Defaults to 'bottom' for multi-series/pie, else 'none'.",
        -        "enum": [
        -          "bottom",
        -          "none"
        -        ],
        -        "type": "string"
        -      },
        -      "markers": {
        -        "description": "Draw point markers on line series. Default false.",
        -        "type": "boolean"
        -      },
        -      "series": {
        -        "description": "Data series. Pie/donut charts use exactly one series (each value becomes a slice).",
        -        "items": {
        -          "additionalProperties": false,
        -          "properties": {
        -            "color": {
        -              "description": "CSS-style hex colour, e.g. \"#3366cc\".",
        -              "pattern": "^#?[0-9a-fA-F]{6}$",
        -              "type": "string"
        -            },
        -            "label": {
        -              "description": "Series label (shown in the legend).",
        -              "maxLength": 200,
        -              "minLength": 1,
        -              "type": "string"
        -            },
        -            "values": {
        -              "description": "Numeric values, one per category. Negative values are supported for bar/line.",
        -              "items": {
        -                "type": "number"
        -              },
        -              "maxItems": 1000,
        -              "minItems": 1,
        -              "type": "array"
        -            },
        -            "xValues": {
        -              "description": "Per-point x positions (same length as values) for scatter charts and for line/area charts with xAxis.type 'linear' or 'time'.",
        -              "items": {
        -                "description": "Positional x value: a number (linear axis) or an ISO-8601 date / epoch milliseconds (time axis).",
        -                "maxLength": 64,
        -                "type": [
        -                  "number",
        -                  "string"
        -                ]
        -              },
        -              "maxItems": 1000,
        -              "minItems": 1,
        -              "type": "array"
        -            },
        -            "yAxis": {
        -              "description": "Bind the series to the left (default) or the secondary right value axis (cartesian charts only; configure its range with 'axis2').",
        -              "enum": [
        -                "left",
        -                "right"
        -              ],
        -              "type": "string"
        -            }
        -          },
        -          "required": [
        -            "label",
        -            "values"
        -          ],
        -          "type": "object"
        -        },
        -        "maxItems": 50,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "title": {
        -        "description": "Chart title rendered above the plot.",
        -        "maxLength": 200,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "chart"
        -      },
        -      "width": {
        -        "description": "Plot width in points (clamped to content width). Default 460.",
        -        "maximum": 2000,
        -        "minimum": 50,
        -        "type": "number"
        -      },
        -      "xAxis": {
        -        "additionalProperties": false,
        -        "description": "Horizontal axis. 'category' (default) positions points by index; 'linear' / 'time' position them by series xValues (line/area/scatter only). Time ticks are UTC-deterministic.",
        -        "properties": {
        -          "grid": {
        -            "description": "Draw vertical gridlines.",
        -            "type": "boolean"
        -          },
        -          "max": {
        -            "description": "Axis maximum (number, or ISO-8601 / epoch ms for time axes).",
        -            "maxLength": 64,
        -            "type": [
        -              "number",
        -              "string"
        -            ]
        -          },
        -          "min": {
        -            "description": "Axis minimum (number, or ISO-8601 / epoch ms for time axes).",
        -            "maxLength": 64,
        -            "type": [
        -              "number",
        -              "string"
        -            ]
        -          },
        -          "ticks": {
        -            "maximum": 20,
        -            "minimum": 2,
        -            "type": "integer"
        -          },
        -          "type": {
        -            "enum": [
        -              "category",
        -              "linear",
        -              "time"
        -            ],
        -            "type": "string"
        -          }
        -        },
        -        "type": "object"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "chartType",
        -      "series"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Inline smart table — same body as add_table (every row must have exactly as many cells as headers).",
        -    "properties": {
        -      "autoFitColumns": {
        -        "description": "Auto-fit column widths to content. Output bytes then depend on text metrics (not byte-deterministic across content changes).",
        -        "type": "boolean"
        -      },
        -      "caption": {
        -        "description": "Caption rendered above the table (tagged as /Caption under PDF/A).",
        -        "maxLength": 200,
        -        "type": "string"
        -      },
        -      "cellBorders": {
        -        "additionalProperties": false,
        -        "description": "Per-cell vector borders (pure strokes, PDF/A-safe). Choose individual sides or `all`.",
        -        "properties": {
        -          "all": {
        -            "description": "Draw all four edges (overrides the individual side flags).",
        -            "type": "boolean"
        -          },
        -          "bottom": {
        -            "type": "boolean"
        -          },
        -          "color": {
        -            "description": "Stroke colour as a PDF operator string ('0.8 0.8 0.8') or hex. Default light grey.",
        -            "type": "string"
        -          },
        -          "left": {
        -            "type": "boolean"
        -          },
        -          "right": {
        -            "type": "boolean"
        -          },
        -          "style": {
        -            "description": "Stroke style (default 'solid').",
        -            "enum": [
        -              "solid",
        -              "dashed",
        -              "dotted"
        -            ],
        -            "type": "string"
        -          },
        -          "top": {
        -            "type": "boolean"
        -          },
        -          "width": {
        -            "description": "Stroke width in points (default 0.5).",
        -            "maximum": 10,
        -            "minimum": 0,
        -            "type": "number"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "cellPadding": {
        -        "description": "Horizontal cell padding in points (default 3).",
        -        "maximum": 50,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "cellVAlign": {
        -        "description": "Vertical alignment of cell content.",
        -        "enum": [
        -          "top",
        -          "middle",
        -          "bottom"
        -        ],
        -        "type": "string"
        -      },
        -      "clipCells": {
        -        "description": "Clip cell contents to the column bounds (PDF clip operators). Recommended for PDF/A and visual safety.",
        -        "type": "boolean"
        -      },
        -      "headers": {
        -        "description": "Column header labels. Must have the same length as each row in `rows`.",
        -        "items": {
        -          "maxLength": 200,
        -          "minLength": 1,
        -          "type": "string"
        -        },
        -        "maxItems": 50,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "minRowHeight": {
        -        "description": "Minimum row height in points (default 12).",
        -        "maximum": 200,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "repeatHeader": {
        -        "description": "Repeat the header row on every continuation page (default true).",
        -        "type": "boolean"
        -      },
        -      "rows": {
        -        "description": "Data rows. Each row is an array of cell strings with the same length as `headers`.",
        -        "items": {
        -          "items": {
        -            "maxLength": 500,
        -            "type": "string"
        -          },
        -          "maxItems": 50,
        -          "minItems": 1,
        -          "type": "array"
        -        },
        -        "maxItems": 5000,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "type": {
        -        "const": "table"
        -      },
        -      "wrap": {
        -        "description": "Cell wrap policy: 'auto' (default) wraps only overflowing cells; 'always' wraps every cell; 'never' truncates.",
        -        "enum": [
        -          "auto",
        -          "always",
        -          "never"
        -        ],
        -        "type": "string"
        -      },
        -      "zebra": {
        -        "description": "Alternate-row light tint (static fill, PDF/A-1b safe).",
        -        "type": "boolean"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "headers",
        -      "rows"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Inline JPEG/PNG image. Without width/height the pixel size is used as points and clamped to the content width; with one dimension the aspect ratio is kept. The decoded bytes of all image blocks in one call are capped at 24 MiB (a watermark image has its own 8 MiB cap).",
        -    "properties": {
        -      "align": {
        -        "default": "left",
        -        "description": "Horizontal placement inside the content width.",
        -        "enum": [
        -          "left",
        -          "center",
        -          "right"
        -        ],
        -        "type": "string"
        -      },
        -      "alt": {
        -        "description": "Accessible description (tagged /Figure /Alt). Always provide it for non-decorative content under PDF/A or PDF/UA.",
        -        "maxLength": 500,
        -        "type": "string"
        -      },
        -      "height": {
        -        "description": "Render height in points.",
        -        "maximum": 1000,
        -        "minimum": 10,
        -        "type": "number"
        -      },
        -      "imageBase64": {
        -        "description": "Base64 image bytes. JPEG (baseline; 1, 3 or 4 components — CMYK raises PDFA_DEVICE_CMYK_IMAGE under PDF/A) or PNG (8-bit greyscale/RGB, non-interlaced; alpha-channel and palette PNGs are rejected with a remedy). No data: URI.",
        -        "maxLength": 12000000,
        -        "minLength": 4,
        -        "type": "string"
        -      },
        -      "mimeType": {
        -        "description": "MIME type of the image. Must match the actual encoding of imageBase64 (magic bytes are checked).",
        -        "enum": [
        -          "image/jpeg",
        -          "image/png"
        -        ],
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "image"
        -      },
        -      "width": {
        -        "description": "Render width in points.",
        -        "maximum": 800,
        -        "minimum": 10,
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "imageBase64",
        -      "mimeType"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Clickable external link (/URI action). Only http:, https: and mailto: URLs are accepted.",
        -    "properties": {
        -      "color": {
        -        "description": "Hex colour (#RGB or #RRGGBB).",
        -        "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$",
        -        "type": "string"
        -      },
        -      "fontSize": {
        -        "description": "Default 10.",
        -        "maximum": 48,
        -        "minimum": 6,
        -        "type": "number"
        -      },
        -      "text": {
        -        "maxLength": 500,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "link"
        -      },
        -      "url": {
        -        "description": "http(s):// or mailto: URL.",
        -        "maxLength": 2048,
        -        "minLength": 1,
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text",
        -      "url"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Printed table of contents generated from the document's heading blocks (internal /GoTo links with dot leaders). Pairs with outline:'auto' for the bookmark pane.",
        -    "properties": {
        -      "fontSize": {
        -        "description": "Default 10.",
        -        "maximum": 24,
        -        "minimum": 6,
        -        "type": "number"
        -      },
        -      "indent": {
        -        "description": "Points of indent per heading level (default 15).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "maxLevel": {
        -        "description": "Deepest heading level listed (default 3).",
        -        "enum": [
        -          1,
        -          2,
        -          3
        -        ],
        -        "type": "integer"
        -      },
        -      "title": {
        -        "description": "Default 'Table of Contents'.",
        -        "maxLength": 200,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "toc"
        -      }
        -    },
        -    "required": [
        -      "type"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Inline barcode — same body as add_barcode (pure vector, no /Alt available in the engine).",
        -    "properties": {
        -      "align": {
        -        "default": "left",
        -        "description": "Horizontal placement inside the content width.",
        -        "enum": [
        -          "left",
        -          "center",
        -          "right"
        -        ],
        -        "type": "string"
        -      },
        -      "data": {
        -        "description": "Raw payload to encode — do NOT URL-encode. For QR/URL pass e.g. \"https://example.com\" verbatim. EAN-13 must be 12 or 13 digits (13th is auto-computed). Code 128 accepts ASCII alphanumerics.",
        -        "maxLength": 4296,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "ecLevel": {
        -        "default": "M",
        -        "description": "QR ONLY. Error correction level (L=7%, M=15%, Q=25%, H=30%). Ignored for code128/ean13/datamatrix/pdf417. Use H for printed media that may get smudged or partially covered (e.g. logo overlay).",
        -        "enum": [
        -          "L",
        -          "M",
        -          "Q",
        -          "H"
        -        ],
        -        "type": "string"
        -      },
        -      "format": {
        -        "description": "Barcode symbology to render.",
        -        "enum": [
        -          "qr",
        -          "code128",
        -          "ean13",
        -          "datamatrix",
        -          "pdf417"
        -        ],
        -        "type": "string"
        -      },
        -      "height": {
        -        "default": 200,
        -        "description": "Barcode height in PDF points (ignored for square symbologies like QR/Data Matrix).",
        -        "maximum": 500,
        -        "minimum": 30,
        -        "type": "number"
        -      },
        -      "type": {
        -        "const": "barcode"
        -      },
        -      "width": {
        -        "default": 200,
        -        "description": "Barcode width in PDF points.",
        -        "maximum": 500,
        -        "minimum": 30,
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "format",
        -      "data"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Vector drawing from an SVG path `d` string or SVG markup. Supported: <path> <rect> (rx/ry) <circle> <ellipse> <line> <polyline> <polygon> and <text>/<tspan> (x, y, font-size, fill, text-anchor, dx/dy); fill / stroke / stroke-width attributes; double-quoted attributes only. NOT supported (silently ignored): transform, <g>, <use>, <image>, <defs>/<clipPath>, gradients, opacity, CSS/style, dash patterns, text word-wrap. No external reference is ever fetched (no XML parser: entities other than &amp; &lt; &gt; &quot; &apos; &nbsp; &#n; are dropped). Pure path operators — PDF/A-safe at every level.",
        -    "properties": {
        -      "align": {
        -        "default": "left",
        -        "description": "Horizontal placement inside the content width.",
        -        "enum": [
        -          "left",
        -          "center",
        -          "right"
        -        ],
        -        "type": "string"
        -      },
        -      "alt": {
        -        "description": "Accessible description (tagged /Figure /Alt). Always provide it for non-decorative content under PDF/A or PDF/UA.",
        -        "maxLength": 500,
        -        "type": "string"
        -      },
        -      "data": {
        -        "description": "Path `d` string or SVG markup (≤ 100 000 characters).",
        -        "maxLength": 100000,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "fill": {
        -        "description": "Hex colour or 'none' (default black).",
        -        "pattern": "^(?:none|#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}))$",
        -        "type": "string"
        -      },
        -      "height": {
        -        "description": "Render height in points (default 200).",
        -        "maximum": 1000,
        -        "minimum": 10,
        -        "type": "number"
        -      },
        -      "stroke": {
        -        "description": "Hex colour or 'none' (default none).",
        -        "pattern": "^(?:none|#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}))$",
        -        "type": "string"
        -      },
        -      "strokeWidth": {
        -        "description": "Stroke width in SVG user units (default 1).",
        -        "maximum": 50,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "type": {
        -        "const": "svg"
        -      },
        -      "viewBox": {
        -        "description": "[minX, minY, width, height] — overrides the viewBox of the markup; required for a bare path string that is not 0-based.",
        -        "items": {
        -          "type": "number"
        -        },
        -        "maxItems": 4,
        -        "minItems": 4,
        -        "type": "array"
        -      },
        -      "width": {
        -        "description": "Render width in points (default 200).",
        -        "maximum": 800,
        -        "minimum": 10,
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "data"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Inline AcroForm field — same body as an add_form field. Under a PDF/A claim the widget appearance font is not embedded (PDFA_UNEMBEDDED_FORM_FONT; strict:true fails the call).",
        -    "properties": {
        -      "checked": {
        -        "description": "Initial checked state for checkbox / radio fields.",
        -        "type": "boolean"
        -      },
        -      "fieldType": {
        -        "description": "Type of form control to render. Radio fields sharing a name form one radio group.",
        -        "enum": [
        -          "text",
        -          "textarea",
        -          "checkbox",
        -          "radio",
        -          "dropdown",
        -          "listbox"
        -        ],
        -        "type": "string"
        -      },
        -      "fontSize": {
        -        "description": "Font size for text rendering inside the field.",
        -        "maximum": 48,
        -        "minimum": 6,
        -        "type": "number"
        -      },
        -      "height": {
        -        "description": "Field height in points (default depends on the type).",
        -        "maximum": 300,
        -        "minimum": 10,
        -        "type": "number"
        -      },
        -      "label": {
        -        "description": "Human-readable label shown above the field.",
        -        "maxLength": 200,
        -        "type": "string"
        -      },
        -      "maxLength": {
        -        "description": "Maximum character length for text/textarea fields.",
        -        "maximum": 32767,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "name": {
        -        "description": "Unique field name used as the PDF annotation identifier (/T).",
        -        "maxLength": 100,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "options": {
        -        "description": "Choices for dropdown, listbox or radio fields.",
        -        "items": {
        -          "maxLength": 200,
        -          "type": "string"
        -        },
        -        "maxItems": 100,
        -        "type": "array"
        -      },
        -      "placeholder": {
        -        "description": "Hint text shown while the field is empty.",
        -        "maxLength": 200,
        -        "type": "string"
        -      },
        -      "readOnly": {
        -        "description": "Prevent editing of this field.",
        -        "type": "boolean"
        -      },
        -      "required": {
        -        "description": "Mark field as required.",
        -        "type": "boolean"
        -      },
        -      "type": {
        -        "const": "formField"
        -      },
        -      "value": {
        -        "description": "Default value pre-filled in the field.",
        -        "maxLength": 2000,
        -        "type": "string"
        -      },
        -      "width": {
        -        "description": "Field width in points (default: full content width).",
        -        "maximum": 500,
        -        "minimum": 10,
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "fieldType",
        -      "name"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "keepWithNext": {
        +        "description": "Keep this heading on the same page as the block that follows. Overrides typography.keepHeadingsWithNext for this block, either way.",
        +        "type": "boolean"
        +      },
        +      "level": {
        +        "enum": [
        +          1,
        +          2,
        +          3
        +        ],
        +        "type": "integer"
        +      },
        +      "text": {
        +        "maxLength": 500,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "heading"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text",
        +      "level"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "align": {
        +        "description": "Text alignment (default left). 'justify' spans every line but the last across the measure; pair it with typography.opticalMargins.",
        +        "enum": [
        +          "left",
        +          "right",
        +          "center",
        +          "justify"
        +        ],
        +        "type": "string"
        +      },
        +      "keepWithNext": {
        +        "description": "Keep this paragraph on the same page as the block that follows (a lead-in line before a table or figure). Default false.",
        +        "type": "boolean"
        +      },
        +      "splittable": {
        +        "description": "Allow / forbid this paragraph breaking across pages, overriding typography.splitParagraphs for this block.",
        +        "type": "boolean"
        +      },
        +      "text": {
        +        "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.",
        +        "maxLength": 50000,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "paragraph"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "items": {
        +        "description": "List items. A string is a leaf; an object { text, items } nests a sub-list (bullets/numbers indent; numbered sub-lists restart at 1).",
        +        "items": {
        +          "oneOf": [
        +            {
        +              "maxLength": 1000,
        +              "minLength": 1,
        +              "type": "string"
        +            },
        +            {
        +              "additionalProperties": false,
        +              "properties": {
        +                "items": {
        +                  "items": {
        +                    "oneOf": [
        +                      {
        +                        "maxLength": 1000,
        +                        "minLength": 1,
        +                        "type": "string"
        +                      },
        +                      {
        +                        "additionalProperties": false,
        +                        "properties": {
        +                          "items": {
        +                            "items": {
        +                              "oneOf": [
        +                                {
        +                                  "maxLength": 1000,
        +                                  "minLength": 1,
        +                                  "type": "string"
        +                                },
        +                                {
        +                                  "additionalProperties": false,
        +                                  "properties": {
        +                                    "items": {
        +                                      "items": {
        +                                        "oneOf": [
        +                                          {
        +                                            "maxLength": 1000,
        +                                            "minLength": 1,
        +                                            "type": "string"
        +                                          },
        +                                          {
        +                                            "additionalProperties": false,
        +                                            "properties": {
        +                                              "items": {
        +                                                "items": {
        +                                                  "oneOf": [
        +                                                    {
        +                                                      "maxLength": 1000,
        +                                                      "minLength": 1,
        +                                                      "type": "string"
        +                                                    },
        +                                                    {
        +                                                      "additionalProperties": false,
        +                                                      "properties": {
        +                                                        "items": {
        +                                                          "items": {
        +                                                            "oneOf": [
        +                                                              {
        +                                                                "maxLength": 1000,
        +                                                                "minLength": 1,
        +                                                                "type": "string"
        +                                                              },
        +                                                              {
        +                                                                "additionalProperties": false,
        +                                                                "properties": {
        +                                                                  "text": {
        +                                                                    "maxLength": 1000,
        +                                                                    "minLength": 1,
        +                                                                    "type": "string"
        +                                                                  }
        +                                                                },
        +                                                                "required": [
        +                                                                  "text"
        +                                                                ],
        +                                                                "type": "object"
        +                                                              }
        +                                                            ]
        +                                                          },
        +                                                          "maxItems": 1000,
        +                                                          "minItems": 1,
        +                                                          "type": "array"
        +                                                        },
        +                                                        "text": {
        +                                                          "maxLength": 1000,
        +                                                          "minLength": 1,
        +                                                          "type": "string"
        +                                                        }
        +                                                      },
        +                                                      "required": [
        +                                                        "text"
        +                                                      ],
        +                                                      "type": "object"
        +                                                    }
        +                                                  ]
        +                                                },
        +                                                "maxItems": 1000,
        +                                                "minItems": 1,
        +                                                "type": "array"
        +                                              },
        +                                              "text": {
        +                                                "maxLength": 1000,
        +                                                "minLength": 1,
        +                                                "type": "string"
        +                                              }
        +                                            },
        +                                            "required": [
        +                                              "text"
        +                                            ],
        +                                            "type": "object"
        +                                          }
        +                                        ]
        +                                      },
        +                                      "maxItems": 1000,
        +                                      "minItems": 1,
        +                                      "type": "array"
        +                                    },
        +                                    "text": {
        +                                      "maxLength": 1000,
        +                                      "minLength": 1,
        +                                      "type": "string"
        +                                    }
        +                                  },
        +                                  "required": [
        +                                    "text"
        +                                  ],
        +                                  "type": "object"
        +                                }
        +                              ]
        +                            },
        +                            "maxItems": 1000,
        +                            "minItems": 1,
        +                            "type": "array"
        +                          },
        +                          "text": {
        +                            "maxLength": 1000,
        +                            "minLength": 1,
        +                            "type": "string"
        +                          }
        +                        },
        +                        "required": [
        +                          "text"
        +                        ],
        +                        "type": "object"
        +                      }
        +                    ]
        +                  },
        +                  "maxItems": 1000,
        +                  "minItems": 1,
        +                  "type": "array"
        +                },
        +                "text": {
        +                  "maxLength": 1000,
        +                  "minLength": 1,
        +                  "type": "string"
        +                }
        +              },
        +              "required": [
        +                "text"
        +              ],
        +              "type": "object"
        +            }
        +          ]
        +        },
        +        "maxItems": 1000,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "style": {
        +        "default": "bullet",
        +        "enum": [
        +          "bullet",
        +          "numbered"
        +        ],
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "list"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "items"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "type": {
        +        "const": "pageBreak"
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "height": {
        +        "maximum": 500,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "type": {
        +        "const": "spacer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "height"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Native vector chart rendered as pure PDF path operators — bar / horizontal-bar / stacked-bar / line / area / scatter / pie / donut (pdfnative 1.7 charts v2: time and log axes, data labels, secondary axis, legends). Same body as add_chart.",
        +    "properties": {
        +      "align": {
        +        "description": "Horizontal alignment within the content width. Default 'left'.",
        +        "enum": [
        +          "left",
        +          "center",
        +          "right"
        +        ],
        +        "type": "string"
        +      },
        +      "altText": {
        +        "description": "Alt text for the tagged-PDF /Figure /Alt. Auto-generated when omitted.",
        +        "maxLength": 500,
        +        "type": "string"
        +      },
        +      "axis": {
        +        "additionalProperties": false,
        +        "description": "Value-axis options (bar/line only).",
        +        "properties": {
        +          "grid": {
        +            "description": "Draw horizontal gridlines.",
        +            "type": "boolean"
        +          },
        +          "scale": {
        +            "description": "Value-axis scale. 'log' requires strictly positive values and is not available for stacked charts.",
        +            "enum": [
        +              "linear",
        +              "log"
        +            ],
        +            "type": "string"
        +          },
        +          "ticks": {
        +            "description": "Target tick count (nice 1/2/5×10ⁿ steps).",
        +            "maximum": 20,
        +            "minimum": 2,
        +            "type": "integer"
        +          },
        +          "yMax": {
        +            "description": "Force the axis maximum (values are clamped to the plot band).",
        +            "type": "number"
        +          },
        +          "yMin": {
        +            "description": "Force the axis minimum (values are clamped to the plot band).",
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "axis2": {
        +        "additionalProperties": false,
        +        "description": "Secondary RIGHT value axis (drawn only when a series sets yAxis:'right').",
        +        "properties": {
        +          "scale": {
        +            "enum": [
        +              "linear",
        +              "log"
        +            ],
        +            "type": "string"
        +          },
        +          "ticks": {
        +            "maximum": 20,
        +            "minimum": 2,
        +            "type": "integer"
        +          },
        +          "yMax": {
        +            "type": "number"
        +          },
        +          "yMin": {
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "categories": {
        +        "description": "Category / slice labels (x-axis). Defaults to 1-based indices when omitted.",
        +        "items": {
        +          "maxLength": 200,
        +          "type": "string"
        +        },
        +        "maxItems": 1000,
        +        "type": "array"
        +      },
        +      "chartType": {
        +        "description": "Chart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'stackedBar'/'stackedBarH'/'line'/'area'/'scatter' support multiple series. 'scatter' requires xValues on every series and a positional xAxis.type ('linear' or 'time').",
        +        "enum": [
        +          "bar",
        +          "barH",
        +          "stackedBar",
        +          "stackedBarH",
        +          "line",
        +          "area",
        +          "scatter",
        +          "pie",
        +          "donut"
        +        ],
        +        "type": "string"
        +      },
        +      "colors": {
        +        "description": "Palette override (per-series for bar/line, per-slice for pie/donut).",
        +        "items": {
        +          "anyOf": [
        +            {
        +              "pattern": "^#?[0-9a-fA-F]{6}$",
        +              "type": "string"
        +            },
        +            {
        +              "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +              "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +              "type": "string"
        +            },
        +            {
        +              "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +              "items": {
        +                "maximum": 100,
        +                "minimum": 0,
        +                "type": "number"
        +              },
        +              "maxItems": 4,
        +              "minItems": 4,
        +              "type": "array"
        +            }
        +          ],
        +          "description": "CSS-style hex colour, e.g. \"#3366cc\"."
        +        },
        +        "maxItems": 50,
        +        "type": "array"
        +      },
        +      "dataLabels": {
        +        "description": "Per-point value labels: true for defaults, or an object to format them.",
        +        "oneOf": [
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "additionalProperties": false,
        +            "properties": {
        +              "decimals": {
        +                "maximum": 6,
        +                "minimum": 0,
        +                "type": "integer"
        +              },
        +              "prefix": {
        +                "maxLength": 16,
        +                "type": "string"
        +              },
        +              "suffix": {
        +                "maxLength": 16,
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          }
        +        ]
        +      },
        +      "height": {
        +        "description": "Plot-area height in points. Default 240.",
        +        "maximum": 2000,
        +        "minimum": 50,
        +        "type": "number"
        +      },
        +      "labelRotation": {
        +        "description": "Rotate category labels counter-clockwise by this many degrees (disables the automatic stride).",
        +        "maximum": 90,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "labelStride": {
        +        "description": "Draw every Nth category label. Default: automatic (measured non-overlap); 1 draws every label.",
        +        "maximum": 1000,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "legend": {
        +        "description": "Legend placement. Defaults to 'bottom' for multi-series/pie, else 'none'.",
        +        "enum": [
        +          "bottom",
        +          "none"
        +        ],
        +        "type": "string"
        +      },
        +      "markers": {
        +        "description": "Draw point markers on line series. Default false.",
        +        "type": "boolean"
        +      },
        +      "series": {
        +        "description": "Data series. Pie/donut charts use exactly one series (each value becomes a slice).",
        +        "items": {
        +          "additionalProperties": false,
        +          "properties": {
        +            "color": {
        +              "anyOf": [
        +                {
        +                  "pattern": "^#?[0-9a-fA-F]{6}$",
        +                  "type": "string"
        +                },
        +                {
        +                  "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +                  "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +                  "type": "string"
        +                },
        +                {
        +                  "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +                  "items": {
        +                    "maximum": 100,
        +                    "minimum": 0,
        +                    "type": "number"
        +                  },
        +                  "maxItems": 4,
        +                  "minItems": 4,
        +                  "type": "array"
        +                }
        +              ],
        +              "description": "CSS-style hex colour, e.g. \"#3366cc\"."
        +            },
        +            "label": {
        +              "description": "Series label (shown in the legend).",
        +              "maxLength": 200,
        +              "minLength": 1,
        +              "type": "string"
        +            },
        +            "values": {
        +              "description": "Numeric values, one per category. Negative values are supported for bar/line.",
        +              "items": {
        +                "type": "number"
        +              },
        +              "maxItems": 1000,
        +              "minItems": 1,
        +              "type": "array"
        +            },
        +            "xValues": {
        +              "description": "Per-point x positions (same length as values) for scatter charts and for line/area charts with xAxis.type 'linear' or 'time'.",
        +              "items": {
        +                "description": "Positional x value: a number (linear axis) or an ISO-8601 date / epoch milliseconds (time axis).",
        +                "maxLength": 64,
        +                "type": [
        +                  "number",
        +                  "string"
        +                ]
        +              },
        +              "maxItems": 1000,
        +              "minItems": 1,
        +              "type": "array"
        +            },
        +            "yAxis": {
        +              "description": "Bind the series to the left (default) or the secondary right value axis (cartesian charts only; configure its range with 'axis2').",
        +              "enum": [
        +                "left",
        +                "right"
        +              ],
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "label",
        +            "values"
        +          ],
        +          "type": "object"
        +        },
        +        "maxItems": 50,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "title": {
        +        "description": "Chart title rendered above the plot.",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "chart"
        +      },
        +      "width": {
        +        "description": "Plot width in points (clamped to content width). Default 460.",
        +        "maximum": 2000,
        +        "minimum": 50,
        +        "type": "number"
        +      },
        +      "xAxis": {
        +        "additionalProperties": false,
        +        "description": "Horizontal axis. 'category' (default) positions points by index; 'linear' / 'time' position them by series xValues (line/area/scatter only). Time ticks are UTC-deterministic.",
        +        "properties": {
        +          "grid": {
        +            "description": "Draw vertical gridlines.",
        +            "type": "boolean"
        +          },
        +          "max": {
        +            "description": "Axis maximum (number, or ISO-8601 / epoch ms for time axes).",
        +            "maxLength": 64,
        +            "type": [
        +              "number",
        +              "string"
        +            ]
        +          },
        +          "min": {
        +            "description": "Axis minimum (number, or ISO-8601 / epoch ms for time axes).",
        +            "maxLength": 64,
        +            "type": [
        +              "number",
        +              "string"
        +            ]
        +          },
        +          "ticks": {
        +            "maximum": 20,
        +            "minimum": 2,
        +            "type": "integer"
        +          },
        +          "type": {
        +            "enum": [
        +              "category",
        +              "linear",
        +              "time"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "chartType",
        +      "series"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Inline smart table — same body as add_table (every row must have exactly as many cells as headers).",
        +    "properties": {
        +      "autoFitColumns": {
        +        "description": "Auto-fit column widths to content. Output bytes then depend on text metrics (not byte-deterministic across content changes).",
        +        "type": "boolean"
        +      },
        +      "caption": {
        +        "description": "Caption rendered above the table (tagged as /Caption under PDF/A).",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "cellBorders": {
        +        "additionalProperties": false,
        +        "description": "Per-cell vector borders (pure strokes, PDF/A-safe). Choose individual sides or `all`.",
        +        "properties": {
        +          "all": {
        +            "description": "Draw all four edges (overrides the individual side flags).",
        +            "type": "boolean"
        +          },
        +          "bottom": {
        +            "type": "boolean"
        +          },
        +          "color": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +                "items": {
        +                  "maximum": 100,
        +                  "minimum": 0,
        +                  "type": "number"
        +                },
        +                "maxItems": 4,
        +                "minItems": 4,
        +                "type": "array"
        +              }
        +            ],
        +            "description": "Stroke colour as a PDF operator string ('0.8 0.8 0.8') or hex. Default light grey."
        +          },
        +          "left": {
        +            "type": "boolean"
        +          },
        +          "right": {
        +            "type": "boolean"
        +          },
        +          "style": {
        +            "description": "Stroke style (default 'solid').",
        +            "enum": [
        +              "solid",
        +              "dashed",
        +              "dotted"
        +            ],
        +            "type": "string"
        +          },
        +          "top": {
        +            "type": "boolean"
        +          },
        +          "width": {
        +            "description": "Stroke width in points (default 0.5).",
        +            "maximum": 10,
        +            "minimum": 0,
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "cellPadding": {
        +        "description": "Horizontal cell padding in points (default 3).",
        +        "maximum": 50,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "cellVAlign": {
        +        "description": "Vertical alignment of cell content.",
        +        "enum": [
        +          "top",
        +          "middle",
        +          "bottom"
        +        ],
        +        "type": "string"
        +      },
        +      "clipCells": {
        +        "description": "Clip cell contents to the column bounds (PDF clip operators). Recommended for PDF/A and visual safety.",
        +        "type": "boolean"
        +      },
        +      "headers": {
        +        "description": "Column header labels. Must have the same length as each row in `rows`.",
        +        "items": {
        +          "maxLength": 200,
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "maxItems": 50,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "minRowHeight": {
        +        "description": "Minimum row height in points (default 12).",
        +        "maximum": 200,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "repeatHeader": {
        +        "description": "Repeat the header row on every continuation page (default true).",
        +        "type": "boolean"
        +      },
        +      "rows": {
        +        "description": "Data rows. Each row is an array of cell strings with the same length as `headers`.",
        +        "items": {
        +          "items": {
        +            "maxLength": 500,
        +            "type": "string"
        +          },
        +          "maxItems": 50,
        +          "minItems": 1,
        +          "type": "array"
        +        },
        +        "maxItems": 5000,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "type": {
        +        "const": "table"
        +      },
        +      "wrap": {
        +        "description": "Cell wrap policy: 'auto' (default) wraps only overflowing cells; 'always' wraps every cell; 'never' truncates.",
        +        "enum": [
        +          "auto",
        +          "always",
        +          "never"
        +        ],
        +        "type": "string"
        +      },
        +      "zebra": {
        +        "description": "Alternate-row light tint (static fill, PDF/A-1b safe).",
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "headers",
        +      "rows"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Inline JPEG/PNG image. Without width/height the pixel size is used as points and clamped to the content width; with one dimension the aspect ratio is kept. The decoded bytes of all image blocks in one call are capped at 24 MiB (a watermark image has its own 8 MiB cap).",
        +    "properties": {
        +      "align": {
        +        "default": "left",
        +        "description": "Horizontal placement inside the content width.",
        +        "enum": [
        +          "left",
        +          "center",
        +          "right"
        +        ],
        +        "type": "string"
        +      },
        +      "alt": {
        +        "description": "Accessible description (tagged /Figure /Alt). Always provide it for non-decorative content under PDF/A or PDF/UA.",
        +        "maxLength": 500,
        +        "type": "string"
        +      },
        +      "height": {
        +        "description": "Render height in points.",
        +        "maximum": 1000,
        +        "minimum": 10,
        +        "type": "number"
        +      },
        +      "imageBase64": {
        +        "description": "Base64 image bytes. JPEG (baseline; 1, 3 or 4 components — CMYK raises PDFA_DEVICE_CMYK_IMAGE under PDF/A) or PNG (8-bit greyscale/RGB, non-interlaced; alpha-channel and palette PNGs are rejected with a remedy). No data: URI.",
        +        "maxLength": 12000000,
        +        "minLength": 4,
        +        "type": "string"
        +      },
        +      "mimeType": {
        +        "description": "MIME type of the image. Must match the actual encoding of imageBase64 (magic bytes are checked).",
        +        "enum": [
        +          "image/jpeg",
        +          "image/png"
        +        ],
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "image"
        +      },
        +      "width": {
        +        "description": "Render width in points.",
        +        "maximum": 800,
        +        "minimum": 10,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "imageBase64",
        +      "mimeType"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Clickable external link (/URI action). Only http:, https: and mailto: URLs are accepted.",
        +    "properties": {
        +      "color": {
        +        "anyOf": [
        +          {
        +            "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$",
        +            "type": "string"
        +          },
        +          {
        +            "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +            "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +            "type": "string"
        +          },
        +          {
        +            "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +            "items": {
        +              "maximum": 100,
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "maxItems": 4,
        +            "minItems": 4,
        +            "type": "array"
        +          }
        +        ],
        +        "description": "Hex colour (#RGB or #RRGGBB)."
        +      },
        +      "fontSize": {
        +        "description": "Default 10.",
        +        "maximum": 48,
        +        "minimum": 6,
        +        "type": "number"
        +      },
        +      "text": {
        +        "maxLength": 500,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "link"
        +      },
        +      "url": {
        +        "description": "http(s):// or mailto: URL.",
        +        "maxLength": 2048,
        +        "minLength": 1,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text",
        +      "url"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Printed table of contents generated from the document's heading blocks (internal /GoTo links with dot leaders). Pairs with outline:'auto' for the bookmark pane.",
        +    "properties": {
        +      "fontSize": {
        +        "description": "Default 10.",
        +        "maximum": 24,
        +        "minimum": 6,
        +        "type": "number"
        +      },
        +      "indent": {
        +        "description": "Points of indent per heading level (default 15).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "maxLevel": {
        +        "description": "Deepest heading level listed (default 3).",
        +        "enum": [
        +          1,
        +          2,
        +          3
        +        ],
        +        "type": "integer"
        +      },
        +      "title": {
        +        "description": "Default 'Table of Contents'.",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "toc"
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Inline barcode — same body as add_barcode (pure vector, no /Alt available in the engine).",
        +    "properties": {
        +      "align": {
        +        "default": "left",
        +        "description": "Horizontal placement inside the content width.",
        +        "enum": [
        +          "left",
        +          "center",
        +          "right"
        +        ],
        +        "type": "string"
        +      },
        +      "data": {
        +        "description": "Raw payload to encode — do NOT URL-encode. For QR/URL pass e.g. \"https://example.com\" verbatim. EAN-13 must be 12 or 13 digits (13th is auto-computed). Code 128 accepts ASCII alphanumerics.",
        +        "maxLength": 4296,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "ecLevel": {
        +        "default": "M",
        +        "description": "QR ONLY. Error correction level (L=7%, M=15%, Q=25%, H=30%). Ignored for code128/ean13/datamatrix/pdf417. Use H for printed media that may get smudged or partially covered (e.g. logo overlay).",
        +        "enum": [
        +          "L",
        +          "M",
        +          "Q",
        +          "H"
        +        ],
        +        "type": "string"
        +      },
        +      "format": {
        +        "description": "Barcode symbology to render.",
        +        "enum": [
        +          "qr",
        +          "code128",
        +          "ean13",
        +          "datamatrix",
        +          "pdf417"
        +        ],
        +        "type": "string"
        +      },
        +      "height": {
        +        "default": 200,
        +        "description": "Barcode height in PDF points (ignored for square symbologies like QR/Data Matrix).",
        +        "maximum": 500,
        +        "minimum": 30,
        +        "type": "number"
        +      },
        +      "type": {
        +        "const": "barcode"
        +      },
        +      "width": {
        +        "default": 200,
        +        "description": "Barcode width in PDF points.",
        +        "maximum": 500,
        +        "minimum": 30,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "format",
        +      "data"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Vector drawing from an SVG path `d` string or SVG markup. Supported: <path> <rect> (rx/ry) <circle> <ellipse> <line> <polyline> <polygon> and <text>/<tspan> (x, y, font-size, fill, text-anchor, dx/dy); fill / stroke / stroke-width attributes; double-quoted attributes only. NOT supported (silently ignored): transform, <g>, <use>, <image>, <defs>/<clipPath>, gradients, opacity, CSS/style, dash patterns, text word-wrap. No external reference is ever fetched (no XML parser: entities other than &amp; &lt; &gt; &quot; &apos; &nbsp; &#n; are dropped). Pure path operators — PDF/A-safe at every level.",
        +    "properties": {
        +      "align": {
        +        "default": "left",
        +        "description": "Horizontal placement inside the content width.",
        +        "enum": [
        +          "left",
        +          "center",
        +          "right"
        +        ],
        +        "type": "string"
        +      },
        +      "alt": {
        +        "description": "Accessible description (tagged /Figure /Alt). Always provide it for non-decorative content under PDF/A or PDF/UA.",
        +        "maxLength": 500,
        +        "type": "string"
        +      },
        +      "data": {
        +        "description": "Path `d` string or SVG markup (≤ 100 000 characters).",
        +        "maxLength": 100000,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "fill": {
        +        "anyOf": [
        +          {
        +            "pattern": "^(?:none|#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}))$",
        +            "type": "string"
        +          },
        +          {
        +            "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +            "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +            "type": "string"
        +          },
        +          {
        +            "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +            "items": {
        +              "maximum": 100,
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "maxItems": 4,
        +            "minItems": 4,
        +            "type": "array"
        +          }
        +        ],
        +        "description": "Hex colour or 'none' (default black)."
        +      },
        +      "height": {
        +        "description": "Render height in points (default 200).",
        +        "maximum": 1000,
        +        "minimum": 10,
        +        "type": "number"
        +      },
        +      "stroke": {
        +        "anyOf": [
        +          {
        +            "pattern": "^(?:none|#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}))$",
        +            "type": "string"
        +          },
        +          {
        +            "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +            "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +            "type": "string"
        +          },
        +          {
        +            "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +            "items": {
        +              "maximum": 100,
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "maxItems": 4,
        +            "minItems": 4,
        +            "type": "array"
        +          }
        +        ],
        +        "description": "Hex colour or 'none' (default none)."
        +      },
        +      "strokeWidth": {
        +        "description": "Stroke width in SVG user units (default 1).",
        +        "maximum": 50,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "type": {
        +        "const": "svg"
        +      },
        +      "viewBox": {
        +        "description": "[minX, minY, width, height] — overrides the viewBox of the markup; required for a bare path string that is not 0-based.",
        +        "items": {
        +          "type": "number"
        +        },
        +        "maxItems": 4,
        +        "minItems": 4,
        +        "type": "array"
        +      },
        +      "width": {
        +        "description": "Render width in points (default 200).",
        +        "maximum": 800,
        +        "minimum": 10,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "data"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Inline AcroForm field — same body as an add_form field. Under a PDF/A claim pass embedFonts:true so the field font is embedded too (PDFA_UNEMBEDDED_FORM_FONT otherwise; strict:true then fails the call).",
        +    "properties": {
        +      "checked": {
        +        "description": "Initial checked state for checkbox / radio fields.",
        +        "type": "boolean"
        +      },
        +      "fieldType": {
        +        "description": "Type of form control to render. Radio fields sharing a name form one radio group.",
        +        "enum": [
        +          "text",
        +          "textarea",
        +          "checkbox",
        +          "radio",
        +          "dropdown",
        +          "listbox"
        +        ],
        +        "type": "string"
        +      },
        +      "fontSize": {
        +        "description": "Font size for text rendering inside the field.",
        +        "maximum": 48,
        +        "minimum": 6,
        +        "type": "number"
        +      },
        +      "height": {
        +        "description": "Field height in points (default depends on the type).",
        +        "maximum": 300,
        +        "minimum": 10,
        +        "type": "number"
        +      },
        +      "label": {
        +        "description": "Human-readable label shown above the field.",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "maxLength": {
        +        "description": "Maximum character length for text/textarea fields.",
        +        "maximum": 32767,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "name": {
        +        "description": "Unique field name used as the PDF annotation identifier (/T).",
        +        "maxLength": 100,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "options": {
        +        "description": "Choices for dropdown, listbox or radio fields.",
        +        "items": {
        +          "maxLength": 200,
        +          "type": "string"
        +        },
        +        "maxItems": 100,
        +        "type": "array"
        +      },
        +      "placeholder": {
        +        "description": "Hint text shown while the field is empty.",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "readOnly": {
        +        "description": "Prevent editing of this field.",
        +        "type": "boolean"
        +      },
        +      "required": {
        +        "description": "Mark field as required.",
        +        "type": "boolean"
        +      },
        +      "type": {
        +        "const": "formField"
        +      },
        +      "value": {
        +        "description": "Pre-filled value. The key is 'value' (there is no defaultValue).",
        +        "maxLength": 2000,
        +        "type": "string"
        +      },
        +      "width": {
        +        "description": "Field width in points (default: full content width).",
        +        "maximum": 500,
        +        "minimum": 10,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "fieldType",
        +      "name"
        +    ],
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / embedFonts / description
        Previous value: -"Measure with the embedded Noto Sans Latin metrics instead of Helvetica — pass the same value you will give generate_basic_pdf. (Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.)"New value: +"Measure with the embedded Noto Sans Latin metrics instead of Helvetica — pass the same value you will give generate_basic_pdf. (Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB.)"
      • changedInput schema / properties / footerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / footerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / footerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / footerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / footerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / footerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / footerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / headerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / headerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / headerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / headerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / headerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / typography
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Fine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.",
        +  "properties": {
        +    "bindShortWords": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "maxLength": {
        +              "maximum": 3,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "words": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never end a line on a short word: up to maxLength letters (default 1), or exactly the listed words."
        +    },
        +    "fontFeatures": {
        +      "description": "OpenType features, later wins. tnum / lnum are no-ops on Noto Sans (TYPOGRAPHY_FEATURE_INEFFECTIVE).",
        +      "items": {
        +        "enum": [
        +          "tnum",
        +          "pnum",
        +          "lnum",
        +          "onum",
        +          "zero",
        +          "ordn",
        +          "sups",
        +          "subs",
        +          "smcp",
        +          "c2sc",
        +          "case"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 11,
        +      "type": "array",
        +      "uniqueItems": true
        +    },
        +    "hyphenationLanguage": {
        +      "description": "BCP 47 tag; no effect here (no hyphenation provider installed).",
        +      "maxLength": 35,
        +      "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
        +      "type": "string"
        +    },
        +    "keepHeadingsWithNext": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "minLines": {
        +              "maximum": 10,
        +              "minimum": 1,
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never strand a heading at a page foot. true = { minLines: 2 }."
        +    },
        +    "kerning": {
        +      "description": "Pair kerning (GPOS).",
        +      "type": "boolean"
        +    },
        +    "metrics": {
        +      "description": "Base-14 text: 'exact' uses the AFM widths (different wraps). Default 'approximate'.",
        +      "enum": [
        +        "approximate",
        +        "exact"
        +      ],
        +      "type": "string"
        +    },
        +    "opticalMargins": {
        +      "description": "Hang punctuation into the margin of align:'justify' text.",
        +      "type": "boolean"
        +    },
        +    "orphans": {
        +      "description": "Min lines left at a page foot (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "punctuationSpacing": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "fr",
        +            "fr-CA"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "char": {
        +                "maxLength": 2,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "side": {
        +                "enum": [
        +                  "before",
        +                  "after"
        +                ],
        +                "type": "string"
        +              },
        +              "space": {
        +                "description": "U+00A0 / U+202F (narrow needs embedFonts).",
        +                "enum": [
        +                  "nbsp",
        +                  "narrow"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "char",
        +              "side",
        +              "space"
        +            ],
        +            "type": "object"
        +          },
        +          "maxItems": 32,
        +          "type": "array"
        +        }
        +      ],
        +      "description": "No-break spaces next to punctuation (existing spaces only). 'fr': narrow before ; ! ?, no-break before ':' and inside « ». 'fr-CA': ':' and « » only. Or explicit rules."
        +    },
        +    "splitParagraphs": {
        +      "description": "Paragraphs may break across pages at a line boundary (default: atomic).",
        +      "type": "boolean"
        +    },
        +    "unitBinding": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "units": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "No-break space between a number and its unit ('150 €', '12 kg'); units replaces the built-in list."
        +    },
        +    "widows": {
        +      "description": "Min lines carried over (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedinspect_pdf5 fields changed
      • changedInput schema / properties / check / description
        Previous value: -"CI assertions → checks (requested keys only) + checksPassed (all hold). 'signed' = a signature field with signed content exists (structural; validity is verify_pdf's job), 'placeholder' = an unsigned placeholder exists, 'dss' = /DSS present, 'docTimestamp' = a /DocTimeStamp exists, 'trapped' = /Info /Trapped set, 'annotations' = at least one page annotation exists."New value: +"CI assertions → checks (requested keys only) + checksPassed (all hold). 'signed' = a signature field with signed content exists (structural; validity is verify_pdf's job), 'placeholder' = an unsigned placeholder exists, 'dss' = /DSS present, 'docTimestamp' = a /DocTimeStamp exists, 'trapped' = /Info /Trapped set, 'annotations' = at least one page annotation exists, 'pdfx' = the XMP claims PDF/X (the claim, not its validity — validate_pdf standard:'pdf-x-4')."
      • changedInput schema / properties / check / items / enum
        Previous value: -[
        -  "pdfa",
        -  "signed",
        -  "encrypted",
        -  "placeholder",
        -  "attachments",
        -  "dss",
        -  "docTimestamp",
        -  "trapped",
        -  "annotations"
        -]New value: +[
        +  "pdfa",
        +  "signed",
        +  "encrypted",
        +  "placeholder",
        +  "attachments",
        +  "dss",
        +  "docTimestamp",
        +  "trapped",
        +  "annotations",
        +  "pdfx"
        +]
      • changedInput schema / properties / check / maxItems
        Previous value: -9New value: +10
      • changedInput schema / properties / verbosity / description
        Previous value: -"'full' (default) or 'summary' (scalars only: version, pageCount, encryption, pdfA, signatureCount, hasSignaturePlaceholder, attachmentCount, + docTimestampCount / trapped / checksPassed when present; arrays and dss dropped)."New value: +"'full' (default) or 'summary' (scalars only: version, pageCount, encryption, pdfA, signatureCount, hasSignaturePlaceholder, attachmentCount, + docTimestampCount / trapped / pdfX / checksPassed when present; arrays and dss dropped)."
      • addedOutput schema / properties / pdfX
        Added value: +{
        +  "description": "PDF/X claim from XMP (pdfxid:GTS_PDFXVersion, e.g. 'PDF/X-4'), present only when the document makes one. A claim, not a verdict: validate_pdf standard:'pdf-x-4' checks it.",
        +  "type": "string"
        +}
    • Changedmerge_pdfs1 field changed
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedprepare_signature_placeholder23 fields changed
      • changedInput schema / properties / creationDate / description
        Previous value: -"ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs."New value: +"ISO-8601 instant for /CreationDate (+ XMP, the trailer /ID and the {date} placeholder), written in UTC. Pin it for byte-identical output across calls and hosts; omitted = wall clock, so every call differs."
      • changedInput schema / properties / embedFonts / description
        Previous value: -"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB."New value: +"Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A or PDF/X claim (every font embedded) and for strict=true; adds ~0.3 MiB."
      • changedInput schema / properties / footerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / footerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / footerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / footerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / footerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / footerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / footerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / center / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • addedInput schema / properties / headerTemplate / properties / color / anyOf
        Added value: +[
        +  {
        +    "pattern": "^#[0-9a-fA-F]{6}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK operands 'C M Y K', each 0.0–1.0.",
        +    "pattern": "^(?:0(?:\\.\\d+)?|1(?:\\.0+)?)(?: (?:0(?:\\.\\d+)?|1(?:\\.0+)?)){3}$",
        +    "type": "string"
        +  },
        +  {
        +    "description": "DeviceCMYK ink percentages [c, m, y, k], each 0–100.",
        +    "items": {
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "maxItems": 4,
        +    "minItems": 4,
        +    "type": "array"
        +  }
        +]
      • changedInput schema / properties / headerTemplate / properties / color / description
        Previous value: -"Hex colour."New value: +"Hex colour (#RRGGBB)."
      • removedInput schema / properties / headerTemplate / properties / color / pattern
        Removed value: -"^#[0-9a-fA-F]{6}$"
      • removedInput schema / properties / headerTemplate / properties / color / type
        Removed value: -"string"
      • changedInput schema / properties / headerTemplate / properties / left / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / headerTemplate / properties / right / description
        Previous value: -"Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate)."New value: +"Placeholders: {page} {pages} {title} {date} (UTC date of creationDate when pinned, else of the build)."
      • changedInput schema / properties / includeDiagnostics / description
        Previous value: -"Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty)."New value: +"Return the diagnostics raised while building (PDFA_*, PDFX_*, TYPOGRAPHY_*) as `diagnostics[]` (possibly empty)."
      • changedInput schema / properties / outputIntent / description
        Previous value: -"Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected)."New value: +"Custom OutputIntent (under pdfA or pdfx): an RGB, CMYK or Gray ICC profile + condition strings, replacing the built-in sRGB intent. The profile must be a real ICC file ('acsp' signature, consistent size — PRINT_ERROR otherwise); pdfx needs device class 'prtr'. Under a CMYK / Gray intent RGB content is mapped through a calibrated default space."
      • changedInput schema / properties / outputIntent / properties / iccProfileBase64 / description
        Previous value: -"ICC profile bytes, base64 (RGB, ≤ 8 MiB)."New value: +"ICC profile bytes, base64 (RGB, CMYK or Gray; ≤ 8 MiB)."
      • changedInput schema / properties / print / properties / marks / oneOf
        Previous value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "crop": {
        -        "description": "Corner crop (trim) marks. Default true.",
        -        "type": "boolean"
        -      },
        -      "length": {
        -        "description": "Mark length in points. Default 14.",
        -        "maximum": 100,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "offset": {
        -        "description": "Gap between TrimBox and marks in points. Default 5.",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "registration": {
        -        "description": "Edge-midpoint registration targets. Default true.",
        -        "type": "boolean"
        -      },
        -      "weight": {
        -        "description": "Stroke width in points. Default 0.25.",
        -        "maximum": 5,
        -        "minimum": 0.05,
        -        "type": "number"
        -      }
        -    },
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "colourBars": {
        +        "anyOf": [
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "additionalProperties": false,
        +            "properties": {
        +              "size": {
        +                "description": "Patch size in points. Default 12.",
        +                "maximum": 72,
        +                "minimum": 4,
        +                "type": "number"
        +              },
        +              "tints": {
        +                "description": "Add the four 50 % tint patches. Default true.",
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          }
        +        ],
        +        "description": "Colour control strip in the bleed (C M Y K solids + their 50 % tints): true for defaults. Off by default; needs a bleed of about 5 mm (14.17 pt) and is skipped when the strip would not fit."
        +      },
        +      "crop": {
        +        "description": "Corner crop (trim) marks. Default true.",
        +        "type": "boolean"
        +      },
        +      "length": {
        +        "description": "Mark length in points. Default 14.",
        +        "maximum": 100,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "offset": {
        +        "description": "Gap between TrimBox and marks in points. Default 5.",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "registration": {
        +        "description": "Edge-midpoint registration targets. Default true.",
        +        "type": "boolean"
        +      },
        +      "weight": {
        +        "description": "Stroke width in points. Default 0.25.",
        +        "maximum": 5,
        +        "minimum": 0.05,
        +        "type": "number"
        +      }
        +    },
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / strict / description
        Previous value: -"Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true."New value: +"Fail instead of producing a file the engine warns about: a PDFA_* diagnostic → PDF_A_COMPLIANCE_VIOLATION (e.g. PDFA_NO_FONT_ENTRIES without embedFonts), a PDFX_* one → PDF_X_COMPLIANCE_VIOLATION, any other → DIAGNOSTIC_ESCALATED. Pair with embedFonts=true."
      • addedInput schema / properties / typography
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Fine typography, all opt-in (omitted = unchanged bytes). kerning, fontFeatures and the 'fr' narrow space need embedFonts:true. No hyphenation dictionary is installed: use soft hyphens (U+00AD). See the typography prompt.",
        +  "properties": {
        +    "bindShortWords": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "maxLength": {
        +              "maximum": 3,
        +              "minimum": 1,
        +              "type": "integer"
        +            },
        +            "words": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never end a line on a short word: up to maxLength letters (default 1), or exactly the listed words."
        +    },
        +    "fontFeatures": {
        +      "description": "OpenType features, later wins. tnum / lnum are no-ops on Noto Sans (TYPOGRAPHY_FEATURE_INEFFECTIVE).",
        +      "items": {
        +        "enum": [
        +          "tnum",
        +          "pnum",
        +          "lnum",
        +          "onum",
        +          "zero",
        +          "ordn",
        +          "sups",
        +          "subs",
        +          "smcp",
        +          "c2sc",
        +          "case"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 11,
        +      "type": "array",
        +      "uniqueItems": true
        +    },
        +    "hyphenationLanguage": {
        +      "description": "BCP 47 tag; no effect here (no hyphenation provider installed).",
        +      "maxLength": 35,
        +      "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$",
        +      "type": "string"
        +    },
        +    "keepHeadingsWithNext": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "minLines": {
        +              "maximum": 10,
        +              "minimum": 1,
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "Never strand a heading at a page foot. true = { minLines: 2 }."
        +    },
        +    "kerning": {
        +      "description": "Pair kerning (GPOS).",
        +      "type": "boolean"
        +    },
        +    "metrics": {
        +      "description": "Base-14 text: 'exact' uses the AFM widths (different wraps). Default 'approximate'.",
        +      "enum": [
        +        "approximate",
        +        "exact"
        +      ],
        +      "type": "string"
        +    },
        +    "opticalMargins": {
        +      "description": "Hang punctuation into the margin of align:'justify' text.",
        +      "type": "boolean"
        +    },
        +    "orphans": {
        +      "description": "Min lines left at a page foot (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "punctuationSpacing": {
        +      "anyOf": [
        +        {
        +          "enum": [
        +            "fr",
        +            "fr-CA"
        +          ],
        +          "type": "string"
        +        },
        +        {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "char": {
        +                "maxLength": 2,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "side": {
        +                "enum": [
        +                  "before",
        +                  "after"
        +                ],
        +                "type": "string"
        +              },
        +              "space": {
        +                "description": "U+00A0 / U+202F (narrow needs embedFonts).",
        +                "enum": [
        +                  "nbsp",
        +                  "narrow"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "char",
        +              "side",
        +              "space"
        +            ],
        +            "type": "object"
        +          },
        +          "maxItems": 32,
        +          "type": "array"
        +        }
        +      ],
        +      "description": "No-break spaces next to punctuation (existing spaces only). 'fr': narrow before ; ! ?, no-break before ':' and inside « ». 'fr-CA': ':' and « » only. Or explicit rules."
        +    },
        +    "splitParagraphs": {
        +      "description": "Paragraphs may break across pages at a line boundary (default: atomic).",
        +      "type": "boolean"
        +    },
        +    "unitBinding": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "units": {
        +              "items": {
        +                "maxLength": 16,
        +                "minLength": 1,
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ],
        +      "description": "No-break space between a number and its unit ('150 €', '12 kg'); units replaces the built-in list."
        +    },
        +    "widows": {
        +      "description": "Min lines carried over (default 2; needs splitParagraphs).",
        +      "maximum": 10,
        +      "minimum": 1,
        +      "type": "integer"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedsign_pdf4 fields changed
      • changedInput schema / properties / certDerBase64 / description
        Previous value: -"Base64 of the signer X.509 certificate in DER form. Convert from PEM with: openssl x509 -in cert.pem -outform DER | base64 -w0"New value: +"Base64 of the signer X.509 certificate in DER form. Convert from PEM with: openssl x509 -in cert.pem -outform DER | openssl base64 -A"
      • changedInput schema / properties / ecPrivateKeyDerBase64 / description
        Previous value: -"Base64 of an ECDSA P-256 private key in SEC1 (RFC 5915) or PKCS#8 (RFC 5208) DER form. Convert from PEM with: openssl pkey -in key.pem -outform DER | base64 -w0  Mutually exclusive with ecPrivateScalarHex."New value: +"Base64 of an ECDSA P-256 private key in SEC1 (RFC 5915) or PKCS#8 (RFC 5208) DER form. Convert from PEM with: openssl pkey -in key.pem -outform DER | openssl base64 -A  Mutually exclusive with ecPrivateScalarHex."
      • changedInput schema / properties / rsaKeyPkcs1DerBase64 / description
        Previous value: -"Base64 of the RSA private key in DER form — PKCS#1 RSAPrivateKey (openssl rsa -in key.pem -outform DER -traditional | base64 -w0) or PKCS#8 PrivateKeyInfo (openssl pkey -in key.pem -outform DER | base64 -w0). NOT PEM. Required for the rsa-* algorithms."New value: +"Base64 of the RSA private key in DER form — PKCS#1 RSAPrivateKey (openssl rsa -in key.pem -outform DER -traditional | openssl base64 -A) or PKCS#8 PrivateKeyInfo (openssl pkey -in key.pem -outform DER | openssl base64 -A). NOT PEM. Required for the rsa-* algorithms."
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedtimestamp_pdf1 field changed
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedupdate_metadata1 field changed
      • changedOutput schema / properties / diagnostics / description
        Previous value: -"PDF/A diagnostics (when includeDiagnostics=true)."New value: +"Engine diagnostics (when includeDiagnostics=true)."
    • Changedvalidate_pdf7 fields changed
      • changedInput schema / properties / pdfBase64 / description
        Previous value: -"Base64-encoded PDF bytes to validate for PDF/UA (ISO 14289-1) structural conformance."New value: +"Base64-encoded PDF bytes to validate for structural conformance."
      • addedInput schema / properties / standard
        Added value: +{
        +  "default": "pdf-ua-1",
        +  "description": "Rule set. 'pdf-ua-1' (default): PDF/UA accessibility structure (ISO 14289-1). 'pdf-x-4': PDF/X-4 print exchange (ISO 15930-7) — OutputIntent + prtr ICC profile, TrimBox, embedded fonts, no annotations / JavaScript / embedded files; structural prerequisites only, not a certified preflight (see caveats[]).",
        +  "enum": [
        +    "pdf-ua-1",
        +    "pdf-x-4"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / description
        Previous value: -"Structured PDF/UA validation result. Every property is optional because the result can be projected: verbosity:'summary' returns only the scalar summary fields, fields:[...] keeps a dot-path subset. Defaults return the full shape."New value: +"Structured PDF/UA or PDF/X-4 validation result. Every property is optional because the result can be projected: verbosity:'summary' returns only the scalar summary fields, fields:[...] keeps a dot-path subset. Defaults return the full shape."
      • addedOutput schema / properties / caveats
        Added value: +{
        +  "description": "standard 'pdf-x-4' only: what a valid verdict does NOT establish.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / errors / description
        Previous value: -"Blocking PDF/UA conformance violations. Empty when valid is true."New value: +"Blocking conformance violations. Empty when valid is true."
      • changedOutput schema / properties / standard / description
        Previous value: -"Conformance standard checked (ISO 14289-1)."New value: +"Conformance standard checked (ISO 14289-1 or ISO 15930-7)."
      • changedOutput schema / properties / standard / enum
        Previous value: -[
        -  "pdf-ua-1"
        -]New value: +[
        +  "pdf-ua-1",
        +  "pdf-x-4"
        +]
  2. 27 tool updates
    • Changedadd_attachment19 fields changed
      • addedInput schema / properties / compress
        Added value: +{
        +  "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / creationDate
        Added value: +{
        +  "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.",
        +  "format": "date-time",
        +  "type": "string"
        +}
      • addedInput schema / properties / debug
        Added value: +{
        +  "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / embedFonts
        Added value: +{
        +  "default": false,
        +  "description": "Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / footerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / headerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running header on every page (left / center / right zones); reserves 15 pt.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / includeDiagnostics
        Added value: +{
        +  "default": false,
        +  "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / margins
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.",
        +  "properties": {
        +    "bottom": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "left": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "right": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "top": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "top",
        +    "right",
        +    "bottom",
        +    "left"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / metadata
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.",
        +  "properties": {
        +    "author": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "keywords": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "subject": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "trapped": {
        +      "description": "/Trapped print flag.",
        +      "enum": [
        +        "True",
        +        "False",
        +        "Unknown"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / outputIntent
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).",
        +  "properties": {
        +    "iccProfileBase64": {
        +      "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).",
        +      "maxLength": 11000000,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "info": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "outputCondition": {
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "outputConditionIdentifier": {
        +      "description": "e.g. \"sRGB IEC61966-2.1\".",
        +      "maxLength": 200,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "registryName": {
        +      "description": "Default \"http://www.color.org\".",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "iccProfileBase64",
        +    "outputConditionIdentifier"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / outputMode / description
        Added value: +"'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured)."
      • addedInput schema / properties / outputPath / description
        Added value: +"Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..')."
      • addedInput schema / properties / pageSize
        Added value: +{
        +  "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.",
        +  "enum": [
        +    "A4",
        +    "Letter",
        +    "Legal",
        +    "A3",
        +    "Tabloid"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / print
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.",
        +  "properties": {
        +    "artBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "bleed": {
        +      "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.",
        +      "exclusiveMinimum": 0,
        +      "maximum": 200,
        +      "type": "number"
        +    },
        +    "bleedBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "cropBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "marks": {
        +      "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.",
        +      "oneOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "crop": {
        +              "description": "Corner crop (trim) marks. Default true.",
        +              "type": "boolean"
        +            },
        +            "length": {
        +              "description": "Mark length in points. Default 14.",
        +              "maximum": 100,
        +              "minimum": 1,
        +              "type": "number"
        +            },
        +            "offset": {
        +              "description": "Gap between TrimBox and marks in points. Default 5.",
        +              "maximum": 100,
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "registration": {
        +              "description": "Edge-midpoint registration targets. Default true.",
        +              "type": "boolean"
        +            },
        +            "weight": {
        +              "description": "Stroke width in points. Default 0.25.",
        +              "maximum": 5,
        +              "minimum": 0.05,
        +              "type": "number"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ]
        +    },
        +    "trimBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "userUnit": {
        +      "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.",
        +      "maximum": 75000,
        +      "minimum": 1,
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / strict
        Added value: +{
        +  "default": false,
        +  "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.",
        +  "type": "boolean"
        +}
      • changedOutput schema / description
        Previous value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`."
      • addedOutput schema / properties / diagnostics
        Added value: +{
        +  "description": "PDF/A diagnostics (when includeDiagnostics=true).",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "code": {
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      },
        +      "severity": {
        +        "enum": [
        +          "warning"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "code",
        +      "message",
        +      "severity"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / filePath / description
        Previous value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)."
      • addedOutput schema / properties / summary
        Added value: +{
        +  "additionalProperties": true,
        +  "description": "Tool-specific summary, when produced.",
        +  "type": "object"
        +}
    • Changedadd_barcode21 fields changed
      • addedInput schema / properties / compress
        Added value: +{
        +  "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / creationDate
        Added value: +{
        +  "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.",
        +  "format": "date-time",
        +  "type": "string"
        +}
      • addedInput schema / properties / debug
        Added value: +{
        +  "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / embedFonts
        Added value: +{
        +  "default": false,
        +  "description": "Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / encrypt
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.",
        +  "properties": {
        +    "algorithm": {
        +      "default": "aes128",
        +      "description": "aes128 (V4/R4, widest compatibility) or aes256 (V5/R6).",
        +      "enum": [
        +        "aes128",
        +        "aes256"
        +      ],
        +      "type": "string"
        +    },
        +    "ownerPassword": {
        +      "description": "Owner password (full access).",
        +      "maxLength": 4096,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "permissions": {
        +      "additionalProperties": false,
        +      "description": "Permission flags; each defaults to allowed.",
        +      "properties": {
        +        "copy": {
        +          "type": "boolean"
        +        },
        +        "extractText": {
        +          "type": "boolean"
        +        },
        +        "modify": {
        +          "type": "boolean"
        +        },
        +        "print": {
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "userPassword": {
        +      "description": "Open password; omitted/empty = opens without a prompt.",
        +      "maxLength": 4096,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "ownerPassword"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / footerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / headerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running header on every page (left / center / right zones); reserves 15 pt.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / includeDiagnostics
        Added value: +{
        +  "default": false,
        +  "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / margins
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.",
        +  "properties": {
        +    "bottom": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "left": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "right": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "top": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "top",
        +    "right",
        +    "bottom",
        +    "left"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / metadata
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.",
        +  "properties": {
        +    "author": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "keywords": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "subject": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "trapped": {
        +      "description": "/Trapped print flag.",
        +      "enum": [
        +        "True",
        +        "False",
        +        "Unknown"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / outputIntent
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).",
        +  "properties": {
        +    "iccProfileBase64": {
        +      "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).",
        +      "maxLength": 11000000,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "info": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "outputCondition": {
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "outputConditionIdentifier": {
        +      "description": "e.g. \"sRGB IEC61966-2.1\".",
        +      "maxLength": 200,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "registryName": {
        +      "description": "Default \"http://www.color.org\".",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "iccProfileBase64",
        +    "outputConditionIdentifier"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / outputMode / description
        Added value: +"'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured)."
      • addedInput schema / properties / outputPath / description
        Added value: +"Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..')."
      • addedInput schema / properties / pageSize
        Added value: +{
        +  "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.",
        +  "enum": [
        +    "A4",
        +    "Letter",
        +    "Legal",
        +    "A3",
        +    "Tabloid"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / pdfA / description
        Previous value: -"Optional PDF/A conformance level (powered by pdfnative v1.2). Use 'pdfa1b' for archival of simple text+images, 'pdfa2b'/'pdfa2u' for richer content (2u guarantees Unicode mapping), 'pdfa3b' when embedding source attachments (Factur-X / ZUGFeRD). Mutually exclusive with PDF encryption. See docs/guides/PDFA.md."New value: +"PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md."
      • addedInput schema / properties / print
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.",
        +  "properties": {
        +    "artBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "bleed": {
        +      "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.",
        +      "exclusiveMinimum": 0,
        +      "maximum": 200,
        +      "type": "number"
        +    },
        +    "bleedBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "cropBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "marks": {
        +      "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.",
        +      "oneOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "crop": {
        +              "description": "Corner crop (trim) marks. Default true.",
        +              "type": "boolean"
        +            },
        +            "length": {
        +              "description": "Mark length in points. Default 14.",
        +              "maximum": 100,
        +              "minimum": 1,
        +              "type": "number"
        +            },
        +            "offset": {
        +              "description": "Gap between TrimBox and marks in points. Default 5.",
        +              "maximum": 100,
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "registration": {
        +              "description": "Edge-midpoint registration targets. Default true.",
        +              "type": "boolean"
        +            },
        +            "weight": {
        +              "description": "Stroke width in points. Default 0.25.",
        +              "maximum": 5,
        +              "minimum": 0.05,
        +              "type": "number"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ]
        +    },
        +    "trimBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "userUnit": {
        +      "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.",
        +      "maximum": 75000,
        +      "minimum": 1,
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / strict
        Added value: +{
        +  "default": false,
        +  "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.",
        +  "type": "boolean"
        +}
      • changedOutput schema / description
        Previous value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`."
      • addedOutput schema / properties / diagnostics
        Added value: +{
        +  "description": "PDF/A diagnostics (when includeDiagnostics=true).",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "code": {
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      },
        +      "severity": {
        +        "enum": [
        +          "warning"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "code",
        +      "message",
        +      "severity"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / filePath / description
        Previous value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)."
      • addedOutput schema / properties / summary
        Added value: +{
        +  "additionalProperties": true,
        +  "description": "Tool-specific summary, when produced.",
        +  "type": "object"
        +}
    • Changedadd_chart29 fields changed
      • addedInput schema / properties / axis / properties / scale
        Added value: +{
        +  "description": "Value-axis scale. 'log' requires strictly positive values and is not available for stacked charts.",
        +  "enum": [
        +    "linear",
        +    "log"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / axis2
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Secondary RIGHT value axis (drawn only when a series sets yAxis:'right').",
        +  "properties": {
        +    "scale": {
        +      "enum": [
        +        "linear",
        +        "log"
        +      ],
        +      "type": "string"
        +    },
        +    "ticks": {
        +      "maximum": 20,
        +      "minimum": 2,
        +      "type": "integer"
        +    },
        +    "yMax": {
        +      "type": "number"
        +    },
        +    "yMin": {
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedInput schema / properties / chartType / description
        Previous value: -"Chart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'line' support multiple series."New value: +"Chart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'stackedBar'/'stackedBarH'/'line'/'area'/'scatter' support multiple series. 'scatter' requires xValues on every series and a positional xAxis.type ('linear' or 'time')."
      • changedInput schema / properties / chartType / enum
        Previous value: -[
        -  "bar",
        -  "barH",
        -  "line",
        -  "pie",
        -  "donut"
        -]New value: +[
        +  "bar",
        +  "barH",
        +  "stackedBar",
        +  "stackedBarH",
        +  "line",
        +  "area",
        +  "scatter",
        +  "pie",
        +  "donut"
        +]
      • addedInput schema / properties / compress
        Added value: +{
        +  "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / creationDate
        Added value: +{
        +  "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.",
        +  "format": "date-time",
        +  "type": "string"
        +}
      • addedInput schema / properties / dataLabels
        Added value: +{
        +  "description": "Per-point value labels: true for defaults, or an object to format them.",
        +  "oneOf": [
        +    {
        +      "type": "boolean"
        +    },
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "decimals": {
        +          "maximum": 6,
        +          "minimum": 0,
        +          "type": "integer"
        +        },
        +        "prefix": {
        +          "maxLength": 16,
        +          "type": "string"
        +        },
        +        "suffix": {
        +          "maxLength": 16,
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    }
        +  ]
        +}
      • addedInput schema / properties / debug
        Added value: +{
        +  "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / embedFonts
        Added value: +{
        +  "default": false,
        +  "description": "Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / encrypt
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.",
        +  "properties": {
        +    "algorithm": {
        +      "default": "aes128",
        +      "description": "aes128 (V4/R4, widest compatibility) or aes256 (V5/R6).",
        +      "enum": [
        +        "aes128",
        +        "aes256"
        +      ],
        +      "type": "string"
        +    },
        +    "ownerPassword": {
        +      "description": "Owner password (full access).",
        +      "maxLength": 4096,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "permissions": {
        +      "additionalProperties": false,
        +      "description": "Permission flags; each defaults to allowed.",
        +      "properties": {
        +        "copy": {
        +          "type": "boolean"
        +        },
        +        "extractText": {
        +          "type": "boolean"
        +        },
        +        "modify": {
        +          "type": "boolean"
        +        },
        +        "print": {
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "userPassword": {
        +      "description": "Open password; omitted/empty = opens without a prompt.",
        +      "maxLength": 4096,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "ownerPassword"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / footerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / headerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running header on every page (left / center / right zones); reserves 15 pt.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / includeDiagnostics
        Added value: +{
        +  "default": false,
        +  "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / labelRotation
        Added value: +{
        +  "description": "Rotate category labels counter-clockwise by this many degrees (disables the automatic stride).",
        +  "maximum": 90,
        +  "minimum": 0,
        +  "type": "number"
        +}
      • addedInput schema / properties / labelStride
        Added value: +{
        +  "description": "Draw every Nth category label. Default: automatic (measured non-overlap); 1 draws every label.",
        +  "maximum": 1000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / margins
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.",
        +  "properties": {
        +    "bottom": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "left": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "right": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "top": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "top",
        +    "right",
        +    "bottom",
        +    "left"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / metadata
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.",
        +  "properties": {
        +    "author": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "keywords": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "subject": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "trapped": {
        +      "description": "/Trapped print flag.",
        +      "enum": [
        +        "True",
        +        "False",
        +        "Unknown"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / outputIntent
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).",
        +  "properties": {
        +    "iccProfileBase64": {
        +      "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).",
        +      "maxLength": 11000000,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "info": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "outputCondition": {
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "outputConditionIdentifier": {
        +      "description": "e.g. \"sRGB IEC61966-2.1\".",
        +      "maxLength": 200,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "registryName": {
        +      "description": "Default \"http://www.color.org\".",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "iccProfileBase64",
        +    "outputConditionIdentifier"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / pageSize
        Added value: +{
        +  "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.",
        +  "enum": [
        +    "A4",
        +    "Letter",
        +    "Legal",
        +    "A3",
        +    "Tabloid"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / pdfA / description
        Previous value: -"Optional PDF/A conformance level (powered by pdfnative v1.2). Use 'pdfa1b' for archival of simple text+images, 'pdfa2b'/'pdfa2u' for richer content (2u guarantees Unicode mapping), 'pdfa3b' when embedding source attachments (Factur-X / ZUGFeRD). Mutually exclusive with PDF encryption. See docs/guides/PDFA.md."New value: +"PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md."
      • addedInput schema / properties / print
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.",
        +  "properties": {
        +    "artBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "bleed": {
        +      "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.",
        +      "exclusiveMinimum": 0,
        +      "maximum": 200,
        +      "type": "number"
        +    },
        +    "bleedBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "cropBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "marks": {
        +      "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.",
        +      "oneOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "crop": {
        +              "description": "Corner crop (trim) marks. Default true.",
        +              "type": "boolean"
        +            },
        +            "length": {
        +              "description": "Mark length in points. Default 14.",
        +              "maximum": 100,
        +              "minimum": 1,
        +              "type": "number"
        +            },
        +            "offset": {
        +              "description": "Gap between TrimBox and marks in points. Default 5.",
        +              "maximum": 100,
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "registration": {
        +              "description": "Edge-midpoint registration targets. Default true.",
        +              "type": "boolean"
        +            },
        +            "weight": {
        +              "description": "Stroke width in points. Default 0.25.",
        +              "maximum": 5,
        +              "minimum": 0.05,
        +              "type": "number"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ]
        +    },
        +    "trimBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "userUnit": {
        +      "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.",
        +      "maximum": 75000,
        +      "minimum": 1,
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / series / items / properties / xValues
        Added value: +{
        +  "description": "Per-point x positions (same length as values) for scatter charts and for line/area charts with xAxis.type 'linear' or 'time'.",
        +  "items": {
        +    "description": "Positional x value: a number (linear axis) or an ISO-8601 date / epoch milliseconds (time axis).",
        +    "maxLength": 64,
        +    "type": [
        +      "number",
        +      "string"
        +    ]
        +  },
        +  "maxItems": 1000,
        +  "minItems": 1,
        +  "type": "array"
        +}
      • addedInput schema / properties / series / items / properties / yAxis
        Added value: +{
        +  "description": "Bind the series to the left (default) or the secondary right value axis (cartesian charts only; configure its range with 'axis2').",
        +  "enum": [
        +    "left",
        +    "right"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / strict
        Added value: +{
        +  "default": false,
        +  "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / xAxis
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Horizontal axis. 'category' (default) positions points by index; 'linear' / 'time' position them by series xValues (line/area/scatter only). Time ticks are UTC-deterministic.",
        +  "properties": {
        +    "grid": {
        +      "description": "Draw vertical gridlines.",
        +      "type": "boolean"
        +    },
        +    "max": {
        +      "description": "Axis maximum (number, or ISO-8601 / epoch ms for time axes).",
        +      "maxLength": 64,
        +      "type": [
        +        "number",
        +        "string"
        +      ]
        +    },
        +    "min": {
        +      "description": "Axis minimum (number, or ISO-8601 / epoch ms for time axes).",
        +      "maxLength": 64,
        +      "type": [
        +        "number",
        +        "string"
        +      ]
        +    },
        +    "ticks": {
        +      "maximum": 20,
        +      "minimum": 2,
        +      "type": "integer"
        +    },
        +    "type": {
        +      "enum": [
        +        "category",
        +        "linear",
        +        "time"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / description
        Previous value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`."
      • addedOutput schema / properties / diagnostics
        Added value: +{
        +  "description": "PDF/A diagnostics (when includeDiagnostics=true).",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "code": {
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      },
        +      "severity": {
        +        "enum": [
        +          "warning"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "code",
        +      "message",
        +      "severity"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / filePath / description
        Previous value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)."
      • addedOutput schema / properties / summary
        Added value: +{
        +  "additionalProperties": true,
        +  "description": "Tool-specific summary, when produced.",
        +  "type": "object"
        +}
    • Changedadd_form27 fields changed
      • addedInput schema / properties / compress
        Added value: +{
        +  "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / creationDate
        Added value: +{
        +  "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.",
        +  "format": "date-time",
        +  "type": "string"
        +}
      • addedInput schema / properties / debug
        Added value: +{
        +  "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / embedFonts
        Added value: +{
        +  "default": false,
        +  "description": "Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / encrypt
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.",
        +  "properties": {
        +    "algorithm": {
        +      "default": "aes128",
        +      "description": "aes128 (V4/R4, widest compatibility) or aes256 (V5/R6).",
        +      "enum": [
        +        "aes128",
        +        "aes256"
        +      ],
        +      "type": "string"
        +    },
        +    "ownerPassword": {
        +      "description": "Owner password (full access).",
        +      "maxLength": 4096,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "permissions": {
        +      "additionalProperties": false,
        +      "description": "Permission flags; each defaults to allowed.",
        +      "properties": {
        +        "copy": {
        +          "type": "boolean"
        +        },
        +        "extractText": {
        +          "type": "boolean"
        +        },
        +        "modify": {
        +          "type": "boolean"
        +        },
        +        "print": {
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "userPassword": {
        +      "description": "Open password; omitted/empty = opens without a prompt.",
        +      "maxLength": 4096,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "ownerPassword"
        +  ],
        +  "type": "object"
        +}
      • changedInput schema / properties / fields / items / properties / checked / description
        Previous value: -"Initial checked state for checkbox fields."New value: +"Initial checked state for checkbox / radio fields."
      • changedInput schema / properties / fields / items / properties / fieldType / description
        Previous value: -"Type of form control to render."New value: +"Type of form control to render. Radio fields sharing a name form one radio group."
      • changedInput schema / properties / fields / items / properties / fieldType / enum
        Previous value: -[
        -  "text",
        -  "textarea",
        -  "checkbox",
        -  "radio",
        -  "dropdown"
        -]New value: +[
        +  "text",
        +  "textarea",
        +  "checkbox",
        +  "radio",
        +  "dropdown",
        +  "listbox"
        +]
      • changedInput schema / properties / fields / items / properties / height / description
        Previous value: -"Field height in points (optional)."New value: +"Field height in points (default depends on the type)."
      • changedInput schema / properties / fields / items / properties / name / description
        Previous value: -"Unique field name used as the PDF annotation identifier."New value: +"Unique field name used as the PDF annotation identifier (/T)."
      • changedInput schema / properties / fields / items / properties / options / description
        Previous value: -"Choices for dropdown or radio fields."New value: +"Choices for dropdown, listbox or radio fields."
      • addedInput schema / properties / fields / items / properties / placeholder
        Added value: +{
        +  "description": "Hint text shown while the field is empty.",
        +  "maxLength": 200,
        +  "type": "string"
        +}
      • changedInput schema / properties / fields / items / properties / width / description
        Previous value: -"Field width in points (optional)."New value: +"Field width in points (default: full content width)."
      • addedInput schema / properties / footerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / headerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running header on every page (left / center / right zones); reserves 15 pt.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / includeDiagnostics
        Added value: +{
        +  "default": false,
        +  "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / margins
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.",
        +  "properties": {
        +    "bottom": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "left": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "right": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "top": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "top",
        +    "right",
        +    "bottom",
        +    "left"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / metadata
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.",
        +  "properties": {
        +    "author": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "keywords": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "subject": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "trapped": {
        +      "description": "/Trapped print flag.",
        +      "enum": [
        +        "True",
        +        "False",
        +        "Unknown"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / outputIntent
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).",
        +  "properties": {
        +    "iccProfileBase64": {
        +      "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).",
        +      "maxLength": 11000000,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "info": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "outputCondition": {
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "outputConditionIdentifier": {
        +      "description": "e.g. \"sRGB IEC61966-2.1\".",
        +      "maxLength": 200,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "registryName": {
        +      "description": "Default \"http://www.color.org\".",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "iccProfileBase64",
        +    "outputConditionIdentifier"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / pageSize
        Added value: +{
        +  "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.",
        +  "enum": [
        +    "A4",
        +    "Letter",
        +    "Legal",
        +    "A3",
        +    "Tabloid"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / pdfA / description
        Previous value: -"Optional PDF/A conformance level (powered by pdfnative v1.2). Use 'pdfa1b' for archival of simple text+images, 'pdfa2b'/'pdfa2u' for richer content (2u guarantees Unicode mapping), 'pdfa3b' when embedding source attachments (Factur-X / ZUGFeRD). Mutually exclusive with PDF encryption. See docs/guides/PDFA.md."New value: +"PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md."
      • addedInput schema / properties / print
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.",
        +  "properties": {
        +    "artBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "bleed": {
        +      "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.",
        +      "exclusiveMinimum": 0,
        +      "maximum": 200,
        +      "type": "number"
        +    },
        +    "bleedBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "cropBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "marks": {
        +      "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.",
        +      "oneOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "crop": {
        +              "description": "Corner crop (trim) marks. Default true.",
        +              "type": "boolean"
        +            },
        +            "length": {
        +              "description": "Mark length in points. Default 14.",
        +              "maximum": 100,
        +              "minimum": 1,
        +              "type": "number"
        +            },
        +            "offset": {
        +              "description": "Gap between TrimBox and marks in points. Default 5.",
        +              "maximum": 100,
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "registration": {
        +              "description": "Edge-midpoint registration targets. Default true.",
        +              "type": "boolean"
        +            },
        +            "weight": {
        +              "description": "Stroke width in points. Default 0.25.",
        +              "maximum": 5,
        +              "minimum": 0.05,
        +              "type": "number"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ]
        +    },
        +    "trimBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "userUnit": {
        +      "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.",
        +      "maximum": 75000,
        +      "minimum": 1,
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / strict
        Added value: +{
        +  "default": false,
        +  "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.",
        +  "type": "boolean"
        +}
      • changedOutput schema / description
        Previous value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`."
      • addedOutput schema / properties / diagnostics
        Added value: +{
        +  "description": "PDF/A diagnostics (when includeDiagnostics=true).",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "code": {
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      },
        +      "severity": {
        +        "enum": [
        +          "warning"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "code",
        +      "message",
        +      "severity"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / filePath / description
        Previous value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)."
      • addedOutput schema / properties / summary
        Added value: +{
        +  "additionalProperties": true,
        +  "description": "Tool-specific summary, when produced.",
        +  "type": "object"
        +}
    • Changedadd_international_text27 fields changed
      • addedInput schema / properties / compress
        Added value: +{
        +  "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / creationDate
        Added value: +{
        +  "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.",
        +  "format": "date-time",
        +  "type": "string"
        +}
      • addedInput schema / properties / debug
        Added value: +{
        +  "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / encrypt
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.",
        +  "properties": {
        +    "algorithm": {
        +      "default": "aes128",
        +      "description": "aes128 (V4/R4, widest compatibility) or aes256 (V5/R6).",
        +      "enum": [
        +        "aes128",
        +        "aes256"
        +      ],
        +      "type": "string"
        +    },
        +    "ownerPassword": {
        +      "description": "Owner password (full access).",
        +      "maxLength": 4096,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "permissions": {
        +      "additionalProperties": false,
        +      "description": "Permission flags; each defaults to allowed.",
        +      "properties": {
        +        "copy": {
        +          "type": "boolean"
        +        },
        +        "extractText": {
        +          "type": "boolean"
        +        },
        +        "modify": {
        +          "type": "boolean"
        +        },
        +        "print": {
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "userPassword": {
        +      "description": "Open password; omitted/empty = opens without a prompt.",
        +      "maxLength": 4096,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "ownerPassword"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / footerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / headerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running header on every page (left / center / right zones); reserves 15 pt.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / includeDiagnostics
        Added value: +{
        +  "default": false,
        +  "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / lang / anyOf
        Added value: +[
        +  {
        +    "enum": [
        +      "ar",
        +      "he",
        +      "th",
        +      "ja",
        +      "zh",
        +      "ko",
        +      "el",
        +      "hi",
        +      "bn",
        +      "ta",
        +      "ru",
        +      "ka",
        +      "hy",
        +      "tr",
        +      "pl",
        +      "vi",
        +      "latin",
        +      "te",
        +      "si",
        +      "bo",
        +      "km",
        +      "my",
        +      "am",
        +      "emoji",
        +      "math"
        +    ],
        +    "type": "string"
        +  },
        +  {
        +    "items": {
        +      "enum": [
        +        "ar",
        +        "he",
        +        "th",
        +        "ja",
        +        "zh",
        +        "ko",
        +        "el",
        +        "hi",
        +        "bn",
        +        "ta",
        +        "ru",
        +        "ka",
        +        "hy",
        +        "tr",
        +        "pl",
        +        "vi",
        +        "latin",
        +        "te",
        +        "si",
        +        "bo",
        +        "km",
        +        "my",
        +        "am",
        +        "emoji",
        +        "math"
        +      ],
        +      "type": "string"
        +    },
        +    "maxItems": 25,
        +    "minItems": 1,
        +    "type": "array"
        +  },
        +  {
        +    "description": "Comma-separated list of supported codes.",
        +    "maxLength": 80,
        +    "minLength": 2,
        +    "type": "string"
        +  }
        +]
      • removedInput schema / properties / lang / oneOf
        Removed value: -[
        -  {
        -    "enum": [
        -      "ar",
        -      "he",
        -      "th",
        -      "ja",
        -      "zh",
        -      "ko",
        -      "el",
        -      "hi",
        -      "bn",
        -      "ta",
        -      "ru",
        -      "ka",
        -      "hy",
        -      "tr",
        -      "pl",
        -      "vi",
        -      "latin",
        -      "te",
        -      "si",
        -      "bo",
        -      "km",
        -      "my",
        -      "am",
        -      "emoji",
        -      "math"
        -    ],
        -    "type": "string"
        -  },
        -  {
        -    "items": {
        -      "enum": [
        -        "ar",
        -        "he",
        -        "th",
        -        "ja",
        -        "zh",
        -        "ko",
        -        "el",
        -        "hi",
        -        "bn",
        -        "ta",
        -        "ru",
        -        "ka",
        -        "hy",
        -        "tr",
        -        "pl",
        -        "vi",
        -        "latin",
        -        "te",
        -        "si",
        -        "bo",
        -        "km",
        -        "my",
        -        "am",
        -        "emoji",
        -        "math"
        -      ],
        -      "type": "string"
        -    },
        -    "maxItems": 25,
        -    "minItems": 1,
        -    "type": "array"
        -  },
        -  {
        -    "description": "Comma-separated list of supported codes.",
        -    "maxLength": 80,
        -    "minLength": 2,
        -    "type": "string"
        -  }
        -]
      • addedInput schema / properties / margins
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.",
        +  "properties": {
        +    "bottom": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "left": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "right": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "top": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "top",
        +    "right",
        +    "bottom",
        +    "left"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / metadata
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.",
        +  "properties": {
        +    "author": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "keywords": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "subject": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "trapped": {
        +      "description": "/Trapped print flag.",
        +      "enum": [
        +        "True",
        +        "False",
        +        "Unknown"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedInput schema / properties / normalize / description
        Previous value: -"Unicode normalization form applied before shaping. Defaults to 'NFC' (recommended for international scripts: composes decomposed sequences for the widest glyph coverage). Override with 'NFD'/'NFKC'/'NFKD' only for specialised needs."New value: +"Unicode normalization before shaping. Default 'NFC' (widest glyph coverage); NFD/NFKC/NFKD or false for special needs."
      • addedInput schema / properties / outputIntent
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).",
        +  "properties": {
        +    "iccProfileBase64": {
        +      "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).",
        +      "maxLength": 11000000,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "info": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "outputCondition": {
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "outputConditionIdentifier": {
        +      "description": "e.g. \"sRGB IEC61966-2.1\".",
        +      "maxLength": 200,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "registryName": {
        +      "description": "Default \"http://www.color.org\".",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "iccProfileBase64",
        +    "outputConditionIdentifier"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / outputMode / description
        Added value: +"'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured)."
      • addedInput schema / properties / outputPath / description
        Added value: +"Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..')."
      • addedInput schema / properties / pageSize
        Added value: +{
        +  "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.",
        +  "enum": [
        +    "A4",
        +    "Letter",
        +    "Legal",
        +    "A3",
        +    "Tabloid"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / pdfA / description
        Previous value: -"Optional PDF/A conformance level. When set, Tagged PDF + sRGB OutputIntent + XMP metadata are emitted; the 'latin' Noto Sans fallback is auto-registered for non-WinAnsi Latin (ISO 19005-1 §6.3.4). See docs/guides/PDFA.md for the full authoring guide."New value: +"PDF/A level (Tagged PDF + sRGB OutputIntent + XMP). Fonts are embedded here, so the claim is valid as-is. See docs/guides/PDFA.md."
      • addedInput schema / properties / print
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.",
        +  "properties": {
        +    "artBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "bleed": {
        +      "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.",
        +      "exclusiveMinimum": 0,
        +      "maximum": 200,
        +      "type": "number"
        +    },
        +    "bleedBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "cropBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "marks": {
        +      "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.",
        +      "oneOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "crop": {
        +              "description": "Corner crop (trim) marks. Default true.",
        +              "type": "boolean"
        +            },
        +            "length": {
        +              "description": "Mark length in points. Default 14.",
        +              "maximum": 100,
        +              "minimum": 1,
        +              "type": "number"
        +            },
        +            "offset": {
        +              "description": "Gap between TrimBox and marks in points. Default 5.",
        +              "maximum": 100,
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "registration": {
        +              "description": "Edge-midpoint registration targets. Default true.",
        +              "type": "boolean"
        +            },
        +            "weight": {
        +              "description": "Stroke width in points. Default 0.25.",
        +              "maximum": 5,
        +              "minimum": 0.05,
        +              "type": "number"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ]
        +    },
        +    "trimBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "userUnit": {
        +      "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.",
        +      "maximum": 75000,
        +      "minimum": 1,
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / strict
        Added value: +{
        +  "default": false,
        +  "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / viewerPreferences / properties / duplex
        Added value: +{
        +  "description": "Print-dialog paper handling default (/Duplex): single-sided or double-sided flipping on the short/long edge.",
        +  "enum": [
        +    "simplex",
        +    "duplexFlipShortEdge",
        +    "duplexFlipLongEdge"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / viewerPreferences / properties / numCopies
        Added value: +{
        +  "description": "Default number of copies for the Print dialog (/NumCopies; viewers honour 2-5 per ISO 32000 Table 150).",
        +  "maximum": 1000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / viewerPreferences / properties / pickTrayByPDFSize
        Added value: +{
        +  "description": "Ask the printer to pick the input tray from the PDF page size (/PickTrayByPDFSize).",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / viewerPreferences / properties / printPageRange
        Added value: +{
        +  "description": "Default page ranges for the Print dialog (/PrintPageRange) as inclusive 1-based [first, last] pairs, e.g. [[1, 4], [7, 7]].",
        +  "items": {
        +    "items": {
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "maxItems": 2,
        +    "minItems": 2,
        +    "type": "array"
        +  },
        +  "maxItems": 100,
        +  "type": "array"
        +}
      • changedOutput schema / description
        Previous value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`."
      • addedOutput schema / properties / diagnostics
        Added value: +{
        +  "description": "PDF/A diagnostics (when includeDiagnostics=true).",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "code": {
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      },
        +      "severity": {
        +        "enum": [
        +          "warning"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "code",
        +      "message",
        +      "severity"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / filePath / description
        Previous value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)."
      • addedOutput schema / properties / summary
        Added value: +{
        +  "additionalProperties": true,
        +  "description": "Tool-specific summary, when produced.",
        +  "type": "object"
        +}
    • Addedadd_ltv
    • Changedadd_table42 fields changed
      • changedInput schema / properties / autoFitColumns / description
        Previous value: -"When true, column widths auto-fit content (pdfnative v1.1). Switches the backend to buildDocumentPDFBytes; byte output differs from the default path."New value: +"Auto-fit column widths to content. Output bytes then depend on text metrics (not byte-deterministic across content changes)."
      • changedInput schema / properties / caption / description
        Previous value: -"Caption rendered above the table (and emitted as /Caption structure element in tagged/PDF/A mode). pdfnative v1.2."New value: +"Caption rendered above the table (tagged as /Caption under PDF/A)."
      • changedInput schema / properties / cellBorders / description
        Previous value: -"Per-cell vector borders (pdfnative v1.4). Switches the backend to buildDocumentPDFBytes. Choose individual sides or `all`."New value: +"Per-cell vector borders (pure strokes, PDF/A-safe). Choose individual sides or `all`."
      • changedInput schema / properties / cellPadding / description
        Previous value: -"Horizontal cell padding in points applied to both insets (default 3). pdfnative v1.2."New value: +"Horizontal cell padding in points (default 3)."
      • changedInput schema / properties / cellVAlign / description
        Previous value: -"Vertical alignment of cell content (pdfnative v1.4). Switches the backend to buildDocumentPDFBytes."New value: +"Vertical alignment of cell content."
      • changedInput schema / properties / clipCells / description
        Previous value: -"When true, cell contents are clipped to column bounds via PDF clip-path operators (pdfnative v1.1). Recommended for PDF/A and visual safety. Switches the backend to buildDocumentPDFBytes."New value: +"Clip cell contents to the column bounds (PDF clip operators). Recommended for PDF/A and visual safety."
      • addedInput schema / properties / compress
        Added value: +{
        +  "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / creationDate
        Added value: +{
        +  "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.",
        +  "format": "date-time",
        +  "type": "string"
        +}
      • addedInput schema / properties / debug
        Added value: +{
        +  "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / embedFonts
        Added value: +{
        +  "default": false,
        +  "description": "Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / encrypt
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.",
        +  "properties": {
        +    "algorithm": {
        +      "default": "aes128",
        +      "description": "aes128 (V4/R4, widest compatibility) or aes256 (V5/R6).",
        +      "enum": [
        +        "aes128",
        +        "aes256"
        +      ],
        +      "type": "string"
        +    },
        +    "ownerPassword": {
        +      "description": "Owner password (full access).",
        +      "maxLength": 4096,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "permissions": {
        +      "additionalProperties": false,
        +      "description": "Permission flags; each defaults to allowed.",
        +      "properties": {
        +        "copy": {
        +          "type": "boolean"
        +        },
        +        "extractText": {
        +          "type": "boolean"
        +        },
        +        "modify": {
        +          "type": "boolean"
        +        },
        +        "print": {
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "userPassword": {
        +      "description": "Open password; omitted/empty = opens without a prompt.",
        +      "maxLength": 4096,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "ownerPassword"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / footerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / headerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running header on every page (left / center / right zones); reserves 15 pt.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / includeDiagnostics
        Added value: +{
        +  "default": false,
        +  "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / margins
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.",
        +  "properties": {
        +    "bottom": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "left": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "right": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "top": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "top",
        +    "right",
        +    "bottom",
        +    "left"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / metadata
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.",
        +  "properties": {
        +    "author": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "keywords": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "subject": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "trapped": {
        +      "description": "/Trapped print flag.",
        +      "enum": [
        +        "True",
        +        "False",
        +        "Unknown"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedInput schema / properties / minRowHeight / description
        Previous value: -"Minimum row height in points (default 12). pdfnative v1.2."New value: +"Minimum row height in points (default 12)."
      • addedInput schema / properties / outputIntent
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).",
        +  "properties": {
        +    "iccProfileBase64": {
        +      "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).",
        +      "maxLength": 11000000,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "info": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "outputCondition": {
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "outputConditionIdentifier": {
        +      "description": "e.g. \"sRGB IEC61966-2.1\".",
        +      "maxLength": 200,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "registryName": {
        +      "description": "Default \"http://www.color.org\".",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "iccProfileBase64",
        +    "outputConditionIdentifier"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / pageSize
        Added value: +{
        +  "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.",
        +  "enum": [
        +    "A4",
        +    "Letter",
        +    "Legal",
        +    "A3",
        +    "Tabloid"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / pdfA / description
        Previous value: -"Optional PDF/A conformance level (powered by pdfnative v1.2). Use 'pdfa1b' for archival of simple text+images, 'pdfa2b'/'pdfa2u' for richer content (2u guarantees Unicode mapping), 'pdfa3b' when embedding source attachments (Factur-X / ZUGFeRD). Mutually exclusive with PDF encryption. See docs/guides/PDFA.md."New value: +"PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md."
      • addedInput schema / properties / print
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.",
        +  "properties": {
        +    "artBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "bleed": {
        +      "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.",
        +      "exclusiveMinimum": 0,
        +      "maximum": 200,
        +      "type": "number"
        +    },
        +    "bleedBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "cropBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "marks": {
        +      "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.",
        +      "oneOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "crop": {
        +              "description": "Corner crop (trim) marks. Default true.",
        +              "type": "boolean"
        +            },
        +            "length": {
        +              "description": "Mark length in points. Default 14.",
        +              "maximum": 100,
        +              "minimum": 1,
        +              "type": "number"
        +            },
        +            "offset": {
        +              "description": "Gap between TrimBox and marks in points. Default 5.",
        +              "maximum": 100,
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "registration": {
        +              "description": "Edge-midpoint registration targets. Default true.",
        +              "type": "boolean"
        +            },
        +            "weight": {
        +              "description": "Stroke width in points. Default 0.25.",
        +              "maximum": 5,
        +              "minimum": 0.05,
        +              "type": "number"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ]
        +    },
        +    "trimBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "userUnit": {
        +      "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.",
        +      "maximum": 75000,
        +      "minimum": 1,
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedInput schema / properties / repeatHeader / description
        Previous value: -"Repeat the header row on every continuation page (pdfnative v1.2). Default true."New value: +"Repeat the header row on every continuation page (default true)."
      • addedInput schema / properties / strict
        Added value: +{
        +  "default": false,
        +  "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / viewerPreferences / properties / duplex
        Added value: +{
        +  "description": "Print-dialog paper handling default (/Duplex): single-sided or double-sided flipping on the short/long edge.",
        +  "enum": [
        +    "simplex",
        +    "duplexFlipShortEdge",
        +    "duplexFlipLongEdge"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / viewerPreferences / properties / numCopies
        Added value: +{
        +  "description": "Default number of copies for the Print dialog (/NumCopies; viewers honour 2-5 per ISO 32000 Table 150).",
        +  "maximum": 1000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / viewerPreferences / properties / pickTrayByPDFSize
        Added value: +{
        +  "description": "Ask the printer to pick the input tray from the PDF page size (/PickTrayByPDFSize).",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / viewerPreferences / properties / printPageRange
        Added value: +{
        +  "description": "Default page ranges for the Print dialog (/PrintPageRange) as inclusive 1-based [first, last] pairs, e.g. [[1, 4], [7, 7]].",
        +  "items": {
        +    "items": {
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "maxItems": 2,
        +    "minItems": 2,
        +    "type": "array"
        +  },
        +  "maxItems": 100,
        +  "type": "array"
        +}
      • changedInput schema / properties / watermark / description
        Previous value: -"Optional semi-transparent text watermark rendered on every page (e.g. 'DRAFT', 'CONFIDENTIAL'). Text only in this version. opacity < 1.0 is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency)."New value: +"Optional semi-transparent watermark rendered centred on every page: `text` (e.g. 'DRAFT'), `image` (JPEG/PNG), or both combined. At least one of text / image is required. opacity < 1.0 (text or image, including the defaults) is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency)."
      • changedInput schema / properties / watermark / properties / angle / description
        Previous value: -"Rotation in degrees (counterclockwise). Default -45."New value: +"Text rotation in degrees (counterclockwise). Default -45."
      • changedInput schema / properties / watermark / properties / color / description
        Previous value: -"RGB colour as a [r, g, b] triple in the 0.0–1.0 range. Default light gray [0.75, 0.75, 0.75]."New value: +"Text RGB colour as a [r, g, b] triple in the 0.0–1.0 range. Default light gray [0.75, 0.75, 0.75]."
      • changedInput schema / properties / watermark / properties / fontSize / description
        Previous value: -"Font size in points. Default 60, auto-fit to the page."New value: +"Text font size in points. Default 60, auto-fit to the page."
      • addedInput schema / properties / watermark / properties / image
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Image watermark (JPEG or PNG) centred on every page, optionally combined with `text`. Bytes are validated against the JPEG/PNG magic numbers; mimeType must match.",
        +  "properties": {
        +    "height": {
        +      "description": "Display height in points (default: from the image pixel size).",
        +      "exclusiveMinimum": 0,
        +      "maximum": 14400,
        +      "type": "number"
        +    },
        +    "imageBase64": {
        +      "description": "Base64-encoded JPEG or 8-bit opaque PNG bytes (max 8 MiB decoded; alpha-channel, palette and interlaced PNGs are rejected with a remedy). Plain base64, no data: URI prefix.",
        +      "maxLength": 12000000,
        +      "minLength": 4,
        +      "type": "string"
        +    },
        +    "mimeType": {
        +      "description": "'image/jpeg' or 'image/png' — must match the actual bytes.",
        +      "enum": [
        +        "image/jpeg",
        +        "image/png"
        +      ],
        +      "type": "string"
        +    },
        +    "opacity": {
        +      "description": "Image opacity 0.0–1.0. Default 0.10.",
        +      "maximum": 1,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "width": {
        +      "description": "Display width in points (default: from the image pixel size).",
        +      "exclusiveMinimum": 0,
        +      "maximum": 14400,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "imageBase64",
        +    "mimeType"
        +  ],
        +  "type": "object"
        +}
      • changedInput schema / properties / watermark / properties / opacity / description
        Previous value: -"Opacity 0.0–1.0. Default 0.15."New value: +"Text opacity 0.0–1.0. Default 0.15. (Image opacity is image.opacity.)"
      • changedInput schema / properties / watermark / properties / position / description
        Previous value: -"'background' (behind page content, default) or 'foreground' (above it)."New value: +"'background' (behind page content, default) or 'foreground' (above it). Applies to text and image alike."
      • changedInput schema / properties / watermark / properties / text / description
        Previous value: -"Watermark text."New value: +"Watermark text. Optional when `image` is given."
      • removedInput schema / properties / watermark / required
        Removed value: -[
        -  "text"
        -]
      • changedInput schema / properties / wrap / description
        Previous value: -"Cell wrap policy (pdfnative v1.2). 'auto' (default) wraps only when a cell overflows; 'always' wraps every cell; 'never' uses v1.1 character truncation."New value: +"Cell wrap policy: 'auto' (default) wraps only overflowing cells; 'always' wraps every cell; 'never' truncates."
      • changedInput schema / properties / zebra / description
        Previous value: -"Enable zebra striping (alternate-row light tint, PDF/A-1b safe). pdfnative v1.2."New value: +"Alternate-row light tint (static fill, PDF/A-1b safe)."
      • changedOutput schema / description
        Previous value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`."
      • addedOutput schema / properties / diagnostics
        Added value: +{
        +  "description": "PDF/A diagnostics (when includeDiagnostics=true).",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "code": {
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      },
        +      "severity": {
        +        "enum": [
        +          "warning"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "code",
        +      "message",
        +      "severity"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / filePath / description
        Previous value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)."
      • addedOutput schema / properties / summary
        Added value: +{
        +  "additionalProperties": true,
        +  "description": "Tool-specific summary, when produced.",
        +  "type": "object"
        +}
    • Changedannotate_pdf6 fields changed
      • addedInput schema / properties / outputMode / description
        Added value: +"'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured)."
      • addedInput schema / properties / outputPath / description
        Added value: +"Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..')."
      • changedOutput schema / description
        Previous value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`."
      • addedOutput schema / properties / diagnostics
        Added value: +{
        +  "description": "PDF/A diagnostics (when includeDiagnostics=true).",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "code": {
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      },
        +      "severity": {
        +        "enum": [
        +          "warning"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "code",
        +      "message",
        +      "severity"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / filePath / description
        Previous value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)."
      • addedOutput schema / properties / summary
        Added value: +{
        +  "additionalProperties": true,
        +  "description": "Tool-specific summary, when produced.",
        +  "type": "object"
        +}
    • Changeddecrypt_pdf5 fields changed
      • addedInput schema / properties / outputMode / description
        Added value: +"'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured)."
      • changedOutput schema / description
        Previous value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`."
      • addedOutput schema / properties / diagnostics
        Added value: +{
        +  "description": "PDF/A diagnostics (when includeDiagnostics=true).",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "code": {
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      },
        +      "severity": {
        +        "enum": [
        +          "warning"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "code",
        +      "message",
        +      "severity"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / filePath / description
        Previous value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)."
      • addedOutput schema / properties / summary
        Added value: +{
        +  "additionalProperties": true,
        +  "description": "Tool-specific summary, when produced.",
        +  "type": "object"
        +}
    • Changedembed_image23 fields changed
      • addedInput schema / properties / align
        Added value: +{
        +  "default": "left",
        +  "description": "Horizontal placement of the image inside the content width.",
        +  "enum": [
        +    "left",
        +    "center",
        +    "right"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / alt
        Added value: +{
        +  "description": "Accessible description of the image (tagged /Figure /Alt). Provide it for non-decorative images under PDF/A or PDF/UA.",
        +  "maxLength": 500,
        +  "type": "string"
        +}
      • addedInput schema / properties / compress
        Added value: +{
        +  "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / creationDate
        Added value: +{
        +  "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.",
        +  "format": "date-time",
        +  "type": "string"
        +}
      • addedInput schema / properties / debug
        Added value: +{
        +  "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / embedFonts
        Added value: +{
        +  "default": false,
        +  "description": "Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / encrypt
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.",
        +  "properties": {
        +    "algorithm": {
        +      "default": "aes128",
        +      "description": "aes128 (V4/R4, widest compatibility) or aes256 (V5/R6).",
        +      "enum": [
        +        "aes128",
        +        "aes256"
        +      ],
        +      "type": "string"
        +    },
        +    "ownerPassword": {
        +      "description": "Owner password (full access).",
        +      "maxLength": 4096,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "permissions": {
        +      "additionalProperties": false,
        +      "description": "Permission flags; each defaults to allowed.",
        +      "properties": {
        +        "copy": {
        +          "type": "boolean"
        +        },
        +        "extractText": {
        +          "type": "boolean"
        +        },
        +        "modify": {
        +          "type": "boolean"
        +        },
        +        "print": {
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "userPassword": {
        +      "description": "Open password; omitted/empty = opens without a prompt.",
        +      "maxLength": 4096,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "ownerPassword"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / footerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / headerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running header on every page (left / center / right zones); reserves 15 pt.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedInput schema / properties / imageBase64 / description
        Previous value: -"Base64-encoded image bytes. Supports JPEG and PNG formats."New value: +"Base64 image bytes. JPEG (baseline; 1, 3 or 4 components — CMYK raises PDFA_DEVICE_CMYK_IMAGE under PDF/A) or PNG (8-bit greyscale/RGB, non-interlaced; alpha-channel and palette PNGs are rejected with a remedy). No data: URI."
      • addedInput schema / properties / includeDiagnostics
        Added value: +{
        +  "default": false,
        +  "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / margins
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.",
        +  "properties": {
        +    "bottom": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "left": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "right": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "top": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "top",
        +    "right",
        +    "bottom",
        +    "left"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / metadata
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.",
        +  "properties": {
        +    "author": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "keywords": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "subject": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "trapped": {
        +      "description": "/Trapped print flag.",
        +      "enum": [
        +        "True",
        +        "False",
        +        "Unknown"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedInput schema / properties / mimeType / description
        Previous value: -"MIME type of the image. Must match the actual encoding of imageBase64."New value: +"MIME type of the image. Must match the actual encoding of imageBase64 (magic bytes are checked)."
      • addedInput schema / properties / outputIntent
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).",
        +  "properties": {
        +    "iccProfileBase64": {
        +      "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).",
        +      "maxLength": 11000000,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "info": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "outputCondition": {
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "outputConditionIdentifier": {
        +      "description": "e.g. \"sRGB IEC61966-2.1\".",
        +      "maxLength": 200,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "registryName": {
        +      "description": "Default \"http://www.color.org\".",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "iccProfileBase64",
        +    "outputConditionIdentifier"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / pageSize
        Added value: +{
        +  "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.",
        +  "enum": [
        +    "A4",
        +    "Letter",
        +    "Legal",
        +    "A3",
        +    "Tabloid"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / pdfA / description
        Previous value: -"Optional PDF/A conformance level (powered by pdfnative v1.2). Use 'pdfa1b' for archival of simple text+images, 'pdfa2b'/'pdfa2u' for richer content (2u guarantees Unicode mapping), 'pdfa3b' when embedding source attachments (Factur-X / ZUGFeRD). Mutually exclusive with PDF encryption. See docs/guides/PDFA.md."New value: +"PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md."
      • addedInput schema / properties / print
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.",
        +  "properties": {
        +    "artBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "bleed": {
        +      "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.",
        +      "exclusiveMinimum": 0,
        +      "maximum": 200,
        +      "type": "number"
        +    },
        +    "bleedBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "cropBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "marks": {
        +      "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.",
        +      "oneOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "crop": {
        +              "description": "Corner crop (trim) marks. Default true.",
        +              "type": "boolean"
        +            },
        +            "length": {
        +              "description": "Mark length in points. Default 14.",
        +              "maximum": 100,
        +              "minimum": 1,
        +              "type": "number"
        +            },
        +            "offset": {
        +              "description": "Gap between TrimBox and marks in points. Default 5.",
        +              "maximum": 100,
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "registration": {
        +              "description": "Edge-midpoint registration targets. Default true.",
        +              "type": "boolean"
        +            },
        +            "weight": {
        +              "description": "Stroke width in points. Default 0.25.",
        +              "maximum": 5,
        +              "minimum": 0.05,
        +              "type": "number"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ]
        +    },
        +    "trimBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "userUnit": {
        +      "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.",
        +      "maximum": 75000,
        +      "minimum": 1,
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / strict
        Added value: +{
        +  "default": false,
        +  "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.",
        +  "type": "boolean"
        +}
      • changedOutput schema / description
        Previous value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`."
      • addedOutput schema / properties / diagnostics
        Added value: +{
        +  "description": "PDF/A diagnostics (when includeDiagnostics=true).",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "code": {
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      },
        +      "severity": {
        +        "enum": [
        +          "warning"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "code",
        +      "message",
        +      "severity"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / filePath / description
        Previous value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)."
      • addedOutput schema / properties / summary
        Added value: +{
        +  "additionalProperties": true,
        +  "description": "Tool-specific summary, when produced.",
        +  "type": "object"
        +}
    • Changedencrypt_pdf9 fields changed
      • changedInput schema / properties / algorithm / description
        Previous value: -"Content cipher: aes128 (V4/R4, widest compatibility) or aes256 (V5/R6, strongest)."New value: +"aes128 (V4/R4, widest compatibility) or aes256 (V5/R6)."
      • addedInput schema / properties / outputMode / description
        Added value: +"'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured)."
      • changedInput schema / properties / ownerPassword / description
        Previous value: -"Owner password (required, non-empty). Controls permissions and full access."New value: +"Owner password (full access)."
      • changedInput schema / properties / permissions / description
        Previous value: -"Access permission flags (enforced by conforming readers). Each defaults to allowed when omitted."New value: +"Permission flags; each defaults to allowed."
      • changedInput schema / properties / userPassword / description
        Previous value: -"User (open) password. Omitted or empty string means the document opens without a password prompt."New value: +"Open password; omitted/empty = opens without a prompt."
      • changedOutput schema / description
        Previous value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`."
      • addedOutput schema / properties / diagnostics
        Added value: +{
        +  "description": "PDF/A diagnostics (when includeDiagnostics=true).",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "code": {
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      },
        +      "severity": {
        +        "enum": [
        +          "warning"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "code",
        +      "message",
        +      "severity"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / filePath / description
        Previous value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)."
      • addedOutput schema / properties / summary
        Added value: +{
        +  "additionalProperties": true,
        +  "description": "Tool-specific summary, when produced.",
        +  "type": "object"
        +}
    • Addedextract_attachments
    • Addedextract_pages
    • Changedextract_text7 fields changed
      • changedInput schema / properties / password / description
        Previous value: -"Password to open an encrypted source PDF (user or owner — both are tried). Omit for unencrypted documents. Never logged or echoed back."New value: +"Password (user or owner) of an encrypted source. Never logged or echoed."
      • addedOutput schema / description
        Added value: +"Structured text-extraction result. Every property is optional because the result can be projected: verbosity:'summary' returns only the scalar summary fields, fields:[...] keeps a dot-path subset. Defaults return the full shape."
      • addedOutput schema / properties / charCount
        Added value: +{
        +  "description": "summary only: length of fullText.",
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedOutput schema / properties / extractableReason / description
        Previous value: -"Human-readable explanation when extractable=false. Absent when extractable=true."New value: +"Present when extractable is false: why no text could be decoded."
      • removedOutput schema / properties / pages / items / properties / runs / items / required
        Removed value: -[
        -  "text",
        -  "x",
        -  "y",
        -  "fontSize",
        -  "fontName"
        -]
      • removedOutput schema / properties / pages / items / required
        Removed value: -[
        -  "index",
        -  "text"
        -]
      • removedOutput schema / required
        Removed value: -[
        -  "pageCount",
        -  "extractedPageCount",
        -  "extractable",
        -  "pages",
        -  "fullText"
        -]
    • Addedfill_form
    • Changedgenerate_basic_pdf34 fields changed
      • changedInput schema / properties / blocks / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "level": {
        -        "enum": [
        -          1,
        -          2,
        -          3
        -        ],
        -        "type": "integer"
        -      },
        -      "text": {
        -        "maxLength": 500,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "heading"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text",
        -      "level"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "text": {
        -        "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.",
        -        "maxLength": 50000,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "paragraph"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "items": {
        -        "description": "List items. A string is a leaf; an object { text, items } nests a sub-list (bullets/numbers indent; numbered sub-lists restart at 1).",
        -        "items": {
        -          "oneOf": [
        -            {
        -              "maxLength": 1000,
        -              "minLength": 1,
        -              "type": "string"
        -            },
        -            {
        -              "additionalProperties": false,
        -              "properties": {
        -                "items": {
        -                  "items": {
        -                    "oneOf": [
        -                      {
        -                        "maxLength": 1000,
        -                        "minLength": 1,
        -                        "type": "string"
        -                      },
        -                      {
        -                        "additionalProperties": false,
        -                        "properties": {
        -                          "items": {
        -                            "items": {
        -                              "oneOf": [
        -                                {
        -                                  "maxLength": 1000,
        -                                  "minLength": 1,
        -                                  "type": "string"
        -                                },
        -                                {
        -                                  "additionalProperties": false,
        -                                  "properties": {
        -                                    "items": {
        -                                      "items": {
        -                                        "oneOf": [
        -                                          {
        -                                            "maxLength": 1000,
        -                                            "minLength": 1,
        -                                            "type": "string"
        -                                          },
        -                                          {
        -                                            "additionalProperties": false,
        -                                            "properties": {
        -                                              "items": {
        -                                                "items": {
        -                                                  "oneOf": [
        -                                                    {
        -                                                      "maxLength": 1000,
        -                                                      "minLength": 1,
        -                                                      "type": "string"
        -                                                    },
        -                                                    {
        -                                                      "additionalProperties": false,
        -                                                      "properties": {
        -                                                        "items": {
        -                                                          "items": {
        -                                                            "oneOf": [
        -                                                              {
        -                                                                "maxLength": 1000,
        -                                                                "minLength": 1,
        -                                                                "type": "string"
        -                                                              },
        -                                                              {
        -                                                                "additionalProperties": false,
        -                                                                "properties": {
        -                                                                  "text": {
        -                                                                    "maxLength": 1000,
        -                                                                    "minLength": 1,
        -                                                                    "type": "string"
        -                                                                  }
        -                                                                },
        -                                                                "required": [
        -                                                                  "text"
        -                                                                ],
        -                                                                "type": "object"
        -                                                              }
        -                                                            ]
        -                                                          },
        -                                                          "maxItems": 1000,
        -                                                          "minItems": 1,
        -                                                          "type": "array"
        -                                                        },
        -                                                        "text": {
        -                                                          "maxLength": 1000,
        -                                                          "minLength": 1,
        -                                                          "type": "string"
        -                                                        }
        -                                                      },
        -                                                      "required": [
        -                                                        "text"
        -                                                      ],
        -                                                      "type": "object"
        -                                                    }
        -                                                  ]
        -                                                },
        -                                                "maxItems": 1000,
        -                                                "minItems": 1,
        -                                                "type": "array"
        -                                              },
        -                                              "text": {
        -                                                "maxLength": 1000,
        -                                                "minLength": 1,
        -                                                "type": "string"
        -                                              }
        -                                            },
        -                                            "required": [
        -                                              "text"
        -                                            ],
        -                                            "type": "object"
        -                                          }
        -                                        ]
        -                                      },
        -                                      "maxItems": 1000,
        -                                      "minItems": 1,
        -                                      "type": "array"
        -                                    },
        -                                    "text": {
        -                                      "maxLength": 1000,
        -                                      "minLength": 1,
        -                                      "type": "string"
        -                                    }
        -                                  },
        -                                  "required": [
        -                                    "text"
        -                                  ],
        -                                  "type": "object"
        -                                }
        -                              ]
        -                            },
        -                            "maxItems": 1000,
        -                            "minItems": 1,
        -                            "type": "array"
        -                          },
        -                          "text": {
        -                            "maxLength": 1000,
        -                            "minLength": 1,
        -                            "type": "string"
        -                          }
        -                        },
        -                        "required": [
        -                          "text"
        -                        ],
        -                        "type": "object"
        -                      }
        -                    ]
        -                  },
        -                  "maxItems": 1000,
        -                  "minItems": 1,
        -                  "type": "array"
        -                },
        -                "text": {
        -                  "maxLength": 1000,
        -                  "minLength": 1,
        -                  "type": "string"
        -                }
        -              },
        -              "required": [
        -                "text"
        -              ],
        -              "type": "object"
        -            }
        -          ]
        -        },
        -        "maxItems": 1000,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "style": {
        -        "default": "bullet",
        -        "enum": [
        -          "bullet",
        -          "numbered"
        -        ],
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "list"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "items"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "type": {
        -        "const": "pageBreak"
        -      }
        -    },
        -    "required": [
        -      "type"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "height": {
        -        "maximum": 500,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "type": {
        -        "const": "spacer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "height"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Native vector chart (pdfnative v1.6.0) — bar / horizontal-bar / line / pie / donut, rendered as pure PDF path operators.",
        -    "properties": {
        -      "align": {
        -        "description": "Horizontal alignment within the content width. Default 'left'.",
        -        "enum": [
        -          "left",
        -          "center",
        -          "right"
        -        ],
        -        "type": "string"
        -      },
        -      "altText": {
        -        "description": "Alt text for the tagged-PDF /Figure /Alt. Auto-generated when omitted.",
        -        "maxLength": 500,
        -        "type": "string"
        -      },
        -      "axis": {
        -        "additionalProperties": false,
        -        "description": "Value-axis options (bar/line only).",
        -        "properties": {
        -          "grid": {
        -            "description": "Draw horizontal gridlines.",
        -            "type": "boolean"
        -          },
        -          "ticks": {
        -            "description": "Target tick count (nice 1/2/5×10ⁿ steps).",
        -            "maximum": 20,
        -            "minimum": 2,
        -            "type": "integer"
        -          },
        -          "yMax": {
        -            "description": "Force the axis maximum (values are clamped to the plot band).",
        -            "type": "number"
        -          },
        -          "yMin": {
        -            "description": "Force the axis minimum (values are clamped to the plot band).",
        -            "type": "number"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "categories": {
        -        "description": "Category / slice labels (x-axis). Defaults to 1-based indices when omitted.",
        -        "items": {
        -          "maxLength": 200,
        -          "type": "string"
        -        },
        -        "maxItems": 1000,
        -        "type": "array"
        -      },
        -      "chartType": {
        -        "description": "Chart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'line' support multiple series.",
        -        "enum": [
        -          "bar",
        -          "barH",
        -          "line",
        -          "pie",
        -          "donut"
        -        ],
        -        "type": "string"
        -      },
        -      "colors": {
        -        "description": "Palette override (per-series for bar/line, per-slice for pie/donut).",
        -        "items": {
        -          "description": "CSS-style hex colour, e.g. \"#3366cc\".",
        -          "pattern": "^#?[0-9a-fA-F]{6}$",
        -          "type": "string"
        -        },
        -        "maxItems": 50,
        -        "type": "array"
        -      },
        -      "height": {
        -        "description": "Plot-area height in points. Default 240.",
        -        "maximum": 2000,
        -        "minimum": 50,
        -        "type": "number"
        -      },
        -      "legend": {
        -        "description": "Legend placement. Defaults to 'bottom' for multi-series/pie, else 'none'.",
        -        "enum": [
        -          "bottom",
        -          "none"
        -        ],
        -        "type": "string"
        -      },
        -      "markers": {
        -        "description": "Draw point markers on line series. Default false.",
        -        "type": "boolean"
        -      },
        -      "series": {
        -        "description": "Data series. Pie/donut charts use exactly one series (each value becomes a slice).",
        -        "items": {
        -          "additionalProperties": false,
        -          "properties": {
        -            "color": {
        -              "description": "CSS-style hex colour, e.g. \"#3366cc\".",
        -              "pattern": "^#?[0-9a-fA-F]{6}$",
        -              "type": "string"
        -            },
        -            "label": {
        -              "description": "Series label (shown in the legend).",
        -              "maxLength": 200,
        -              "minLength": 1,
        -              "type": "string"
        -            },
        -            "values": {
        -              "description": "Numeric values, one per category. Negative values are supported for bar/line.",
        -              "items": {
        -                "type": "number"
        -              },
        -              "maxItems": 1000,
        -              "minItems": 1,
        -              "type": "array"
        -            }
        -          },
        -          "required": [
        -            "label",
        -            "values"
        -          ],
        -          "type": "object"
        -        },
        -        "maxItems": 50,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "title": {
        -        "description": "Chart title rendered above the plot.",
        -        "maxLength": 200,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "chart"
        -      },
        -      "width": {
        -        "description": "Plot width in points (clamped to content width). Default 460.",
        -        "maximum": 2000,
        -        "minimum": 50,
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "chartType",
        -      "series"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "level": {
        +        "enum": [
        +          1,
        +          2,
        +          3
        +        ],
        +        "type": "integer"
        +      },
        +      "text": {
        +        "maxLength": 500,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "heading"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text",
        +      "level"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "text": {
        +        "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.",
        +        "maxLength": 50000,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "paragraph"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "items": {
        +        "description": "List items. A string is a leaf; an object { text, items } nests a sub-list (bullets/numbers indent; numbered sub-lists restart at 1).",
        +        "items": {
        +          "oneOf": [
        +            {
        +              "maxLength": 1000,
        +              "minLength": 1,
        +              "type": "string"
        +            },
        +            {
        +              "additionalProperties": false,
        +              "properties": {
        +                "items": {
        +                  "items": {
        +                    "oneOf": [
        +                      {
        +                        "maxLength": 1000,
        +                        "minLength": 1,
        +                        "type": "string"
        +                      },
        +                      {
        +                        "additionalProperties": false,
        +                        "properties": {
        +                          "items": {
        +                            "items": {
        +                              "oneOf": [
        +                                {
        +                                  "maxLength": 1000,
        +                                  "minLength": 1,
        +                                  "type": "string"
        +                                },
        +                                {
        +                                  "additionalProperties": false,
        +                                  "properties": {
        +                                    "items": {
        +                                      "items": {
        +                                        "oneOf": [
        +                                          {
        +                                            "maxLength": 1000,
        +                                            "minLength": 1,
        +                                            "type": "string"
        +                                          },
        +                                          {
        +                                            "additionalProperties": false,
        +                                            "properties": {
        +                                              "items": {
        +                                                "items": {
        +                                                  "oneOf": [
        +                                                    {
        +                                                      "maxLength": 1000,
        +                                                      "minLength": 1,
        +                                                      "type": "string"
        +                                                    },
        +                                                    {
        +                                                      "additionalProperties": false,
        +                                                      "properties": {
        +                                                        "items": {
        +                                                          "items": {
        +                                                            "oneOf": [
        +                                                              {
        +                                                                "maxLength": 1000,
        +                                                                "minLength": 1,
        +                                                                "type": "string"
        +                                                              },
        +                                                              {
        +                                                                "additionalProperties": false,
        +                                                                "properties": {
        +                                                                  "text": {
        +                                                                    "maxLength": 1000,
        +                                                                    "minLength": 1,
        +                                                                    "type": "string"
        +                                                                  }
        +                                                                },
        +                                                                "required": [
        +                                                                  "text"
        +                                                                ],
        +                                                                "type": "object"
        +                                                              }
        +                                                            ]
        +                                                          },
        +                                                          "maxItems": 1000,
        +                                                          "minItems": 1,
        +                                                          "type": "array"
        +                                                        },
        +                                                        "text": {
        +                                                          "maxLength": 1000,
        +                                                          "minLength": 1,
        +                                                          "type": "string"
        +                                                        }
        +                                                      },
        +                                                      "required": [
        +                                                        "text"
        +                                                      ],
        +                                                      "type": "object"
        +                                                    }
        +                                                  ]
        +                                                },
        +                                                "maxItems": 1000,
        +                                                "minItems": 1,
        +                                                "type": "array"
        +                                              },
        +                                              "text": {
        +                                                "maxLength": 1000,
        +                                                "minLength": 1,
        +                                                "type": "string"
        +                                              }
        +                                            },
        +                                            "required": [
        +                                              "text"
        +                                            ],
        +                                            "type": "object"
        +                                          }
        +                                        ]
        +                                      },
        +                                      "maxItems": 1000,
        +                                      "minItems": 1,
        +                                      "type": "array"
        +                                    },
        +                                    "text": {
        +                                      "maxLength": 1000,
        +                                      "minLength": 1,
        +                                      "type": "string"
        +                                    }
        +                                  },
        +                                  "required": [
        +                                    "text"
        +                                  ],
        +                                  "type": "object"
        +                                }
        +                              ]
        +                            },
        +                            "maxItems": 1000,
        +                            "minItems": 1,
        +                            "type": "array"
        +                          },
        +                          "text": {
        +                            "maxLength": 1000,
        +                            "minLength": 1,
        +                            "type": "string"
        +                          }
        +                        },
        +                        "required": [
        +                          "text"
        +                        ],
        +                        "type": "object"
        +                      }
        +                    ]
        +                  },
        +                  "maxItems": 1000,
        +                  "minItems": 1,
        +                  "type": "array"
        +                },
        +                "text": {
        +                  "maxLength": 1000,
        +                  "minLength": 1,
        +                  "type": "string"
        +                }
        +              },
        +              "required": [
        +                "text"
        +              ],
        +              "type": "object"
        +            }
        +          ]
        +        },
        +        "maxItems": 1000,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "style": {
        +        "default": "bullet",
        +        "enum": [
        +          "bullet",
        +          "numbered"
        +        ],
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "list"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "items"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "type": {
        +        "const": "pageBreak"
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "height": {
        +        "maximum": 500,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "type": {
        +        "const": "spacer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "height"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Native vector chart rendered as pure PDF path operators — bar / horizontal-bar / stacked-bar / line / area / scatter / pie / donut (pdfnative 1.7 charts v2: time and log axes, data labels, secondary axis, legends). Same body as add_chart.",
        +    "properties": {
        +      "align": {
        +        "description": "Horizontal alignment within the content width. Default 'left'.",
        +        "enum": [
        +          "left",
        +          "center",
        +          "right"
        +        ],
        +        "type": "string"
        +      },
        +      "altText": {
        +        "description": "Alt text for the tagged-PDF /Figure /Alt. Auto-generated when omitted.",
        +        "maxLength": 500,
        +        "type": "string"
        +      },
        +      "axis": {
        +        "additionalProperties": false,
        +        "description": "Value-axis options (bar/line only).",
        +        "properties": {
        +          "grid": {
        +            "description": "Draw horizontal gridlines.",
        +            "type": "boolean"
        +          },
        +          "scale": {
        +            "description": "Value-axis scale. 'log' requires strictly positive values and is not available for stacked charts.",
        +            "enum": [
        +              "linear",
        +              "log"
        +            ],
        +            "type": "string"
        +          },
        +          "ticks": {
        +            "description": "Target tick count (nice 1/2/5×10ⁿ steps).",
        +            "maximum": 20,
        +            "minimum": 2,
        +            "type": "integer"
        +          },
        +          "yMax": {
        +            "description": "Force the axis maximum (values are clamped to the plot band).",
        +            "type": "number"
        +          },
        +          "yMin": {
        +            "description": "Force the axis minimum (values are clamped to the plot band).",
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "axis2": {
        +        "additionalProperties": false,
        +        "description": "Secondary RIGHT value axis (drawn only when a series sets yAxis:'right').",
        +        "properties": {
        +          "scale": {
        +            "enum": [
        +              "linear",
        +              "log"
        +            ],
        +            "type": "string"
        +          },
        +          "ticks": {
        +            "maximum": 20,
        +            "minimum": 2,
        +            "type": "integer"
        +          },
        +          "yMax": {
        +            "type": "number"
        +          },
        +          "yMin": {
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "categories": {
        +        "description": "Category / slice labels (x-axis). Defaults to 1-based indices when omitted.",
        +        "items": {
        +          "maxLength": 200,
        +          "type": "string"
        +        },
        +        "maxItems": 1000,
        +        "type": "array"
        +      },
        +      "chartType": {
        +        "description": "Chart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'stackedBar'/'stackedBarH'/'line'/'area'/'scatter' support multiple series. 'scatter' requires xValues on every series and a positional xAxis.type ('linear' or 'time').",
        +        "enum": [
        +          "bar",
        +          "barH",
        +          "stackedBar",
        +          "stackedBarH",
        +          "line",
        +          "area",
        +          "scatter",
        +          "pie",
        +          "donut"
        +        ],
        +        "type": "string"
        +      },
        +      "colors": {
        +        "description": "Palette override (per-series for bar/line, per-slice for pie/donut).",
        +        "items": {
        +          "description": "CSS-style hex colour, e.g. \"#3366cc\".",
        +          "pattern": "^#?[0-9a-fA-F]{6}$",
        +          "type": "string"
        +        },
        +        "maxItems": 50,
        +        "type": "array"
        +      },
        +      "dataLabels": {
        +        "description": "Per-point value labels: true for defaults, or an object to format them.",
        +        "oneOf": [
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "additionalProperties": false,
        +            "properties": {
        +              "decimals": {
        +                "maximum": 6,
        +                "minimum": 0,
        +                "type": "integer"
        +              },
        +              "prefix": {
        +                "maxLength": 16,
        +                "type": "string"
        +              },
        +              "suffix": {
        +                "maxLength": 16,
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          }
        +        ]
        +      },
        +      "height": {
        +        "description": "Plot-area height in points. Default 240.",
        +        "maximum": 2000,
        +        "minimum": 50,
        +        "type": "number"
        +      },
        +      "labelRotation": {
        +        "description": "Rotate category labels counter-clockwise by this many degrees (disables the automatic stride).",
        +        "maximum": 90,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "labelStride": {
        +        "description": "Draw every Nth category label. Default: automatic (measured non-overlap); 1 draws every label.",
        +        "maximum": 1000,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "legend": {
        +        "description": "Legend placement. Defaults to 'bottom' for multi-series/pie, else 'none'.",
        +        "enum": [
        +          "bottom",
        +          "none"
        +        ],
        +        "type": "string"
        +      },
        +      "markers": {
        +        "description": "Draw point markers on line series. Default false.",
        +        "type": "boolean"
        +      },
        +      "series": {
        +        "description": "Data series. Pie/donut charts use exactly one series (each value becomes a slice).",
        +        "items": {
        +          "additionalProperties": false,
        +          "properties": {
        +            "color": {
        +              "description": "CSS-style hex colour, e.g. \"#3366cc\".",
        +              "pattern": "^#?[0-9a-fA-F]{6}$",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Series label (shown in the legend).",
        +              "maxLength": 200,
        +              "minLength": 1,
        +              "type": "string"
        +            },
        +            "values": {
        +              "description": "Numeric values, one per category. Negative values are supported for bar/line.",
        +              "items": {
        +                "type": "number"
        +              },
        +              "maxItems": 1000,
        +              "minItems": 1,
        +              "type": "array"
        +            },
        +            "xValues": {
        +              "description": "Per-point x positions (same length as values) for scatter charts and for line/area charts with xAxis.type 'linear' or 'time'.",
        +              "items": {
        +                "description": "Positional x value: a number (linear axis) or an ISO-8601 date / epoch milliseconds (time axis).",
        +                "maxLength": 64,
        +                "type": [
        +                  "number",
        +                  "string"
        +                ]
        +              },
        +              "maxItems": 1000,
        +              "minItems": 1,
        +              "type": "array"
        +            },
        +            "yAxis": {
        +              "description": "Bind the series to the left (default) or the secondary right value axis (cartesian charts only; configure its range with 'axis2').",
        +              "enum": [
        +                "left",
        +                "right"
        +              ],
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "label",
        +            "values"
        +          ],
        +          "type": "object"
        +        },
        +        "maxItems": 50,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "title": {
        +        "description": "Chart title rendered above the plot.",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "chart"
        +      },
        +      "width": {
        +        "description": "Plot width in points (clamped to content width). Default 460.",
        +        "maximum": 2000,
        +        "minimum": 50,
        +        "type": "number"
        +      },
        +      "xAxis": {
        +        "additionalProperties": false,
        +        "description": "Horizontal axis. 'category' (default) positions points by index; 'linear' / 'time' position them by series xValues (line/area/scatter only). Time ticks are UTC-deterministic.",
        +        "properties": {
        +          "grid": {
        +            "description": "Draw vertical gridlines.",
        +            "type": "boolean"
        +          },
        +          "max": {
        +            "description": "Axis maximum (number, or ISO-8601 / epoch ms for time axes).",
        +            "maxLength": 64,
        +            "type": [
        +              "number",
        +              "string"
        +            ]
        +          },
        +          "min": {
        +            "description": "Axis minimum (number, or ISO-8601 / epoch ms for time axes).",
        +            "maxLength": 64,
        +            "type": [
        +              "number",
        +              "string"
        +            ]
        +          },
        +          "ticks": {
        +            "maximum": 20,
        +            "minimum": 2,
        +            "type": "integer"
        +          },
        +          "type": {
        +            "enum": [
        +              "category",
        +              "linear",
        +              "time"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "chartType",
        +      "series"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Inline smart table — same body as add_table (every row must have exactly as many cells as headers).",
        +    "properties": {
        +      "autoFitColumns": {
        +        "description": "Auto-fit column widths to content. Output bytes then depend on text metrics (not byte-deterministic across content changes).",
        +        "type": "boolean"
        +      },
        +      "caption": {
        +        "description": "Caption rendered above the table (tagged as /Caption under PDF/A).",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "cellBorders": {
        +        "additionalProperties": false,
        +        "description": "Per-cell vector borders (pure strokes, PDF/A-safe). Choose individual sides or `all`.",
        +        "properties": {
        +          "all": {
        +            "description": "Draw all four edges (overrides the individual side flags).",
        +            "type": "boolean"
        +          },
        +          "bottom": {
        +            "type": "boolean"
        +          },
        +          "color": {
        +            "description": "Stroke colour as a PDF operator string ('0.8 0.8 0.8') or hex. Default light grey.",
        +            "type": "string"
        +          },
        +          "left": {
        +            "type": "boolean"
        +          },
        +          "right": {
        +            "type": "boolean"
        +          },
        +          "style": {
        +            "description": "Stroke style (default 'solid').",
        +            "enum": [
        +              "solid",
        +              "dashed",
        +              "dotted"
        +            ],
        +            "type": "string"
        +          },
        +          "top": {
        +            "type": "boolean"
        +          },
        +          "width": {
        +            "description": "Stroke width in points (default 0.5).",
        +            "maximum": 10,
        +            "minimum": 0,
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "cellPadding": {
        +        "description": "Horizontal cell padding in points (default 3).",
        +        "maximum": 50,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "cellVAlign": {
        +        "description": "Vertical alignment of cell content.",
        +        "enum": [
        +          "top",
        +          "middle",
        +          "bottom"
        +        ],
        +        "type": "string"
        +      },
        +      "clipCells": {
        +        "description": "Clip cell contents to the column bounds (PDF clip operators). Recommended for PDF/A and visual safety.",
        +        "type": "boolean"
        +      },
        +      "headers": {
        +        "description": "Column header labels. Must have the same length as each row in `rows`.",
        +        "items": {
        +          "maxLength": 200,
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "maxItems": 50,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "minRowHeight": {
        +        "description": "Minimum row height in points (default 12).",
        +        "maximum": 200,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "repeatHeader": {
        +        "description": "Repeat the header row on every continuation page (default true).",
        +        "type": "boolean"
        +      },
        +      "rows": {
        +        "description": "Data rows. Each row is an array of cell strings with the same length as `headers`.",
        +        "items": {
        +          "items": {
        +            "maxLength": 500,
        +            "type": "string"
        +          },
        +          "maxItems": 50,
        +          "minItems": 1,
        +          "type": "array"
        +        },
        +        "maxItems": 5000,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "type": {
        +        "const": "table"
        +      },
        +      "wrap": {
        +        "description": "Cell wrap policy: 'auto' (default) wraps only overflowing cells; 'always' wraps every cell; 'never' truncates.",
        +        "enum": [
        +          "auto",
        +          "always",
        +          "never"
        +        ],
        +        "type": "string"
        +      },
        +      "zebra": {
        +        "description": "Alternate-row light tint (static fill, PDF/A-1b safe).",
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "headers",
        +      "rows"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Inline JPEG/PNG image. Without width/height the pixel size is used as points and clamped to the content width; with one dimension the aspect ratio is kept. The decoded bytes of all image blocks in one call are capped at 24 MiB (a watermark image has its own 8 MiB cap).",
        +    "properties": {
        +      "align": {
        +        "default": "left",
        +        "description": "Horizontal placement inside the content width.",
        +        "enum": [
        +          "left",
        +          "center",
        +          "right"
        +        ],
        +        "type": "string"
        +      },
        +      "alt": {
        +        "description": "Accessible description (tagged /Figure /Alt). Always provide it for non-decorative content under PDF/A or PDF/UA.",
        +        "maxLength": 500,
        +        "type": "string"
        +      },
        +      "height": {
        +        "description": "Render height in points.",
        +        "maximum": 1000,
        +        "minimum": 10,
        +        "type": "number"
        +      },
        +      "imageBase64": {
        +        "description": "Base64 image bytes. JPEG (baseline; 1, 3 or 4 components — CMYK raises PDFA_DEVICE_CMYK_IMAGE under PDF/A) or PNG (8-bit greyscale/RGB, non-interlaced; alpha-channel and palette PNGs are rejected with a remedy). No data: URI.",
        +        "maxLength": 12000000,
        +        "minLength": 4,
        +        "type": "string"
        +      },
        +      "mimeType": {
        +        "description": "MIME type of the image. Must match the actual encoding of imageBase64 (magic bytes are checked).",
        +        "enum": [
        +          "image/jpeg",
        +          "image/png"
        +        ],
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "image"
        +      },
        +      "width": {
        +        "description": "Render width in points.",
        +        "maximum": 800,
        +        "minimum": 10,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "imageBase64",
        +      "mimeType"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Clickable external link (/URI action). Only http:, https: and mailto: URLs are accepted.",
        +    "properties": {
        +      "color": {
        +        "description": "Hex colour (#RGB or #RRGGBB).",
        +        "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$",
        +        "type": "string"
        +      },
        +      "fontSize": {
        +        "description": "Default 10.",
        +        "maximum": 48,
        +        "minimum": 6,
        +        "type": "number"
        +      },
        +      "text": {
        +        "maxLength": 500,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "link"
        +      },
        +      "url": {
        +        "description": "http(s):// or mailto: URL.",
        +        "maxLength": 2048,
        +        "minLength": 1,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text",
        +      "url"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Printed table of contents generated from the document's heading blocks (internal /GoTo links with dot leaders). Pairs with outline:'auto' for the bookmark pane.",
        +    "properties": {
        +      "fontSize": {
        +        "description": "Default 10.",
        +        "maximum": 24,
        +        "minimum": 6,
        +        "type": "number"
        +      },
        +      "indent": {
        +        "description": "Points of indent per heading level (default 15).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "maxLevel": {
        +        "description": "Deepest heading level listed (default 3).",
        +        "enum": [
        +          1,
        +          2,
        +          3
        +        ],
        +        "type": "integer"
        +      },
        +      "title": {
        +        "description": "Default 'Table of Contents'.",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "toc"
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Inline barcode — same body as add_barcode (pure vector, no /Alt available in the engine).",
        +    "properties": {
        +      "align": {
        +        "default": "left",
        +        "description": "Horizontal placement inside the content width.",
        +        "enum": [
        +          "left",
        +          "center",
        +          "right"
        +        ],
        +        "type": "string"
        +      },
        +      "data": {
        +        "description": "Raw payload to encode — do NOT URL-encode. For QR/URL pass e.g. \"https://example.com\" verbatim. EAN-13 must be 12 or 13 digits (13th is auto-computed). Code 128 accepts ASCII alphanumerics.",
        +        "maxLength": 4296,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "ecLevel": {
        +        "default": "M",
        +        "description": "QR ONLY. Error correction level (L=7%, M=15%, Q=25%, H=30%). Ignored for code128/ean13/datamatrix/pdf417. Use H for printed media that may get smudged or partially covered (e.g. logo overlay).",
        +        "enum": [
        +          "L",
        +          "M",
        +          "Q",
        +          "H"
        +        ],
        +        "type": "string"
        +      },
        +      "format": {
        +        "description": "Barcode symbology to render.",
        +        "enum": [
        +          "qr",
        +          "code128",
        +          "ean13",
        +          "datamatrix",
        +          "pdf417"
        +        ],
        +        "type": "string"
        +      },
        +      "height": {
        +        "default": 200,
        +        "description": "Barcode height in PDF points (ignored for square symbologies like QR/Data Matrix).",
        +        "maximum": 500,
        +        "minimum": 30,
        +        "type": "number"
        +      },
        +      "type": {
        +        "const": "barcode"
        +      },
        +      "width": {
        +        "default": 200,
        +        "description": "Barcode width in PDF points.",
        +        "maximum": 500,
        +        "minimum": 30,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "format",
        +      "data"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Vector drawing from an SVG path `d` string or SVG markup. Supported: <path> <rect> (rx/ry) <circle> <ellipse> <line> <polyline> <polygon> and <text>/<tspan> (x, y, font-size, fill, text-anchor, dx/dy); fill / stroke / stroke-width attributes; double-quoted attributes only. NOT supported (silently ignored): transform, <g>, <use>, <image>, <defs>/<clipPath>, gradients, opacity, CSS/style, dash patterns, text word-wrap. No external reference is ever fetched (no XML parser: entities other than &amp; &lt; &gt; &quot; &apos; &nbsp; &#n; are dropped). Pure path operators — PDF/A-safe at every level.",
        +    "properties": {
        +      "align": {
        +        "default": "left",
        +        "description": "Horizontal placement inside the content width.",
        +        "enum": [
        +          "left",
        +          "center",
        +          "right"
        +        ],
        +        "type": "string"
        +      },
        +      "alt": {
        +        "description": "Accessible description (tagged /Figure /Alt). Always provide it for non-decorative content under PDF/A or PDF/UA.",
        +        "maxLength": 500,
        +        "type": "string"
        +      },
        +      "data": {
        +        "description": "Path `d` string or SVG markup (≤ 100 000 characters).",
        +        "maxLength": 100000,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "fill": {
        +        "description": "Hex colour or 'none' (default black).",
        +        "pattern": "^(?:none|#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}))$",
        +        "type": "string"
        +      },
        +      "height": {
        +        "description": "Render height in points (default 200).",
        +        "maximum": 1000,
        +        "minimum": 10,
        +        "type": "number"
        +      },
        +      "stroke": {
        +        "description": "Hex colour or 'none' (default none).",
        +        "pattern": "^(?:none|#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}))$",
        +        "type": "string"
        +      },
        +      "strokeWidth": {
        +        "description": "Stroke width in SVG user units (default 1).",
        +        "maximum": 50,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "type": {
        +        "const": "svg"
        +      },
        +      "viewBox": {
        +        "description": "[minX, minY, width, height] — overrides the viewBox of the markup; required for a bare path string that is not 0-based.",
        +        "items": {
        +          "type": "number"
        +        },
        +        "maxItems": 4,
        +        "minItems": 4,
        +        "type": "array"
        +      },
        +      "width": {
        +        "description": "Render width in points (default 200).",
        +        "maximum": 800,
        +        "minimum": 10,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "data"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Inline AcroForm field — same body as an add_form field. Under a PDF/A claim the widget appearance font is not embedded (PDFA_UNEMBEDDED_FORM_FONT; strict:true fails the call).",
        +    "properties": {
        +      "checked": {
        +        "description": "Initial checked state for checkbox / radio fields.",
        +        "type": "boolean"
        +      },
        +      "fieldType": {
        +        "description": "Type of form control to render. Radio fields sharing a name form one radio group.",
        +        "enum": [
        +          "text",
        +          "textarea",
        +          "checkbox",
        +          "radio",
        +          "dropdown",
        +          "listbox"
        +        ],
        +        "type": "string"
        +      },
        +      "fontSize": {
        +        "description": "Font size for text rendering inside the field.",
        +        "maximum": 48,
        +        "minimum": 6,
        +        "type": "number"
        +      },
        +      "height": {
        +        "description": "Field height in points (default depends on the type).",
        +        "maximum": 300,
        +        "minimum": 10,
        +        "type": "number"
        +      },
        +      "label": {
        +        "description": "Human-readable label shown above the field.",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "maxLength": {
        +        "description": "Maximum character length for text/textarea fields.",
        +        "maximum": 32767,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "name": {
        +        "description": "Unique field name used as the PDF annotation identifier (/T).",
        +        "maxLength": 100,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "options": {
        +        "description": "Choices for dropdown, listbox or radio fields.",
        +        "items": {
        +          "maxLength": 200,
        +          "type": "string"
        +        },
        +        "maxItems": 100,
        +        "type": "array"
        +      },
        +      "placeholder": {
        +        "description": "Hint text shown while the field is empty.",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "readOnly": {
        +        "description": "Prevent editing of this field.",
        +        "type": "boolean"
        +      },
        +      "required": {
        +        "description": "Mark field as required.",
        +        "type": "boolean"
        +      },
        +      "type": {
        +        "const": "formField"
        +      },
        +      "value": {
        +        "description": "Default value pre-filled in the field.",
        +        "maxLength": 2000,
        +        "type": "string"
        +      },
        +      "width": {
        +        "description": "Field width in points (default: full content width).",
        +        "maximum": 500,
        +        "minimum": 10,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "fieldType",
        +      "name"
        +    ],
        +    "type": "object"
        +  }
        +]
      • addedInput schema / properties / compress
        Added value: +{
        +  "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / creationDate
        Added value: +{
        +  "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.",
        +  "format": "date-time",
        +  "type": "string"
        +}
      • addedInput schema / properties / debug
        Added value: +{
        +  "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / embedFonts
        Added value: +{
        +  "default": false,
        +  "description": "Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / encrypt
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.",
        +  "properties": {
        +    "algorithm": {
        +      "default": "aes128",
        +      "description": "aes128 (V4/R4, widest compatibility) or aes256 (V5/R6).",
        +      "enum": [
        +        "aes128",
        +        "aes256"
        +      ],
        +      "type": "string"
        +    },
        +    "ownerPassword": {
        +      "description": "Owner password (full access).",
        +      "maxLength": 4096,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "permissions": {
        +      "additionalProperties": false,
        +      "description": "Permission flags; each defaults to allowed.",
        +      "properties": {
        +        "copy": {
        +          "type": "boolean"
        +        },
        +        "extractText": {
        +          "type": "boolean"
        +        },
        +        "modify": {
        +          "type": "boolean"
        +        },
        +        "print": {
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "userPassword": {
        +      "description": "Open password; omitted/empty = opens without a prompt.",
        +      "maxLength": 4096,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "ownerPassword"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / footerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / headerTemplate
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Running header on every page (left / center / right zones); reserves 15 pt.",
        +  "properties": {
        +    "center": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "color": {
        +      "description": "Hex colour.",
        +      "pattern": "^#[0-9a-fA-F]{6}$",
        +      "type": "string"
        +    },
        +    "fontSize": {
        +      "description": "Default 7.",
        +      "maximum": 14,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "left": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "right": {
        +      "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / includeDiagnostics
        Added value: +{
        +  "default": false,
        +  "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / margins
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.",
        +  "properties": {
        +    "bottom": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "left": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "right": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "top": {
        +      "maximum": 200,
        +      "minimum": 0,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "top",
        +    "right",
        +    "bottom",
        +    "left"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / metadata
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.",
        +  "properties": {
        +    "author": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "keywords": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "subject": {
        +      "maxLength": 1000,
        +      "type": "string"
        +    },
        +    "trapped": {
        +      "description": "/Trapped print flag.",
        +      "enum": [
        +        "True",
        +        "False",
        +        "Unknown"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedInput schema / properties / normalize / description
        Previous value: -"Optional Unicode normalization applied to all rendered text before shaping. 'NFC' (recommended) composes base + combining marks into precomposed code points for better glyph coverage; 'NFD'/'NFKC'/'NFKD' are also accepted. Omit for byte-stable output (no normalization)."New value: +"Unicode normalization before shaping ('NFC' recommended for glyph coverage; NFD/NFKC/NFKD accepted). Omit = none."
      • addedInput schema / properties / outputIntent
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).",
        +  "properties": {
        +    "iccProfileBase64": {
        +      "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).",
        +      "maxLength": 11000000,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "info": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "outputCondition": {
        +      "maxLength": 200,
        +      "type": "string"
        +    },
        +    "outputConditionIdentifier": {
        +      "description": "e.g. \"sRGB IEC61966-2.1\".",
        +      "maxLength": 200,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "registryName": {
        +      "description": "Default \"http://www.color.org\".",
        +      "maxLength": 200,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "iccProfileBase64",
        +    "outputConditionIdentifier"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / pageSize
        Added value: +{
        +  "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.",
        +  "enum": [
        +    "A4",
        +    "Letter",
        +    "Legal",
        +    "A3",
        +    "Tabloid"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / pdfA / description
        Previous value: -"Optional PDF/A conformance level (powered by pdfnative v1.2). Use 'pdfa1b' for archival of simple text+images, 'pdfa2b'/'pdfa2u' for richer content (2u guarantees Unicode mapping), 'pdfa3b' when embedding source attachments (Factur-X / ZUGFeRD). Mutually exclusive with PDF encryption. See docs/guides/PDFA.md."New value: +"PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md."
      • addedInput schema / properties / print
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.",
        +  "properties": {
        +    "artBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "bleed": {
        +      "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.",
        +      "exclusiveMinimum": 0,
        +      "maximum": 200,
        +      "type": "number"
        +    },
        +    "bleedBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "cropBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "marks": {
        +      "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.",
        +      "oneOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "additionalProperties": false,
        +          "properties": {
        +            "crop": {
        +              "description": "Corner crop (trim) marks. Default true.",
        +              "type": "boolean"
        +            },
        +            "length": {
        +              "description": "Mark length in points. Default 14.",
        +              "maximum": 100,
        +              "minimum": 1,
        +              "type": "number"
        +            },
        +            "offset": {
        +              "description": "Gap between TrimBox and marks in points. Default 5.",
        +              "maximum": 100,
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "registration": {
        +              "description": "Edge-midpoint registration targets. Default true.",
        +              "type": "boolean"
        +            },
        +            "weight": {
        +              "description": "Stroke width in points. Default 0.25.",
        +              "maximum": 5,
        +              "minimum": 0.05,
        +              "type": "number"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      ]
        +    },
        +    "trimBox": {
        +      "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.",
        +      "items": {
        +        "type": "number"
        +      },
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "type": "array"
        +    },
        +    "userUnit": {
        +      "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.",
        +      "maximum": 75000,
        +      "minimum": 1,
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / strict
        Added value: +{
        +  "default": false,
        +  "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / viewerPreferences / properties / duplex
        Added value: +{
        +  "description": "Print-dialog paper handling default (/Duplex): single-sided or double-sided flipping on the short/long edge.",
        +  "enum": [
        +    "simplex",
        +    "duplexFlipShortEdge",
        +    "duplexFlipLongEdge"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / viewerPreferences / properties / numCopies
        Added value: +{
        +  "description": "Default number of copies for the Print dialog (/NumCopies; viewers honour 2-5 per ISO 32000 Table 150).",
        +  "maximum": 1000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / viewerPreferences / properties / pickTrayByPDFSize
        Added value: +{
        +  "description": "Ask the printer to pick the input tray from the PDF page size (/PickTrayByPDFSize).",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / viewerPreferences / properties / printPageRange
        Added value: +{
        +  "description": "Default page ranges for the Print dialog (/PrintPageRange) as inclusive 1-based [first, last] pairs, e.g. [[1, 4], [7, 7]].",
        +  "items": {
        +    "items": {
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "maxItems": 2,
        +    "minItems": 2,
        +    "type": "array"
        +  },
        +  "maxItems": 100,
        +  "type": "array"
        +}
      • changedInput schema / properties / watermark / description
        Previous value: -"Optional semi-transparent text watermark rendered on every page (e.g. 'DRAFT', 'CONFIDENTIAL'). Text only in this version. opacity < 1.0 is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency)."New value: +"Optional semi-transparent watermark rendered centred on every page: `text` (e.g. 'DRAFT'), `image` (JPEG/PNG), or both combined. At least one of text / image is required. opacity < 1.0 (text or image, including the defaults) is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency)."
      • changedInput schema / properties / watermark / properties / angle / description
        Previous value: -"Rotation in degrees (counterclockwise). Default -45."New value: +"Text rotation in degrees (counterclockwise). Default -45."
      • changedInput schema / properties / watermark / properties / color / description
        Previous value: -"RGB colour as a [r, g, b] triple in the 0.0–1.0 range. Default light gray [0.75, 0.75, 0.75]."New value: +"Text RGB colour as a [r, g, b] triple in the 0.0–1.0 range. Default light gray [0.75, 0.75, 0.75]."
      • changedInput schema / properties / watermark / properties / fontSize / description
        Previous value: -"Font size in points. Default 60, auto-fit to the page."New value: +"Text font size in points. Default 60, auto-fit to the page."
      • addedInput schema / properties / watermark / properties / image
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Image watermark (JPEG or PNG) centred on every page, optionally combined with `text`. Bytes are validated against the JPEG/PNG magic numbers; mimeType must match.",
        +  "properties": {
        +    "height": {
        +      "description": "Display height in points (default: from the image pixel size).",
        +      "exclusiveMinimum": 0,
        +      "maximum": 14400,
        +      "type": "number"
        +    },
        +    "imageBase64": {
        +      "description": "Base64-encoded JPEG or 8-bit opaque PNG bytes (max 8 MiB decoded; alpha-channel, palette and interlaced PNGs are rejected with a remedy). Plain base64, no data: URI prefix.",
        +      "maxLength": 12000000,
        +      "minLength": 4,
        +      "type": "string"
        +    },
        +    "mimeType": {
        +      "description": "'image/jpeg' or 'image/png' — must match the actual bytes.",
        +      "enum": [
        +        "image/jpeg",
        +        "image/png"
        +      ],
        +      "type": "string"
        +    },
        +    "opacity": {
        +      "description": "Image opacity 0.0–1.0. Default 0.10.",
        +      "maximum": 1,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "width": {
        +      "description": "Display width in points (default: from the image pixel size).",
        +      "exclusiveMinimum": 0,
        +      "maximum": 14400,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "imageBase64",
        +    "mimeType"
        +  ],
        +  "type": "object"
        +}
      • changedInput schema / properties / watermark / properties / opacity / description
        Previous value: -"Opacity 0.0–1.0. Default 0.15."New value: +"Text opacity 0.0–1.0. Default 0.15. (Image opacity is image.opacity.)"
      • changedInput schema / properties / watermark / properties / position / description
        Previous value: -"'background' (behind page content, default) or 'foreground' (above it)."New value: +"'background' (behind page content, default) or 'foreground' (above it). Applies to text and image alike."
      • changedInput schema / properties / watermark / properties / text / description
        Previous value: -"Watermark text."New value: +"Watermark text. Optional when `image` is given."
      • removedInput schema / properties / watermark / required
        Removed value: -[
        -  "text"
        -]
      • changedOutput schema / description
        Previous value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`."
      • addedOutput schema / properties / diagnostics
        Added value: +{
        +  "description": "PDF/A diagnostics (when includeDiagnostics=true).",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "code": {
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      },
        +      "severity": {
        +        "enum": [
        +          "warning"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "code",
        +      "message",
        +      "severity"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / filePath / description
        Previous value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)."
      • addedOutput schema / properties / summary
        Added value: +{
        +  "additionalProperties": true,
        +  "description": "Tool-specific summary, when produced.",
        +  "type": "object"
        +}
    • Addedinspect_layout
    • Addedinspect_pdf
    • Addedmerge_pdfs
    • Addedprepare_signature_placeholder
    • Addedread_form_fields
    • Addedsign_pdf
    • Changedsplit_pdf8 fields changed
      • changedInput schema / properties / encrypt / description
        Previous value: -"Re-encrypt the produced PDF with the PDF Standard Security Handler (AES-128 V4/R4 default, or AES-256 V5/R6). RC4 is never emitted. Requires a Web Crypto CSPRNG. Applied to every produced range."New value: +"Re-encrypt the output (Standard Security Handler; AES-128 default or AES-256; RC4 never emitted). Applied to every produced range."
      • changedInput schema / properties / encrypt / properties / algorithm / description
        Previous value: -"Content cipher: aes128 (V4/R4, widest compatibility) or aes256 (V5/R6, strongest)."New value: +"aes128 (V4/R4, widest compatibility) or aes256 (V5/R6)."
      • changedInput schema / properties / encrypt / properties / ownerPassword / description
        Previous value: -"Owner password (required, non-empty). Controls permissions and full access."New value: +"Owner password (full access)."
      • changedInput schema / properties / encrypt / properties / permissions / description
        Previous value: -"Access permission flags (enforced by conforming readers). Each defaults to allowed when omitted."New value: +"Permission flags; each defaults to allowed."
      • changedInput schema / properties / encrypt / properties / userPassword / description
        Previous value: -"User (open) password. Omitted or empty string means the document opens without a password prompt."New value: +"Open password; omitted/empty = opens without a prompt."
      • addedInput schema / properties / outputMode / description
        Added value: +"'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured)."
      • changedInput schema / properties / password / description
        Previous value: -"Password to open an encrypted source PDF (user or owner — both are tried). Omit for unencrypted documents. Never logged or echoed back."New value: +"Password (user or owner) of an encrypted source. Never logged or echoed."
      • changedOutput schema / properties / parts / items / properties / filePath / description
        Previous value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)."
    • Addedtimestamp_pdf
    • Addedupdate_metadata
    • Addedvalidate_pdf
    • Addedverify_pdf
  3. 14 tool updatesv1.6.0
    • Addedadd_chart
    • Addeddecrypt_pdf
    • Addedencrypt_pdf
    • Removedextract_attachments
    • Removedextract_pages
    • Changedextract_text5 fields changed
      • addedInput schema / properties / includeRuns
        Added value: +{
        +  "default": false,
        +  "description": "When true, each page also carries `runs[]` — positioned text-showing operations `{ text, x, y, fontSize, fontName }` in device space (content-stream order). Useful for layout-aware extraction; larger responses.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / maxTextLength
        Added value: +{
        +  "description": "Hard cap on total extracted characters across all pages (memory bound for adversarial input). Default 16000000. Exceeding it fails with OUTPUT_TOO_LARGE.",
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / password
        Added value: +{
        +  "description": "Password to open an encrypted source PDF (user or owner — both are tried). Omit for unencrypted documents. Never logged or echoed back.",
        +  "maxLength": 4096,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • changedOutput schema / properties / extractable / description
        Previous value: -"False when one or more requested pages had a non-empty content stream but yielded no extractable text (likely subset fonts without /ToUnicode)."New value: +"False when one or more requested pages produced text that is entirely U+FFFD replacement characters — a font with no usable /ToUnicode CMap or base encoding. Blank pages are still considered extractable."
      • addedOutput schema / properties / pages / items / properties / runs
        Added value: +{
        +  "description": "Positioned text runs (present only when includeRuns is true).",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "fontName": {
        +        "type": "string"
        +      },
        +      "fontSize": {
        +        "type": "number"
        +      },
        +      "text": {
        +        "type": "string"
        +      },
        +      "x": {
        +        "type": "number"
        +      },
        +      "y": {
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "text",
        +      "x",
        +      "y",
        +      "fontSize",
        +      "fontName"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedgenerate_basic_pdf1 field changed
      • changedInput schema / properties / blocks / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "level": {
        -        "enum": [
        -          1,
        -          2,
        -          3
        -        ],
        -        "type": "integer"
        -      },
        -      "text": {
        -        "maxLength": 500,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "heading"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text",
        -      "level"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "text": {
        -        "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.",
        -        "maxLength": 50000,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "paragraph"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "items": {
        -        "description": "List items. A string is a leaf; an object { text, items } nests a sub-list (bullets/numbers indent; numbered sub-lists restart at 1).",
        -        "items": {
        -          "oneOf": [
        -            {
        -              "maxLength": 1000,
        -              "minLength": 1,
        -              "type": "string"
        -            },
        -            {
        -              "additionalProperties": false,
        -              "properties": {
        -                "items": {
        -                  "items": {
        -                    "oneOf": [
        -                      {
        -                        "maxLength": 1000,
        -                        "minLength": 1,
        -                        "type": "string"
        -                      },
        -                      {
        -                        "additionalProperties": false,
        -                        "properties": {
        -                          "items": {
        -                            "items": {
        -                              "oneOf": [
        -                                {
        -                                  "maxLength": 1000,
        -                                  "minLength": 1,
        -                                  "type": "string"
        -                                },
        -                                {
        -                                  "additionalProperties": false,
        -                                  "properties": {
        -                                    "items": {
        -                                      "items": {
        -                                        "oneOf": [
        -                                          {
        -                                            "maxLength": 1000,
        -                                            "minLength": 1,
        -                                            "type": "string"
        -                                          },
        -                                          {
        -                                            "additionalProperties": false,
        -                                            "properties": {
        -                                              "items": {
        -                                                "items": {
        -                                                  "oneOf": [
        -                                                    {
        -                                                      "maxLength": 1000,
        -                                                      "minLength": 1,
        -                                                      "type": "string"
        -                                                    },
        -                                                    {
        -                                                      "additionalProperties": false,
        -                                                      "properties": {
        -                                                        "items": {
        -                                                          "items": {
        -                                                            "oneOf": [
        -                                                              {
        -                                                                "maxLength": 1000,
        -                                                                "minLength": 1,
        -                                                                "type": "string"
        -                                                              },
        -                                                              {
        -                                                                "additionalProperties": false,
        -                                                                "properties": {
        -                                                                  "text": {
        -                                                                    "maxLength": 1000,
        -                                                                    "minLength": 1,
        -                                                                    "type": "string"
        -                                                                  }
        -                                                                },
        -                                                                "required": [
        -                                                                  "text"
        -                                                                ],
        -                                                                "type": "object"
        -                                                              }
        -                                                            ]
        -                                                          },
        -                                                          "maxItems": 1000,
        -                                                          "minItems": 1,
        -                                                          "type": "array"
        -                                                        },
        -                                                        "text": {
        -                                                          "maxLength": 1000,
        -                                                          "minLength": 1,
        -                                                          "type": "string"
        -                                                        }
        -                                                      },
        -                                                      "required": [
        -                                                        "text"
        -                                                      ],
        -                                                      "type": "object"
        -                                                    }
        -                                                  ]
        -                                                },
        -                                                "maxItems": 1000,
        -                                                "minItems": 1,
        -                                                "type": "array"
        -                                              },
        -                                              "text": {
        -                                                "maxLength": 1000,
        -                                                "minLength": 1,
        -                                                "type": "string"
        -                                              }
        -                                            },
        -                                            "required": [
        -                                              "text"
        -                                            ],
        -                                            "type": "object"
        -                                          }
        -                                        ]
        -                                      },
        -                                      "maxItems": 1000,
        -                                      "minItems": 1,
        -                                      "type": "array"
        -                                    },
        -                                    "text": {
        -                                      "maxLength": 1000,
        -                                      "minLength": 1,
        -                                      "type": "string"
        -                                    }
        -                                  },
        -                                  "required": [
        -                                    "text"
        -                                  ],
        -                                  "type": "object"
        -                                }
        -                              ]
        -                            },
        -                            "maxItems": 1000,
        -                            "minItems": 1,
        -                            "type": "array"
        -                          },
        -                          "text": {
        -                            "maxLength": 1000,
        -                            "minLength": 1,
        -                            "type": "string"
        -                          }
        -                        },
        -                        "required": [
        -                          "text"
        -                        ],
        -                        "type": "object"
        -                      }
        -                    ]
        -                  },
        -                  "maxItems": 1000,
        -                  "minItems": 1,
        -                  "type": "array"
        -                },
        -                "text": {
        -                  "maxLength": 1000,
        -                  "minLength": 1,
        -                  "type": "string"
        -                }
        -              },
        -              "required": [
        -                "text"
        -              ],
        -              "type": "object"
        -            }
        -          ]
        -        },
        -        "maxItems": 1000,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "style": {
        -        "default": "bullet",
        -        "enum": [
        -          "bullet",
        -          "numbered"
        -        ],
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "list"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "items"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "type": {
        -        "const": "pageBreak"
        -      }
        -    },
        -    "required": [
        -      "type"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "height": {
        -        "maximum": 500,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "type": {
        -        "const": "spacer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "height"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "level": {
        +        "enum": [
        +          1,
        +          2,
        +          3
        +        ],
        +        "type": "integer"
        +      },
        +      "text": {
        +        "maxLength": 500,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "heading"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text",
        +      "level"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "text": {
        +        "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.",
        +        "maxLength": 50000,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "paragraph"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "items": {
        +        "description": "List items. A string is a leaf; an object { text, items } nests a sub-list (bullets/numbers indent; numbered sub-lists restart at 1).",
        +        "items": {
        +          "oneOf": [
        +            {
        +              "maxLength": 1000,
        +              "minLength": 1,
        +              "type": "string"
        +            },
        +            {
        +              "additionalProperties": false,
        +              "properties": {
        +                "items": {
        +                  "items": {
        +                    "oneOf": [
        +                      {
        +                        "maxLength": 1000,
        +                        "minLength": 1,
        +                        "type": "string"
        +                      },
        +                      {
        +                        "additionalProperties": false,
        +                        "properties": {
        +                          "items": {
        +                            "items": {
        +                              "oneOf": [
        +                                {
        +                                  "maxLength": 1000,
        +                                  "minLength": 1,
        +                                  "type": "string"
        +                                },
        +                                {
        +                                  "additionalProperties": false,
        +                                  "properties": {
        +                                    "items": {
        +                                      "items": {
        +                                        "oneOf": [
        +                                          {
        +                                            "maxLength": 1000,
        +                                            "minLength": 1,
        +                                            "type": "string"
        +                                          },
        +                                          {
        +                                            "additionalProperties": false,
        +                                            "properties": {
        +                                              "items": {
        +                                                "items": {
        +                                                  "oneOf": [
        +                                                    {
        +                                                      "maxLength": 1000,
        +                                                      "minLength": 1,
        +                                                      "type": "string"
        +                                                    },
        +                                                    {
        +                                                      "additionalProperties": false,
        +                                                      "properties": {
        +                                                        "items": {
        +                                                          "items": {
        +                                                            "oneOf": [
        +                                                              {
        +                                                                "maxLength": 1000,
        +                                                                "minLength": 1,
        +                                                                "type": "string"
        +                                                              },
        +                                                              {
        +                                                                "additionalProperties": false,
        +                                                                "properties": {
        +                                                                  "text": {
        +                                                                    "maxLength": 1000,
        +                                                                    "minLength": 1,
        +                                                                    "type": "string"
        +                                                                  }
        +                                                                },
        +                                                                "required": [
        +                                                                  "text"
        +                                                                ],
        +                                                                "type": "object"
        +                                                              }
        +                                                            ]
        +                                                          },
        +                                                          "maxItems": 1000,
        +                                                          "minItems": 1,
        +                                                          "type": "array"
        +                                                        },
        +                                                        "text": {
        +                                                          "maxLength": 1000,
        +                                                          "minLength": 1,
        +                                                          "type": "string"
        +                                                        }
        +                                                      },
        +                                                      "required": [
        +                                                        "text"
        +                                                      ],
        +                                                      "type": "object"
        +                                                    }
        +                                                  ]
        +                                                },
        +                                                "maxItems": 1000,
        +                                                "minItems": 1,
        +                                                "type": "array"
        +                                              },
        +                                              "text": {
        +                                                "maxLength": 1000,
        +                                                "minLength": 1,
        +                                                "type": "string"
        +                                              }
        +                                            },
        +                                            "required": [
        +                                              "text"
        +                                            ],
        +                                            "type": "object"
        +                                          }
        +                                        ]
        +                                      },
        +                                      "maxItems": 1000,
        +                                      "minItems": 1,
        +                                      "type": "array"
        +                                    },
        +                                    "text": {
        +                                      "maxLength": 1000,
        +                                      "minLength": 1,
        +                                      "type": "string"
        +                                    }
        +                                  },
        +                                  "required": [
        +                                    "text"
        +                                  ],
        +                                  "type": "object"
        +                                }
        +                              ]
        +                            },
        +                            "maxItems": 1000,
        +                            "minItems": 1,
        +                            "type": "array"
        +                          },
        +                          "text": {
        +                            "maxLength": 1000,
        +                            "minLength": 1,
        +                            "type": "string"
        +                          }
        +                        },
        +                        "required": [
        +                          "text"
        +                        ],
        +                        "type": "object"
        +                      }
        +                    ]
        +                  },
        +                  "maxItems": 1000,
        +                  "minItems": 1,
        +                  "type": "array"
        +                },
        +                "text": {
        +                  "maxLength": 1000,
        +                  "minLength": 1,
        +                  "type": "string"
        +                }
        +              },
        +              "required": [
        +                "text"
        +              ],
        +              "type": "object"
        +            }
        +          ]
        +        },
        +        "maxItems": 1000,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "style": {
        +        "default": "bullet",
        +        "enum": [
        +          "bullet",
        +          "numbered"
        +        ],
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "list"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "items"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "type": {
        +        "const": "pageBreak"
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "height": {
        +        "maximum": 500,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "type": {
        +        "const": "spacer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "height"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Native vector chart (pdfnative v1.6.0) — bar / horizontal-bar / line / pie / donut, rendered as pure PDF path operators.",
        +    "properties": {
        +      "align": {
        +        "description": "Horizontal alignment within the content width. Default 'left'.",
        +        "enum": [
        +          "left",
        +          "center",
        +          "right"
        +        ],
        +        "type": "string"
        +      },
        +      "altText": {
        +        "description": "Alt text for the tagged-PDF /Figure /Alt. Auto-generated when omitted.",
        +        "maxLength": 500,
        +        "type": "string"
        +      },
        +      "axis": {
        +        "additionalProperties": false,
        +        "description": "Value-axis options (bar/line only).",
        +        "properties": {
        +          "grid": {
        +            "description": "Draw horizontal gridlines.",
        +            "type": "boolean"
        +          },
        +          "ticks": {
        +            "description": "Target tick count (nice 1/2/5×10ⁿ steps).",
        +            "maximum": 20,
        +            "minimum": 2,
        +            "type": "integer"
        +          },
        +          "yMax": {
        +            "description": "Force the axis maximum (values are clamped to the plot band).",
        +            "type": "number"
        +          },
        +          "yMin": {
        +            "description": "Force the axis minimum (values are clamped to the plot band).",
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "categories": {
        +        "description": "Category / slice labels (x-axis). Defaults to 1-based indices when omitted.",
        +        "items": {
        +          "maxLength": 200,
        +          "type": "string"
        +        },
        +        "maxItems": 1000,
        +        "type": "array"
        +      },
        +      "chartType": {
        +        "description": "Chart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'line' support multiple series.",
        +        "enum": [
        +          "bar",
        +          "barH",
        +          "line",
        +          "pie",
        +          "donut"
        +        ],
        +        "type": "string"
        +      },
        +      "colors": {
        +        "description": "Palette override (per-series for bar/line, per-slice for pie/donut).",
        +        "items": {
        +          "description": "CSS-style hex colour, e.g. \"#3366cc\".",
        +          "pattern": "^#?[0-9a-fA-F]{6}$",
        +          "type": "string"
        +        },
        +        "maxItems": 50,
        +        "type": "array"
        +      },
        +      "height": {
        +        "description": "Plot-area height in points. Default 240.",
        +        "maximum": 2000,
        +        "minimum": 50,
        +        "type": "number"
        +      },
        +      "legend": {
        +        "description": "Legend placement. Defaults to 'bottom' for multi-series/pie, else 'none'.",
        +        "enum": [
        +          "bottom",
        +          "none"
        +        ],
        +        "type": "string"
        +      },
        +      "markers": {
        +        "description": "Draw point markers on line series. Default false.",
        +        "type": "boolean"
        +      },
        +      "series": {
        +        "description": "Data series. Pie/donut charts use exactly one series (each value becomes a slice).",
        +        "items": {
        +          "additionalProperties": false,
        +          "properties": {
        +            "color": {
        +              "description": "CSS-style hex colour, e.g. \"#3366cc\".",
        +              "pattern": "^#?[0-9a-fA-F]{6}$",
        +              "type": "string"
        +            },
        +            "label": {
        +              "description": "Series label (shown in the legend).",
        +              "maxLength": 200,
        +              "minLength": 1,
        +              "type": "string"
        +            },
        +            "values": {
        +              "description": "Numeric values, one per category. Negative values are supported for bar/line.",
        +              "items": {
        +                "type": "number"
        +              },
        +              "maxItems": 1000,
        +              "minItems": 1,
        +              "type": "array"
        +            }
        +          },
        +          "required": [
        +            "label",
        +            "values"
        +          ],
        +          "type": "object"
        +        },
        +        "maxItems": 50,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "title": {
        +        "description": "Chart title rendered above the plot.",
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "chart"
        +      },
        +      "width": {
        +        "description": "Plot width in points (clamped to content width). Default 460.",
        +        "maximum": 2000,
        +        "minimum": 50,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "chartType",
        +      "series"
        +    ],
        +    "type": "object"
        +  }
        +]
    • Removedinspect_pdf
    • Removedmerge_pdfs
    • Removedprepare_signature_placeholder
    • Removedsign_pdf
    • Changedsplit_pdf3 fields changed
      • addedInput schema / properties / encrypt
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Re-encrypt the produced PDF with the PDF Standard Security Handler (AES-128 V4/R4 default, or AES-256 V5/R6). RC4 is never emitted. Requires a Web Crypto CSPRNG. Applied to every produced range.",
        +  "properties": {
        +    "algorithm": {
        +      "default": "aes128",
        +      "description": "Content cipher: aes128 (V4/R4, widest compatibility) or aes256 (V5/R6, strongest).",
        +      "enum": [
        +        "aes128",
        +        "aes256"
        +      ],
        +      "type": "string"
        +    },
        +    "ownerPassword": {
        +      "description": "Owner password (required, non-empty). Controls permissions and full access.",
        +      "maxLength": 4096,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "permissions": {
        +      "additionalProperties": false,
        +      "description": "Access permission flags (enforced by conforming readers). Each defaults to allowed when omitted.",
        +      "properties": {
        +        "copy": {
        +          "type": "boolean"
        +        },
        +        "extractText": {
        +          "type": "boolean"
        +        },
        +        "modify": {
        +          "type": "boolean"
        +        },
        +        "print": {
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "userPassword": {
        +      "description": "User (open) password. Omitted or empty string means the document opens without a password prompt.",
        +      "maxLength": 4096,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "ownerPassword"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / password
        Added value: +{
        +  "description": "Password to open an encrypted source PDF (user or owner — both are tried). Omit for unencrypted documents. Never logged or echoed back.",
        +  "maxLength": 4096,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • changedInput schema / properties / pdfBase64 / description
        Previous value: -"Base64-encoded source PDF. Must not be encrypted."New value: +"Base64-encoded source PDF. Pass `password` for an encrypted source."
    • Removedvalidate_pdf
    • Removedverify_pdf
  4. 4 tool updatesv1.4.0
    • Changedadd_international_text1 field changed
      • changedInput schema / properties / lang / oneOf
        Previous value: -[
        -  {
        -    "enum": [
        -      "ar",
        -      "he",
        -      "th",
        -      "ja",
        -      "zh",
        -      "ko",
        -      "el",
        -      "hi",
        -      "bn",
        -      "ta",
        -      "ru",
        -      "ka",
        -      "hy",
        -      "tr",
        -      "pl",
        -      "vi",
        -      "latin",
        -      "te",
        -      "si",
        -      "bo",
        -      "km",
        -      "my",
        -      "am",
        -      "emoji"
        -    ],
        -    "type": "string"
        -  },
        -  {
        -    "items": {
        -      "enum": [
        -        "ar",
        -        "he",
        -        "th",
        -        "ja",
        -        "zh",
        -        "ko",
        -        "el",
        -        "hi",
        -        "bn",
        -        "ta",
        -        "ru",
        -        "ka",
        -        "hy",
        -        "tr",
        -        "pl",
        -        "vi",
        -        "latin",
        -        "te",
        -        "si",
        -        "bo",
        -        "km",
        -        "my",
        -        "am",
        -        "emoji"
        -      ],
        -      "type": "string"
        -    },
        -    "maxItems": 24,
        -    "minItems": 1,
        -    "type": "array"
        -  },
        -  {
        -    "description": "Comma-separated list of supported codes.",
        -    "maxLength": 80,
        -    "minLength": 2,
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "enum": [
        +      "ar",
        +      "he",
        +      "th",
        +      "ja",
        +      "zh",
        +      "ko",
        +      "el",
        +      "hi",
        +      "bn",
        +      "ta",
        +      "ru",
        +      "ka",
        +      "hy",
        +      "tr",
        +      "pl",
        +      "vi",
        +      "latin",
        +      "te",
        +      "si",
        +      "bo",
        +      "km",
        +      "my",
        +      "am",
        +      "emoji",
        +      "math"
        +    ],
        +    "type": "string"
        +  },
        +  {
        +    "items": {
        +      "enum": [
        +        "ar",
        +        "he",
        +        "th",
        +        "ja",
        +        "zh",
        +        "ko",
        +        "el",
        +        "hi",
        +        "bn",
        +        "ta",
        +        "ru",
        +        "ka",
        +        "hy",
        +        "tr",
        +        "pl",
        +        "vi",
        +        "latin",
        +        "te",
        +        "si",
        +        "bo",
        +        "km",
        +        "my",
        +        "am",
        +        "emoji",
        +        "math"
        +      ],
        +      "type": "string"
        +    },
        +    "maxItems": 25,
        +    "minItems": 1,
        +    "type": "array"
        +  },
        +  {
        +    "description": "Comma-separated list of supported codes.",
        +    "maxLength": 80,
        +    "minLength": 2,
        +    "type": "string"
        +  }
        +]
    • Addedannotate_pdf
    • Addeddraft_governance_issue
    • Changedinspect_pdf1 field changed
      • addedOutput schema / properties / pageLabels
        Added value: +{
        +  "description": "Logical page-numbering ranges from the /PageLabels number tree (ISO 32000-1 §12.4.2), or absent when the document has none. Each range gives the 0-based first page, numbering style, optional prefix and start value.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "prefix": {
        +        "type": "string"
        +      },
        +      "start": {
        +        "type": "integer"
        +      },
        +      "startPage": {
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "style": {
        +        "enum": [
        +          "decimal",
        +          "roman",
        +          "Roman",
        +          "alpha",
        +          "Alpha",
        +          "none"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "startPage"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
  5. 6 tool updatesv1.2.2
    • Changedadd_international_text1 field changed
      • addedInput schema / properties / viewerPreferences
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Reader presentation hints (catalog /PageLayout, /PageMode, /ViewerPreferences). PDF/A-safe; all optional.",
        +  "properties": {
        +    "centerWindow": {
        +      "type": "boolean"
        +    },
        +    "direction": {
        +      "enum": [
        +        "l2r",
        +        "r2l"
        +      ],
        +      "type": "string"
        +    },
        +    "displayDocTitle": {
        +      "type": "boolean"
        +    },
        +    "fitWindow": {
        +      "type": "boolean"
        +    },
        +    "hideMenubar": {
        +      "type": "boolean"
        +    },
        +    "hideToolbar": {
        +      "type": "boolean"
        +    },
        +    "hideWindowUI": {
        +      "type": "boolean"
        +    },
        +    "nonFullScreenPageMode": {
        +      "enum": [
        +        "useNone",
        +        "useOutlines",
        +        "useThumbs",
        +        "useOC"
        +      ],
        +      "type": "string"
        +    },
        +    "pageLayout": {
        +      "enum": [
        +        "singlePage",
        +        "oneColumn",
        +        "twoColumnLeft",
        +        "twoColumnRight",
        +        "twoPageLeft",
        +        "twoPageRight"
        +      ],
        +      "type": "string"
        +    },
        +    "pageMode": {
        +      "enum": [
        +        "useNone",
        +        "useOutlines",
        +        "useThumbs",
        +        "fullScreen",
        +        "useOC",
        +        "useAttachments"
        +      ],
        +      "type": "string"
        +    },
        +    "printScaling": {
        +      "enum": [
        +        "none",
        +        "appDefault"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedadd_table3 fields changed
      • addedInput schema / properties / cellBorders
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Per-cell vector borders (pdfnative v1.4). Switches the backend to buildDocumentPDFBytes. Choose individual sides or `all`.",
        +  "properties": {
        +    "all": {
        +      "description": "Draw all four edges (overrides the individual side flags).",
        +      "type": "boolean"
        +    },
        +    "bottom": {
        +      "type": "boolean"
        +    },
        +    "color": {
        +      "description": "Stroke colour as a PDF operator string ('0.8 0.8 0.8') or hex. Default light grey.",
        +      "type": "string"
        +    },
        +    "left": {
        +      "type": "boolean"
        +    },
        +    "right": {
        +      "type": "boolean"
        +    },
        +    "style": {
        +      "description": "Stroke style (default 'solid').",
        +      "enum": [
        +        "solid",
        +        "dashed",
        +        "dotted"
        +      ],
        +      "type": "string"
        +    },
        +    "top": {
        +      "type": "boolean"
        +    },
        +    "width": {
        +      "description": "Stroke width in points (default 0.5).",
        +      "maximum": 10,
        +      "minimum": 0,
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / cellVAlign
        Added value: +{
        +  "description": "Vertical alignment of cell content (pdfnative v1.4). Switches the backend to buildDocumentPDFBytes.",
        +  "enum": [
        +    "top",
        +    "middle",
        +    "bottom"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / viewerPreferences
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Reader presentation hints (catalog /PageLayout, /PageMode, /ViewerPreferences). PDF/A-safe; all optional.",
        +  "properties": {
        +    "centerWindow": {
        +      "type": "boolean"
        +    },
        +    "direction": {
        +      "enum": [
        +        "l2r",
        +        "r2l"
        +      ],
        +      "type": "string"
        +    },
        +    "displayDocTitle": {
        +      "type": "boolean"
        +    },
        +    "fitWindow": {
        +      "type": "boolean"
        +    },
        +    "hideMenubar": {
        +      "type": "boolean"
        +    },
        +    "hideToolbar": {
        +      "type": "boolean"
        +    },
        +    "hideWindowUI": {
        +      "type": "boolean"
        +    },
        +    "nonFullScreenPageMode": {
        +      "enum": [
        +        "useNone",
        +        "useOutlines",
        +        "useThumbs",
        +        "useOC"
        +      ],
        +      "type": "string"
        +    },
        +    "pageLayout": {
        +      "enum": [
        +        "singlePage",
        +        "oneColumn",
        +        "twoColumnLeft",
        +        "twoColumnRight",
        +        "twoPageLeft",
        +        "twoPageRight"
        +      ],
        +      "type": "string"
        +    },
        +    "pageMode": {
        +      "enum": [
        +        "useNone",
        +        "useOutlines",
        +        "useThumbs",
        +        "fullScreen",
        +        "useOC",
        +        "useAttachments"
        +      ],
        +      "type": "string"
        +    },
        +    "printScaling": {
        +      "enum": [
        +        "none",
        +        "appDefault"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Addedextract_pages
    • Changedgenerate_basic_pdf4 fields changed
      • changedInput schema / properties / blocks / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "level": {
        -        "enum": [
        -          1,
        -          2,
        -          3
        -        ],
        -        "type": "integer"
        -      },
        -      "text": {
        -        "maxLength": 500,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "heading"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text",
        -      "level"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "text": {
        -        "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.",
        -        "maxLength": 50000,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "paragraph"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "items": {
        -        "items": {
        -          "maxLength": 1000,
        -          "minLength": 1,
        -          "type": "string"
        -        },
        -        "maxItems": 1000,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "style": {
        -        "default": "bullet",
        -        "enum": [
        -          "bullet",
        -          "numbered"
        -        ],
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "list"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "items"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "type": {
        -        "const": "pageBreak"
        -      }
        -    },
        -    "required": [
        -      "type"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "height": {
        -        "maximum": 500,
        -        "minimum": 1,
        -        "type": "number"
        -      },
        -      "type": {
        -        "const": "spacer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "height"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "level": {
        +        "enum": [
        +          1,
        +          2,
        +          3
        +        ],
        +        "type": "integer"
        +      },
        +      "text": {
        +        "maxLength": 500,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "heading"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text",
        +      "level"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "text": {
        +        "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.",
        +        "maxLength": 50000,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "paragraph"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "items": {
        +        "description": "List items. A string is a leaf; an object { text, items } nests a sub-list (bullets/numbers indent; numbered sub-lists restart at 1).",
        +        "items": {
        +          "oneOf": [
        +            {
        +              "maxLength": 1000,
        +              "minLength": 1,
        +              "type": "string"
        +            },
        +            {
        +              "additionalProperties": false,
        +              "properties": {
        +                "items": {
        +                  "items": {
        +                    "oneOf": [
        +                      {
        +                        "maxLength": 1000,
        +                        "minLength": 1,
        +                        "type": "string"
        +                      },
        +                      {
        +                        "additionalProperties": false,
        +                        "properties": {
        +                          "items": {
        +                            "items": {
        +                              "oneOf": [
        +                                {
        +                                  "maxLength": 1000,
        +                                  "minLength": 1,
        +                                  "type": "string"
        +                                },
        +                                {
        +                                  "additionalProperties": false,
        +                                  "properties": {
        +                                    "items": {
        +                                      "items": {
        +                                        "oneOf": [
        +                                          {
        +                                            "maxLength": 1000,
        +                                            "minLength": 1,
        +                                            "type": "string"
        +                                          },
        +                                          {
        +                                            "additionalProperties": false,
        +                                            "properties": {
        +                                              "items": {
        +                                                "items": {
        +                                                  "oneOf": [
        +                                                    {
        +                                                      "maxLength": 1000,
        +                                                      "minLength": 1,
        +                                                      "type": "string"
        +                                                    },
        +                                                    {
        +                                                      "additionalProperties": false,
        +                                                      "properties": {
        +                                                        "items": {
        +                                                          "items": {
        +                                                            "oneOf": [
        +                                                              {
        +                                                                "maxLength": 1000,
        +                                                                "minLength": 1,
        +                                                                "type": "string"
        +                                                              },
        +                                                              {
        +                                                                "additionalProperties": false,
        +                                                                "properties": {
        +                                                                  "text": {
        +                                                                    "maxLength": 1000,
        +                                                                    "minLength": 1,
        +                                                                    "type": "string"
        +                                                                  }
        +                                                                },
        +                                                                "required": [
        +                                                                  "text"
        +                                                                ],
        +                                                                "type": "object"
        +                                                              }
        +                                                            ]
        +                                                          },
        +                                                          "maxItems": 1000,
        +                                                          "minItems": 1,
        +                                                          "type": "array"
        +                                                        },
        +                                                        "text": {
        +                                                          "maxLength": 1000,
        +                                                          "minLength": 1,
        +                                                          "type": "string"
        +                                                        }
        +                                                      },
        +                                                      "required": [
        +                                                        "text"
        +                                                      ],
        +                                                      "type": "object"
        +                                                    }
        +                                                  ]
        +                                                },
        +                                                "maxItems": 1000,
        +                                                "minItems": 1,
        +                                                "type": "array"
        +                                              },
        +                                              "text": {
        +                                                "maxLength": 1000,
        +                                                "minLength": 1,
        +                                                "type": "string"
        +                                              }
        +                                            },
        +                                            "required": [
        +                                              "text"
        +                                            ],
        +                                            "type": "object"
        +                                          }
        +                                        ]
        +                                      },
        +                                      "maxItems": 1000,
        +                                      "minItems": 1,
        +                                      "type": "array"
        +                                    },
        +                                    "text": {
        +                                      "maxLength": 1000,
        +                                      "minLength": 1,
        +                                      "type": "string"
        +                                    }
        +                                  },
        +                                  "required": [
        +                                    "text"
        +                                  ],
        +                                  "type": "object"
        +                                }
        +                              ]
        +                            },
        +                            "maxItems": 1000,
        +                            "minItems": 1,
        +                            "type": "array"
        +                          },
        +                          "text": {
        +                            "maxLength": 1000,
        +                            "minLength": 1,
        +                            "type": "string"
        +                          }
        +                        },
        +                        "required": [
        +                          "text"
        +                        ],
        +                        "type": "object"
        +                      }
        +                    ]
        +                  },
        +                  "maxItems": 1000,
        +                  "minItems": 1,
        +                  "type": "array"
        +                },
        +                "text": {
        +                  "maxLength": 1000,
        +                  "minLength": 1,
        +                  "type": "string"
        +                }
        +              },
        +              "required": [
        +                "text"
        +              ],
        +              "type": "object"
        +            }
        +          ]
        +        },
        +        "maxItems": 1000,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "style": {
        +        "default": "bullet",
        +        "enum": [
        +          "bullet",
        +          "numbered"
        +        ],
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "list"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "items"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "type": {
        +        "const": "pageBreak"
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "height": {
        +        "maximum": 500,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "type": {
        +        "const": "spacer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "height"
        +    ],
        +    "type": "object"
        +  }
        +]
      • addedInput schema / properties / outline
        Added value: +{
        +  "description": "Document outline (bookmarks panel). Either 'auto' (derive a flat outline from heading blocks) or an explicit nested bookmark tree.",
        +  "oneOf": [
        +    {
        +      "enum": [
        +        "auto"
        +      ],
        +      "type": "string"
        +    },
        +    {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "bold": {
        +            "type": "boolean"
        +          },
        +          "children": {
        +            "items": {
        +              "additionalProperties": false,
        +              "properties": {
        +                "bold": {
        +                  "type": "boolean"
        +                },
        +                "children": {
        +                  "items": {
        +                    "additionalProperties": false,
        +                    "properties": {
        +                      "bold": {
        +                        "type": "boolean"
        +                      },
        +                      "children": {
        +                        "items": {
        +                          "additionalProperties": false,
        +                          "properties": {
        +                            "bold": {
        +                              "type": "boolean"
        +                            },
        +                            "children": {
        +                              "items": {
        +                                "additionalProperties": false,
        +                                "properties": {
        +                                  "bold": {
        +                                    "type": "boolean"
        +                                  },
        +                                  "children": {
        +                                    "items": {
        +                                      "additionalProperties": false,
        +                                      "properties": {
        +                                        "bold": {
        +                                          "type": "boolean"
        +                                        },
        +                                        "color": {
        +                                          "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').",
        +                                          "type": "string"
        +                                        },
        +                                        "italic": {
        +                                          "type": "boolean"
        +                                        },
        +                                        "open": {
        +                                          "description": "Initial expansion state (default true). false renders the branch collapsed.",
        +                                          "type": "boolean"
        +                                        },
        +                                        "pageIndex": {
        +                                          "description": "0-based destination page index.",
        +                                          "minimum": 0,
        +                                          "type": "integer"
        +                                        },
        +                                        "title": {
        +                                          "description": "Bookmark label.",
        +                                          "maxLength": 500,
        +                                          "minLength": 1,
        +                                          "type": "string"
        +                                        },
        +                                        "y": {
        +                                          "description": "Destination Y coordinate in points (default: top of page).",
        +                                          "type": "number"
        +                                        }
        +                                      },
        +                                      "required": [
        +                                        "title",
        +                                        "pageIndex"
        +                                      ],
        +                                      "type": "object"
        +                                    },
        +                                    "maxItems": 1000,
        +                                    "type": "array"
        +                                  },
        +                                  "color": {
        +                                    "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').",
        +                                    "type": "string"
        +                                  },
        +                                  "italic": {
        +                                    "type": "boolean"
        +                                  },
        +                                  "open": {
        +                                    "description": "Initial expansion state (default true). false renders the branch collapsed.",
        +                                    "type": "boolean"
        +                                  },
        +                                  "pageIndex": {
        +                                    "description": "0-based destination page index.",
        +                                    "minimum": 0,
        +                                    "type": "integer"
        +                                  },
        +                                  "title": {
        +                                    "description": "Bookmark label.",
        +                                    "maxLength": 500,
        +                                    "minLength": 1,
        +                                    "type": "string"
        +                                  },
        +                                  "y": {
        +                                    "description": "Destination Y coordinate in points (default: top of page).",
        +                                    "type": "number"
        +                                  }
        +                                },
        +                                "required": [
        +                                  "title",
        +                                  "pageIndex"
        +                                ],
        +                                "type": "object"
        +                              },
        +                              "maxItems": 1000,
        +                              "type": "array"
        +                            },
        +                            "color": {
        +                              "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').",
        +                              "type": "string"
        +                            },
        +                            "italic": {
        +                              "type": "boolean"
        +                            },
        +                            "open": {
        +                              "description": "Initial expansion state (default true). false renders the branch collapsed.",
        +                              "type": "boolean"
        +                            },
        +                            "pageIndex": {
        +                              "description": "0-based destination page index.",
        +                              "minimum": 0,
        +                              "type": "integer"
        +                            },
        +                            "title": {
        +                              "description": "Bookmark label.",
        +                              "maxLength": 500,
        +                              "minLength": 1,
        +                              "type": "string"
        +                            },
        +                            "y": {
        +                              "description": "Destination Y coordinate in points (default: top of page).",
        +                              "type": "number"
        +                            }
        +                          },
        +                          "required": [
        +                            "title",
        +                            "pageIndex"
        +                          ],
        +                          "type": "object"
        +                        },
        +                        "maxItems": 1000,
        +                        "type": "array"
        +                      },
        +                      "color": {
        +                        "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').",
        +                        "type": "string"
        +                      },
        +                      "italic": {
        +                        "type": "boolean"
        +                      },
        +                      "open": {
        +                        "description": "Initial expansion state (default true). false renders the branch collapsed.",
        +                        "type": "boolean"
        +                      },
        +                      "pageIndex": {
        +                        "description": "0-based destination page index.",
        +                        "minimum": 0,
        +                        "type": "integer"
        +                      },
        +                      "title": {
        +                        "description": "Bookmark label.",
        +                        "maxLength": 500,
        +                        "minLength": 1,
        +                        "type": "string"
        +                      },
        +                      "y": {
        +                        "description": "Destination Y coordinate in points (default: top of page).",
        +                        "type": "number"
        +                      }
        +                    },
        +                    "required": [
        +                      "title",
        +                      "pageIndex"
        +                    ],
        +                    "type": "object"
        +                  },
        +                  "maxItems": 1000,
        +                  "type": "array"
        +                },
        +                "color": {
        +                  "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').",
        +                  "type": "string"
        +                },
        +                "italic": {
        +                  "type": "boolean"
        +                },
        +                "open": {
        +                  "description": "Initial expansion state (default true). false renders the branch collapsed.",
        +                  "type": "boolean"
        +                },
        +                "pageIndex": {
        +                  "description": "0-based destination page index.",
        +                  "minimum": 0,
        +                  "type": "integer"
        +                },
        +                "title": {
        +                  "description": "Bookmark label.",
        +                  "maxLength": 500,
        +                  "minLength": 1,
        +                  "type": "string"
        +                },
        +                "y": {
        +                  "description": "Destination Y coordinate in points (default: top of page).",
        +                  "type": "number"
        +                }
        +              },
        +              "required": [
        +                "title",
        +                "pageIndex"
        +              ],
        +              "type": "object"
        +            },
        +            "maxItems": 1000,
        +            "type": "array"
        +          },
        +          "color": {
        +            "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').",
        +            "type": "string"
        +          },
        +          "italic": {
        +            "type": "boolean"
        +          },
        +          "open": {
        +            "description": "Initial expansion state (default true). false renders the branch collapsed.",
        +            "type": "boolean"
        +          },
        +          "pageIndex": {
        +            "description": "0-based destination page index.",
        +            "minimum": 0,
        +            "type": "integer"
        +          },
        +          "title": {
        +            "description": "Bookmark label.",
        +            "maxLength": 500,
        +            "minLength": 1,
        +            "type": "string"
        +          },
        +          "y": {
        +            "description": "Destination Y coordinate in points (default: top of page).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "title",
        +          "pageIndex"
        +        ],
        +        "type": "object"
        +      },
        +      "maxItems": 1000,
        +      "minItems": 1,
        +      "type": "array"
        +    }
        +  ]
        +}
      • addedInput schema / properties / pageLabels
        Added value: +{
        +  "description": "Page-label ranges (the visible page numbers in the viewer, e.g. roman front-matter then decimal body). startPage values must be unique and strictly increasing.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "prefix": {
        +        "description": "Optional label prefix (e.g. 'A-').",
        +        "maxLength": 64,
        +        "type": "string"
        +      },
        +      "start": {
        +        "description": "First numeric value in the range (default 1).",
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "startPage": {
        +        "description": "0-based index of the first page in this range.",
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "style": {
        +        "description": "Numbering style. 'none' (or omitted with a prefix) yields prefix-only labels.",
        +        "enum": [
        +          "decimal",
        +          "roman",
        +          "Roman",
        +          "alpha",
        +          "Alpha",
        +          "none"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "startPage"
        +    ],
        +    "type": "object"
        +  },
        +  "maxItems": 1000,
        +  "minItems": 1,
        +  "type": "array"
        +}
      • addedInput schema / properties / viewerPreferences
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Reader presentation hints (catalog /PageLayout, /PageMode, /ViewerPreferences). PDF/A-safe; all optional.",
        +  "properties": {
        +    "centerWindow": {
        +      "type": "boolean"
        +    },
        +    "direction": {
        +      "enum": [
        +        "l2r",
        +        "r2l"
        +      ],
        +      "type": "string"
        +    },
        +    "displayDocTitle": {
        +      "type": "boolean"
        +    },
        +    "fitWindow": {
        +      "type": "boolean"
        +    },
        +    "hideMenubar": {
        +      "type": "boolean"
        +    },
        +    "hideToolbar": {
        +      "type": "boolean"
        +    },
        +    "hideWindowUI": {
        +      "type": "boolean"
        +    },
        +    "nonFullScreenPageMode": {
        +      "enum": [
        +        "useNone",
        +        "useOutlines",
        +        "useThumbs",
        +        "useOC"
        +      ],
        +      "type": "string"
        +    },
        +    "pageLayout": {
        +      "enum": [
        +        "singlePage",
        +        "oneColumn",
        +        "twoColumnLeft",
        +        "twoColumnRight",
        +        "twoPageLeft",
        +        "twoPageRight"
        +      ],
        +      "type": "string"
        +    },
        +    "pageMode": {
        +      "enum": [
        +        "useNone",
        +        "useOutlines",
        +        "useThumbs",
        +        "fullScreen",
        +        "useOC",
        +        "useAttachments"
        +      ],
        +      "type": "string"
        +    },
        +    "printScaling": {
        +      "enum": [
        +        "none",
        +        "appDefault"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Addedmerge_pdfs
    • Addedsplit_pdf
  6. 14 tool updatesv1.2.0
    • Changedadd_attachment2 fields changed
      • addedOutput schema / description
        Added value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."
      • removedOutput schema / properties / base64
        Removed value: -{
        -  "description": "Base64-encoded PDF bytes (when mode='base64').",
        -  "type": "string"
        -}
    • Changedadd_barcode2 fields changed
      • addedOutput schema / description
        Added value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."
      • removedOutput schema / properties / base64
        Removed value: -{
        -  "description": "Base64-encoded PDF bytes (when mode='base64').",
        -  "type": "string"
        -}
    • Changedadd_form2 fields changed
      • addedOutput schema / description
        Added value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."
      • removedOutput schema / properties / base64
        Removed value: -{
        -  "description": "Base64-encoded PDF bytes (when mode='base64').",
        -  "type": "string"
        -}
    • Changedadd_international_text3 fields changed
      • addedInput schema / properties / normalize
        Added value: +{
        +  "description": "Unicode normalization form applied before shaping. Defaults to 'NFC' (recommended for international scripts: composes decomposed sequences for the widest glyph coverage). Override with 'NFD'/'NFKC'/'NFKD' only for specialised needs.",
        +  "enum": [
        +    "NFC",
        +    "NFD",
        +    "NFKC",
        +    "NFKD"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / description
        Added value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."
      • removedOutput schema / properties / base64
        Removed value: -{
        -  "description": "Base64-encoded PDF bytes (when mode='base64').",
        -  "type": "string"
        -}
    • Changedadd_table3 fields changed
      • addedInput schema / properties / watermark
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Optional semi-transparent text watermark rendered on every page (e.g. 'DRAFT', 'CONFIDENTIAL'). Text only in this version. opacity < 1.0 is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency).",
        +  "properties": {
        +    "angle": {
        +      "description": "Rotation in degrees (counterclockwise). Default -45.",
        +      "maximum": 360,
        +      "minimum": -360,
        +      "type": "number"
        +    },
        +    "color": {
        +      "description": "RGB colour as a [r, g, b] triple in the 0.0–1.0 range. Default light gray [0.75, 0.75, 0.75].",
        +      "items": {
        +        "maximum": 1,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "maxItems": 3,
        +      "minItems": 3,
        +      "type": "array"
        +    },
        +    "fontSize": {
        +      "description": "Font size in points. Default 60, auto-fit to the page.",
        +      "maximum": 300,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "opacity": {
        +      "description": "Opacity 0.0–1.0. Default 0.15.",
        +      "maximum": 1,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "position": {
        +      "default": "background",
        +      "description": "'background' (behind page content, default) or 'foreground' (above it).",
        +      "enum": [
        +        "background",
        +        "foreground"
        +      ],
        +      "type": "string"
        +    },
        +    "text": {
        +      "description": "Watermark text.",
        +      "maxLength": 100,
        +      "minLength": 1,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "text"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / description
        Added value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."
      • removedOutput schema / properties / base64
        Removed value: -{
        -  "description": "Base64-encoded PDF bytes (when mode='base64').",
        -  "type": "string"
        -}
    • Changedembed_image2 fields changed
      • addedOutput schema / description
        Added value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."
      • removedOutput schema / properties / base64
        Removed value: -{
        -  "description": "Base64-encoded PDF bytes (when mode='base64').",
        -  "type": "string"
        -}
    • Addedextract_attachments
    • Changedextract_text2 fields changed
      • addedInput schema / properties / fields
        Added value: +{
        +  "description": "Optional dot-path projection applied to the structured result (e.g. ['fullText'] or ['extractable']). Composes after verbosity. Unknown paths are omitted.",
        +  "items": {
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 16,
        +  "type": "array"
        +}
      • addedInput schema / properties / verbosity
        Added value: +{
        +  "default": "full",
        +  "description": "Response verbosity. 'full' (default) returns the per-page pages[] array and fullText; 'summary' returns a token-frugal { pageCount, extractedPageCount, extractable, charCount } and drops the text payloads.",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "type": "string"
        +}
    • Changedgenerate_basic_pdf4 fields changed
      • addedInput schema / properties / normalize
        Added value: +{
        +  "description": "Optional Unicode normalization applied to all rendered text before shaping. 'NFC' (recommended) composes base + combining marks into precomposed code points for better glyph coverage; 'NFD'/'NFKC'/'NFKD' are also accepted. Omit for byte-stable output (no normalization).",
        +  "enum": [
        +    "NFC",
        +    "NFD",
        +    "NFKC",
        +    "NFKD"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / watermark
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Optional semi-transparent text watermark rendered on every page (e.g. 'DRAFT', 'CONFIDENTIAL'). Text only in this version. opacity < 1.0 is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency).",
        +  "properties": {
        +    "angle": {
        +      "description": "Rotation in degrees (counterclockwise). Default -45.",
        +      "maximum": 360,
        +      "minimum": -360,
        +      "type": "number"
        +    },
        +    "color": {
        +      "description": "RGB colour as a [r, g, b] triple in the 0.0–1.0 range. Default light gray [0.75, 0.75, 0.75].",
        +      "items": {
        +        "maximum": 1,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "maxItems": 3,
        +      "minItems": 3,
        +      "type": "array"
        +    },
        +    "fontSize": {
        +      "description": "Font size in points. Default 60, auto-fit to the page.",
        +      "maximum": 300,
        +      "minimum": 6,
        +      "type": "number"
        +    },
        +    "opacity": {
        +      "description": "Opacity 0.0–1.0. Default 0.15.",
        +      "maximum": 1,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "position": {
        +      "default": "background",
        +      "description": "'background' (behind page content, default) or 'foreground' (above it).",
        +      "enum": [
        +        "background",
        +        "foreground"
        +      ],
        +      "type": "string"
        +    },
        +    "text": {
        +      "description": "Watermark text.",
        +      "maxLength": 100,
        +      "minLength": 1,
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "text"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / description
        Added value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."
      • removedOutput schema / properties / base64
        Removed value: -{
        -  "description": "Base64-encoded PDF bytes (when mode='base64').",
        -  "type": "string"
        -}
    • Changedinspect_pdf2 fields changed
      • addedInput schema / properties / fields
        Added value: +{
        +  "description": "Optional dot-path projection applied to the structured result (e.g. ['pageCount','signatureCount']). Composes after verbosity. Unknown paths are omitted.",
        +  "items": {
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 16,
        +  "type": "array"
        +}
      • addedInput schema / properties / verbosity
        Added value: +{
        +  "default": "full",
        +  "description": "Response verbosity. 'full' (default) returns every field; 'summary' returns a token-frugal scalar subset (version, pageCount, encryption, pdfA, signatureCount, hasSignaturePlaceholder, attachmentCount) — drops the attachments[], info and perPage arrays.",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "type": "string"
        +}
    • Changedprepare_signature_placeholder2 fields changed
      • addedOutput schema / description
        Added value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."
      • removedOutput schema / properties / base64
        Removed value: -{
        -  "description": "Base64-encoded PDF bytes (when mode='base64').",
        -  "type": "string"
        -}
    • Changedsign_pdf2 fields changed
      • addedOutput schema / description
        Added value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."
      • removedOutput schema / properties / base64
        Removed value: -{
        -  "description": "Base64-encoded PDF bytes (when mode='base64').",
        -  "type": "string"
        -}
    • Changedvalidate_pdf2 fields changed
      • addedInput schema / properties / fields
        Added value: +{
        +  "description": "Optional dot-path projection applied to the structured result (e.g. ['valid']). Composes after verbosity. Unknown paths are omitted.",
        +  "items": {
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 16,
        +  "type": "array"
        +}
      • addedInput schema / properties / verbosity
        Added value: +{
        +  "default": "full",
        +  "description": "Response verbosity. 'full' (default) returns errors[] and warnings[]; 'summary' returns a token-frugal verdict { standard, valid, errorCount, warningCount, summary } and drops the message arrays.",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "type": "string"
        +}
    • Changedverify_pdf2 fields changed
      • addedInput schema / properties / fields
        Added value: +{
        +  "description": "Optional dot-path projection applied to the structured result (e.g. ['allValid'] or ['signatures.valid']). Composes after verbosity. Unknown paths are omitted.",
        +  "items": {
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 16,
        +  "type": "array"
        +}
      • addedInput schema / properties / verbosity
        Added value: +{
        +  "default": "full",
        +  "description": "Response verbosity. 'full' (default) returns the per-signature signatures[] array; 'summary' returns a token-frugal verdict { signatureCount, allValid, invalid, summary } and drops signatures[].",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "type": "string"
        +}
  7. 13 tool updatesv1.1.0
    • First observedadd_attachment
    • First observedadd_barcode
    • First observedadd_form
    • First observedadd_international_text
    • First observedadd_table
    • First observedembed_image
    • First observedextract_text
    • First observedgenerate_basic_pdf
    • First observedinspect_pdf
    • First observedprepare_signature_placeholder
    • First observedsign_pdf
    • First observedvalidate_pdf
    • First observedverify_pdf

TDQS

A4.1/5.0

Scored across 28 tools

Disambiguation4/5

Most tools target clearly distinct PDF operations, and descriptions repeatedly clarify boundaries (e.g. generate_basic_pdf as default vs standalone add_table/embed_image/add_barcode/add_form/add_chart). The intentional overlap between the general builder and five dedicated artefact tools creates some selection ambiguity, but it is well documented rather than confusing.

Naming Consistency5/5

Names are consistently snake_case with a verb-object pattern across creation, extraction, inspection, security, and signing tools (generate_basic_pdf, add_table, extract_text, validate_pdf, sign_pdf, verify_pdf, etc.). Minor variations like generate_basic_pdf do not disrupt an otherwise predictable convention.

Tool Count2/5

At 28 tools the server is well beyond the typical 3-15 well-scoped range, and several add_* tools duplicate block types already supported by generate_basic_pdf. It also includes a governance-drafting tool unrelated to PDF processing, so the surface feels over-expanded rather than tightly scoped.

Completeness4/5

The surface is very complete for PDF generation, forms, signing, encryption, validation, attachments, extraction, merge/split, metadata, LTV/timestamping, and layout inspection. Remaining gaps include true redaction (annotate_pdf is visual-only) and image extraction or PDF-to-image conversion.

Maintenance

ActivityMaintained
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Generate professional PDFs from Claude, Cursor, and other AI tools. Create invoices, contracts, reports, and certificates from templates or inline HTML markup.
    7
    42 npm
    1
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Local document intelligence for AI agents — extract text, detect tables, read metadata, analyze structure, search keywords, and detect language from PDF and DOCX files. No cloud API required, no API key needed.
    MIT
  • F
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents to perform comprehensive PDF operations locally, including compression, text extraction, PII redaction, page organization, splitting, merging, watermarking, creation, and form filling, all without cloud uploads.
    11 npm
    -
  • A
    license
    A
    quality
    B
    maintenance
    Enables AI agents to inspect PDFs, merge or extract pages, and clean text entirely offline through the Model Context Protocol, with no uploads, API keys, or network calls.
    4
    10 npm
    MIT