コンテンツにスキップ

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/premiumPDF コンテンツを生成、検査、変換します。トランスポートや認証に関する事項。

各トランスポートは独自のエントリーポイントと起動ファクトリーを持ち、それぞれがオブジェクトグラフを明示的に構築します。登録すべき依存性注入コンテナーはありません。

  1. 構成の読み込み。 MCP サーバーは、構成を環境変数(NEXTPDF_MCP_*)、YAML ファイルの nextpdf_mcp セクション、組み込みの既定値の順に resolve(解決)し、readonlyMcpConfig を生成します。REST サーバーと gRPC サーバーは、HttpConfigNEXTPDF_* 環境変数から読み込みます。構成を参照してください。
  2. セキュリティポリシーの構築。 enabled_tools 許可リストはレジストリより前に構築されるため、最初の登録から検出を制約します。
  3. レジストリの構築とツールの検出。 ToolRegistry::registerDefaults() は、まずコアティアを登録し、次に該当クラスを解決できる場合に Pro および Enterprise のプロバイダーを登録し、続いて環境ゲートに従ってバンドルされた AST およびミューテーションのプロバイダーを登録します。
  4. 共有ストアとゲートの構築。 インメモリのドキュメントストアは、構成された TTL と容量に基づいて構築されます。ConfirmationGate は、単回使用のトークンストアとともに組み立てられます。
  5. トランスポートのバインド。 MCP は、ファイルの終端まで stdio 上で読み取り・処理・書き込みのループに入ります。REST と gRPC は、検出されたティアからルートまたはサービスのテーブルを構築し、リクエストループを RoadRunner に引き渡します。

その後、リクエストは次の順に流れます。認証(REST と gRPC)、ツールまたは操作の解決、ApprovalRequired 処理に対する確認ゲートの実行、エンジンに対する実行、そして結果の返却です。起動と検出を参照してください。

3 つのトランスポートは、概念上はレジストリ、構成、ゲートを共有しますが、それぞれ独立したプロセスです。1 つを起動しても、他は起動しません。

トランスポートエントリーポイント選択する場面
MCPbin/nextpdf-mcpサーバーを信頼済みサブプロセスとして起動するローカルの AI クライアント。
RESTbin/nextpdf-serverネットワーク経由の HTTP クライアント。OpenAPI 3.1 ドキュメントで記述されます。
gRPCbin/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.yaml1 つのスーパーバイザーの下で REST と gRPC を結合するプロファイル。
NEXTPDF_API_KEYS_FILEシークレットとしてマウントされ、ホットリロードされる API キーファイルへのパス。
NEXTPDF_REDIS_HOSTマルチワーカープール向けに、Redis ベースのレート制限、冪等性、ドキュメントストアを有効化します。
NEXTPDF_WORKER_COUNT / NEXTPDF_GRPC_WORKER_COUNTHTTP プールと gRPC プールのワーカー数の設定。
出力ベースディレクトリファイル出力ツール向けに、最小権限のファイルシステム権限を備えた専用ボリューム。

次のシェルサンプルは、シークレットとしてマウントされたキーと共有 Redis ストアを用いて結合プロファイルを起動します。ファイル自体にシークレットは含まれません。キーは /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

マルチワーカープールの場合は、Redis を構成し、実行中のイメージに ext-redis が存在することを確認してください。これがないと、レート制限、冪等性、ドキュメントの各ストアはワーカー単位になります。デプロイを参照してください。

NextPDF\Server\ToolRegistrysrc/ToolRegistry.php)は、起動時にカタログを構築します。ティアは宣言された不変条件です。各ツールは独自の tier()riskLevel() を返します。レジストリが名前空間やパッケージングからティアを推測することは決してありません。

  1. コアティアは無条件に登録されます。具体的には、ドキュメントツールと診断ツール、さらにコアのバーコードエンコーダーレジストリが存在する場合の generate_barcode、そして NEXTPDF_MCP_TOOL_PARSE_PDF_ENABLEDtrue または 1 の場合に限り parse_pdf が登録されます。
  2. Pro および Enterprise のプロバイダーは、プロバイダークラスを解決できるときに、class_exists() でプローブされて登録されます。存在しないティアは、暗黙的にスキップされます。
  3. バンドルされた AST およびミューテーションのプロバイダーは、NEXTPDF_AST_TOOLS_ENABLEDNEXTPDF_MUTATION_TOOLS_ENABLED(どちらも既定で有効)によってゲートされ、Pro ティアの下で登録されます。
  4. セキュリティポリシーフィルターは、すべての登録を 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 ツールが有効なトークンなしで呼び出されると、ConfirmationGatesrc/Mcp/ConfirmationGate.php)は単回使用のチャレンジトークンを返します。トークンは、ツール名、ランダムなノンス、300 秒の time-to-live(TTL)をバインドします。引数はバインドしません。クライアントが再試行時に異なるキー順序で引数を再シリアライズする可能性があるためです。エージェントはチャレンジを人間に中継し、トークンを _confirmation_token 引数に入れて同じツールを再度呼び出します。トークンは使用時に消費され、ゲートされた呼び出しをちょうど 1 回だけ解放します。

