Guía para desarrolladores de NextPDF Connect
De un vistazo
Sección titulada «De un vistazo»NextPDF Connect (nextpdf/server) expone como servicio el motor PDF 2.0 de NextPDF, independiente del framework. No reimplementa la generación de PDF. Publica cada capacidad del motor como una herramienta con nombre y descrita mediante un esquema, y sirve ese catálogo a través de tres transportes: el Model Context Protocol (MCP) sobre la entrada y la salida estándar, una interfaz de programación de aplicaciones (API) REST y gRPC. Usar esta guía al desarrollar contra el servidor, ampliar su conjunto de herramientas u operarlo en producción.
Tres conceptos sostienen todo el diseño: el registro de herramientas, los tres transportes independientes y la compuerta de confirmación con intervención humana (HITL). Esta página explica cómo encajan entre sí y cómo trabajar con ellos sin debilitar el modelo de seguridad. Para conocer los símbolos exactos de herramientas, RPC y mensajes, consulta la referencia de la API.
Requisitos previos: PHP 8.4, Composer 2 y, para los transportes en red, el binario de RoadRunner y al menos una clave de API. Instalarlo con composer require nextpdf/server.
Límite de la arquitectura
Sección titulada «Límite de la arquitectura»Se deben mantener las responsabilidades en el lado correcto de cada límite. Una herramienta es un envoltorio delgado sobre una llamada al motor; no debe contener la interpretación del diseño, la semántica del documento ni inteligencia de transformación.
| Capa | Propiedad de | Responsabilidad | No colocar aquí |
|---|---|---|---|
| Cliente o agente | La integración | Decidir a qué herramienta llamar; transmitir los desafíos de confirmación a una persona. | Lógica del motor o detección de niveles. |
| Transporte | nextpdf/server | Estructurar las solicitudes (JSON-RPC, HTTP o Protocol Buffers), autenticar y enrutar hacia el ejecutor de herramientas. | Semántica del documento. |
| Registro de herramientas | nextpdf/server | Descubrir niveles, registrar herramientas sujetas a la lista de permitidos de seguridad y buscar una herramienta por su nombre. | Generación de PDF. |
| Herramienta | nextpdf/server | Validar los argumentos contra el esquema de entrada y llamar al motor. | Interpretación del diseño u orquestación de varios pasos. |
| Compuerta de confirmación | nextpdf/server | Retener una operación ApprovalRequired hasta que una persona la autorice. | Autenticación de quien llama. |
| Motor | nextpdf/core (y nextpdf/premium) | Generar, inspeccionar y transformar el contenido del PDF. | Asuntos de transporte o de autenticación. |
Ciclo de vida en ejecución
Sección titulada «Ciclo de vida en ejecución»Cada transporte tiene su propio punto de entrada y su factoría de arranque, y cada uno construye su grafo de objetos de forma explícita. No hay ningún contenedor de inyección de dependencias por registrar.
- Carga la configuración. El servidor MCP resuelve la configuración dando prioridad a las variables de entorno (
NEXTPDF_MCP_*) sobre la secciónnextpdf_mcpdel archivo YAML y, a su vez, sobre los valores predeterminados integrados, y produce unreadonlyMcpConfig. Los servidores REST y gRPC leenHttpConfigde las variables de entornoNEXTPDF_*. Consultar Configuración. - Construye la política de seguridad. La lista de permitidos
enabled_toolsse construye antes que el registro para restringir el descubrimiento desde el primer registro. - Construye el registro y descubre las herramientas.
ToolRegistry::registerDefaults()registra el nivel core, luego los proveedores Pro y Enterprise cuando sus clases se pueden resolver, y después los proveedores de AST y de mutación incluidos, sujetos a sus controles de entorno. - Construye los almacenes compartidos y la compuerta. El almacén de documentos en memoria se construye a partir del TTL y la capacidad configurados; la
ConfirmationGatese ensambla con su almacén de tokens de un solo uso. - Vincula el transporte. El MCP entra en un bucle de lectura, procesamiento y escritura sobre stdio hasta el fin del archivo. REST y gRPC construyen su tabla de rutas o de servicios a partir de los niveles detectados y entregan el bucle de solicitudes a RoadRunner.
A partir de ahí, una solicitud fluye así: autenticar (REST y gRPC), resolver la herramienta o la operación, ejecutar la compuerta de confirmación para el trabajo ApprovalRequired, ejecutar contra el motor y devolver el resultado. Consultar Arranque y descubrimiento.
Modelo de transporte
Sección titulada «Modelo de transporte»Los tres transportes comparten el registro, la configuración y la compuerta como conceptos, pero son procesos independientes. Iniciar uno no inicia los demás.
| Transporte | Punto de entrada | Cuándo elegirlo |
|---|---|---|
| MCP | bin/nextpdf-mcp | Un cliente de IA local que lanza el servidor como un subproceso de confianza. |
| REST | bin/nextpdf-server | Clientes HTTP en red; descrito por un documento OpenAPI 3.1. |
| gRPC | bin/nextpdf-grpc | Clientes tipados y de streaming; el servicio nextpdf.connect.v1.NextPDFConnect. |
Los transportes se eligen según el perfil de RoadRunner que se ejecute: .rr.yaml (solo REST), .rr.grpc.yaml (solo gRPC) o .rr.full.yaml (ambos). El transporte MCP es un subproceso simple y no necesita supervisor. Los detalles del protocolo por transporte están en Transporte MCP, Transporte REST y Transporte gRPC.
Estructura de despliegue recomendada
Sección titulada «Estructura de despliegue recomendada»Ejecutar los transportes en red bajo RoadRunner con almacenes compartidos y claves montadas desde secretos. El perfil combinado permite que REST y gRPC compartan un único supervisor.
| Ruta o ajuste | Propósito |
|---|---|
.rr.full.yaml | Perfil combinado de REST y gRPC bajo un único supervisor. |
NEXTPDF_API_KEYS_FILE | Ruta a un archivo de claves de API montado desde un secreto y con recarga en caliente. |
NEXTPDF_REDIS_HOST | Habilita los almacenes de límite de tasa, idempotencia y documentos respaldados por Redis para grupos de varios workers. |
NEXTPDF_WORKER_COUNT / NEXTPDF_GRPC_WORKER_COUNT | Dimensionamiento del grupo de workers para HTTP y gRPC. |
| Directorio base de salida | Volumen dedicado con permisos de sistema de archivos de mínimo privilegio para las herramientas de salida a archivo. |
El siguiente ejemplo de shell arranca el perfil combinado con claves montadas desde secretos y un almacén de Redis compartido. No contiene secretos en el propio archivo; las claves se montan en /run/secrets/api-keys.
export NEXTPDF_API_KEYS_FILE=/run/secrets/api-keysexport NEXTPDF_WORKER_COUNT=8export NEXTPDF_GRPC_WORKER_COUNT=4export NEXTPDF_REDIS_HOST=redis./vendor/bin/rr serve -c .rr.full.yamlPara un grupo de varios workers, configurar Redis y confirmar que ext-redis esté presente en la imagen en ejecución; sin él, los almacenes de límite de tasa, idempotencia y documentos son por worker. Consultar Despliegue.
Registro de herramientas y resolución de niveles
Sección titulada «Registro de herramientas y resolución de niveles»NextPDF\Server\ToolRegistry (src/ToolRegistry.php) construye el catálogo en el arranque. El nivel es un invariante declarado: cada herramienta devuelve su propio tier() y riskLevel(); el registro nunca infiere el nivel a partir del espacio de nombres ni del empaquetado.
- El nivel core se registra incondicionalmente: las herramientas de documento y de diagnóstico, además de
generate_barcodecuando el registro de codificadores de código de barras del core está presente, yparse_pdfsolo cuandoNEXTPDF_MCP_TOOL_PARSE_PDF_ENABLEDestrueo1. - Los proveedores Pro y Enterprise se registran cuando sus clases de proveedor se pueden resolver, comprobadas con
class_exists(). Un nivel ausente se omite en silencio. - Los proveedores de AST y de mutación incluidos se registran bajo el nivel Pro, controlados por
NEXTPDF_AST_TOOLS_ENABLEDyNEXTPDF_MUTATION_TOOLS_ENABLED(ambos habilitados de forma predeterminada). - El filtro de la política de seguridad intersecta cada registro con la lista de permitidos
enabled_tools. La lista de permitidos solo resta; nunca añade. El contador por nivel solo cuenta una herramienta admitida por la política.
Los recuentos resultantes por nivel y el total se informan en la respuesta initialize del MCP y en el endpoint GET /api/v1/capabilities de REST. Tratar cualquier total fijo en el texto como obsoleto; consultar el servidor en ejecución. Consultar Catálogo de herramientas.
Niveles de riesgo y la compuerta de confirmación
Sección titulada «Niveles de riesgo y la compuerta de confirmación»Cada herramienta declara uno de los cuatro niveles de riesgo del enum RiskLevel (src/Config/RiskLevel.php): Safe (0), Caution (1), Review (2) y ApprovalRequired (3). El registro de auditoría se aplica en Caution y superiores. Una sustitución de configuración puede elevar el riesgo de una herramienta; nunca puede rebajar una herramienta que es ApprovalRequired por diseño. El cargador de configuración lanza una excepción en el momento de la carga y el servidor se niega a arrancar en lugar de ejecutarse con una compuerta debilitada.
Cuando se invoca una herramienta ApprovalRequired sin un token válido, la ConfirmationGate (src/Mcp/ConfirmationGate.php) devuelve un token de desafío de un solo uso. El token vincula el nombre de la herramienta, un nonce aleatorio y un tiempo de vida (TTL) de 300 segundos, no los argumentos, porque los clientes pueden volver a serializar los argumentos con un orden de claves distinto en el reintento. El agente transmite el desafío a una persona y vuelve a invocar la misma herramienta con el token en el argumento _confirmation_token. El token se consume al usarlo, habilitando exactamente una llamada controlada.
El siguiente ejemplo de PHP muestra un ayudante independiente del transporte que dirige una llamada a una herramienta MCP y, ante un desafío de confirmación, muestra el desafío a un aprobador humano antes de reintentar con el token emitido. Declara tipos estrictos, está completamente tipado y captura la excepción más específica en lugar de ocultar cualquier error.
<?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); }}Conectar McpClientInterface, HumanApproverInterface y ApprovalDeniedException al transporte y canal de aprobación propios. El reintento reutiliza los argumentos originales más el token emitido; no aprobar nunca un desafío automáticamente sin una decisión humana. Consultar Niveles de riesgo HITL.
Puntos de extensión
Sección titulada «Puntos de extensión»El servidor se extiende añadiendo herramientas y aportando proveedores, no editando el registro.
| Punto de extensión | Uso | Restricción |
|---|---|---|
Una clase que implementa ToolInterface | Una nueva capacidad del motor expuesta como herramienta. | Declarar tier(), riskLevel(), category() y un inputSchema() de JSON Schema; mantenerla como un envoltorio delgado del motor. |
Un ToolProviderInterface como proveedor | Registrar un conjunto de herramientas para un nivel. | Los proveedores Pro y Enterprise se descubren mediante class_exists(); no exigir el paquete propietario desde el servidor. |
enabled_tools (lista de permitidos) | Acotar con mínimo privilegio el catálogo expuesto. | La lista de permitidos solo resta; no puede registrar una herramienta ausente. |
risk_level_overrides | Endurecer un despliegue elevando el riesgo de una herramienta. | Solo permite elevar; rebajar una herramienta ApprovalRequired hace fallar el arranque. |
| Costuras inyectables de transporte y de worker | Probar el servidor de forma aislada. | Estas costuras existen para las pruebas, no para el cableado de la aplicación. |
Flujo de operaciones
Sección titulada «Flujo de operaciones»- Elegir un perfil. Ejecutar
.rr.yaml,.rr.grpc.yamlo.rr.full.yamlpara los transportes expuestos. - Montar las claves desde un secreto. Apuntar
NEXTPDF_API_KEYS_FILEa un archivo de secreto; preferir el almacén de claves de archivo con recarga en caliente para que la rotación no necesite reinicio. - Configurar los almacenes compartidos. Establecer
NEXTPDF_REDIS_HOSTy confirmarext-redispara cualquier grupo de más de un worker; colocar el almacén de trabajos de SQLite en un volumen en el que todos los workers puedan escribir. - Terminar el TLS. Ejecutar REST detrás de un terminador de seguridad de la capa de transporte (TLS); ejecutar gRPC con TLS mutuo en cualquier red no confiable, con la clave del servidor, el certificado del servidor y la autoridad certificadora del cliente aportados como secretos de despliegue.
- Sondear el estado. Usar los endpoints anónimos
/healthzy/readyz(REST) o los RPCHealthCheckyReadinessCheck(gRPC) para los sondeos del orquestador. - Acotar el catálogo. Restringir
enabled_toolsal conjunto mínimo que necesite una integración.
Verificar el estado de Redis en lugar de darlo por sentado: el servidor REST recurre a almacenes en memoria cuando una conexión de Redis configurada falla. Consultar Despliegue y Seguridad y operaciones.
Gestión de fallos
Sección titulada «Gestión de fallos»| Fallo | Dónde aparece | Respuesta recomendada |
|---|---|---|
Desconocido: document_id | Ejecución de la herramienta | Devolver un error definido a quien llama; indicarle que llame primero a create_pdf. |
| ETag obsoleto en una mutación | Herramienta de mutación de AST | Volver a leer el documento con get_document_ast y reintentar con el ETag fresco. |
| Clave de API ausente o inválida (REST) | Middleware de autenticación | Devolver 401 con un desafío WWW-Authenticate: Bearer; no revelar qué parte estaba mal. |
| Nivel sin derecho (REST) | Autorización | Devolver 403; el nivel de la clave está por debajo del nivel de la operación. |
| Ruta de nivel ausente (REST) | Enrutador | Devolver 404; el paquete no está instalado. Es una operación esperada, no un fallo. |
| Token incorrecto (gRPC) | Autenticador de gRPC | Hacer fallar la llamada con UNAUTHENTICATED. |
| Redis inalcanzable | Arranque o ejecución | Degradar a almacenes en memoria; alertar a los operadores y verificar el estado de Redis. |
| Ruta de salida fuera del directorio base | Herramienta de salida a archivo | Fallar de forma cerrada; la ruta se canonicaliza y el recorrido se rechaza. |
Exponer los fallos del motor como objetos de error definidos, nunca como éxitos silenciosos. El modelo de error por transporte se detalla en la referencia de la API.
Valores predeterminados seguros
Sección titulada «Valores predeterminados seguros»| Asunto | Predeterminado | Cuándo sustituirlo |
|---|---|---|
parse_pdf | Deshabilitado (opcional mediante NEXTPDF_MCP_TOOL_PARSE_PDF_ENABLED). | Habilitarlo solo cuando una integración necesite inspección estructural. |
enabled_tools | Vacío (todas las herramientas descubiertas permitidas). | Definir una lista de permitidos explícita para despliegues de mínimo privilegio. |
| Sustituciones de riesgo | Ninguna. | Elevar el riesgo para un despliegue endurecido; no intentar nunca una rebaja. |
document_ttl / max_documents | 1800 segundos / 50 documentos. | Reducirlos para despliegues sensibles a la residencia o con memoria limitada. |
allow_file_output | Habilitado. | Establecerlo en false para despliegues sin estado y sensibles a la residencia. |
| Número de workers | Cuatro (HTTP), dos (gRPC). | Dimensionarlos según la latencia observada y los núcleos disponibles. |
| Escucha REST | HTTP en texto plano detrás de un terminador de TLS. | Terminar siempre el TLS aguas arriba; no exponer nunca texto plano en una red no confiable. |
| gRPC en redes no confiables | TLS mutuo. | Obligatorio; no ejecutar nunca una escucha gRPC en texto plano en una red no confiable. |
Lista de verificación de pruebas
Sección titulada «Lista de verificación de pruebas»- Las pruebas del registro verifican que un nivel Pro o Enterprise ausente se omite en silencio y que el catálogo core sigue registrándose.
- Las pruebas de la lista de permitidos verifican que
enabled_toolsresta y nunca añade una herramienta que el registro no descubrió. - Las pruebas de la compuerta de confirmación verifican que una herramienta
ApprovalRequireddevuelve un desafío en la primera llamada y se ejecuta una vez con un token válido de un solo uso, y que el token expira tras su TTL. - Las pruebas de rebaja verifican que una entrada de
risk_level_overridesque debilita una herramientaApprovalRequiredhace fallar el arranque. - Las pruebas de autenticación cubren claves ausentes, malformadas, deshabilitadas y expiradas en REST (
401conWWW-Authenticate) y gRPC (UNAUTHENTICATED), y el rechazo por derecho de nivel (403). - Las pruebas de concurrencia aseveran que un ETag obsoleto hace fallar una mutación y que una
idempotency_keyrepetida reproduce el resultado en caché. - Las pruebas de contención de rutas verifican que se rechaza una ruta de salida a archivo que se resuelve fuera del directorio base.
- Mantener los fixtures pequeños y no sensibles; no confirmar nunca una clave de API real ni el contenido de un documento.
Ver también
Sección titulada «Ver también»- Referencia de la API — símbolos exactos de herramientas, RPC y mensajes
- Catálogo de herramientas — el conjunto core verificado y el recuento en ejecución
- Niveles de riesgo HITL — el modelo de riesgo y el sobre de confirmación
- Configuración — el orden de resolución y la sustitución que solo permite elevar
- Despliegue — perfiles de RoadRunner, Redis y TLS mutuo
- Seguridad y operaciones — autenticación, seguridad del transporte y el modelo de amenazas