Pular para o conteúdo
getnextpdf.com

Guia do desenvolvedor do Connect

O NextPDF Connect (nextpdf/server) encapsula como serviço o motor PDF 2.0 do NextPDF, que é agnóstico de framework. Ele não reimplementa a geração de PDF. Ele expõe cada capacidade do motor como uma ferramenta nomeada com um schema e, em seguida, disponibiliza esse catálogo por três transportes: Model Context Protocol (MCP) sobre entrada e saída padrão, Application Programming Interface (API) no estilo Representational State Transfer (REST) e gRPC. Use este guia ao desenvolver para o servidor, estender o conjunto de ferramentas dele ou executá-lo em produção.

Três conceitos definem o design: o registro de ferramentas, os três transportes independentes e o gate de confirmação com humano no circuito (human-in-the-loop, HITL). Esta página explica como eles se encaixam e como trabalhar com eles sem enfraquecer o modelo de segurança. Para os símbolos exatos de ferramenta, chamada de procedimento remoto (RPC) e mensagem, consulte a referência da API.

Pré-requisitos: PHP 8.4, Composer 2 e — para os transportes em rede — o binário do RoadRunner e pelo menos uma chave de API. Instale com composer require nextpdf/server.

Mantenha cada responsabilidade no lado correto da fronteira. Uma ferramenta é um wrapper fino em torno de uma chamada ao motor; ela não deve conter interpretação de layout, semântica do documento nem lógica de transformação.

CamadaPertence aResponsabilidadeNão coloque aqui
Cliente ou agenteSua integraçãoEscolher qual ferramenta chamar; encaminhar os desafios de confirmação a um humano.Lógica do motor ou detecção de tier.
Transportenextpdf/serverEstruturar requisições como JSON-RPC, HTTP ou Protocol Buffers; autenticar; e rotear para o executor de ferramentas.Semântica do documento.
Registro de ferramentasnextpdf/serverDescobrir tiers, registrar ferramentas sujeitas à allowlist de segurança e localizar uma ferramenta pelo nome.Geração de PDF.
Ferramentanextpdf/serverValidar os argumentos contra o schema de entrada e chamar o motor.Interpretação de layout ou orquestração em várias etapas.
Gate de confirmaçãonextpdf/serverReter uma operação ApprovalRequired até que um humano a aprove.Autenticação do chamador.
Motornextpdf/core (e nextpdf/premium)Gerar, inspecionar e transformar o conteúdo de PDF.Questões de transporte ou autenticação.

Cada transporte tem seu próprio ponto de entrada e sua própria fábrica de inicialização. Cada um constrói explicitamente o próprio grafo de objetos. Não há um container de injeção de dependências a configurar.

  1. Carregue a configuração. O servidor MCP resolve a configuração a partir de variáveis de ambiente (NEXTPDF_MCP_*), depois da seção nextpdf_mcp do arquivo YAML, depois dos padrões embutidos, e produz uma readonlyMcpConfig. Os servidores REST e gRPC leem a HttpConfig das variáveis de ambiente NEXTPDF_*. Consulte Configuração.
  2. Construa a política de segurança. A allowlist enabled_tools é construída antes do registro, restringindo a descoberta desde o primeiro registro.
  3. Construa o registro e descubra as ferramentas. O ToolRegistry::registerDefaults() registra o tier core, depois os provedores Pro e Enterprise quando suas classes são resolvidas e, em seguida, os provedores AST e de mutação empacotados, sujeitos aos seus gates de ambiente.
  4. Construa os stores compartilhados e o gate. O document store em memória é construído a partir do TTL e da capacidade configurados; o ConfirmationGate é montado com seu store de tokens de uso único.
  5. Vincule o transporte. O MCP entra em um laço de leitura-tratamento-escrita sobre o stdio até o fim do arquivo. O REST e o gRPC constroem sua tabela de rotas ou serviços a partir dos tiers detectados e, então, entregam ao RoadRunner o laço de requisições.

Depois disso, uma requisição segue este caminho: autenticar (REST e gRPC), resolver a ferramenta ou operação, executar o gate de confirmação para o trabalho ApprovalRequired, executar contra o motor e retornar o resultado. Consulte Inicialização e descoberta.

Os três transportes compartilham os conceitos de registro, configuração e gate, mas são executados como processos independentes. Iniciar um deles não inicia os outros.

