Bỏ qua để đến nội dung

Hướng dẫn cho nhà phát triển NextPDF Connect

NextPDF Connect (nextpdf/server) bao bọc engine PDF 2.0 không phụ thuộc framework của NextPDF thành một dịch vụ. Nó không triển khai lại việc tạo PDF. Nó cung cấp từng khả năng của engine dưới dạng một tool có tên và schema, rồi phục vụ danh mục đó qua ba transport: Model Context Protocol (MCP) qua đầu vào và đầu ra chuẩn, Representational State Transfer (REST) Application Programming Interface (API), và gRPC. Hãy dùng hướng dẫn này khi bạn xây dựng trên server, mở rộng bộ tool của nó, hoặc chạy nó trong môi trường production.

Ba khái niệm định hình thiết kế: tool registry, ba transport độc lập, và cổng xác nhận có con người trong vòng lặp (human-in-the-loop, HITL). Trang này giải thích cách chúng liên kết với nhau và cách làm việc với chúng mà không làm suy yếu mô hình an toàn. Để biết chính xác các ký hiệu tool, lệnh gọi thủ tục từ xa (remote procedure call, RPC) và message, hãy xem Tài liệu tham khảo API.

Điều kiện tiên quyết: PHP 8.4, Composer 2, và — đối với các transport có kết nối mạng — binary RoadRunner cùng ít nhất một API key. Cài đặt bằng composer require nextpdf/server.

Hãy giữ mỗi trách nhiệm ở đúng bên ranh giới của nó. Một tool là lớp bao mỏng quanh một lệnh gọi engine; nó không được chứa logic diễn giải bố cục, ngữ nghĩa tài liệu, hay logic chuyển đổi.

LớpSở hữu bởiTrách nhiệmKhông đặt ở đây
Client hoặc agentPhần tích hợp của bạnChọn tool cần gọi; chuyển tiếp các thử thách xác nhận tới một con người.Logic engine hoặc phát hiện tầng (tier).
Transportnextpdf/serverĐóng gói yêu cầu dưới dạng JSON-RPC, HTTP hoặc Protocol Buffers; xác thực; và định tuyến tới bộ thực thi tool.Ngữ nghĩa tài liệu.
Tool registrynextpdf/serverPhát hiện các tầng, đăng ký tool theo allowlist bảo mật, tra cứu một tool theo tên.Tạo PDF.
Toolnextpdf/serverKiểm tra tính hợp lệ của đối số dựa trên input schema rồi gọi engine.Diễn giải bố cục hoặc điều phối nhiều bước.
Cổng xác nhậnnextpdf/serverTạm giữ một thao tác ApprovalRequired cho đến khi một con người phê duyệt nó.Xác thực bên gọi.
Enginenextpdf/core (và nextpdf/premium)Tạo, kiểm tra và chuyển đổi nội dung PDF.Phần việc thuộc transport hoặc xác thực.

Mỗi transport có điểm vào (entry point) và factory khởi động riêng. Mỗi transport xây dựng đồ thị đối tượng của nó một cách tường minh. Không cần đăng ký container tiêm phụ thuộc (dependency-injection) nào.

  1. Nạp cấu hình. Server MCP phân giải cấu hình từ các biến môi trường (NEXTPDF_MCP_*), sau đó đến phần nextpdf_mcp trong tệp YAML, rồi đến giá trị mặc định tích hợp sẵn, và tạo ra một readonlyMcpConfig. Server REST và gRPC đọc HttpConfig từ các biến môi trường NEXTPDF_*. Xem Cấu hình.
  2. Thiết lập chính sách bảo mật. Allowlist enabled_tools được thiết lập trước registry, nên nó giới hạn việc phát hiện ngay từ lần đăng ký đầu tiên.
  3. Xây dựng registry và phát hiện các tool. ToolRegistry::registerDefaults() đăng ký tầng core, rồi đến các provider Pro và Enterprise khi class tương ứng phân giải được, rồi đến các provider AST và mutation đi kèm tùy theo các cổng môi trường của chúng.
  4. Tạo các kho lưu trữ dùng chung và cổng. Kho tài liệu trong bộ nhớ được tạo từ TTL và sức chứa đã cấu hình; ConfirmationGate được lắp ráp cùng kho token dùng một lần của nó.
  5. Gắn transport. MCP đi vào một vòng lặp đọc-xử lý-ghi trên stdio cho đến khi gặp cuối tệp. REST và gRPC tạo bảng tuyến (route) hoặc dịch vụ của chúng từ các tầng đã phát hiện, rồi trao vòng lặp yêu cầu cho RoadRunner.

