Điều khiển phiên tài liệu của agent qua MCP
Tổng quan nhanh
Phần tiêu đề “Tổng quan nhanh”Đây là một phiên agent hoàn chỉnh với máy chủ NextPDF Connect Model
Context Protocol (MCP), từng thông điệp một: initialize,
tools/list, sáu lời gọi tools/call dựng nên một bản tóm tắt dự án
một trang, và vòng trao đổi có con người tham gia (HITL) đặt cổng kiểm
soát cho thao tác ghi tệp cuối cùng. Mọi thông điệp JSON-RPC bên dưới đều
được ghi lại nguyên văn từ một tiến trình bin/nextpdf-mcp đang chạy
(chỉ các công cụ bậc core), rồi được làm sạch theo đúng hai cách: token
xác nhận dùng một lần được hiển thị dưới dạng
confirm_<single-use-hex>, và thư mục tạm hệ thống của máy được rút gọn
thành C:\Temp. Các định danh, schema, vị trí và số byte đúng chính xác
những gì máy chủ đã gửi.
Cài đặt
Phần tiêu đề “Cài đặt”composer require nextpdf/serverLiên kết transport stdio trong MCP host của bạn — với Claude Desktop (các host khởi chạy lệnh từ thư mục của riêng chúng, nên hãy dùng đường dẫn tuyệt đối; transport stdio không cần API key, khác với transport REST):
{ "mcpServers": { "nextpdf": { "command": "php", "args": ["/absolute/path/to/your/project/vendor/bin/nextpdf-mcp"] } }}Máy chủ giao tiếp JSON-RPC 2.0 phân tách bằng ký tự xuống dòng trên stdin/stdout và giữ đầu ra giao thức tách biệt hoàn toàn khỏi thông tin chẩn đoán: các dòng khởi động và audit đi tới stderr, không bao giờ tới stdout.
Tổng quan khái niệm
Phần tiêu đề “Tổng quan khái niệm”Một phiên tài liệu MCP có trạng thái. create_pdf mở một tài liệu trong
kho lưu trữ trong bộ nhớ của máy chủ và trả về một document_id; mọi lời
gọi sau đó đều nhắm tới định danh đó. Các công cụ nội dung (set_font,
add_text, add_table) thực thi ngay lập tức ở mức rủi ro Caution kèm
ghi log audit; preview_layout là một thao tác đọc Safe; và output_pdf
kèm file_path là Approval Required — nó không chạy ở lời gọi đầu tiên.
Thay vào đó, máy chủ trả về một thử thách kèm token dùng một lần, agent
chuyển tiếp thử thách đó tới con người, và chỉ một lời gọi lại mang theo
_confirmation_token mới thực thi thao tác ghi. Các tài liệu để lại
trong kho sẽ hết hạn sau thời gian tồn tại được cấu hình (mặc định 30 phút).
Cũng chính những lời gọi công cụ này điều khiển tool engine qua REST và gRPC — các transport dùng chung một executor — nên mọi thứ ở đây, ngoại trừ khung stdio, đều áp dụng được. Xem Kết xuất hóa đơn từ đầu đến cuối qua REST để xem chính engine đó trên bề mặt HTTP.
Bề mặt API
Phần tiêu đề “Bề mặt API”| Công cụ | Vai trò trong phiên này | Mức rủi ro |
|---|---|---|
create_pdf | Mở tài liệu, lấy document_id | Caution |
set_font | Chọn phông tiêu đề, rồi phông nội dung | Caution |
add_text | Dòng tiêu đề, rồi đoạn giới thiệu | Caution |
add_table | Bảng danh sách kiểm người phụ trách/hạn chót | Caution |
preview_layout | Đọc trạng thái bố cục trước khi xuất | Safe |
output_pdf (chế độ tệp) | Ghi PDF — có cổng kiểm soát | Approval Required |
Bản triển khai được ghi lại ở đây đã đăng ký 20 công cụ (13 core, 6 Pro, 1
Enterprise — các con số xuất hiện trong phản hồi initialize bên dưới);
phiên này chỉ dùng các công cụ core, nên nó chạy y nguyên trên một bản
cài đặt chỉ mã nguồn mở. Danh mục chính thức là phản hồi tools/list từ
chính máy chủ của bạn, và thang rủi ro được định nghĩa trong
tài liệu tham chiếu HITL risk tiers.
Phiên làm việc, từng thông điệp một
Phần tiêu đề “Phiên làm việc, từng thông điệp một”1. Khởi tạo kết nối
Phần tiêu đề “1. Khởi tạo kết nối”Client mở phiên và khai báo phiên bản giao thức của nó:
{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": { "name": "planning-agent", "version": "1.0.0" } }}Máy chủ xác nhận phiên bản giao thức và khai báo các khả năng của nó, bao gồm số lượng công cụ theo từng bậc và việc cổng kiểm soát HITL đã được bật:
{ "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "2025-06-18", "capabilities": { "tools": { "listChanged": false }, "nextpdf": { "tiers": { "core": 13, "pro": 6, "enterprise": 1 }, "tool_count": 20, "risk_model_version": 1, "hitl_enabled": true } }, "serverInfo": { "name": "NextPDF Connect", "version": "1.0.0" } }}Client xác nhận bằng một thông báo (các thông báo không mang id và
không nhận phản hồi):
{ "jsonrpc": "2.0", "method": "notifications/initialized"}2. Khám phá các công cụ
Phần tiêu đề “2. Khám phá các công cụ”{ "jsonrpc": "2.0", "id": 2, "method": "tools/list"}Phản hồi đầy đủ liệt kê toàn bộ 20 công cụ đã đăng ký cùng các input schema hoàn chỉnh của chúng. Ở đây nó được rút gọn còn hai công cụ mở và đóng phiên này — 18 mục bị lược bỏ có cùng dạng cấu trúc:
{ "jsonrpc": "2.0", "id": 2, "result": { "tools": [ { "name": "create_pdf", "description": "Create a new PDF document and return a document_id for subsequent operations", "inputSchema": { "type": "object", "properties": { "page_size": { "type": "string", "description": "Page size name (e.g. \"A4\", \"Letter\", \"Legal\", \"A3\")", "default": "A4" }, "orientation": { "type": "string", "enum": [ "portrait", "landscape" ], "description": "Page orientation", "default": "portrait" }, "title": { "type": "string", "description": "Document title metadata" }, "author": { "type": "string", "description": "Document author metadata" } }, "required": [] }, "annotations": { "destructiveHint": false, "idempotentHint": false } }, { "name": "output_pdf", "description": "Finalize the PDF and output to file or return as base64", "inputSchema": { "type": "object", "properties": { "document_id": { "type": "string", "description": "The document_id returned by create_pdf" }, "file_path": { "type": "string", "description": "Absolute file path to save the PDF. If omitted, returns base64-encoded PDF data." }, "destroy": { "type": "boolean", "description": "Whether to remove the document from the store after output", "default": true } }, "required": [ "document_id" ] }, "annotations": { "destructiveHint": false, "openWorldHint": true } } ] }}Lưu ý schema của output_pdf: file_path là tùy chọn, và các annotation
mang openWorldHint: true — công cụ này có thể tác động tới thế giới bên
ngoài phiên, và đó chính là lý do chế độ tệp có cổng kiểm soát.
3. Mở tài liệu
Phần tiêu đề “3. Mở tài liệu”{ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "create_pdf", "arguments": { "page_size": "A4", "orientation": "portrait", "title": "Project kickoff brief", "author": "Planning agent" } }}{ "jsonrpc": "2.0", "id": 3, "result": { "content": [ { "type": "text", "text": "{\"document_id\":\"doc_3b9f435efa0f32d1da7a131d\",\"page_count\":1,\"page_size\":\"A4\",\"orientation\":\"portrait\"}" } ], "structuredContent": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "page_count": 1, "page_size": "A4", "orientation": "portrait" } }}Mỗi kết quả công cụ xuất hiện hai lần trong cùng một thông điệp: một khối văn bản
content mà con người đọc được, và structuredContent mà máy đọc được.
Đọc structuredContent.document_id và luồn nó qua mọi lời gọi tiếp theo.
4. Thêm tiêu đề
Phần tiêu đề “4. Thêm tiêu đề”Chọn phông đậm cỡ 16 point, rồi đặt tiêu đề:
{ "jsonrpc": "2.0", "id": 4, "method": "tools/call", "params": { "name": "set_font", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "family": "helvetica", "style": "B", "size": 16 } }}{ "jsonrpc": "2.0", "id": 4, "result": { "content": [ { "type": "text", "text": "Font set to helvetica B 16pt on document doc_3b9f435efa0f32d1da7a131d." } ] }}{ "jsonrpc": "2.0", "id": 5, "method": "tools/call", "params": { "name": "add_text", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "text": "Project kickoff brief" } }}{ "jsonrpc": "2.0", "id": 5, "result": { "content": [ { "type": "text", "text": "{\"document_id\":\"doc_3b9f435efa0f32d1da7a131d\",\"position\":{\"x\":10,\"y\":16,\"page\":0}}" } ], "structuredContent": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "position": { "x": 10, "y": 16, "page": 0 } } }}5. Thêm đoạn văn nội dung
Phần tiêu đề “5. Thêm đoạn văn nội dung”Trở lại phông thường cỡ 11 point cho phần văn bản giới thiệu; width: 0
chọn bố cục multi-cell toàn chiều rộng:
{ "jsonrpc": "2.0", "id": 6, "method": "tools/call", "params": { "name": "set_font", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "family": "helvetica", "style": "", "size": 11 } }}{ "jsonrpc": "2.0", "id": 6, "result": { "content": [ { "type": "text", "text": "Font set to helvetica 11pt on document doc_3b9f435efa0f32d1da7a131d." } ] }}{ "jsonrpc": "2.0", "id": 7, "method": "tools/call", "params": { "name": "add_text", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "text": "Prepared by the planning agent for the 14 July kickoff. Scope, owners, and the first-week checklist are tabled below.", "width": 0, "line_height": 6 } }}{ "jsonrpc": "2.0", "id": 7, "result": { "content": [ { "type": "text", "text": "{\"document_id\":\"doc_3b9f435efa0f32d1da7a131d\",\"position\":{\"x\":10,\"y\":29.75,\"page\":0}}" } ], "structuredContent": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "position": { "x": 10, "y": 29.75, "page": 0 } } }}6. Thêm bảng danh sách kiểm
Phần tiêu đề “6. Thêm bảng danh sách kiểm”{ "jsonrpc": "2.0", "id": 8, "method": "tools/call", "params": { "name": "add_table", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "html": "<table><tr><th>Work item</th><th>Owner</th><th>Due</th></tr><tr><td>Repository bootstrap</td><td>Devon</td><td>2026-07-15</td></tr><tr><td>CI pipeline</td><td>Ana</td><td>2026-07-17</td></tr><tr><td>Staging deploy</td><td>Priya</td><td>2026-07-21</td></tr></table>" } }}{ "jsonrpc": "2.0", "id": 8, "result": { "content": [ { "type": "text", "text": "{\"document_id\":\"doc_3b9f435efa0f32d1da7a131d\",\"position\":{\"x\":10,\"y\":84.75,\"page\":0}}" } ], "structuredContent": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "position": { "x": 10, "y": 84.75, "page": 0 } } }}Mỗi lời gọi nội dung trả về vị trí con trỏ position đã cập nhật, nên agent
luôn biết phần tử tiếp theo sẽ rơi vào đâu.
7. Xem trước rồi mới yêu cầu phê duyệt
Phần tiêu đề “7. Xem trước rồi mới yêu cầu phê duyệt”preview_layout là một lời gọi Safe, chỉ đọc — một agent hành xử đúng
mực sẽ kiểm tra thứ nó vừa dựng trước khi yêu cầu con người phê duyệt một
thao tác ghi:
{ "jsonrpc": "2.0", "id": 9, "method": "tools/call", "params": { "name": "preview_layout", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d" } }}{ "jsonrpc": "2.0", "id": 9, "result": { "content": [ { "type": "text", "text": "{\"document_id\":\"doc_3b9f435efa0f32d1da7a131d\",\"total_pages\":1,\"current_page\":0,\"page_dimensions\":{\"width\":595.276,\"height\":841.89},\"margins\":{\"top\":10,\"right\":10,\"bottom\":10,\"left\":10},\"cursor_position\":{\"x\":10,\"y\":84.75}}" } ], "structuredContent": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "total_pages": 1, "current_page": 0, "page_dimensions": { "width": 595.276, "height": 841.89 }, "margins": { "top": 10, "right": 10, "bottom": 10, "left": 10 }, "cursor_position": { "x": 10, "y": 84.75 } } }}8. Yêu cầu ghi tệp — cổng kiểm soát trả lời trước
Phần tiêu đề “8. Yêu cầu ghi tệp — cổng kiểm soát trả lời trước”Agent yêu cầu output_pdf ghi bản tóm tắt đã hoàn thiện ra đĩa, giữ cho
tài liệu còn tồn tại (destroy: false) phòng khi con người từ chối và nó cần
chuyển sang đầu ra base64:
{ "jsonrpc": "2.0", "id": 10, "method": "tools/call", "params": { "name": "output_pdf", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "file_path": "C:\\Temp\\nextpdf-mcp\\kickoff-brief.pdf", "destroy": false } }}Tệp không được ghi. Vì chế độ tệp là Approval Required, máy chủ trả lời bằng một thử thách xác nhận thay vì ghi:
{ "jsonrpc": "2.0", "id": 10, "result": { "content": [ { "type": "text", "text": "⚠️ CONFIRMATION REQUIRED\n\nOperation: output_pdf\nDescription: Finalize the PDF and output to file or return as base64\n\nTo proceed, call output_pdf again with parameter _confirmation_token: \"confirm_<single-use-hex>\"\nExpires in 300 seconds." } ], "isError": false }}9. Con người phê duyệt — gọi lại với token
Phần tiêu đề “9. Con người phê duyệt — gọi lại với token”Agent chuyển tiếp nội dung thử thách tới con người. Khi được phê duyệt,
nó gọi output_pdf lần nữa với cùng các tham số cộng thêm
_confirmation_token:
{ "jsonrpc": "2.0", "id": 11, "method": "tools/call", "params": { "name": "output_pdf", "arguments": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "file_path": "C:\\Temp\\nextpdf-mcp\\kickoff-brief.pdf", "destroy": false, "_confirmation_token": "confirm_<single-use-hex>" } }}Token bị tiêu thụ, thao tác ghi được thực thi, và kết quả báo cáo tệp đã ghi:
{ "jsonrpc": "2.0", "id": 11, "result": { "content": [ { "type": "text", "text": "{\"document_id\":\"doc_3b9f435efa0f32d1da7a131d\",\"file_path\":\"C:\\\\Temp\\\\nextpdf-mcp\\\\kickoff-brief.pdf\",\"file_size\":3612,\"page_count\":1,\"destroyed\":false}" } ], "structuredContent": { "document_id": "doc_3b9f435efa0f32d1da7a131d", "file_path": "C:\\Temp\\nextpdf-mcp\\kickoff-brief.pdf", "file_size": 3612, "page_count": 1, "destroyed": false } }}Xác minh tệp đã ghi
Phần tiêu đề “Xác minh tệp đã ghi”Phiên này đã ghi kickoff-brief.pdf (3.612 byte, một trang, khớp với
structuredContent.file_size và page_count). Đầu ra qpdf --check
được ghi lại cho đúng tệp đó:
checking kickoff-brief.pdfPDF Version: 2.0File is not encryptedFile is not linearizedNo syntax or stream encoding errors found; the file may still containerrors that qpdf cannot detectĐó là một kiểm tra cấu trúc, theo đúng lời của qpdf — không phải một phán định tuân thủ.
Trường hợp biên & lưu ý
Phần tiêu đề “Trường hợp biên & lưu ý”- Lời gọi lại phải lặp lại đúng các tham số. Token xác nhận được ràng
buộc với tên công cụ cộng với một digest chuẩn tắc của bộ tham số mà token
được cấp cho. Gọi lại với bất kỳ thay đổi nào — kể cả đảo
destroy— đều không tiêu thụ token; thay vào đó máy chủ trả lời bằng một thử thách mới. Hãy lặp lại các tham số y hệt và chỉ thêm_confirmation_token. - Token dùng một lần và sẽ hết hạn. Thử thách nêu rõ thời hạn (300 giây). Sau khi hết hạn hoặc bị tiêu thụ, lời gọi có cổng kiểm soát tiếp theo sẽ nhận một thử thách mới; hãy chuyển tiếp thử thách mới đó.
- Đầu ra tệp rơi vào một thư mục nằm trong danh sách cho phép. Máy chủ
từ chối một
file_pathnằm ngoài thư mục tạm đã cấu hình với thông báoOutput path rejected by security policy. Gốc danh sách cho phép mặc định lànextpdf-mcpbên dưới thư mục tạm hệ thống; người vận hành thay đổi nó bằng thiết lậptemp_dirtrongnextpdf-mcp.yaml. - Chế độ base64 không có cổng kiểm soát.
output_pdfkhông cófile_pathtrả về PDF dưới dạng base64 ở mức Review, không có tác dụng phụ tới hệ thống tệp — xem Yêu cầu phê duyệt của con người để xuất tệp để tìm hiểu sâu về ranh giới đó. - Một thử thách là một kết quả, không phải một lỗi. Thông điệp thử
thách mang
isError: false; một phê duyệt đang chờ là một điểm tạm dừng của quy trình. Đừng thử lại trong vòng lặp, và tuyệt đối đừng bịa ra một token. - Các thông báo không có phản hồi. Sau
notifications/initialized, đừng chặn để chờ một dòng phản hồi.
Hiệu năng
Phần tiêu đề “Hiệu năng”Phiên này hoàn toàn nằm trong bộ nhớ từ đầu đến cuối: các lời gọi nội dung trả về trong vài mili-giây ở lần chạy được ghi lại, và thời gian thực tế bị chi phối bởi vòng trao đổi phê duyệt của con người, vốn chính là mục đích của cổng kiểm soát. Kho tài liệu giữ một phiên trong 30 phút nhàn rỗi theo mặc định (tối đa 50 tài liệu), nên một lần phê duyệt chậm không làm mất tài liệu đã dựng — nhưng một tài liệu bị bỏ rơi sẽ được thu hồi.
Ghi chú bảo mật
Phần tiêu đề “Ghi chú bảo mật”- Hãy coi token xác nhận như một bí mật dùng một lần. Chuyển tiếp nội dung thử thách tới con người; đừng ghi log token hay lưu lại nó. Trang này che token đã ghi lại vì đúng lý do đó.
- Vết audit nằm trên stderr. Mọi thao tác ở mức Caution trở lên đều được ghi log audit (công cụ, rủi ro, tham số, kết quả) qua PSR-3, với các tham số nhạy cảm được che. Thông tin chẩn đoán không bao giờ trộn vào luồng giao thức.
- Danh sách cho phép đường dẫn là ranh giới của hệ thống tệp. Hãy trỏ
temp_dirtới một thư mục dành riêng cho đầu ra Connect; đừng mở rộng nó tới một vị trí dùng chung. - Các mức rủi ro chỉ tăng một chiều. Một ghi đè của người vận hành
trong
nextpdf-mcp.yamlcó thể nâng mức rủi ro của một công cụ nhưng không bao giờ có thể hạoutput_pdfxuống dưới Approval Required.
Tuân thủ
Phần tiêu đề “Tuân thủ”Công thức này không đưa ra tuyên bố tiêu chuẩn mang tính quy phạm nào. Nó
ghi lại transport stdio của MCP (JSON-RPC 2.0, phiên bản giao thức
2025-06-18 như được thương lượng trong trao đổi initialize đã ghi
lại) và hợp đồng rủi ro và xác nhận của máy chủ. Bước qpdf --check ở
trên chỉ xác nhận tính toàn vẹn cấu trúc của tệp đã ghi mà thôi; sự tuân
thủ một tiêu chuẩn được xác định bởi một trình kiểm định độc lập, chứ
không phải do phần mềm tạo ra tệp khẳng định.
Xem thêm
Phần tiêu đề “Xem thêm”- Yêu cầu phê duyệt của con người để xuất tệp — chi tiết về cổng xác nhận, bao gồm cả đường dẫn từ chối.
- Kết xuất hóa đơn từ đầu đến cuối qua REST — cùng tool engine đó qua HTTP, kèm bản ghi wire đã lưu.
- Tạo PDF đầu tiên của bạn — phiên Connect nhỏ nhất.
- Quy ước công thức Connect — hợp đồng mà mọi công thức Connect tuân theo.
- HITL risk tiers — thang rủi ro chuẩn và cách phân giải chính sách.
- Tool catalog — danh mục công cụ chính thức.