TransportePonto de entradaQuando escolhê-lo
MCPbin/nextpdf-mcpUm cliente local de inteligência artificial (IA) que inicia o servidor como subprocesso confiável.
RESTbin/nextpdf-serverClientes HTTP em rede; transporte descrito por um documento OpenAPI 3.1.
gRPCbin/nextpdf-grpcClientes tipados e com streaming; serviço nextpdf.connect.v1.NextPDFConnect.

Escolha os transportes pelo perfil do RoadRunner que você executa: .rr.yaml (apenas REST), .rr.grpc.yaml (apenas gRPC) ou .rr.full.yaml (ambos). O transporte MCP é um subprocesso simples e não precisa de supervisor. Para detalhes de protocolo, consulte Transporte MCP, Transporte REST e Transporte gRPC.

Execute os transportes em rede sob o RoadRunner, com stores compartilhados e chaves montadas como segredos. O perfil combinado permite que REST e gRPC compartilhem um supervisor.

Caminho ou configuraçãoFinalidade
.rr.full.yamlPerfil combinado de REST e gRPC sob um único supervisor.
NEXTPDF_API_KEYS_FILECaminho para um arquivo de chaves de API montado como segredo e com recarga a quente.
NEXTPDF_REDIS_HOSTHabilita stores de limite de taxa, idempotência e documentos com suporte do Redis para pools de vários workers.
NEXTPDF_WORKER_COUNT / NEXTPDF_GRPC_WORKER_COUNTDimensionamento dos pools de workers HTTP e gRPC.
Diretório base de saídaVolume dedicado com permissões de sistema de arquivos com privilégio mínimo para as ferramentas de saída em arquivo.

O exemplo de shell abaixo inicializa o perfil combinado com chaves montadas como segredos e um store Redis compartilhado. Ele não contém segredos; as chaves são montadas em /run/secrets/api-keys.

Terminal window
export NEXTPDF_API_KEYS_FILE=/run/secrets/api-keys
export NEXTPDF_WORKER_COUNT=8
export NEXTPDF_GRPC_WORKER_COUNT=4
export NEXTPDF_REDIS_HOST=redis
./vendor/bin/rr serve -c .rr.full.yaml

Para um pool de vários workers, configure o Redis e confirme que a ext-redis está presente na imagem em execução. Sem ela, os stores de limite de taxa, idempotência e documentos ficam isolados por worker. Consulte Implantação.

NextPDF\Server\ToolRegistry (src/ToolRegistry.php) constrói o catálogo na inicialização. O tier é uma invariante declarada: cada ferramenta retorna seu próprio tier() e riskLevel(). O registro nunca infere o tier a partir do namespace ou do empacotamento.

  1. Tier core é registrado incondicionalmente: as ferramentas de documento e de diagnóstico, mais a ferramenta @api estável generate_barcode (o registro de codificadores de código de barras do core acompanha o nextpdf/core, então as simbologias core sempre são resolvidas; as simbologias Pro exigem o nextpdf/pro), mais o parse_pdf apenas quando NEXTPDF_MCP_TOOL_PARSE_PDF_ENABLED é true ou 1.
  2. Provedores Pro e Enterprise são registrados quando suas classes de provedor são resolvidas, verificadas com class_exists(). Um tier ausente é ignorado silenciosamente.
  3. Provedores AST e de mutação empacotados são registrados sob o tier Pro, controlados por NEXTPDF_AST_TOOLS_ENABLED e NEXTPDF_MUTATION_TOOLS_ENABLED (ambos habilitados por padrão).
  4. O filtro de política de segurança intersecta cada registro com a allowlist enabled_tools. A allowlist subtrai; nunca adiciona. O contador por tier inclui apenas as ferramentas que a política admite.

A resposta de initialize do MCP e o endpoint REST GET /api/v1/capabilities reportam as contagens por tier resultantes e o total. Considere desatualizado qualquer total fixo escrito em prosa; consulte o servidor em execução. Consulte Catálogo de ferramentas.

Toda ferramenta declara um dos quatro níveis de risco do enum RiskLevel (src/Config/RiskLevel.php): Safe (0), Caution (1), Review (2) e ApprovalRequired (3). O registro de auditoria se aplica a partir de Caution. Uma sobrescrita de configuração pode elevar o risco de uma ferramenta; nunca pode rebaixar uma ferramenta que é ApprovalRequired por design. O carregador de configuração lança uma exceção durante o carregamento, e o servidor se recusa a inicializar em vez de executar com um gate enfraquecido.