Sau đó, một yêu cầu đi theo luồng này: xác thực (REST và gRPC), phân giải tool hoặc thao tác, chạy cổng xác nhận cho thao tác ApprovalRequired, thực thi trên engine, và trả về kết quả. Xem Khởi động và phát hiện.

Ba transport dùng chung các khái niệm registry, cấu hình và cổng, nhưng chúng chạy như các tiến trình độc lập. Khởi động một transport không khởi động các transport còn lại.

TransportĐiểm vàoKhi nào nên chọn nó
MCPbin/nextpdf-mcpMột client trí tuệ nhân tạo (artificial intelligence, AI) cục bộ khởi chạy server như một tiến trình con tin cậy.
RESTbin/nextpdf-serverCác client HTTP qua mạng; được mô tả bằng một tài liệu OpenAPI 3.1.
gRPCbin/nextpdf-grpcCác client có kiểu, dạng luồng; dùng dịch vụ nextpdf.connect.v1.NextPDFConnect.

Hãy chọn các transport theo profile RoadRunner bạn chạy: .rr.yaml (chỉ REST), .rr.grpc.yaml (chỉ gRPC), hoặc .rr.full.yaml (cả hai). Transport MCP là một tiến trình con thông thường và không cần bộ giám sát (supervisor). Để biết chi tiết cho từng transport, hãy xem Transport MCP, Transport REST, và Transport gRPC.

Hãy chạy các transport qua mạng dưới RoadRunner với các kho dùng chung và khóa được gắn từ secret. Profile kết hợp cho phép REST và gRPC dùng chung một bộ giám sát.

Đường dẫn hoặc thiết lậpMục đích
.rr.full.yamlProfile kết hợp REST và gRPC dưới một bộ giám sát duy nhất.
NEXTPDF_API_KEYS_FILEĐường dẫn tới một tệp API key được gắn từ secret và tự nạp lại nóng.
NEXTPDF_REDIS_HOSTBật kho giới hạn tốc độ (rate-limit), kho idempotency và kho tài liệu dựa trên Redis cho các pool nhiều worker.
NEXTPDF_WORKER_COUNT / NEXTPDF_GRPC_WORKER_COUNTĐịnh cỡ pool worker cho các pool HTTP và gRPC.
Thư mục đầu ra gốcVolume chuyên dụng với quyền hệ thống tệp tối thiểu cho các tool xuất tệp.

Ví dụ shell sau khởi động profile kết hợp với các khóa được gắn từ secret và một kho Redis dùng chung. Nó không chứa secret nào; các khóa được gắn tại /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

Với pool có nhiều worker, hãy cấu hình Redis và xác nhận ext-redis có mặt trong image đang chạy. Nếu thiếu nó, các kho giới hạn tốc độ, idempotency và tài liệu sẽ là riêng cho từng worker. Xem Triển khai.

NextPDF\Server\ToolRegistry (src/ToolRegistry.php) xây dựng danh mục lúc khởi động. Tầng (tier) là một bất biến được khai báo: mỗi tool trả về tier()riskLevel() của riêng nó. Registry không bao giờ suy ra tầng từ namespace hay cách đóng gói.

  1. Tầng Core đăng ký vô điều kiện: các tool tài liệu và chẩn đoán, cộng thêm generate_barcode khi registry bộ mã hóa barcode của core có mặt, cộng thêm parse_pdf chỉ khi NEXTPDF_MCP_TOOL_PARSE_PDF_ENABLEDtrue hoặc 1.
  2. Các provider Pro và Enterprise đăng ký khi các class provider tương ứng phân giải được, được dò bằng class_exists(). Một tầng vắng mặt sẽ bị bỏ qua âm thầm.
  3. Các provider AST và mutation đi kèm đăng ký dưới tầng Pro, được kiểm soát bởi NEXTPDF_AST_TOOLS_ENABLEDNEXTPDF_MUTATION_TOOLS_ENABLED (cả hai đều được bật theo mặc định).
  4. Bộ lọc chính sách bảo mật đối chiếu mọi lần đăng ký với allowlist enabled_tools. Allowlist chỉ loại bớt; nó không bao giờ thêm vào. Bộ đếm theo từng tầng chỉ đếm các tool mà chính sách cho phép.

Phản hồi initialize của MCP và endpoint GET /api/v1/capabilities của REST báo cáo số lượng theo từng tầng và tổng số. Hãy coi mọi tổng số cố định trong văn bản là đã lỗi thời; hãy truy vấn server đang chạy. Xem Danh mục tool.

