Pular para o conteúdo

Guia do desenvolvedor do NextPDF 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 o generate_barcode quando o registro de codificadores de código de barras do core está presente, 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 nonce aleatório e um tempo de vida (time-to-live, TTL) de 300 segundos, mas não os argumentos, porque os clientes podem reserializar os argumentos com uma ordenação de chaves diferente na nova tentativa. 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.