Quando uma ferramenta ApprovalRequired é invocada sem um token válido, o ConfirmationGate (src/Mcp/ConfirmationGate.php) retorna um token de desafio de uso único. O token vincula o nome da ferramenta, um digest canônico dos argumentos relevantes para a decisão, um nonce aleatório e um tempo de vida (time-to-live, TTL) de 300 segundos. O digest é um SHA-256 estável sob normalização (ordenação recursiva de chaves, excluindo o próprio argumento _confirmation_token), de modo que um cliente que reserializa os argumentos com uma ordenação de chaves diferente na nova tentativa ainda corresponde, ao passo que um token emitido para um conjunto de argumentos não pode autorizar a mesma ferramenta com argumentos substituídos (confused-deputy / substituição de argumentos). O agente encaminha o desafio a um humano e invoca novamente a mesma ferramenta com o token no argumento _confirmation_token. O token é consumido no momento do uso, liberando exatamente uma chamada controlada pelo gate.

O exemplo de PHP abaixo é um auxiliar agnóstico de transporte. Ele conduz uma chamada de ferramenta MCP e, diante de um desafio de confirmação, mostra o desafio a um aprovador humano antes de tentar novamente com o token emitido. Ele declara tipos estritos, é totalmente tipado e captura a exceção mais específica em vez de capturar todos os erros indiscriminadamente.

examples/connect/confirm-and-call.php
<?php
declare(strict_types=1);
namespace App\Connect;
use JsonException;
/**
* Drives one tool call and resolves an ApprovalRequired confirmation
* challenge through a human approver before retrying.
*/
final readonly class ConfirmingToolCaller
{
public function __construct(
private McpClientInterface $client,
private HumanApproverInterface $approver,
) {}
/**
* @param non-empty-string $toolName
* @param array<string, mixed> $arguments
*
* @return array<string, mixed> The tool result content
*
* @throws JsonException When a response cannot be decoded
* @throws ApprovalDeniedException When the human declines the challenge
*/
public function call(string $toolName, array $arguments): array
{
$response = $this->client->callTool($toolName, $arguments);
if (!isset($response['challenge'], $response['token'])) {
return $response;
}
$challenge = (string) $response['challenge'];
$token = (string) $response['token'];
if (!$this->approver->approve($toolName, $challenge)) {
throw new ApprovalDeniedException($toolName);
}
$arguments['_confirmation_token'] = $token;
return $this->client->callTool($toolName, $arguments);
}
}

Conecte McpClientInterface, HumanApproverInterface e ApprovalDeniedException ao seu próprio transporte e canal de aprovação. A nova tentativa reutiliza os argumentos originais junto com o token emitido; nunca aprove um desafio automaticamente sem uma decisão humana. Consulte Tiers de risco HITL.

Estenda o servidor adicionando ferramentas e fornecendo provedores, não editando o registro.

Ponto de extensãoUse-o paraRestrição
Uma classe que implementa ToolInterfaceUma nova capacidade do motor exposta como ferramenta.Declare tier(), riskLevel(), category() e um inputSchema() em JSON Schema; mantenha a classe como um wrapper fino do motor.
Um provedor ToolProviderInterface de ferramentasRegistrar um conjunto de ferramentas para um tier.Os provedores Pro e Enterprise são descobertos por class_exists(); não faça o servidor exigir o pacote proprietário.
enabled_tools allowlistEscopo de privilégio mínimo do catálogo exposto.A allowlist apenas subtrai; ela não pode registrar uma ferramenta ausente.
risk_level_overridesFortalecer uma implantação elevando o risco de uma ferramenta.Apenas elevação; um rebaixamento de uma ferramenta ApprovalRequired falha na inicialização.
Pontos de injeção de transporte e workerTestar o servidor isoladamente.Essas fronteiras existem para testes, não para a integração da aplicação.
  1. Escolha um perfil. Execute .rr.yaml, .rr.grpc.yaml ou .rr.full.yaml para os transportes que você expõe.
  2. Monte as chaves a partir de um segredo. Aponte NEXTPDF_API_KEYS_FILE para um arquivo de segredo; prefira o store de chaves em arquivo com recarga a quente, para que a rotação não exija reinicialização.
  3. Configure os stores compartilhados. Defina NEXTPDF_REDIS_HOST e confirme a ext-redis para qualquer pool maior que um worker; coloque o job store SQLite em um volume no qual todos os workers possam escrever.
  4. Termine o TLS. Execute o REST atrás de um terminador de Transport Layer Security (TLS); execute o gRPC com TLS mútuo em qualquer rede não confiável, com a chave do servidor, o certificado do servidor e a autoridade certificadora do cliente fornecidos como segredos de implantação.
  5. Verifique a saúde. Use os endpoints anônimos /healthz e /readyz (REST) ou os RPCs HealthCheck e ReadinessCheck (gRPC) para sondas do orquestrador.
  6. Defina o escopo do catálogo. Restrinja enabled_tools ao conjunto mínimo que uma integração necessita.

