Руководство разработчика NextPDF Connect
NextPDF Connect (nextpdf/server) предоставляет независимый от фреймворка движок NextPDF PDF 2.0 как сервис. Он не реализует генерацию PDF заново, а представляет каждую возможность движка как именованный инструмент со схемой и обслуживает этот каталог по трём транспортам: Model Context Protocol (MCP) через стандартный ввод и вывод, Representational State Transfer (REST) Application Programming Interface (API) и gRPC. Используйте это руководство, когда разрабатываете для сервера, расширяете его набор инструментов или запускаете его в продакшене.
Дизайн строится на трёх концепциях: реестре инструментов, трёх независимых транспортах и шлюзе подтверждения с участием человека (human-in-the-loop, HITL). На этой странице объясняется, как они сочетаются и как работать с ними, не ослабляя модель безопасности. Точные символы инструментов, удалённых вызовов процедур (RPC) и сообщений см. в разделе Справочник API.
Предварительные требования: PHP 8.4, Composer 2 и — для сетевых транспортов — бинарный файл RoadRunner и хотя бы один ключ API. Установите командой composer require nextpdf/server.
Граница архитектуры
Заголовок раздела «Граница архитектуры»Держите каждую обязанность по правильную сторону границы. Инструмент — это тонкая обёртка вокруг вызова движка; в нём не должно быть интерпретации макета, семантики документа или логики преобразования.
| Слой | Владелец | Обязанность | Не размещайте здесь |
|---|---|---|---|
| Клиент или агент | Ваша интеграция | Выбор инструмента для вызова; передача запросов на подтверждение человеку. | Логика движка или определение уровня. |
| Транспорт | nextpdf/server | Оформление запросов как JSON-RPC, HTTP или Protocol Buffers; аутентификация; маршрутизация к исполнителю инструментов. | Семантика документа. |
| Реестр инструментов | nextpdf/server | Обнаружение уровней, регистрация инструментов с учётом списка разрешённых для безопасности, поиск инструмента по имени. | Генерация PDF. |
| Инструмент | nextpdf/server | Проверка аргументов по входной схеме и вызов движка. | Интерпретация макета или многошаговая оркестрация. |
| Шлюз подтверждения | nextpdf/server | Удержание операции ApprovalRequired, пока её не одобрит человек. | Аутентификация вызывающей стороны. |
| Движок | nextpdf/core (и nextpdf/premium) | Генерация, инспектирование и преобразование содержимого PDF. | Вопросы транспорта или аутентификации. |
Жизненный цикл выполнения
Заголовок раздела «Жизненный цикл выполнения»У каждого транспорта есть собственная точка входа и фабрика загрузки. Каждый транспорт явно конструирует свой граф объектов. Контейнер внедрения зависимостей при регистрации не используется.
- Загрузка конфигурации. Сервер MCP разрешает конфигурацию сначала из переменных окружения (
NEXTPDF_MCP_*), затем из секцииnextpdf_mcpYAML-файла, затем из встроенных значений по умолчанию и формируетreadonlyMcpConfig. Серверы REST и gRPC читаютHttpConfigиз переменных окруженияNEXTPDF_*. См. Конфигурация. - Построение политики безопасности. Список разрешённых
enabled_toolsстроится до реестра, поэтому он ограничивает обнаружение начиная с самой первой регистрации. - Конструирование реестра и обнаружение инструментов.
ToolRegistry::registerDefaults()регистрирует уровень core, затем провайдеры Pro и Enterprise, когда их классы разрешаются, а затем встроенные провайдеры AST и мутаций с учётом их условий окружения. - Построение общих хранилищ и шлюза. Хранилище документов в памяти строится на основе настроенных TTL и ёмкости;
ConfirmationGateсобирается со своим хранилищем одноразовых токенов. - Привязка транспорта. MCP входит в цикл «чтение — обработка — запись» через stdio до конца файла. REST и gRPC строят свою таблицу маршрутов или сервисов из обнаруженных уровней, а затем передают цикл обработки запросов RoadRunner.
Далее запрос проходит такой путь: аутентификация (REST и gRPC), разрешение инструмента или операции, прохождение шлюза подтверждения для работы ApprovalRequired, выполнение на движке и возврат результата. См. Загрузка и обнаружение.
Модель транспорта
Заголовок раздела «Модель транспорта»Три транспорта используют общие концепции реестра, конфигурации и шлюза, но выполняются как независимые процессы. Запуск одного транспорта не запускает остальные.
| Транспорт | Точка входа | Когда его выбирать |
|---|---|---|
| MCP | bin/nextpdf-mcp | Локальный клиент искусственного интеллекта (ИИ), запускающий сервер как доверенный подпроцесс. |
| REST | bin/nextpdf-server | Сетевые HTTP-клиенты; описывается документом OpenAPI 3.1. |
| gRPC | bin/nextpdf-grpc | Типизированные потоковые клиенты; сервис nextpdf.connect.v1.NextPDFConnect. |
Выбирайте транспорты по профилю RoadRunner, который запускаете: .rr.yaml (только REST), .rr.grpc.yaml (только gRPC) или .rr.full.yaml (оба). Транспорт MCP — обычный подпроцесс, ему не нужен супервизор. Подробности обмена данными см. в разделах Транспорт MCP, Транспорт REST и Транспорт gRPC.
Рекомендуемая структура развёртывания
Заголовок раздела «Рекомендуемая структура развёртывания»Запускайте сетевые транспорты под RoadRunner с общими хранилищами и ключами, смонтированными как секреты. Объединённый профиль позволяет REST и gRPC работать под общим супервизором.
| Путь или параметр | Назначение |
|---|---|
.rr.full.yaml | Объединённый профиль REST и gRPC под единым супервизором. |
NEXTPDF_API_KEYS_FILE | Путь к файлу ключей API, смонтированному как секрет и перезагружаемому на лету. |
NEXTPDF_REDIS_HOST | Включает хранилища ограничения частоты, идемпотентности и документов на основе Redis для пулов с несколькими воркерами. |
NEXTPDF_WORKER_COUNT / NEXTPDF_GRPC_WORKER_COUNT | Размер пула воркеров для пулов HTTP и gRPC. |
| Базовый каталог вывода | Выделенный том с минимально необходимыми правами файловой системы для инструментов файлового вывода. |
Следующий пример командной оболочки загружает объединённый профиль с ключами, смонтированными как секреты, и общим хранилищем Redis. В нём нет секретов; ключи монтируются по пути /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.yamlДля пула с несколькими воркерами настройте Redis и убедитесь, что ext-redis есть в запущенном образе. Без него хранилища ограничения частоты, идемпотентности и документов работают отдельно в каждом воркере. См. развёртывание.
Реестр инструментов и определение уровня
Заголовок раздела «Реестр инструментов и определение уровня»NextPDF\Server\ToolRegistry (src/ToolRegistry.php) строит каталог при загрузке. Уровень — объявленный инвариант: каждый инструмент возвращает собственные tier() и riskLevel(). Реестр никогда не выводит уровень из пространства имён или пакета.
- Уровень core регистрируется безусловно: инструменты документов и диагностики, плюс
generate_barcode, когда присутствует основной реестр кодировщиков штрихкодов, плюсparse_pdfтолько тогда, когдаNEXTPDF_MCP_TOOL_PARSE_PDF_ENABLEDравноtrueили1. - Провайдеры Pro и Enterprise регистрируются, когда разрешаются их классы провайдеров; это проверяется через
class_exists(). Отсутствующий уровень пропускается без сообщений. - Встроенные провайдеры AST и мутаций регистрируются под уровнем Pro и управляются через
NEXTPDF_AST_TOOLS_ENABLEDиNEXTPDF_MUTATION_TOOLS_ENABLED(оба включены по умолчанию). - Фильтр политики безопасности пересекает каждую регистрацию со списком разрешённых
enabled_tools. Список разрешённых только вычитает; он никогда ничего не добавляет. Счётчик по уровням учитывает только инструменты, которые допускает политика.
Ответ MCP initialize и конечная точка REST GET /api/v1/capabilities сообщают итоговые счётчики по уровням и общее число. Считайте любое фиксированное итоговое число в тексте устаревшим; запрашивайте его у работающего сервера. См. Каталог инструментов.
Уровни риска и шлюз подтверждения
Заголовок раздела «Уровни риска и шлюз подтверждения»Каждый инструмент объявляет один из четырёх уровней риска из перечисления RiskLevel (src/Config/RiskLevel.php): Safe (0), Caution (1), Review (2) и ApprovalRequired (3). Аудит-логирование применяется на уровне Caution и выше. Переопределение конфигурации может повысить риск инструмента, но никогда не может понизить риск инструмента, который по замыслу относится к ApprovalRequired. Загрузчик конфигурации выбрасывает исключение во время загрузки, и сервер отказывается запускаться, вместо того чтобы работать с ослабленным шлюзом.
Когда инструмент ApprovalRequired вызывается без действительного токена, ConfirmationGate (src/Mcp/ConfirmationGate.php) возвращает одноразовый токен-запрос. Токен связывает имя инструмента, случайный nonce и время жизни (TTL) в 300 секунд, но не аргументы, потому что при повторе клиенты могут заново сериализовать аргументы с другим порядком ключей. Агент передаёт запрос человеку и повторно вызывает тот же инструмент с токеном в аргументе _confirmation_token. При использовании токен расходуется и разрешает ровно один защищённый шлюзом вызов.
Следующий пример на PHP — вспомогательная функция, не зависящая от транспорта. Она выполняет вызов инструмента MCP и при запросе подтверждения показывает запрос человеку, который принимает решение, прежде чем повторить вызов с выданным токеном. Она объявляет строгие типы, полностью снабжена подсказками типов и перехватывает наиболее конкретное исключение, а не подавляет все ошибки.
<?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); }}Подключите McpClientInterface, HumanApproverInterface и ApprovalDeniedException к своему транспорту и каналу утверждения. Повторный вызов использует исходные аргументы плюс выданный токен; никогда не подтверждайте запрос автоматически без решения человека. См. Уровни риска HITL.
Точки расширения
Заголовок раздела «Точки расширения»Расширяйте сервер через добавление инструментов и предоставление провайдеров, а не через редактирование реестра.
| Точка расширения | Для чего использовать | Ограничение |
|---|---|---|
Класс, реализующий ToolInterface | Новая возможность движка, представленная как инструмент. | Объявите tier(), riskLevel(), category() и схему JSON Schema inputSchema(); оставляйте класс тонкой обёрткой движка. |
Провайдер, реализующий ToolProviderInterface | Регистрация набора инструментов для уровня. | Провайдеры Pro и Enterprise обнаруживаются через class_exists(); не требуйте проприетарный пакет со стороны сервера. |
enabled_tools — список разрешённых | Ограничение области каталога по принципу минимальных привилегий. | Список разрешённых только вычитает; он не может зарегистрировать отсутствующий инструмент. |
risk_level_overrides | Усиление защиты развёртывания за счёт повышения риска инструмента. | Только повышение; понижение инструмента ApprovalRequired приводит к сбою загрузки. |
| Внедряемые точки сопряжения транспорта и воркеров | Тестирование сервера в изоляции. | Эти границы существуют для тестов, а не для подключения приложения. |
Рабочий процесс эксплуатации
Заголовок раздела «Рабочий процесс эксплуатации»- Выберите профиль. Запустите
.rr.yaml,.rr.grpc.yamlили.rr.full.yamlдля тех транспортов, которые вы предоставляете. - Смонтируйте ключи из секрета. Укажите в
NEXTPDF_API_KEYS_FILEфайл секрета; предпочтите файловое хранилище ключей с перезагрузкой на лету, чтобы ротация не требовала перезапуска. - Настройте общие хранилища. Установите
NEXTPDF_REDIS_HOSTи убедитесь в наличииext-redisдля любого пула размером более одного воркера; разместите хранилище задач SQLite на томе, доступном для записи всем воркерам. - Завершайте TLS. Запускайте REST за терминатором Transport Layer Security (TLS); запускайте gRPC со взаимным TLS в любой недоверенной сети, передавая ключ сервера, сертификат сервера и центр сертификации клиентов как секреты развёртывания.
- Проверяйте работоспособность. Используйте анонимные конечные точки
/healthzи/readyz(REST) или RPCHealthCheckиReadinessCheck(gRPC) для проб оркестратора. - Ограничьте область каталога. Ограничьте
enabled_toolsминимальным набором, который нужен интеграции.
Проверяйте работоспособность Redis, а не считайте её гарантированной. Сервер REST переходит на хранилища в памяти, когда настроенное соединение с Redis не удаётся установить. См. развёртывание и Безопасность и эксплуатация.
Обработка сбоев
Заголовок раздела «Обработка сбоев»| Сбой | Где проявляется | Рекомендуемая реакция |
|---|---|---|
Неизвестный document_id | Выполнение инструмента | Верните вызывающей стороне конкретную ошибку; укажите ей сначала вызвать create_pdf. |
| Устаревший ETag при мутации | Инструмент мутации AST | Перечитайте документ с помощью get_document_ast и повторите попытку со свежим ETag. |
| Отсутствующий или недействительный ключ API (REST) | Промежуточное ПО аутентификации | Верните 401 с запросом WWW-Authenticate: Bearer; не раскрывайте, какая именно часть была неверной. |
| Нет права на уровень (REST) | Авторизация | Верните 403; уровень ключа ниже уровня операции. |
| Маршрут уровня отсутствует (REST) | Маршрутизатор | Верните 404; пакет не установлен. Это ожидаемая операция, а не ошибка. |
| Неверный токен (gRPC) | Аутентификатор gRPC | Завершите вызов с ошибкой UNAUTHENTICATED. |
| Redis недоступен | Загрузка или выполнение | Переходите на хранилища в памяти; оповестите операторов и проверьте работоспособность Redis. |
| Путь вывода за пределами базового каталога | Инструмент вывода в файлы | Откажите по умолчанию; путь нормализуется, и обход каталогов отклоняется. |
Представляйте сбои движка как конкретные объекты ошибок, а не как тихие успехи. Справочник API подробно описывает модель ошибок для каждого транспорта.
Безопасные значения по умолчанию
Заголовок раздела «Безопасные значения по умолчанию»| Аспект | По умолчанию | Когда переопределять |
|---|---|---|
parse_pdf | Отключено (включается через NEXTPDF_MCP_TOOL_PARSE_PDF_ENABLED). | Включайте только тогда, когда интеграции нужно структурное инспектирование. |
enabled_tools | Пусто (разрешены все обнаруженные инструменты). | Задайте явный список разрешённых для развёртываний с минимальными привилегиями. |
| Переопределения риска | Нет. | Повышайте риск для усиленного развёртывания; никогда не пытайтесь его понизить. |
document_ttl / max_documents | 1800 секунд / 50 документов. | Снижайте для развёртываний, чувствительных к месту хранения данных, или с ограничением памяти. |
allow_file_output | Включено. | Установите false для развёртываний без состояния, чувствительных к месту хранения данных. |
| Число воркеров | Четыре (HTTP), два (gRPC). | Подбирайте с учётом наблюдаемой задержки и доступных ядер. |
| Слушатель REST | Открытый HTTP за терминатором TLS. | Всегда завершайте TLS на вышестоящем узле; никогда не открывайте незашифрованный трафик в недоверенной сети. |
| gRPC в недоверенных сетях | Взаимный TLS. | Обязательно; никогда не запускайте незашифрованный слушатель gRPC в недоверенной сети. |
Контрольный список тестирования
Заголовок раздела «Контрольный список тестирования»- Тесты реестра подтверждают, что отсутствующий уровень Pro или Enterprise пропускается без сообщений, а основной каталог всё равно регистрируется.
- Тесты списка разрешённых подтверждают, что
enabled_toolsвычитает и никогда не добавляет инструмент, который реестр не обнаружил. - Тесты шлюза подтверждения проверяют, что инструмент
ApprovalRequiredвозвращает запрос при первом вызове, выполняется один раз по действительному одноразовому токену и аннулирует токен по истечении его TTL. - Тесты понижения подтверждают, что запись
risk_level_overrides, ослабляющая инструментApprovalRequired, приводит к сбою загрузки. - Тесты аутентификации охватывают отсутствующие, некорректные, отключённые и просроченные ключи в REST (
401сWWW-Authenticate) и gRPC (UNAUTHENTICATED), а также отклонение по праву на уровень (403). - Тесты параллелизма подтверждают, что устаревший ETag приводит к сбою мутации, а повторный
idempotency_keyвоспроизводит кэшированный результат. - Тесты ограничения по пути подтверждают, что путь вывода в файл, разрешающийся за пределы базового каталога, отклоняется.
- Держите фикстуры небольшими и нечувствительными; никогда не фиксируйте в системе контроля версий настоящий ключ API или содержимое документа.
См. также
Заголовок раздела «См. также»- Справочник API — точные символы инструментов, RPC и сообщений
- Каталог инструментов — проверенный основной набор и счётчик во время выполнения
- Уровни риска HITL — модель риска и конверт подтверждения
- Конфигурация — порядок разрешения и переопределение только в сторону повышения
- развёртывание — профили RoadRunner, Redis и взаимный TLS
- Безопасность и эксплуатация — аутентификация, безопасность транспорта и модель угроз