pdfnative
Motor de PDF local para agentes de IA. TypeScript sem dependências, PDF/A, assinaturas, 800+ páginas/seg.
Documentação
pdfnative-mcp
Servidor MCP para geração de PDF, arquivamento PDF/A, troca de impressão PDF/X-4, tipografia refinada, assinatura PAdES com validação de longo prazo, AcroForms, mesclagem/divisão, criptografia e pré-visualização de layout — 28 ferramentas e 7 prompts no mecanismo pdfnative (sem dependências, compatível com ISO 32000-1), para Claude Desktop, Cursor, ChatGPT e qualquer cliente do Model Context Protocol.
✨ Recursos
pdfnative-mcp expõe 28 ferramentas de nível de produção para qualquer host MCP:
| Ferramenta | Finalidade |
|---|---|
generate_basic_pdf | Documentos de várias páginas a partir de 13 tipos de blocos — heading, paragraph, list, table, image (JPEG/PNG), link, toc (sumário impresso), barcode, svg, formField, chart, pageBreak, spacer — todos os DocumentBlock que o mecanismo oferece. Quebras de linha incorporadas são divididas automaticamente em parágrafos. Opcionais: pdfA, pdfx (novo na v1.7.0), print, metadata, embedFonts, watermark, outline, opções de layout (pageSize, margins, headerTemplate / footerTemplate, compress, debug, encrypt), typography (novo na v1.7.0) e cores CMYK (novo na v1.7.0). |
inspect_layout (novo na v1.6.0) | Simulação de paginação somente leitura do mesmo blocks (+ title, footerText, pdfA, normalize, embedFonts, pageSize, margins, headerTemplate, footerTemplate, typography): contagem de páginas e onde cada bloco é posicionado, sem gerar PDF. |
add_barcode | QR Code, Code 128, EAN-13, Data Matrix, PDF417 — incorporados em um PDF de página única. |
add_international_text | 27 alfabetos Unicode — Lao, Tai Tham, New Tai Lue, Tai Le e Cham (novo na v1.7.0) — além de Latim, matemática e emoji coloridos COLRv1 (sequências de bandeira / ZWJ, modificadores de tom de pele), com modelagem BiDi e OpenType; vários idiomas por documento. |
add_table | Relatórios tabulares com campos inteligentes (wrap, repeatHeader, zebra, caption, minRowHeight, cellPadding). |
add_form | Cria um novo PDF interativo com AcroForm contendo campos de texto, áreas de texto, caixas de seleção, botões de opção, listas suspensas, caixas de lista (+ texto de dica placeholder). |
read_form_fields | Enumeração somente leitura da árvore de campos de um AcroForm existente (nomes, tipos, valores, widgets). |
fill_form | Preenche e/ou achata um AcroForm existente (atualização incremental não destrutiva). |
add_chart | Gráficos vetoriais nativos v2 — barra / barraH / barraEmpilhada / barraEmpilhadaH / linha / área / dispersão / pizza / rosca, eixo secundário, escalas logarítmica e de tempo, rótulos de dados (operadores de caminho PDF puros, compatíveis com PDF/A). |
embed_image | Incorpora uma imagem JPEG ou PNG (base64) em um documento PDF com título (texto align, alt para saída marcada). |
prepare_signature_placeholder | Etapa 1 opcional do fluxo de assinatura — cria um PDF com um espaço reservado /Sig (metadados do signatário, subFilter, reserveTimestamp incorporados). |
sign_pdf | Assinatura CMS PAdES B-B / B-T (RSA-SHA256/384/512, ECDSA-SHA256 P-256; profile: 'pades', timestamp, certChainDerBase64, múltiplas assinaturas, signingTime fixável). Injeta automaticamente um espaço reservado quando necessário. |
add_ltv (novo na v1.6.0) | PAdES B-LT — incorpora um /DSS com certificados + material OCSP/CRL (provedor configurado pelo operador, ou material offline fornecido pelo chamador). |
timestamp_pdf (novo na v1.6.0) | PAdES B-LTA — anexa um /DocTimeStamp RFC 3161 da TSA configurada pelo operador; execute novamente para estender a cadeia de arquivamento. |
verify_pdf | Verifica cada assinatura PAdES e carimbo de tempo do documento (integridade + valor da assinatura + confiança opcional da cadeia; um /DocTimeStamp conta no allValid como qualquer assinatura); ltv: true relata o nível B-B…B-LTA. |
validate_pdf | Valida um PDF marcado para conformidade estrutural PDF/UA (ISO 14289-1), ou com standard: 'pdf-x-4' (novo na v1.7.0) os pré-requisitos estruturais de PDF/X-4 (ISO 15930-7) — somente leitura, não é uma pré-verificação certificada. |
add_attachment | Gera um documento PDF/A-3 com arquivos incorporados (faturas Factur-X / ZUGFeRD). |
extract_attachments | Extração somente leitura de arquivos incorporados (round-trip XML Factur-X / ZUGFeRD) com cargas úteis byte a byte. |
extract_text | Extração de texto Unicode (resolve /ToUnicode) com execuções posicionadas opcionais; abre PDFs criptografados via password. |
inspect_pdf | Inspeção somente leitura: versão do PDF, contagem de páginas, criptografia (+ encryptionInfo preciso), declaração PDF/A, declaração PDF/X (pdfX, novo na v1.7.0), assinaturas (+ inventário, /DSS, carimbos de tempo do documento), caixas de página, /Trapped, anexos, estado do espaço reservado, inventário annotations: true de anotações de página existentes. |
update_metadata (novo na v1.6.0) | Reescreve /Info título / autor / assunto / palavras-chave (+ XMP, datas incluídas) de um PDF existente como atualização incremental; fixa modDate para bytes reproduzíveis. |
encrypt_pdf | Re-protege um PDF com AES-128 / AES-256 (senhas de proprietário/usuário, permissões, rotação de senha). |
decrypt_pdf | Emite uma cópia não criptografada de um documento RC4 / AES-128 / AES-256. |
merge_pdfs | Concatena 2–50 PDFs em um único via API de árvore de páginas do pdfnative (caixas de página preservadas). |
split_pdf | Divide um PDF em um documento por intervalo de páginas (saída múltipla). |
extract_pages | Extrai um subconjunto arbitrário de páginas para um único PDF. |
annotate_pdf | Adiciona anotações de marcação (realce, nota, quadrado/círculo, linha, texto livre) como sobreposição visual — não é uma redação. |
draft_governance_issue | Redige uma issue do GitHub em conformidade com governança localmente para revisão humana; nunca envia, sem rede. |
Novo na v1.7.0:
- 🔤 Tipografia fina — um objeto
typographyopcional nos nove documentos e eminspect_layout:splitParagraphscomorphans/widows,keepHeadingsWithNext,unitBinding,bindShortWords,punctuationSpacing('fr','fr-CA'ou regras explícitas),opticalMargins,metrics: 'exact',fontFeatures(11 tags OpenType),kerning,hyphenationLanguage. Blocos de parágrafo ganhamalign(left/right/center/justify),keepWithNextesplittable; blocos de título ganhamkeepWithNext. Limites honestos:kerning,fontFeaturese o'fr'espaço estreito sem quebra precisam deembedFonts: true(a Helvetica base-14 degrada'fr'para'fr-CA');tnum/lnumnão mudam nada no Noto Sans incluído (diagnósticoTYPOGRAPHY_FEATURE_INEFFECTIVE); nenhum dicionário de hifenização está instalado, entãohyphenationLanguagenão tem efeito aqui — hifens suaves (U+00AD) são respeitados. Vejadocs/guides/TYPOGRAPHY.md. - 🎨 CMYK em qualquer lugar onde uma cor é aceita — strings de operando
'c m y k'(0–1) e tuplas percentuais[c, m, y, k](0–100) ao lado das formas hex / RGB existentes: marcas d'água, modelos de cabeçalho / rodapé, bordas de células de tabela, entradas de contorno, gráficos, blocoslinkesvg,annotate_pdf. Cada forma de cor da 1.6.0 ainda valida. - 🖨️ PDF/X-4 —
pdfx: 'pdfx4'em seis ferramentas de geração (generate_basic_pdf,add_table,add_chart,add_barcode,embed_image,add_international_text), perfis CMYK ou GrayoutputIntentao lado de RGB,print.marks.colourBarsevalidate_pdf { standard: 'pdf-x-4' }para verificar o resultado;inspect_pdfrelata a alegação (pdfX, verifique'pdfx'). Requer o perfil ICC da impressora (classe de dispositivoprtr— nenhum está incluído), precisa deembedFonts: truepara um arquivo conforme (PDFX_NO_FONT_ENTRIEScaso contrário;strict: truerecusa), e é exclusivo compdfAeencrypt. A validação é estrutural — não é um preflight certificado; o resultado diz isso por si só emcaveats[]. Vejadocs/guides/PRINT.md. - 🌏 27 scripts Unicode —
add_international_textaceitalo(Lao),nod(Tai Tham),khb(New Tai Lue),tdd(Tai Le) ecjm(Cham);ha,yo,ig,swsão aliases delatin(marcas de tom se anexam); modificadores de tom de pele emoji renderizam. Tai Tham sob PDF/A deve usarpdfa2b, nãopdfa2u(um glifo não tem uma entradaToUnicodeupstream). - 🔁 Reprodutível em qualquer host — cada data é escrita em UTC,
{date}em um cabeçalho ou rodapé segue o instante fixado, e o operador pode fixar todo o processo comPDFNATIVE_MCP_CREATION_DATEouSOURCE_DATE_EPOCH(veja Variáveis de ambiente). Não coberto, por design:signingTime,modDate, tokens RFC 3161 e dados de revogação, criptografia, assinaturas ECDSA. Vejadocs/guides/REPRODUCIBLE.md. - 🚦
strictescala por código de diagnóstico —PDFA_*→PDF_A_COMPLIANCE_VIOLATION,PDFX_*→PDF_X_COMPLIANCE_VIOLATION(novo), qualquer outra coisa →DIAGNOSTIC_ESCALATED(novo). Ambos os novos códigos só podem ser retornados por uma chamada que definestrict: true. - 🧩 Um sétimo prompt MCP,
typography— eprint_ready,reproducible_output,pdfa_validreescritos para CMYK, PDF/X-4, barras de cor e o pin UTC / operador. - 🐛 Correções — um tripleto RGB 0–1 (
watermark.color, as coresannotate_pdf) agora renderiza a cor que nomeia ([1, 0, 0]costumava renderizar quase preto); qualquer falha inesperada de uma ferramenta que recebe entrada PDF é classificada comoPDF_PARSE_FAILEDem vez de aparecer sem código. - ✅ Fechado upstream — um formulário PDF/A construído com
embedFonts: trueagora valida sob veraPDF (a fonte AcroForm está incorporada), einspect_layoutmede um blocotocexatamente como a construção o dispõe. - 🧪 Um portão, CI endurecido, docs verificados —
npm run gateé a única definição de verde (o servidor construído é dirigido sobre stdio e stdout deve carregar apenas quadros JSON-RPC); veraPDF é bloqueante sobre um corpus de conformidade de 41 arquivos; uma linha de base de bytes de 96 amostras protege a saída;npm run verify:docsmantém cada contagem, versão, ferramenta, código de erro e variável de operador citados nos docs paradocs/assets/ecosystem.jsone a árvore de origem. - 🧾 Catálogo —
tools/listcresce para ≈ 306 kB (o fragmento de tipografia e os esquemas de cor ampliados são embutidos em cada ferramenta que os carrega;npx tsx scripts/tool-shape.ts --checko mantém abaixo de 320 KiB e as instruções abaixo de 8 KiB);_meta.apiVersioné1.7.0. - ⬆ Atualização do motor — pdfnative v1.8.0. Sem mudança que quebre a API da ferramenta; os bytes que mudam (subconjuntos TrueType incorporados,
print.marks, texto moldado com posicionamento de marca, datas UTC) estão listados sob Upgrade emrelease-notes/v1.7.0.md.
Novo na v1.6.0:
- 🧱 Cobertura completa do mecanismo — 13 tipos de blocos —
generate_basic_pdfaceita todos osDocumentBlockque o pdfnative oferece: os novos blocostable,image,link,toc,barcode,svgeformFieldcompartilham seu corpo com as ferramentas dedicadas (add_table,embed_image,add_barcode,add_form), de modo que um artefato independente e um bloco inline validam e renderizam de forma idêntica. Regras:linkaceita apenashttp:/https:/mailto:(caracteres de controle rejeitados); blocosimagesão limitados (12 M de caracteres base64 cada, 24 MiB decodificados por chamada; PNG deve ser de 8 bits, não entrelaçado, sem alfa ou paleta — rejeitado com uma solução);svgcobre caminhos, formas básicas e<text>(semtransform,<g>, gradientes ou CSS — ignorados silenciosamente; nada é jamais buscado);tocemparelha comoutline: 'auto';formFieldsob uma alegação de PDF/A relataPDFA_UNEMBEDDED_FORM_FONT;barcodenão temalt(limitação do mecanismo). - 📐 Opções de layout nas nove ferramentas de documento —
pageSize(padrãoA4,Letter,Legal,A3,Tabloid),margins(todos os quatro, 0–200 pt),headerTemplate/footerTemplatecom{page}{pages}{title}{date}(umfooterTemplatesubstitui o rodapé padrão, entãofooterTexté ignorado nesse caso;{date}era o relógio de parede do dia da compilação na 1.6.0 — desde a v1.7.0 segue o instante fixado),compress(fluxos FlateDecode — arquivo menor, bytes diferentes; XMP permanece simples sob PDF/A) edebug(retângulos de guia, conteúdo não marcado — não para PDF/UA). Ausentes por padrão, então a saída padrão permanece byte-idêntica. - 🔐 Criptografia em tempo de compilação —
encryptem sete ferramentas de documento (generate_basic_pdf,add_table,add_form,add_international_text,embed_image,add_barcode,add_chart): Standard Security Handler, AES-128 padrão / AES-256, mantém o AcroForm (diferente deencrypt_pdf, que reconstrói a árvore de páginas). Exclusivo compdfA(VALIDATION_ERROR), nunca armazenado em cache; não oferecido emprepare_signature_placeholder(deve permanecer assinável) ouadd_attachment(PDF/A-3). - 📏
inspect_layout— a 28ª ferramenta: uma simulação de paginação somente leitura sobre os mesmosblockse entradas de layout, relatandototalPagese a página / x / topo / largura / altura de cada bloco sem renderizar um PDF. Lacuna conhecida do mecanismo na 1.6.0 (corrigida na v1.7.0): um blocotocera medido como 0 pt, então documentos com um conteúdo impresso podiam paginar uma página depois do previsto. - 🔎
inspect_pdf annotations: true— lista cada anotação de página (subtipo, página baseada em 0, retângulo, conteúdo truncado a 200 caracteres, título, cor, quadPoints, URL do link) além deannotationCount; novocheck: 'annotations'. - 🖼️ Marcas d'água de imagem —
watermark.image(JPEG/PNG, opacidade padrão 0,10, próprio limite de 8 MiB) emgenerate_basic_pdfeadd_table, sozinho ou combinado comtext(opacidade padrão 0,15);position: 'background' | 'foreground'para ambos. Qualquer opacidade abaixo de 1,0 é rejeitada sobpdfa1b. - 🧯
PDFNATIVE_MCP_MAX_INFLATE_BYTES— substituição pelo operador do limite de descompressão de 100 MiB por fluxo do mecanismo (inteiro ≥ 1024; um valor inválido recusa iniciar). Um fluxo de anexo limitado falhaextract_attachments includeData: truecomPDF_PARSE_FAILED;extract_textdegrada para texto de página vazio (o mecanismo engole falhas de decodificação por página). - 📝 Formulários — blocos
add_formeformFieldganhamlistboxeplaceholder;fieldType: 'textarea'agora chega ao mecanismo comomultilineText(antes era passado sem mapeamento e renderizado como um campo de linha única — uma correção de bug que muda bytes para essa entrada).embed_imageganhaalignealt. - 🔏 Escada de validação de longo prazo PAdES —
sign_pdfganhaprofile: 'pades'(ETSI EN 319 142-1 baseline, ESS signing-certificate-v2,ETSI.CAdES.detached),timestamp: true(B-T, RFC 3161), RSA-SHA384/512,certChainDerBase64,fieldName/allowMultiplepara várias assinaturas; novoadd_ltvincorpora um/DSS(B-LT,mode: 'online'através do provedor do operador oumode: 'offline'com material DER fornecido pelo chamador); novotimestamp_pdfanexa um/DocTimeStamp(B-LTA).verify_pdf ltv: truerelata perfil, carimbo de tempo, status de revogação eltvLevel. Vejadocs/guides/LTV.md. - 🌐 Carta de rede — nenhuma solicitação de saída por padrão. O único egresso que o servidor pode realizar vai para os endpoints RFC 3161 / OCSP / CRL que o operador configurou (
PDFNATIVE_MCP_TSA_URL,PDFNATIVE_MCP_REVOCATION,PDFNATIVE_MCP_NETWORK_ALLOWED_HOSTS), atrás de uma proteção SSRF; argumentos de ferramenta nunca podem fornecer uma URL. - 🖨️ Produção de impressão — toda ferramenta de documento aceita
print(TrimBox / BleedBox / ArtBox / CropBox ou a abreviaçãobleed, recorte + marcas de registromarks,/UserUnit),metadata(/Author,/Subject,/Keywords,/Trapped) eoutputIntent(ICC RGB personalizado para PDF/A);viewerPreferencesganhaduplex,pickTrayByPDFSize,printPageRange,numCopies.inspect_pdf pages: truerelata as caixas; mesclar / dividir / extrair as preservam. Vejadocs/guides/PRINT.md. - ✍️
update_metadata— reescreve/Info+ XMP de um PDF existente como uma atualização incremental (revisões anteriores e assinaturas preservadas verbatim). - 📊 Gráficos v2 —
stackedBar/stackedBarH/area/scatter, eixo direito secundário (axis2),axis.scale: 'log',xAxis.type: 'linear' | 'time',dataLabels,labelStride/labelRotation; rótulos de categoria sobrepostos são reduzidos automaticamente. - 📜 PDF/A honesto —
embedFonts: trueincorpora Noto Sans Latin (Helvetica base-14 não é incorporada, então uma alegação de PDF/A em texto latino simples é rejeitada pelo veraPDF),strict: truefalha em vez de produzir um arquivo não conforme,includeDiagnostics: trueecoa diagnósticos do mecanismo. Script local veraPDF (npm run validate:pdfa) sobre um corpus de 26 arquivos (24 validados, 3 deles canários negativos; 2 saídas de árvore de páginas ignoradas) e um modoVERAPDF_REQUIRED=1com falha fechada; o fluxo de trabalho CI fixa o instalador por SHA-256 e permanece não bloqueante na 1.6.0 (bloqueante desde a v1.7.0, onde--require-allno portão substituiVERAPDF_REQUIRED=1). Lacunas conhecidas do mecanismo na 1.6.0: saídaadd_formfalha PDF/A-2b mesmo comembedFonts(/DR /Helvnão incorporado — corrigido na v1.7.0), e uma saídaprepare_signature_placeholderé conforme apenas uma vez assinada. - 🧰
inspect_pdf— inventáriosignatures: true,dss/docTimestampCount/trapped(com portão de presença), novos valorescheckdss,docTimestamp,trapped;checkslista apenas as chaves que você solicitou, esignedé estrutural (um campo assinado existe — validade é trabalho deverify_pdf). - 🔁 Saída reproduzível —
creationDateopcional em todas as nove ferramentas de documento fixa/CreationDate, as datas XMP e o/IDdo trailer;signingTimeemprepare_signature_placeholder(e emsign_pdf, agora com deslocamentos de fuso horário) fixa/Sig /M. Bytes idênticos no mesmo fuso horário do host na 1.6.0 (em todo host desde a v1.7.0: datas escritas em UTC). Apoiado pelo promptreproducible_output. - 🛡️ Limite endurecido — esquemas de entrada estritos (chaves desconhecidas ou com erro de digitação →
VALIDATION_ERRORem vez de serem ignoradas silenciosamente); prefixosdata:…;base64,tolerados, cargas PEM-onde-DER e duplamente codificadas rejeitadas com a solução exata; erros de índice de página nas ferramentas de árvore de páginas sãoVALIDATION_ERRORcom uma dica baseada em 0; um nome de ferramenta desconhecido é um erro de protocolo JSON-RPC (-32602,[UNKNOWN_TOOL]). - 🔑 Token de portador HTTP —
PDFNATIVE_MCP_HTTP_TOKENopcional protege o endpoint HTTP Streamable (401+WWW-Authenticatecaso contrário). Sem ele, o endpoint de loopback não tem autenticação — vejaSECURITY.md. - 🧾 Catálogo —
tools/listé ≈ 245 kB (1.5.0: ≈ 108 kB) porque cada tipo de bloco, opção de layout e fragmentoencryptagora é anunciado inline — sem$ref/$defspor política, então hosts que encaminhaminputSchemapara APIs de chamada de função nunca encontram uma referência; as instruções do servidor são ≈ 6,7 kB (de 12,9 kB). A estrutura é protegida porscripts/tool-shape.mjs(scripts/tool-shape.tsdesde a v1.7.0) +tests/catalogue-parity.test.ts, etests/catalogue-superset.test.tsprova que o catálogo ao vivo é um superconjunto do publicado na 1.5.0; no máximo dois_meta.examplesexecutáveis por ferramenta, o resto sobexamples/. Quatro novos prompts de receita:pades_ladder,print_ready,reproducible_output,pdfa_valid. - 🐛 Correções — metadados do signatário (
signerName/reason/location/contactInfo) nunca alcançavam o dicionário/Signo pdfnative < 1.7; agora são gravados no momento do placeholder.verify_pdfnão relata maisallValid: falseem documentos B-LTA (um/DocTimeStampera analisado como uma assinatura CMS). - 🔌 MCP 2026-07-28 no SDK TypeScript MCP v2 (
@modelcontextprotocol/server) com fallback automático para o handshakeinitializeda era 2025 — hosts existentes continuam funcionando sem alterações. Veja conformidade com o protocolo MCP. - ⬆ Atualização do mecanismo — pdfnative v1.7.0 (LTV, produção de impressão, gráficos v2, agilidade de digest, sequências de emoji com bandeira / ZWJ, correções UAX #9).
Novo na v1.5.0:
- 📊 Gráficos vetoriais nativos —
add_chartrenderiza gráficos de barras / barras horizontais / linhas / pizza / rosca como operadores de caminho PDF puros (zero rasterização, seguro para PDF/A com texto alternativo automático).generate_basic_pdftambém aceita um blocochartpara composição com texto e tabelas. - 📝 Preencher e achatar formulários —
read_form_fieldslista os campos de um AcroForm existente;fill_formpreenche e/ou achata via uma atualização incremental não destrutiva (a contraparte deadd_form). - 🔐 Criptografia de ida e volta —
encrypt_pdfre-protege com AES-128 / AES-256 (RC4 nunca emitido),decrypt_pdfrecupera uma cópia não criptografada, uma entradapasswordabre fontes criptografadas nas ferramentas somente leitura, emerge_pdfs/split_pdf/extract_pagesganhampassword+encrypt. - 🔤 Extração de texto real —
extract_textagora resolve o CMap/ToUnicodede cada fonte (sem mais saída de índice de glifo) e pode retornarrunsposicionados. - 🔗 Recursos MCP nativos — PDFs gerados em sandbox tornam-se recursos
pdfnative://output/…(resources/list+resources/read), com umresource_linkem resultados de modo de arquivo para referência cruzada entre chamadas. - 🏷️ Anotações de ferramenta — toda ferramenta anuncia
readOnlyHint/destructiveHint/idempotentHint/openWorldHint. - ⬆ Atualização do mecanismo — pdfnative v1.6.0 (descriptografar/re-criptografar,
extractText, preencher/achatar, gráficos; subconjunto de emoji colorido 221 → 1167 glifos).
Novo na v1.4.0:
- 🤝 Governança de IA + humano no circuito —
draft_governance_issuepermite que um agente elabore uma issue do GitHub totalmente compatível localmente (rascunho.md+ relatório de conformidade legível por máquina). O agente é um redator, nunca um submissor autônomo: um humano é o único portão, e o servidor faz zero gravações no GitHub (e, desde a v1.6.0, nenhuma chamada de saída além dos endpoints TSA / OCSP / CRL configurados pelo operador). Com suporte dos prompts MCPgovernance_contractedraft_issue_workflow. - ✏️ Anotações de marcação —
annotate_pdfsobrepõe anotações de destaque, nota adesiva, sublinhado, tachado, ondulado, quadrado, círculo, linha e texto livre em um PDF existente via atualização incremental. É uma camada de revisão visual, não uma redação — os bytes subjacentes permanecem. - 🔢 Rótulos de página em
inspect_pdf— exibição somente leitura de intervalos/PageLabels(romano, decimal, prefixado). - ∑ Script matemático / científico —
add_international_textaceitalang: 'math'(explícito, comoemoji) para incorporar a fonte Noto Sans Math sob demanda. - 🧩 Prompts MCP — o servidor agora anuncia o recurso
promptscomgovernance_contractedraft_issue_workflow. - ⬆ Atualização do mecanismo — pdfnative v1.5.0.
Novidades na v1.3.0:
-
🆕 Três ferramentas de árvore de páginas —
merge_pdfs,split_pdf,extract_pages(baseadas na API de árvore de páginas do pdfnative v1.4.0; fontes criptografadas foram rejeitadas até a v1.5.0 adicionarpassword). -
🔖 Favoritos, rótulos de página e listas aninhadas —
generate_basic_pdfganhaoutline('auto'ou árvore explícita),pageLabels, itens de listalistmultinível eviewerPreferences. -
📐 Bordas e alinhamento de células de tabela —
add_tableganhacellBorders,cellVAligneviewerPreferences;add_international_textganhaviewerPreferences. -
🔐 Assinatura em tempo constante —
sign_pdfassina chaves RSA e EC-DER por meio de um provedornode:cryptocom fallback transparente em JS puro (escalares P-256 brutos permanecem em JS puro, e a verificação é em JS puro); as assinaturas permanecem interoperáveis. -
⬆ Atualização do mecanismo — pdfnative v1.4.0.
-
🆕 Ferramenta
extract_attachments— lê arquivos incorporados de volta de um PDF (completa o ciclo Factur-X / ZUGFeRD) com payloads byte a byte, um filtrofilenamee uma sonda somente de metadadosincludeData: false. -
💧 Marcas d'água —
generate_basic_pdfeadd_tableaceitam umwatermarkopcional (texto, opacidade, ângulo, cor, posição;imagedesde a v1.6.0) renderizado em todas as páginas. -
🌐 Unicode
normalize—NFC/NFD/NFKC/NFKDopcionais emgenerate_basic_pdfeadd_international_text. -
🪙 Leituras econômicas em tokens — as ferramentas somente leitura (
inspect_pdf,verify_pdf,validate_pdf,extract_text,extract_attachments;read_form_fieldsdesde a v1.5.0) aceitam entradas opcionaisverbosity: 'summary'efields: […]para respostas ~90% menores em resultados grandes, sem perda dos campos em que os agentes se baseiam. Os padrões permanecem inalterados. -
🪙 Sem duplicação de base64 — PDFs gerados (modo base64) são retornados uma vez como um bloco de conteúdo
resourceincorporado, em vez de também serem copiados parastructuredContent. -
🔧 Correção de publicação no registro MCP —
mcpNameagora usa a grafia canônica do login do GitHub (io.github.Nizoka/pdfnative-mcp) para que a validação sensível a maiúsculas/minúsculas do registro aceite o pacote npm. -
⬆ Dependência — atualizado para zod 4.
Novidades na v1.1.0:
- 🆕 Ferramenta
validate_pdf— verificação de conformidade estrutural PDF/UA (ISO 14289-1) somente leitura. - 🆕 Seis novos scripts — Telugu, Sinhala, Tibetano, Khmer, Birmanês, Etíope (24 scripts no total).
- 🆕 Emoji colorido COLRv1 — emoji colorido nativo com fallback monocromático.
- 🆕 Sanitizador de novas linhas —
\nincorporado em parágrafos divide automaticamente em parágrafos separados (PDF/A seguro). - 🆕 Normalização NFC automática para
add_international_text. - 🛠 Atualização do mecanismo — pdfnative v1.3.0: o sinal de Euro / símbolos CP-1252 agora são extraídos corretamente, e células de tabela quebradas recebem MCIDs únicos por linha (seguro para PDF/UA).
Novidades na v1.0.0:
- 🆕 Três novas ferramentas:
verify_pdf,add_attachment(Factur-X / ZUGFeRD),extract_text. - 🆕 Campos de tabela inteligente:
wrap,repeatHeader,zebra,caption,minRowHeight,cellPadding. - 🆕
inspect_pdfagora relatahasSignaturePlaceholdere resumo por anexo; novos valorescheck'placeholder'e'attachments'. - 🆕 Ergonomia de assinatura:
sign_pdfaceita chaves ECDSA SEC1 / PKCS#8 DER e injeta automaticamente um espaço reservado/Sigquando ausente (assinatura de qualquer PDF em uma única chamada). - 🆕 Cache opcional (
PDFNATIVE_MCP_CACHE_DIR): chaveado por SHA-256, TTL de 1 h, LRU de 256 MiB. - 🆕
_meta.apiVersione_meta.examplespor ferramenta para descoberta por agentes de IA — vejadocs/API_STABILITY.md. - 🆕 Guia para agentes de IA:
docs/AI_GUIDE.md— árvore de decisão + armadilhas comuns. Veja também o contrato de agente,docs/AGENT_CONTRACT.md(catálogo, árvore de decisão, receitas, tabela de erros); contribuidores e agentes de codificação começam emAGENTS.md. - 🆕 Guia de autoria PDF/A:
docs/guides/PDFA.md. - 🛠 Renomeação de variável de ambiente:
PDFNATIVE_MCP_OUTPUT_DIR(eraPDFNATIVE_MPC_OUTPUT_DIR; o nome antigo ainda funciona com um aviso de depreciação único). - ✅ Agora incluído:
merge_pdfs,split_pdf,extract_pages(v1.3.0),annotate_pdf(v1.4.0), as ferramentasadd_chart/read_form_fields/fill_form/encrypt_pdf/decrypt_pdfalém do ciclo criptografado e recursos MCP nativos (v1.5.0), eadd_ltv/timestamp_pdf/update_metadataalém de produção de impressão e gráficos v2 (v1.6.0).redact_pdfpermanece adiado — pdfnative pode sobrepor/achatar, mas não remover conteúdo de página, e uma "redação" apenas de sobreposição criaria falsa segurança, então intencionalmente não é incluído (rastreado como solicitação de remoção de conteúdo upstream).
Todas as ferramentas suportam dois modos de saída:
base64(padrão) — o PDF gerado é retornado uma vez como um bloco de conteúdoresourceincorporado (um URIdata:application/pdf;base64,…);structuredContentcarrega apenas{ mode, sizeBytes }(maisdiagnostics[]quandoincludeDiagnostics: true, e umsummaryparaadd_ltv).file— o PDF é gravado em um diretório em sandbox configurado viaPDFNATIVE_MCP_OUTPUT_DIR. A saída de arquivo é desabilitada a menos que esta variável seja definida; caminhos absolutos, travessia de caminho, extensões não-.pdfe bytes NUL são todos rejeitados.
Atualizando da v1.1.0: a única mudança de comportamento é que os bytes em modo base64 não são mais duplicados em
structuredContent.base64. Leia-os do blocoresourceincorporado:- 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
Leituras econômicas em tokens (v1.2.0). As sete ferramentas somente leitura (inspect_pdf, verify_pdf, validate_pdf, extract_text, extract_attachments, read_form_fields, inspect_layout) aceitam duas entradas opcionais:
verbosity: 'summary'— retorna um veredito compacto somente com escalares (descarta os arrays pesados / texto completo). Ex.:verify_pdf→{ signatureCount, allValid, invalid, summary }(+ltvLevelcomltv: true);inspect_pdfmantémdocTimestampCount/trapped/checksPassedquando presentes.fields: ['a', 'b.c']— projeta o resultado estruturado para caminhos de ponto nomeados; compõe apósverbosity. Caminhos sem correspondência são omitidos e relatados em_meta.unmatchedFields(com_meta.availableFields).
Menor sonda "este PDF está assinado e válido?": { "pdfBase64": "…", "verbosity": "summary", "fields": ["allValid"] }.
Por que pdfnative?
pdfnative-mcp herda todas as garantias do mecanismo subjacente:
- Zero dependências de runtime no mecanismo — JavaScript puro, sem bindings nativos (este servidor adiciona apenas o SDK MCP e zod: três dependências de runtime no total).
- Saída compatível com ISO 32000-1 (PDF 1.7).
- PDF/A-1b/2b/2u/3b, criptografia AES-128/256, AcroForm, assinaturas digitais.
- 27 scripts Unicode (34 códigos
langincl.latin,emoji,mathe os quatro aliaseslatin) com reordenação BiDi integrada, modelagem posicional árabe, modelagem OpenType tailandês/devanágari/bengali/tâmil. - Troca de impressão PDF/X-4, cor DeviceCMYK e tipografia fina (controle de órfãs/viúvas, justificação, espaçamento de pontuação francesa, recursos OpenType).
- Build ESM com tree-shaking.
🚀 Instalação
# Run directly with npx (recommended for MCP clients)
npx -y pdfnative-mcp
# Or install globally
npm install -g pdfnative-mcp
pdfnative-mcp
Requisitos: Node.js ≥ 22.
⚙️ Configuração
Claude Desktop
Edite ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) ou %APPDATA%\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
Qualquer cliente compatível com MCP que suporte servidores stdio funcionará. Use a mesma tríplice command + args + env. Exemplo para 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 usam o mesmo formato dentro de seus respectivos arquivos de configuração MCP.
🌐 Ecossistema de IA e Clientes Suportados
pdfnative-mcp é projetado para ambientes nativos MCP e funciona com clientes que suportam MCP via stdio ou Streamable HTTP.
Compatibilidade verificada pela comunidade inclui:
- Ontheia — uma plataforma de agentes de IA open-source auto-hospedada (prioridade à privacidade). Relatada como funcionando pronta para uso na issue #41 e listada na página de servidores MCP compatíveis da Ontheia.
🔌 Conformidade com o protocolo MCP
Desde a v1.6.0, o servidor é construído no SDK TypeScript MCP v2 (@modelcontextprotocol/server) e fala MCP 2026-07-28:
- Serviço sem estado —
server/discoversubstitui o handshake de sessão; cada resultado carregaresultTypee o envelope_metaserverInfo. Via HTTP, clientes 2026-07-28 enviam cabeçalhosMcp-Method/Mcp-Namecom cadaPOST /mcp. - Dicas de cache —
tools/listeprompts/listsãopubliccom TTL de 24 httlMs,server/discoverépublicpor 1 h, eresources/list/resources/templates/list/resources/readsãoprivatecomttlMs: 0(PDFs gerados são dados de usuário por host). - Erros de recurso — um URI de recurso desconhecido é relatado como JSON-RPC
-32602(Invalid params), conforme exige a especificação de 2026-07-28. - Fallback legado automático — um cliente que abre com
initialize(2025-11-25, 2025-06-18 ou 2025-03-26) é atendido pelo caminho legado do SDK tanto em stdio quanto em HTTP. Nada muda para hosts existentes. - HTTP —
GET/DELETE /mcprespondem 405 (sem retomabilidade SSE; o servidor é sem estado). O bind de loopback e a proteçãoHost/Originpermanecem inalterados, e a portaOriginagora deve ser igual à porta do servidor (a verificação do SDK sozinha é agnóstica de porta);PDFNATIVE_MCP_HTTP_TOKENadiciona um gate de bearer token opt-in (401+WWW-Authenticatesem ele). Arrays de lote JSON-RPC (2025-03-26) são aceitos via HTTP. Conexões keep-alive não acumulam mais listeners de socket. - stdio — como em todas as versões do SDK até hoje, uma solicitação enviada antes de
initializeé descartada sem resposta e arrays de lote JSON-RPC não são aceitos em stdio (inalterado desde 1.5.0; nenhum host importante usa lotes). - Erros de protocolo —
tools/callcom um nome de ferramenta desconhecido é um erro JSON-RPC (-32602,[UNKNOWN_TOOL] Unknown tool: …) em vez de um resultadoisError, conforme a especificação classifica;isError: trueé reservado para falhas de execução. - Schemas de saída — cada
structuredContentvalida contra ooutputSchemada ferramenta (um MUST de 2026-07-28), incluindo projeçõesverbosity: 'summary'efields: as sete ferramentas de leitura declaram schemas projetáveis (todas as propriedades opcionais,additionalProperties: falsemantido). Schemas de entrada não carregam a palavra-chave$schemapor política (MCP ≥ 2025-11-25 usa por padrão JSON Schema 2020-12; alguns hosts encaminhaminputSchemapara APIs de function-calling que rejeitam palavras-chave desconhecidas).serverInfocarregawebsiteUrl; o template de recurso épdfnative://output/{+path}.
O payload tools/call (content, structuredContent, isError) é idêntico entre o caminho 2026-07-28 e o caminho legado; tests/http-modern.test.ts o afirma, e tests/schema-conformance.test.ts valida structuredContent com o validador JSON Schema 2020-12 do SDK.
| Cliente | Transporte | Protocolo negociado |
|---|---|---|
| Claude Desktop, Cursor, Continue, Zed, Windsurf, Cline | stdio | legado initialize (2025-xx) — inalterado |
| ChatGPT e outros hosts Streamable HTTP | HTTP POST /mcp | streamable HTTP legado sem estado — inalterado |
Clientes MCP 2026-07-28 (SDK v2 Client, MCP Inspector atual) | stdio / HTTP | server/discover, dicas de cache, envelope _meta |
| Ontheia | stdio | legado initialize (verificado pela comunidade, #41) |
Variáveis de ambiente
| Variável | Finalidade |
|---|---|
PDFNATIVE_MCP_OUTPUT_DIR | Caminho absoluto para o diretório de sandbox. Obrigatório para habilitar outputMode: 'file'. |
PDFNATIVE_MCP_CACHE_DIR | Caminho absoluto para habilitar o cache de resultados persistente com chave SHA-256 (TTL de 1 h, LRU de 256 MiB; chave com namespace por API da ferramenta + versão do pacote + o instante de criação fixado). Quando não definido, o cache é desabilitado. Nunca armazena em cache encrypt_pdf / decrypt_pdf / sign_pdf / add_ltv / timestamp_pdf / update_metadata ou chamadas de modo de arquivo; um hit carrega _meta.cached: true e retorna os bytes da chamada anterior. |
PDFNATIVE_MCP_PORT | Quando definido para uma porta válida (1–65535), inicia um servidor HTTP em http://127.0.0.1:<port>/mcp em vez de stdio. Faz bind apenas em loopback e habilita proteção contra DNS rebinding (Host/Origin estrangeiros → 403). Sem autenticação a menos que PDFNATIVE_MCP_HTTP_TOKEN esteja definido — outros processos locais podem alcançar o endpoint. |
PDFNATIVE_MCP_HTTP_TOKEN | (v1.6.0, segredo) Bearer token opt-in para o transporte HTTP (≥ 16 caracteres, sem espaços em branco — um valor mais fraco aborta a inicialização). Quando definido, toda solicitação /mcp deve carregar Authorization: Bearer <token>; caso contrário, 401 + WWW-Authenticate: Bearer realm="pdfnative-mcp" (com error="invalid_token" somente quando credenciais foram enviadas — RFC 6750 §3.1). Comparado em tempo constante, nunca registrado em log. |
PDFNATIVE_MCP_MAX_INFLATE_BYTES | (v1.6.0) Substitui o limite de descompressão de 100 MiB por stream do mecanismo (proteção contra zip-bomb): um número inteiro positivo de bytes ≥ 1024, lido uma vez na inicialização — um valor inválido recusa iniciar. Reduza em um host compartilhado, aumente para arquivos confiáveis de grandes digitalizações. Um stream de anexo limitado falha extract_attachments includeData: true com PDF_PARSE_FAILED; extract_text degrada para texto de página vazio para um stream de conteúdo limitado (comportamento do mecanismo, nenhum erro exibido). |
PDFNATIVE_MCP_TSA_URL | (v1.6.0) URL absoluta http(s) da autoridade de timestamp RFC 3161 usada por sign_pdf timestamp: true e timestamp_pdf. Não definido: TSA_NOT_CONFIGURED, nenhuma solicitação é feita. |
PDFNATIVE_MCP_TSA_AUTH | (v1.6.0, segredo) Valor opcional do cabeçalho Authorization enviado ao TSA. Nunca registrado em log ou ecoado. |
PDFNATIVE_MCP_REVOCATION | (v1.6.0) ocsp, crl ou ocsp,crl — habilita coleta de revogação online para add_ltv mode: 'online'. Não definido: REVOCATION_NOT_CONFIGURED. |
PDFNATIVE_MCP_NETWORK_ALLOWED_HOSTS | (v1.6.0) Lista de permissões separada por vírgulas (host, host:port, *.suffix) para respondedores OCSP / CRL. Obrigatória quando PDFNATIVE_MCP_REVOCATION está definido — URLs de respondedores vêm de certificados não confiáveis. |
PDFNATIVE_MCP_NETWORK_TIMEOUT_MS | (v1.6.0) Timeout por solicitação para chamadas TSA / OCSP / CRL, 1000–120000 ms (padrão 10000). |
PDFNATIVE_MCP_CREATION_DATE | (v1.7.0) Instante ISO 8601 com fuso horário (ex.: 2026-01-01T00:00:00Z) que fixa o instante de criação de todo documento que o processo constrói: /CreationDate, as datas XMP, o /ID do trailer e o placeholder de cabeçalho / rodapé {date}. Lido uma vez na inicialização — um valor inválido recusa iniciar; a fonte da fixação é registrada em stderr. |
SOURCE_DATE_EPOCH | (v1.7.0) A convenção reproducible-builds.org: segundos inteiros desde a época Unix, usados quando PDFNATIVE_MCP_CREATION_DATE não está definido. Um valor inválido recusa iniciar. Muitos ambientes de build já o exportam: a partir desta versão, ele fixa a data de criação de todo documento — desdefina-o para o processo do servidor se isso não for desejado. |
Precedência da data de criação (maior primeiro): o creationDate por chamada → PDFNATIVE_MCP_CREATION_DATE → SOURCE_DATE_EPOCH → o relógio de parede. As datas são sempre escritas em UTC, então a saída fixada é byte-idêntica em todo host e em todo fuso horário. A fixação não cobre, por design: signingTime (sign_pdf, prepare_signature_placeholder), modDate (update_metadata), o segundo /ID regenerado de escritores incrementais (annotate_pdf, fill_form), tokens de timestamp RFC 3161 e dados de revogação online, criptografia (nova chave de arquivo, salts e IVs) e assinaturas ECDSA (randomizadas por design). Veja docs/guides/REPRODUCIBLE.md.
🛠 Referência de ferramentas
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"
}
Os 13 tipos de bloco: heading, paragraph, list, table, image, link, toc, barcode, svg, formField, chart, pageBreak, spacer. Um relatório composto:
{
"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
}
Regras de bloco: table, barcode, formField e chart aceitam o mesmo corpo que add_table / add_barcode / add_form / add_chart; URLs link devem ser http:, https: ou mailto:; blocos image são limitados a 12 M caracteres base64 cada e 24 MiB decodificados por chamada (PNG: 8-bit grayscale/RGB, não entrelaçado, sem alpha, sem paleta — caso contrário VALIDATION_ERROR com uma solução); svg suporta <path>, <rect>, <circle>, <ellipse>, <line>, <polyline>, <polygon>, <text>/<tspan> e ignora silenciosamente transform, <g>, <use>, <image>, gradientes, opacidade e CSS (nenhuma referência externa é jamais buscada); toc é construído a partir dos blocos de cabeçalho e emparelha com outline: 'auto'; formField sob pdfA precisa de embedFonts: true para que a fonte do campo também seja incorporada (PDFA_UNEMBEDDED_FORM_FONT caso contrário; strict: true então falha); barcode não tem alt. Use inspect_layout com as mesmas entradas para pré-visualizar a paginação antes de renderizar.
Tipografia (v1.7.0). typography é um objeto opt-in (12 chaves, todas desligadas por padrão — omitido significa bytes inalterados) nas nove ferramentas de documento e em inspect_layout:
{
"title": "Annual report",
"embedFonts": true,
"typography": {
"splitParagraphs": true, "orphans": 3, "widows": 3,
"keepHeadingsWithNext": { "minLines": 3 },
"opticalMargins": true, "kerning": true, "fontFeatures": ["onum", "smcp"],
"unitBinding": true, "bindShortWords": true, "punctuationSpacing": "fr"
},
"blocks": [
{ "type": "heading", "text": "Outlook", "level": 2, "keepWithNext": true },
{ "type": "paragraph", "text": "A long justified paragraph…", "align": "justify" },
{ "type": "paragraph", "text": "Figures by region:", "keepWithNext": true, "splittable": false }
]
}
- Chaves:
splitParagraphs,orphans/widows(1–10, padrão 2, precisam desplitParagraphs),keepHeadingsWithNext(trueou{ minLines }),unitBinding(trueou{ units }),bindShortWords(trueou{ maxLength, words }),punctuationSpacing('fr','fr-CA'ou um array de regras{ char, side, space }),opticalMargins,metrics(padrão'approximate'/'exact'),fontFeatures(tnum,pnum,lnum,onum,zero,ordn,sups,subs,smcp,c2sc,case),kerning,hyphenationLanguage. - Entradas de bloco: um
paragraphaceitaalign(padrãoleft/right/center/justify),keepWithNextesplittable(substituitypography.splitParagraphspara aquele bloco); umheadingaceitakeepWithNext(substituitypography.keepHeadingsWithNextpara aquele bloco). - Limites:
kerning,fontFeaturese o espaço no-break estreito'fr'precisam de uma fonte incorporada (embedFonts: true; na Helvetica base-14'fr'degrada para'fr-CA');metrics: 'exact'atua apenas em texto base-14;tnum/lnumnão mudam nada no Noto Sans incluído (TYPOGRAPHY_FEATURE_INEFFECTIVEde diagnóstico); nenhum dicionário de hifenização está instalado, entãohyphenationLanguagenão tem efeito neste servidor — hifens suaves (U+00AD) no texto são respeitados. Vejadocs/guides/TYPOGRAPHY.mde o prompttypography. Cores CMYK (v1.7.0). Cada entrada de cor mantém a forma que sempre aceitou (hex em gráficos, modelos, blocoslinkesvg; um trio RGB 0–1 em marcas d'água eannotate_pdf; uma string livre em entradas de contorno e bordas de células de tabela) e ganha DeviceCMYK ao lado: uma string de operando'c m y k'com componentes 0–1 ("1 0.6 0 0.1") e uma tupla percentual[c, m, y, k]com componentes 0–100 ([100, 60, 0, 10]). Sob uma declaração PDF/A contra a intenção sRGB padrão, uma cor CMYK relataPDFA_DEVICE_CMYK_CONTENT— mantenha as cores RGB lá, ou forneça umoutputIntentCMYK.
PDF/X-4 (v1.7.0). pdfx: 'pdfx4' em generate_basic_pdf, add_table, add_chart, add_barcode, embed_image e add_international_text grava um arquivo PDF/X-4 (ISO 15930-7): cabeçalho %PDF-1.6, a identificação XMP PDF/X-4, uma intenção de saída /GTS_PDFX, uma TrimBox em cada página e /Trapped.
{
"title": "Spring catalogue",
"pdfx": "pdfx4",
"embedFonts": true,
"outputIntent": { "iccProfileBase64": "<the printer's CMYK ICC profile, base64>", "outputConditionIdentifier": "FOGRA39" },
"metadata": { "trapped": "False" },
"print": { "bleed": 14.17, "marks": { "colourBars": true } },
"blocks": [{ "type": "paragraph", "text": "Four-colour job exchanged as PDF/X-4." }]
}
- Requer
outputIntentcom o perfil ICC da condição de impressão (classe de dispositivoprtr, CMYK ou Gray — nenhum perfil de impressora é incluído; pergunte à sua gráfica); precisa deembedFonts: truepara um arquivo conforme (PDFX_NO_FONT_ENTRIEScaso contrário;strict: truerecusa); é exclusivo compdfAeencrypt;metadata.trappeddeve ser'True'ou'False'; uma página carrega uma TrimBox ou uma ArtBox, não ambas. Solicitações incoerentes são recusadas comVALIDATION_ERRORantes de qualquer trabalho ser feito. Links e campos de formulário são relatados (PDFX_ANNOTATIONS); comstrict: trueum diagnósticoPDFX_*falha a chamada comPDF_X_COMPLIANCE_VIOLATION. outputIntentaceita perfis RGB, CMYK e Gray (≤ 8 MiB, sobpdfAoupdfx). O perfil deve ser um arquivo ICC real (assinaturaacsp, campo de tamanho consistente) — um stub feito à mão é rejeitado.print.marksaceitatrueou um objeto;marks.colourBars(trueou{ tints, size },size4–72 pt, padrão 12) adiciona os sólidos C M Y K e seus tons de 50 % no sangramento. Desativado por padrão; precisa de um sangramento de cerca de 5 mm (14,17 pt) e é ignorado quando a faixa não caberia.- Verifique o resultado com
validate_pdf { standard: 'pdf-x-4' }— uma verificação estrutural, não um preflight certificado. Vejadocs/guides/PRINT.mde o promptprint_ready.
add_barcode
{
"format": "qr",
"data": "https://pdfnative.dev",
"caption": "Scan to learn more",
"ecLevel": "H",
"outputMode": "file",
"outputPath": "tickets/event-42.pdf"
}
Formatos suportados: qr, code128, ean13, datamatrix, pdf417.
add_international_text
{
"title": "مرحبا بالعالم",
"lang": "ar",
"paragraphs": [
"هذا اختبار للنص العربي مع تشكيل OpenType ومحارف ثنائية الاتجاه.",
"Mixed content: العربية + English ✓"
]
}
Códigos lang suportados: os 27 scripts Unicode — ar, he, th, ja, zh, ko, el, hi, bn, ta, ru, ka, hy, tr, pl, vi, te, si, bo, km, my, am, e desde v1.7.0 lo (Lao), nod (Tai Tham), khb (New Tai Lue), tdd (Tai Le), cjm (Cham) — mais as faces utilitárias latin, emoji e math. Desde v1.7.0 ha (Hausa), yo (Yoruba), ig (Igbo) e sw (Suaíli) são aliases de latin: o Noto Sans incluído ancora suas marcas de tom, nenhuma fonte extra é incorporada. Fontes são sempre incorporadas (sem entrada embedFonts); fixe creationDate para saída byte-idêntica. A ferramenta também aceita typography e pdfx (veja generate_basic_pdf).
Tai Tham sob PDF/A: use
pdfA: 'pdfa2b'comlang: 'nod', nãopdfa2u— um glifo carece de uma entradaToUnicodeno mecanismo, que o veraPDF rejeita sob PDF/A-2u (rastreado upstream).
Documentos multi-script — passe um array ou lista separada por vírgulas:
{
"title": "Mixed Script",
"lang": ["ar", "emoji"],
"paragraphs": ["العربية مع رموز 🎉🚀"],
"pdfA": "pdfa2u"
}
sign_pdf
A partir de v1.0.0, sign_pdf injeta automaticamente um placeholder /Sig quando ausente — você pode assinar qualquer PDF em uma chamada:
{
"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"
}
Para ECDSA P-256: use algorithm: "ecdsa-sha256" e forneça ecPrivateKeyDerBase64 (SEC1 ou PKCS#8 DER) ou ecPrivateScalarHex (64 caracteres hex).
Conversão PEM → DER:
openssl x509 -in cert.pem -outform DER | openssl base64 -A # cert
openssl rsa -in key.pem -outform DER -traditional | openssl base64 -A # RSA PKCS#1
openssl pkey -in key.pem -outform DER | openssl base64 -A # ECDSA
Use
prepare_signature_placeholderapenas quando precisar personalizar o placeholder (por exemplo,placeholderBytesmaior para chaves RSA >4096 bits,subFilter: 'ETSI.CAdES.detached',reserveTimestamp: true). Caso contrário, chamesign_pdfdiretamente.
Escada PAdES (v1.6.0). sign_pdf com profile: "pades" produz uma assinatura B-B; adicione timestamp: true para B-T (precisa de PDFNATIVE_MCP_TSA_URL), depois add_ltv (B-LT) e 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"
Metadados do signatário (signerName, reason, location, contactInfo) são gravados no placeholder; fieldName seleciona um de vários placeholders não assinados (PLACEHOLDER_AMBIGUOUS caso contrário) e allowMultiple: true adiciona uma assinatura adicional. Veja 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"
}
Tipos de campo: text, textarea (multilinha, /Ff 4096), checkbox, radio, dropdown, listbox; placeholder mostra texto de dica enquanto um campo está vazio. Adicione encrypt para produzir um formulário protegido por senha que mantém seu AcroForm. Sob uma declaração PDF/A, passe embedFonts: true para que a fonte do campo também seja incorporada (desde v1.7.0 tal formulário valida sob veraPDF); sem isso, a chamada relata PDFA_UNEMBEDDED_FORM_FONT (strict: true então falha).
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"
}
Nota: o decodificador PNG do mecanismo aceita apenas imagens de 8 bits, não entrelaçadas, em escala de cinza / RGB. Canais alfa (tipo de cor 4 / 6), paleta (tipo 3), PNGs de 16 bits e entrelaçados são rejeitados no limite com
VALIDATION_ERRORe uma solução (achatar ou reexportar) — a mesma regra se aplica a blocosimagee marcas d'água de imagem.embed_image.imageBase64mantém seu contrato 1.5.0 sem limite de comprimento; o limite de 12 M caracteres se aplica apenas a blocosimageinline e imagens de marca d'água.
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"
}
Passe os bytes PDF retornados para sign_pdf para concluir o fluxo de assinatura.
inspect_pdf
Inspeção estrutural e de segurança somente leitura — útil para verificação downstream, asserções de CI e agentes de IA que precisam raciocinar sobre um PDF antes de agir sobre ele.
{
"pdfBase64": "<base64 PDF>",
"pages": true,
"check": ["pdfa", "signed", "attachments"]
}
Retorna:
{
"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[] aceita qualquer um de 'pdfa', 'signed', 'encrypted', 'placeholder', 'attachments', 'dss', 'docTimestamp', 'trapped', 'annotations' (os últimos quatro desde v1.6.0) e 'pdfx' (desde v1.7.0: o XMP declara PDF/X — a declaração, não sua validade; isso é validate_pdf standard: 'pdf-x-4'). pdfX aparece no resultado apenas quando o XMP declara PDF/X (mantido por verbosity: 'summary'). checksPassed é o E de todas as verificações solicitadas. signatures: true adiciona um inventário por campo (subFilter, isDocTimestamp, isPlaceholder, byteRange, vriKey); annotations: true adiciona annotations[] (cada entrada /Annots: page baseado em 0, subtype, rect, e quando presente contents truncado para 200 caracteres, title, color, quadPoints, link url) mais annotationCount; dss, docTimestampCount e trapped aparecem apenas quando presentes; com pages: true cada entrada perPage também carrega trimBox / bleedBox / artBox / cropBox / userUnit quando definidos.
inspect_layout
Simulação de paginação somente leitura — o mesmo blocks que generate_basic_pdf mais cada entrada que move um bloco (title, footerText, pdfA, normalize, embedFonts, pageSize, margins, headerTemplate, footerTemplate, e desde v1.7.0 typography). Nenhum PDF é produzido; passe exatamente o que você dará a generate_basic_pdf e totalPages corresponde.
{ "title": "Memo", "blocks": [{ "type": "paragraph", "text": "Short note." }], "pageSize": "Letter", "verbosity": "summary", "fields": ["totalPages"] }
O resultado completo carrega pageWidth, pageHeight, margins, totalPages e pages[].blocks[] (type, page, x, top, width, height em pontos, arredondados para duas casas decimais). Desde v1.7.0 a simulação e a construção compartilham um planejador de paginação, então cada tipo de bloco — toc incluído — é medido exatamente como é disposto (em 1.6.0 um bloco toc era medido como 0 pt).
validate_pdf
Verificação de conformidade estrutural somente leitura. standard escolhe o conjunto de regras: 'pdf-ua-1' (padrão — PDF/UA, ISO 14289-1, para um PDF marcado) ou, desde v1.7.0, 'pdf-x-4' (PDF/X-4, ISO 15930-7). Gere um documento acessível com qualquer ferramenta usando pdfA (por exemplo, pdfA: 'pdfa2u'), depois valide o resultado:
{ "pdfBase64": "<tagged-pdf-base64>" }
Retorna:
{
"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."
}
Verifica catálogo /MarkInfo /Marked true, /StructTreeRoot (+ /ParentTree), /Metadata (XMP), /Lang, e unicidade de MCID por página. Esta é uma porta rápida de tempo de desenvolvimento — não um substituto para um validador de referência completo (veraPDF), que adicionalmente verifica fontes, cor e renderização.
PDF/X-4 (v1.7.0). { "pdfBase64": "<pdf>", "standard": "pdf-x-4" } verifica os pré-requisitos estruturais da ISO 15930-7: cabeçalho PDF 1.6, sem criptografia, trailer /ID, a identificação XMP PDF/X-4, uma intenção de saída /GTS_PDFX com um perfil ICC prtr incorporado, uma TrimBox ou ArtBox por página aninhada na BleedBox e MediaBox, toda fonte incorporada, nenhuma anotação na área impressa, nenhum JavaScript, nenhum arquivo incorporado, cor de dispositivo consistente com a intenção de saída. O resultado tem a mesma forma mais caveats[], que declara o que um veredito valid: true não estabelece: isto não é um preflight certificado, e o veraPDF não cobre PDF/X — confirme um trabalho de impressão com callas pdfToolbox ou Acrobat Preflight. A resposta padrão (pdf-ua-1) é inalterada e não carrega caveats.
annotate_pdf
Sobreponha anotações de marcação em um PDF existente via atualização incremental. Esta é uma camada de revisão visual, não uma redação — o conteúdo subjacente é intocado.
{
"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" }
]
}
Tipos: text, highlight, underline, strikeout, squiggly, square, circle, line, freetext. Índices de página são baseados em 0. color / interiorColor aceitam uma string hex ou operando (incluindo uma string de operando CMYK), um trio RGB 0–1 ([1, 1, 0]) ou, desde v1.7.0, uma tupla percentual CMYK ([0, 0, 100, 0]); v1.7.0 também corrige o trio 0–1, que costumava renderizar quase preto. Fontes criptografadas são rejeitadas (ENCRYPTED_SOURCE) — execute decrypt_pdf primeiro (remove assinaturas / AcroForm), anote, depois encrypt_pdf novamente.
draft_governance_issue
Rascunhe uma issue GitHub compatível com governança localmente para um humano revisar e enviar. O servidor nunca contata o GitHub (seu único egresso possível são os endpoints TSA / OCSP / CRL configurados pelo operador — veja Rede e egresso); ele retorna o rascunho em Markdown mais um relatório de conformidade legível por máquina.
{
"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
}
Um rascunho que propõe uma dependência de tempo de execução, omite uma reprodução ou define duplicateSearchPerformed: false é rejeitado com GOVERNANCE_VIOLATION. Veja docs/guides/AI_GOVERNANCE.md para o contrato completo de humano-no-loop.
verify_pdf, add_attachment, extract_text
Veja as seções dedicadas em docs/AI_GUIDE.md e a referência em docs/KNOWLEDGE_BASE.md. Exemplos prontos para execução estão em examples/.
🔐 Modelo de segurança
pdfnative-mcp executa dentro do processo host e expõe um servidor MCP via stdio (ou um endpoint HTTP somente loopback). Ele não realiza nenhuma operação de E/S fora do sandbox configurado.
- Gravações de arquivos são controladas por
PDFNATIVE_MCP_OUTPUT_DIR. Quando não definido, o modo de saídafileé rejeitado com umSecurityError. - Resolução de caminhos rejeita caminhos absolutos, sequências de travessia (
..), bytes NUL e qualquer extensão diferente de.pdf. - Tamanho da saída é limitado a 50 MB por chamada.
- Entradas são validadas contra esquemas JSON estritos + verificações de runtime Zod na fronteira de cada ferramenta — chaves desconhecidas ou com erro de digitação (no nível superior ou aninhadas) são rejeitadas com
VALIDATION_ERROR, e cargas base64 / DER passam por verificação de sanidade (prefixodata:tolerado, entrada PEM ou duplamente codificada rejeitada com a correção) antes de qualquer parser ser executado. - Transporte HTTP (
PDFNATIVE_MCP_PORT) vincula-se apenas a loopback; não possui autenticação a menos quePDFNATIVE_MCP_HTTP_TOKENesteja definido (então401sem um token bearer válido).
Rede e saída de dados
O servidor não faz nenhuma chamada de rede de saída por padrão. A única saída que ele pode realizar vai para os endpoints RFC 3161 / OCSP / CRL que o operador configurou no ambiente para validação de longo prazo PAdES (PDFNATIVE_MCP_TSA_URL, PDFNATIVE_MCP_REVOCATION, PDFNATIVE_MCP_NETWORK_ALLOWED_HOSTS) — nunca para uma URL fornecida por um argumento de ferramenta, nunca para o GitHub, nunca para telemetria. Sem essa configuração sign_pdf timestamp: true, timestamp_pdf e add_ltv mode: 'online' falham rapidamente com TSA_NOT_CONFIGURED / REVOCATION_NOT_CONFIGURED antes de tocar no documento; add_ltv mode: 'offline' incorpora material fornecido pelo chamador com zero acesso à rede.
As URLs de OCSP / CRL vêm das extensões AIA / CRL-distribution-point de certificados não confiáveis dentro do PDF, portanto cada busca passa por uma proteção SSRF:
- o host deve corresponder à lista de permissões do operador (
host,host:portou*.suffix; curingas simples são rejeitados). As entradas são nomes de host, não URLs: uma entradahost:portsó corresponde a URLs com uma porta explícita (o parser de URL descarta as portas padrão:80/:443— liste o host simples para essas); entradas curinga não podem ter porta; nomes de host IDN devem ser listados em punycode (xn--…); literais IPv6 entre colchetes ([2001:db8::1]); - apenas
http:/https:, sem credenciais incorporadas, redirecionamentos nunca são seguidos; - literais de endereço loopback, link-local, privado, unique-local, CGNAT, não especificado e multicast (incluindo grafias decimal / octal / hexadecimal e IPv6 mapeado para IPv4) são rejeitados, a menos que esse literal esteja na lista de permissões literalmente. A proteção verifica apenas literais — um nome de host listado que resolve para um endereço interno (DNS rebinding) não é detectado, pois não há resolvedor sem adicionar uma dependência; coloque na lista de permissões apenas hosts que você controla;
- tempo limite por solicitação (
PDFNATIVE_MCP_NETWORK_TIMEOUT_MS) e limites de resposta (256 KiB TSA, 1 MiB OCSP, 16 MiB CRL) aplicados durante o streaming, portanto uma resposta superdimensionada é cortada em vez de armazenada em buffer; - respostas OCSP e CRLs retornadas pelos respondedores são validadas por parse antes de
add_ltvincorporá-las; - a URL do TSA é confiável pelo operador (verificações de esquema + credenciais apenas); o segredo
PDFNATIVE_MCP_TSA_AUTHnunca é registrado em log ou ecoado em mensagens de erro.
Os provedores são construídos por chamada e passados pelas opções por chamada do pdfnative — os setters de provedor em todo o processo nunca são usados, portanto solicitações concorrentes não compartilham nada. As instruções server/discover relatam a política de saída atual (apenas tipos de endpoint, nunca segredos).
Veja SECURITY.md para o processo de divulgação responsável e docs/guides/LTV.md para a configuração do operador.
🧪 Desenvolvimento local
git clone https://github.com/Nizoka/pdfnative-mcp.git
cd pdfnative-mcp
npm ci # .npmrc sets ignore-scripts=true: nothing builds on install
npm run gate:fast # before every commit: typecheck:all, lint, test, server-json, verify:docs
npm run gate # the CI profile: build, dist checks, stdio smoke test, tool shape, samples, coverage, docs, corpus, validate:pdfx
npx tsx scripts/gate.ts --publish --require-all # release branches: everything incl. validate:pdfa (veraPDF); a skipped step fails
npm run gate (scripts/gate.ts) é a definição única de "verde" — 1631 testes, os limites de cobertura de vitest.config.ts, e o servidor compilado acionado via stdio, onde o stdout deve conter apenas quadros JSON-RPC. Ele imprime uma linha por etapa e grava os logs em test-output/.gate/<step>.log; --only <step> executa uma etapa e --json fornece saída de máquina (chame o script diretamente para passar flags: npx tsx scripts/gate.ts --fast). As etapas individuais são scripts npm comuns:
npm run build && npm run test:generate # drive the built server under TZ=UTC, operator variables scrubbed -> test-output/samples/
npm run verify:samples # hold the 96 samples to tests/_fixtures/samples.sha256.json (93 by bytes, 3 by a semantic projection)
npm run corpus:pdfa # write the 41-file conformance corpus (33 claim PDF/A, 6 claim PDF/X-4, 2 page-tree outputs claim nothing)
npm run validate:pdfx # in-process structural PDF/X-4 check of the corpus; never skips
npm run validate:pdfa # veraPDF over the PDF/A files (VERAPDF_HOME, JAVACMD); exit 0 ok / 1 conformance / 2 infrastructure
npm run verify:docs # every count, version, tool, error code, operator variable, link and anchor in the docs vs docs/assets/ecosystem.json and src/
npx tsx scripts/tool-shape.ts --write # only after a deliberate tools/list schema change (npm run verify:tool-shape checks the fixture)
Uma mudança de saída pretendida é re-baselined com npx tsx scripts/verify-samples.ts --update e declarada na nota de versão — nunca para silenciar uma surpresa. Com veraPDF 1.30.2, o corpus dá 27 PASS e 6 falhas esperadas (canários negativos que devem permanecer rejeitados). Cada script, suas flags e seus códigos de saída estão listados em scripts/README.md.
Teste o servidor via stdio:
node dist/cli.js
# In another terminal, send a JSON-RPC initialize request via stdin (e.g. with mcp-inspector).
Colaboradores: comece em
AGENTS.md(as regras do repositório compartilhadas por todo agente de codificação e colaborador) e veja docs/guides/LOCAL_TESTING.md para o fluxo completo de verificação local — o portão de qualidade, exemplos-como-testes, validação de que PDFs gerados são estruturalmente corretos (assertValidPdf,inspect_pdf,validate_pdf,verify_pdf), abertura de saída em um visualizador, verificação externa de PDF/A com veraPDF e o MCP Inspector.
📣 Processo de lançamento
pdfnative-mcp segue o mesmo formalismo de lançamento que pdfnative:
- Um arquivo de nota de versão por tag em
release-notes/vX.Y.Z.md CHANGELOG.mdespelha cada lista de marcadores da versão- O corpo da Release do GitHub é copiado de
release-notes/vX.Y.Z.md npx tsx scripts/release-prepare.ts --version X.Y.Zaplica a parte mecânica de um incremento de versão (nunca faz commit, tag ou publicação); a versão se move em sincronia empackage.json,src/version.ts,server.jsonedocs/assets/ecosystem.json- Uma branch de lançamento deve passar em
npx tsx scripts/gate.ts --publish --require-all— cada etapa, incluindo veraPDF, sem pular - A publicação no npm é tratada pelo GitHub Actions Trusted Publishing (OIDC), sem
NPM_TOKEN, a partir de um ambiente protegido: o workflow verifica se a tag é igual à versão do pacote, executa o portão de publicação e publica com--provenance; um segundo job atesta o tarball (proveniência de build) juntamente com um SBOM CycloneDX e anexa ambos à Release do GitHub - Cada job Linux e Windows começa com
step-security/harden-runner(a ação não suporta macOS; o job macOS é a exceção documentada), faz checkout compersist-credentials: false, instala comnpm ci --ignore-scriptse executa sobpermissionsde privilégio mínimo; as ações são fixadas por SHA de commit; o job veraPDF é bloqueante - Humano no circuito: agentes de codificação preparam e verificam; o mantenedor faz push, abre o pull request, cria a tag e publica (
.github/AGENT_RULES.md)
Veja release-notes/TEMPLATE.md para a estrutura canônica e a lista de verificação de publicação, e CONTRIBUTING.md para o procedimento de lançamento.
📚 Estrutura do projeto
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 + colour bars, userUnit, RGB / CMYK / Gray outputIntent, metadata, creationDate)
├── pdfx.ts # pdfx: 'pdfx4' conformance target + the static conflicts refused before the build
├── color.ts # shared colour fragment: CMYK operand string / percent tuple beside each historical form, toEngineColor()
├── typography.ts # the typography fragment (12 opt-in keys) + TypographyOptions mapper
├── reproducible.ts # operator-pinned creation instant (PDFNATIVE_MCP_CREATION_DATE, SOURCE_DATE_EPOCH)
├── diagnostics.ts # engine diagnostics sink (PDFA_* / PDFX_* / TYPOGRAPHY_*), strict escalation by code, 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 / typography (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/ # TypeScript run by tsx — the full table is in scripts/README.md
├── gate.ts # THE quality gate (npm run gate / gate:fast; --publish --require-all on release branches)
├── generate-samples.ts # npm run test:generate — the built server under TZ=UTC -> test-output/samples/
├── verify-samples.ts # npm run verify:samples — the byte baseline (tests/_fixtures/samples.sha256.json)
├── generate-pdfa-corpus.ts # npm run corpus:pdfa — the 41-file PDF/A + PDF/X-4 conformance corpus
├── validate-pdfa.ts # npm run validate:pdfa — veraPDF (PASS/FAIL/XFAIL/XPASS; exit 0 / 1 / 2)
├── validate-pdfx.ts # npm run validate:pdfx — in-process structural PDF/X-4 check, never skips
├── tool-shape.ts # structural tools/list fingerprint (--write refreshes tests/_fixtures/tool-shape.json)
├── verify-docs.ts # npm run verify:docs — the docs held to docs/assets/ecosystem.json and the source tree
├── release-prepare.ts # mechanical version bump (never commits, tags or publishes)
├── build-claude-rules.ts # npm run agents:rules — .github/instructions/ -> .claude/rules/
└── verify-issue.mjs # governance draft checker (npm run verify:issue)
docs/
├── AGENT_CONTRACT.md # the consumer contract for agents that USE the server (catalogue, decision tree, recipes, error codes)
├── AI_GUIDE.md, KNOWLEDGE_BASE.md, API_STABILITY.md
├── guides/ # PDFA, PRINT, TYPOGRAPHY, REPRODUCIBLE, CHARTS, FORMS, ENCRYPTION, LTV, AI_GOVERNANCE, LOCAL_TESTING
└── assets/ecosystem.json # the single source of every count and version quoted in the docs
examples/ # 43 executable tools/call sequences (npm run examples:check)
AGENTS.md, CLAUDE.md # repository rules for coding agents; .github/instructions/ holds the per-area rules
.claude/ # shared agent settings, the fail-closed guard hook, generated rules, the release-audit skill
.github/workflows/ # ci (Node 22 / 24 on Linux, plus Windows and macOS, all running the gate, all required), publish, sample-regression, verapdf (blocking),
# docs, codeql, scorecard, dependency-review, audit
.github/rulesets/ # branch and tag rulesets to import
tests/ # vitest suites (one per tool / module), _fixtures/ (tool shape, sample baseline, engine-surface matrix,
# the frozen 1.5.0 catalogue), tools/ (repository tooling)
🗺 Roteiro
A v1.7.0 foi lançada (tipografia fina, cores CMYK, PDF/X-4, 27 scripts Unicode, saída reproduzível em todos os hosts, pdfnative 1.8), sobre a v1.6.0 (cobertura completa do motor — 13 tipos de bloco, opções de layout, inspect_layout — escada PAdES LTV, produção gráfica, gráficos v2, update_metadata, MCP 2026-07-28). O plano completo — marcos lançados, trabalho em andamento e direção de longo prazo — está em ROADMAP.md.
Ainda adiado:
redact_pdf— pdfnative não tem API de remoção de conteúdo; uma "redação" somente sobreposição criaria falsa segurança.- Fontes personalizadas (um diretório de fontes do lado do operador) e uma anotação
linkemannotate_pdf— no roteiro, não na v1.7.0. - Verificação ECDSA nativa — pdfnative não exporta
ecdsaVerifyHash;verify_pdfmantém seu caminho puro em JS para P-256. - Streaming de páginas HTTP — MCP 2026-07-28 ainda não tem
structuredContentparcial, então resultados grandes permanecem em disparo único.
Tem uma ideia de recurso? Abra uma issue ou PR.
⭐ Marque o projeto com estrela
Se pdfnative-mcp é útil para você, por favor ⭐ este repositório — e considere também marcar com estrela o motor subjacente Nizoka/pdfnative. Estrelas ajudam outros a descobrir o projeto e motivam o desenvolvimento contínuo.
🤝 Contribuindo
Contribuições são muito bem-vindas. Por favor, leia CONTRIBUTING.md, verifique as issues abertas e siga o código de conduta.
📄 Licença
MIT © 2026 Nizoka. Material de terceiros: THIRD-PARTY-NOTICES.md.
pdfnative-mcp é construído sobre pdfnative e o Model Context Protocol TypeScript SDK.