Mỗi tool khai báo một trong bốn mức rủi ro từ enum RiskLevel (src/Config/RiskLevel.php): Safe (0), Caution (1), Review (2), và ApprovalRequired (3). Ghi nhật ký kiểm toán áp dụng từ mức Caution trở lên. Một ghi đè cấu hình có thể nâng mức rủi ro của một tool; nó không bao giờ được hạ một tool vốn được thiết kế là ApprovalRequired. Bộ nạp cấu hình ném lỗi ngay khi nạp, và server từ chối khởi động thay vì chạy với một cổng đã bị suy yếu.

Khi một tool ApprovalRequired được gọi mà không có token hợp lệ, ConfirmationGate (src/Mcp/ConfirmationGate.php) trả về một token thử thách dùng một lần. Token ràng buộc tên tool, một nonce ngẫu nhiên, và thời gian sống (time-to-live, TTL) 300 giây, nhưng không ràng buộc các đối số, vì các client có thể tuần tự hóa lại đối số với thứ tự khóa khác nhau khi thử lại. Agent chuyển tiếp thử thách tới một con người và gọi lại đúng tool đó với token nằm trong đối số _confirmation_token. Token bị tiêu thụ khi sử dụng, cho phép đúng một lệnh gọi đi qua cổng.

Ví dụ PHP sau là một helper độc lập với transport. Nó điều khiển một lệnh gọi tool MCP và, khi gặp một thử thách xác nhận, hiển thị thử thách cho một người phê duyệt trước khi thử lại với token đã cấp. Nó khai báo strict types, có type-hint đầy đủ, và bắt ngoại lệ cụ thể nhất thay vì nuốt mọi lỗi.

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

Hãy kết nối McpClientInterface, HumanApproverInterface, và ApprovalDeniedException với transport và kênh phê duyệt của riêng bạn. Lần thử lại tái sử dụng các đối số gốc cùng token đã cấp; không bao giờ tự động phê duyệt một thử thách mà không có quyết định của con người. Xem Các tầng rủi ro HITL.

Hãy mở rộng server bằng cách thêm tool và cung cấp provider, thay vì sửa registry.

Điểm mở rộngDùng choRàng buộc
Một class hiện thực ToolInterfaceMột khả năng mới của engine được cung cấp dưới dạng một tool.Hãy khai báo tier(), riskLevel(), category(), và một inputSchema() theo JSON Schema; hãy giữ class là một lớp bao mỏng quanh engine.
Một ToolProviderInterface providerĐăng ký một tập tool cho một tầng.Các provider Pro và Enterprise được phát hiện bằng class_exists(); đừng khiến server phụ thuộc vào gói độc quyền.
enabled_tools allowlistGiới hạn danh mục được cung cấp theo nguyên tắc quyền tối thiểu.Allowlist chỉ loại bớt; nó không thể đăng ký một tool vắng mặt.
risk_level_overridesCủng cố một triển khai bằng cách nâng mức rủi ro của một tool.Chỉ nâng cấp; việc hạ cấp một tool ApprovalRequired sẽ làm khởi động thất bại.
Các điểm nối transport và worker có thể tiêm vàoKiểm thử server một cách biệt lập.Những ranh giới này tồn tại để phục vụ kiểm thử, không phải để tích hợp ứng dụng.
  1. Chọn một profile. Hãy chạy .rr.yaml, .rr.grpc.yaml, hoặc .rr.full.yaml cho các transport bạn cung cấp.
  2. Gắn các khóa từ một secret. Hãy trỏ NEXTPDF_API_KEYS_FILE tới một tệp secret; ưu tiên kho khóa dạng tệp tự nạp lại nóng để việc xoay khóa không cần khởi động lại.
  3. Cấu hình các kho dùng chung. Hãy đặt NEXTPDF_REDIS_HOST và xác nhận ext-redis cho bất kỳ pool nào có hơn một worker; đặt kho job SQLite trên một volume mà tất cả worker đều ghi được.
  4. Kết thúc TLS. Hãy chạy REST phía sau một bộ kết thúc Transport Layer Security (TLS); chạy gRPC với TLS song phương (mutual TLS) trên bất kỳ mạng không tin cậy nào, với khóa server, chứng chỉ server và tổ chức phát hành chứng chỉ client được cung cấp dưới dạng các secret triển khai.
  5. Thăm dò tình trạng (health). Hãy dùng các endpoint ẩn danh /healthz/readyz (REST) hoặc các RPC HealthCheckReadinessCheck (gRPC) cho các thăm dò của bộ điều phối (orchestrator).
  6. Giới hạn phạm vi danh mục. Hãy hạn chế enabled_tools về tập tối thiểu mà một phần tích hợp cần.

Hãy xác minh tình trạng của Redis thay vì giả định nó. Server REST quay về các kho trong bộ nhớ khi một kết nối Redis đã cấu hình thất bại. Xem Triển khaiBảo mật và vận hành.