次の PHP サンプルは、MCP ツール呼び出しを駆動するトランスポート非依存のヘルパーです。確認チャレンジが発生した場合、発行されたトークンで再試行する前に、そのチャレンジを人間の承認者に提示します。strict types を宣言し、完全に型ヒントが付けられており、すべてのエラーを握りつぶすのではなく最も具体的な例外を捕捉します。

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);
}
}

お客様の実装では、McpClientInterfaceHumanApproverInterfaceApprovalDeniedException を独自のトランスポートと承認チャネルに接続してください。再試行では、元の引数に加えて発行されたトークンを再利用します。人間の判断なしにチャレンジを自動承認することは決してしないでください。HITL リスクティアを参照してください。

サーバーは、レジストリを編集するのではなく、ツールを追加し、プロバイダーを提供することで拡張します。

拡張ポイント用途制約
クラスとして実装する ToolInterfaceツールとして公開される新しいエンジン機能。tier()riskLevel()category()、および JSON Schema の inputSchema() を宣言し、薄いエンジンラッパーに保ってください。
プロバイダーとしての ToolProviderInterfaceあるティア向けの一連のツールの登録。Pro および Enterprise のプロバイダーは class_exists() で検出されます。サーバーからプロプライエタリパッケージを必須にしないでください。
enabled_tools 許可リスト公開されるカタログの最小権限スコープ設定。許可リストは差し引くだけであり、存在しないツールを登録することはできません。
risk_level_overridesツールのリスクを引き上げてデプロイを堅牢化する用途。アップグレードのみ。ApprovalRequired ツールのダウングレードは起動に失敗します。
注入可能なトランスポートおよびワーカーのシームサーバーを単独でテストする用途。これらのシームはテストのために存在し、アプリケーションの結線のためではありません。
  1. プロファイルの選択。 公開するトランスポートに応じて、.rr.yaml.rr.grpc.yaml、または .rr.full.yaml を実行します。
  2. シークレットからキーをマウント。 NEXTPDF_API_KEYS_FILE をシークレットファイルに向けてください。ローテーション時に再起動が不要になるよう、ホットリロードされるファイルキーストアを推奨します。
  3. 共有ストアの構成。 NEXTPDF_REDIS_HOST を設定し、ext-redis を確認してください(ワーカーが 1 つを超えるプールの場合)。SQLite ジョブストアは、すべてのワーカーが書き込めるボリュームに配置してください。
  4. TLS の終端。 REST は Transport Layer Security(TLS)ターミネーターの背後で実行してください。信頼されていないネットワークでは gRPC を相互 TLS で実行し、サーバー鍵、サーバー証明書、クライアント認証局をデプロイのシークレットとして供給してください。
  5. ヘルスのプローブ。 オーケストレーターのプローブには、匿名の /healthz/readyz エンドポイント(REST)、または HealthCheckReadinessCheck RPC(gRPC)を使用してください。
  6. カタログのスコープ設定。 enabled_tools を、インテグレーションが必要とする最小限のセットに制限してください。

Redis の正常性は前提とせず検証してください。構成された Redis 接続が失敗すると、REST サーバーはインメモリストアにフォールバックします。デプロイ および セキュリティと運用を参照してください。

障害発生箇所推奨される対応
不明な document_idツールの実行定義済みのエラーを呼び出し元に返し、まず create_pdf を呼び出すよう案内します。
ミューテーションでの古い ETagAST ミューテーションツールドキュメントを get_document_ast で再読み込みし、新しい ETag で再試行します。
API キーの欠落または無効(REST)認証ミドルウェア応答として 401WWW-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_documents1800 秒 / 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(401WWW-Authenticate)と gRPC(UNAUTHENTICATED)における、欠落、不正な形式、無効化、期限切れのキー、およびティア権限による拒否(403)を対象にします。
  • 並行性のテストは、古い ETag がミューテーションを失敗させること、および同一の idempotency_key がキャッシュされた結果を再生することを確認します。
  • パス封じ込めのテストは、ベースディレクトリ外に解決されるファイル出力パスが拒否されることを確認します。
  • フィクスチャは小さく、機微でないものに保ってください。実際の API キーやドキュメントの内容を決してコミットしないでください。