Verifique a saúde do Redis em vez de presumi-la. O servidor REST recorre a stores em memória quando uma conexão Redis configurada falha. Consulte Implantação e Segurança e operações.

FalhaOnde se manifestaResposta recomendada
Desconhecido document_idExecução da ferramentaRetorne um erro definido ao chamador; instrua-o a chamar create_pdf primeiro.
ETag desatualizada em uma mutaçãoFerramenta de mutação ASTReleia o documento com get_document_ast e tente novamente com a ETag atualizada.
Chave de API ausente ou inválida (REST)Middleware de autenticaçãoRetorne 401 com um desafio WWW-Authenticate: Bearer; não revele qual parte estava errada.
Tier sem direito de acesso (REST)AutorizaçãoRetorne 403; o tier da chave está abaixo do tier da operação.
Rota do tier ausente (REST)RoteadorRetorne 404; o pacote não está instalado. Esta é uma condição esperada, não uma falha.
Token inválido (gRPC)Autenticador gRPCFaça a chamada falhar com UNAUTHENTICATED.
Redis inacessívelInicialização ou tempo de execuçãoRecorra a stores em memória; alerte os operadores e verifique a saúde do Redis.
Caminho de saída fora do diretório baseFerramenta de saída em arquivoFalhe em modo fechado; o caminho é canonicalizado e a travessia é rejeitada.

Exponha as falhas do motor como objetos de erro definidos, nunca como sucessos silenciosos. A referência da API detalha o modelo de erro para cada transporte.

QuestãoPadrãoQuando sobrescrever
parse_pdfDesabilitado (opt-in via NEXTPDF_MCP_TOOL_PARSE_PDF_ENABLED).Habilite apenas quando uma integração precisar de inspeção estrutural.
enabled_toolsVazio (todas as ferramentas descobertas são permitidas).Defina uma allowlist explícita para implantações de privilégio mínimo.
Sobrescritas de riscoNenhuma.Eleve o risco para uma implantação fortalecida; nunca tente um rebaixamento.
document_ttl / max_documents1800 segundos / 50 documentos.Reduza para implantações sensíveis à residência de dados ou com memória limitada.
allow_file_outputHabilitado.Defina como false para implantações sem estado e sensíveis à residência.
Contagem de workersQuatro (HTTP), dois (gRPC).Dimensione conforme a latência observada e os núcleos disponíveis.
Listener RESTHTTP em texto puro atrás de um terminador de TLS.Sempre termine o TLS a montante; nunca exponha texto puro em uma rede não confiável.
gRPC em redes não confiáveisTLS mútuo.Obrigatório; nunca execute um listener gRPC em texto puro em uma rede não confiável.
  • Os testes de registro asseguram que um tier Pro ou Enterprise ausente é ignorado silenciosamente e que o catálogo core ainda se registra.
  • Os testes de allowlist asseguram que enabled_tools subtrai e nunca adiciona uma ferramenta que o registro não descobriu.
  • Os testes do gate de confirmação asseguram que uma ferramenta ApprovalRequired retorna um desafio na primeira chamada, executa uma vez com um token válido de uso único e expira o token após o seu TTL.
  • Os testes de rebaixamento asseguram que uma entrada risk_level_overrides que enfraquece uma ferramenta ApprovalRequired falha na inicialização.
  • Os testes de autenticação cobrem chaves ausentes, malformadas, desabilitadas e expiradas no REST (401 com WWW-Authenticate) e no gRPC (UNAUTHENTICATED), e a rejeição por tier sem direito de acesso (403).
  • Os testes de concorrência asseguram que uma ETag desatualizada faz uma mutação falhar e que uma idempotency_key repetida reproduz o resultado em cache.
  • Os testes de contenção de caminho asseguram que um caminho de saída em arquivo resolvido para fora do diretório base é rejeitado.
  • Mantenha as fixtures pequenas e não sensíveis; nunca faça commit de uma chave de API real ou do conteúdo de um documento.