LỗiNơi nó xuất hiệnPhản hồi được khuyến nghị
Không xác định được document_idThực thi toolTrả về một lỗi đã định nghĩa cho bên gọi; hướng dẫn bên gọi chạy create_pdf trước.
ETag lỗi thời trên một thao tác mutationTool mutation ASTĐọc lại tài liệu bằng get_document_ast rồi thử lại với ETag mới.
Thiếu hoặc không hợp lệ API key (REST)Middleware xác thựcTrả về 401 kèm một thử thách WWW-Authenticate: Bearer; đừng tiết lộ phần nào đã sai.
Tầng không có quyền (REST)Phân quyềnTrả về 403; tầng của khóa thấp hơn tầng của thao tác.
Vắng tuyến tầng (REST)RouterTrả về 404; gói chưa được cài đặt. Đây là tình huống dự kiến, không phải một lỗi.
Token sai (gRPC)Bộ xác thực gRPCĐể lệnh gọi thất bại với UNAUTHENTICATED.
Không truy cập được RedisKhởi động hoặc lúc chạyHạ cấp xuống các kho trong bộ nhớ; cảnh báo cho người vận hành và xác minh tình trạng của Redis.
Đường dẫn đầu ra nằm ngoài thư mục gốcTool xuất tệpThất bại an toàn (fail closed); đường dẫn được chuẩn hóa, và việc đi xuyên thư mục bị từ chối.

Hãy trả các lỗi của engine dưới dạng các đối tượng lỗi đã định nghĩa, không bao giờ dưới dạng thành công âm thầm. Tài liệu tham khảo API trình bày chi tiết mô hình lỗi cho từng transport.

Mối quan tâmMặc địnhKhi nào nên ghi đè
parse_pdfBị tắt (chọn bật qua NEXTPDF_MCP_TOOL_PARSE_PDF_ENABLED).Chỉ bật khi một phần tích hợp cần kiểm tra cấu trúc.
enabled_toolsRỗng (cho phép tất cả các tool đã phát hiện).Đặt một allowlist tường minh cho các triển khai theo nguyên tắc quyền tối thiểu.
Ghi đè rủi roKhông có.Nâng mức rủi ro cho một triển khai được củng cố; không bao giờ thử hạ cấp.
document_ttl / max_documents1.800 giây / 50 tài liệu.Hạ thấp cho các triển khai nhạy cảm về nơi lưu trú dữ liệu hoặc bị giới hạn bộ nhớ.
allow_file_outputĐược bật.Đặt thành false cho các triển khai phi trạng thái, nhạy cảm về nơi lưu trú dữ liệu.
Số lượng workerBốn (HTTP), hai (gRPC).Định cỡ theo độ trễ quan sát được và số lõi có sẵn.
Bộ lắng nghe RESTHTTP văn bản thuần phía sau một bộ kết thúc TLS.Luôn kết thúc TLS ở thượng nguồn; không bao giờ phơi bày văn bản thuần trên một mạng không tin cậy.
gRPC trên các mạng không tin cậyTLS song phương (mutual TLS).Bắt buộc; không bao giờ chạy một bộ lắng nghe gRPC văn bản thuần trên một mạng không tin cậy.
  • Các bài kiểm thử registry xác nhận rằng một tầng Pro hoặc Enterprise vắng mặt sẽ bị bỏ qua âm thầm và danh mục core vẫn đăng ký.
  • Các bài kiểm thử allowlist xác nhận rằng enabled_tools chỉ loại bớt và không bao giờ thêm vào một tool mà registry chưa phát hiện.
  • Các bài kiểm thử cổng xác nhận xác nhận rằng một tool ApprovalRequired trả về một thử thách ở lần gọi đầu tiên, chạy một lần với một token dùng một lần hợp lệ, và làm hết hạn token sau TTL của nó.
  • Các bài kiểm thử hạ cấp xác nhận rằng một mục risk_level_overrides làm suy yếu một tool ApprovalRequired sẽ làm khởi động thất bại.
  • Các bài kiểm thử xác thực bao phủ các khóa thiếu, sai định dạng, bị tắt và hết hạn trên REST (401 kèm WWW-Authenticate) và gRPC (UNAUTHENTICATED), và việc từ chối quyền theo tầng (403).
  • Các bài kiểm thử đồng thời xác nhận rằng một ETag lỗi thời làm một thao tác mutation thất bại và rằng một idempotency_key lặp lại sẽ phát lại kết quả đã được cache.
  • Các bài kiểm thử giới hạn đường dẫn xác nhận rằng một đường dẫn đầu ra phân giải ra ngoài thư mục gốc sẽ bị từ chối.
  • Hãy giữ các fixture nhỏ và không nhạy cảm; không bao giờ commit một API key thật hay nội dung tài liệu thật.