NextPDF Connect 開発者ガイド
NextPDF Connect(nextpdf/server)は、フレームワークに依存しない NextPDF PDF 2.0 エンジンをサービスとしてラップします。PDF 生成を再実装するものではありません。各エンジン機能を、名前付きでスキーマ記述されたツールとして公開し、そのカタログを 3 つのトランスポート、すなわち標準入出力上の Model Context Protocol(MCP)、Representational State Transfer(REST)Application Programming Interface(API)、および gRPC を介して提供します。サーバー向けに開発する場合、そのツールセットを拡張する場合、または本番環境で運用する場合は、このガイドを参照してください。
設計全体を支える概念は 3 つあります。ツールレジストリ、3 つの独立したトランスポート、そして human-in-the-loop(HITL)確認ゲートです。このページでは、これらがどのように連携するか、また安全性モデルを弱めずに扱う方法を説明します。正確なツール、RPC、メッセージのシンボルについては、API リファレンスを参照してください。
前提条件: PHP 8.4、Composer 2、そしてネットワーク経由のトランスポートでは RoadRunner バイナリと少なくとも 1 つの 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_*)、YAML ファイルのnextpdf_mcpセクション、組み込みの既定値の順に resolve(解決)し、readonlyMcpConfigを生成します。REST サーバーと gRPC サーバーは、HttpConfigをNEXTPDF_*環境変数から読み込みます。構成を参照してください。 - セキュリティポリシーの構築。
enabled_tools許可リストはレジストリより前に構築されるため、最初の登録から検出を制約します。 - レジストリの構築とツールの検出。
ToolRegistry::registerDefaults()は、まずコアティアを登録し、次に該当クラスを解決できる場合に Pro および Enterprise のプロバイダーを登録し、続いて環境ゲートに従ってバンドルされた AST およびミューテーションのプロバイダーを登録します。 - 共有ストアとゲートの構築。 インメモリのドキュメントストアは、構成された TTL と容量に基づいて構築されます。
ConfirmationGateは、単回使用のトークンストアとともに組み立てられます。 - トランスポートのバインド。 MCP は、ファイルの終端まで stdio 上で読み取り・処理・書き込みのループに入ります。REST と gRPC は、検出されたティアからルートまたはサービスのテーブルを構築し、リクエストループを RoadRunner に引き渡します。
その後、リクエストは次の順に流れます。認証(REST と gRPC)、ツールまたは操作の解決、ApprovalRequired 処理に対する確認ゲートの実行、エンジンに対する実行、そして結果の返却です。起動と検出を参照してください。
トランスポートモデル
「トランスポートモデル」という見出しのセクション3 つのトランスポートは、概念上はレジストリ、構成、ゲートを共有しますが、それぞれ独立したプロセスです。1 つを起動しても、他は起動しません。
| トランスポート | エントリーポイント | 選択する場面 |
|---|---|---|
| MCP | bin/nextpdf-mcp | サーバーを信頼済みサブプロセスとして起動するローカルの AI クライアント。 |
| 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 は 1 つのスーパーバイザーを共有できます。
| パスまたは設定 | 目的 |
|---|---|
.rr.full.yaml | 1 つのスーパーバイザーの下で 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() を返します。レジストリが名前空間やパッケージングからティアを推測することは決してありません。
- コアティアは無条件に登録されます。具体的には、ドキュメントツールと診断ツール、さらにコアのバーコードエンコーダーレジストリが存在する場合の
generate_barcode、そしてNEXTPDF_MCP_TOOL_PARSE_PDF_ENABLEDがtrueまたは1の場合に限りparse_pdfが登録されます。 - Pro および Enterprise のプロバイダーは、プロバイダークラスを解決できるときに、
class_exists()でプローブされて登録されます。存在しないティアは、暗黙的にスキップされます。 - バンドルされた AST およびミューテーションのプロバイダーは、
NEXTPDF_AST_TOOLS_ENABLEDとNEXTPDF_MUTATION_TOOLS_ENABLED(どちらも既定で有効)によってゲートされ、Pro ティアの下で登録されます。 - セキュリティポリシーフィルターは、すべての登録を
enabled_tools許可リストと突き合わせます。許可リストは差し引くものであり、追加することは決してありません。ティアごとのカウンターは、ポリシーが許可したツールのみを数えます。
結果として得られるティアごとの件数と合計は、MCP の initialize レスポンスと REST の GET /api/v1/capabilities エンドポイントで報告されます。本文中の固定された合計値は古いものとして扱い、実行中のサーバーに問い合わせてください。ツールカタログを参照してください。
リスクティアと確認ゲート
「リスクティアと確認ゲート」という見出しのセクションすべてのツールは、RiskLevel 列挙型(src/Config/RiskLevel.php)の 4 つのリスクレベル、すなわち Safe(0)、Caution(1)、Review(2)、ApprovalRequired(3)のいずれか 1 つを宣言します。監査ログは Caution 以上で適用されます。構成のオーバーライドでツールのリスクを引き上げることはできますが、設計上 ApprovalRequired であるツールを引き下げることは決してできません。構成ローダーは読み込み時に例外をスローし、サーバーは弱められたゲートで実行するのではなく起動を拒否します。
ある ApprovalRequired ツールが有効なトークンなしで呼び出されると、ConfirmationGate(src/Mcp/ConfirmationGate.php)は単回使用のチャレンジトークンを返します。トークンは、ツール名、ランダムなノンス、300 秒の time-to-live(TTL)をバインドします。引数はバインドしません。クライアントが再試行時に異なるキー順序で引数を再シリアライズする可能性があるためです。エージェントはチャレンジを人間に中継し、トークンを _confirmation_token 引数に入れて同じツールを再度呼び出します。トークンは使用時に消費され、ゲートされた呼び出しをちょうど 1 回だけ解放します。
次の PHP サンプルは、MCP ツール呼び出しを駆動するトランスポート非依存のヘルパーです。確認チャレンジが発生した場合、発行されたトークンで再試行する前に、そのチャレンジを人間の承認者に提示します。strict types を宣言し、完全に型ヒントが付けられており、すべてのエラーを握りつぶすのではなく最も具体的な例外を捕捉します。
<?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を確認してください(ワーカーが 1 つを超えるプールの場合)。SQLite ジョブストアは、すべてのワーカーが書き込めるボリュームに配置してください。 - TLS の終端。 REST は Transport Layer Security(TLS)ターミネーターの背後で実行してください。信頼されていないネットワークでは gRPC を相互 TLS で実行し、サーバー鍵、サーバー証明書、クライアント認証局をデプロイのシークレットとして供給してください。
- ヘルスのプローブ。 オーケストレーターのプローブには、匿名の
/healthzと/readyzエンドポイント(REST)、またはHealthCheckとReadinessCheckRPC(gRPC)を使用してください。 - カタログのスコープ設定。
enabled_toolsを、インテグレーションが必要とする最小限のセットに制限してください。
Redis の正常性は前提とせず検証してください。構成された Redis 接続が失敗すると、REST サーバーはインメモリストアにフォールバックします。デプロイ および セキュリティと運用を参照してください。
| 障害 | 発生箇所 | 推奨される対応 |
|---|---|---|
不明な 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 に設定すると、ステートレスでデータ所在地に配慮するデプロイになります。 |
| ワーカー数 | 4(HTTP)、2(gRPC)。 | 観測されたレイテンシーと利用可能なコア数に合わせてサイズを設定してください。 |
| REST リスナー | TLS ターミネーターの背後の平文 HTTP。 | 常に上流で 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
- セキュリティと運用 — 認証、トランスポートのセキュリティ、脅威モデル