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

Máy chủ MCP dành cho Python

NextPDF Python SDK bao gồm một máy chủ Model Context Protocol (MCP), trình bày các thao tác trích xuất PDF dưới dạng công cụ gốc cho tác nhân. Một tác nhân hỗ trợ MCP, chẳng hạn như Claude Code, chỉ cần đăng ký máy chủ một lần rồi gọi các công cụ NextPDF giống như cách gọi bất kỳ công cụ nào khác.

Máy chủ là một lớp chuyển đổi mỏng. Mỗi công cụ đọc một tệp PDF từ ổ đĩa cục bộ, gọi client bất đồng bộ tới endpoint NextPDF Connect của bạn, rồi trả kết quả dưới dạng chuỗi JSON. Máy chủ không chứa logic nghiệp vụ và không lưu dữ liệu giữa các lần gọi.

Cài đặt SDK với extra MCP:

Terminal window
pip install nextpdf[mcp]

Extra mcp sẽ cài gói mcp từ upstream (ràng buộc mcp>=1.0,<2.0). Máy chủ yêu cầu Python 3.10 trở lên.

Chạy mô-đun máy chủ từ cấu hình MCP client của bạn. Ví dụ bên dưới đọc cả hai giá trị kết nối từ môi trường máy chủ thay vì nhúng bí mật vào tệp cấu hình (xem Bảo mật):

{
"mcpServers": {
"nextpdf": {
"command": "python",
"args": ["-m", "nextpdf.mcp"],
"env": {
"NEXTPDF_BASE_URL": "https://connect.example.com",
"NEXTPDF_API_KEY": "${NEXTPDF_API_KEY}"
}
}
}
}

Điểm vào python -m nextpdf.mcp chạy main(), khởi động máy chủ qua input/output chuẩn (stdio) bằng asyncio.run(serve()). Đừng nhầm với python -m nextpdf, lệnh này chạy giao diện dòng lệnh (CLI), không phải máy chủ MCP.

NEXTPDF_BASE_URLNEXTPDF_API_KEY là bắt buộc. Máy chủ tạo client theo kiểu lazy trong lần gọi công cụ đầu tiên. Nếu một trong hai biến rỗng, máy chủ sẽ phát sinh RuntimeError và trả về cho tác nhân dưới dạng lỗi công cụ, thay vì làm sập tiến trình.

Máy chủ đăng ký tám công cụ. Tên của mọi công cụ đều dùng tiền tố nextpdf_. Mỗi công cụ ánh xạ tới một phương thức trong không gian tên ast của client bất đồng bộ (AsyncNextPDF.ast), ngoại trừ hai công cụ tổng hợp được ghi chú bên dưới. Máy chủ ghép chúng từ các lệnh gọi cấp thấp hơn.

Công cụ MCPLệnh gọi SDKGhi chú
nextpdf_extract_textast.extract_cited_text(pdf_data, page_index=..., headings_only=...)Trả về một danh sách CitedTextBlock.
nextpdf_extract_tablesast.extract_cited_tables(pdf_data, page_range=...)Trả về ExtractCitedTablesResponse.
nextpdf_get_astast.get_document_ast(pdf_data, page_range_start=0, page_range_end=..., token_budget=...)Trả về AstDocument.
nextpdf_infoast.get_document_ast(pdf_data)Máy chủ tạo một bản tóm tắt metadata; không có endpoint chuyên dụng.
nextpdf_healthkhông cóChỉ kiểm tra các biến môi trường; không thực hiện lệnh gọi mạng nào.
nextpdf_searchast.search_ast_nodes(pdf_data, node_type=..., page_index=..., text_query=..., max_results=...)Trả về SearchAstNodesResponse.
nextpdf_get_outlineast.search_ast_nodes(pdf_data, node_type="heading", max_results=500)Máy chủ định hình lại các nút tiêu đề thành một dàn ý.
nextpdf_diffast.get_ast_diff(original_pdf_data, modified_pdf_data)Trả về GetAstDiffResponse.

Hãy lưu ý các chi tiết đầu vào công cụ sau đây trước khi bạn kết nối một tác nhân:

  • Mọi đầu vào đường dẫn (pdf_path, original_pdf_path, modified_pdf_path) đều là đường dẫn tuyệt đối tới tệp trên máy đang chạy máy chủ. Tác nhân truyền một đường dẫn, còn máy chủ đọc các byte cục bộ. Không có công cụ tải lên.
  • nextpdf_extract_text khai báo một trường max_pages trong schema đầu vào, nhưng trình xử lý văn bản không truyền trường đó cho SDK. Việc giới hạn phạm vi trang cho văn bản được thực hiện qua page_index (một trang đơn lẻ tính từ 0). Dùng nextpdf_get_ast với max_pages khi bạn cần giới hạn một lượt duyệt toàn tài liệu.
  • nextpdf_get_ast chuyển max_pages thành dải trang bao gồm cả hai đầu là [0, max_pages - 1] (mặc định max_pages là 50). Truyền token_budget để giới hạn kích thước cây được trả về.
  • nextpdf_info trả về schema_version, source_hash, page_count, estimated_tokens, root_node_type, và root_children_count. Các giá trị này đến từ mô hình AstDocument, trong đó estimated_tokens là thuộc tính được tính toán (xấp xỉ bốn ký tự cho mỗi token).
  • nextpdf_get_outline trả về một mục cho mỗi tiêu đề với id, page_index, text, và depth (đọc từ attributes["level"] của nút, mặc định là 1), cùng với heading_count, total_matches, và truncated.

Các công cụ trích xuất có trích dẫn sẽ gắn một CitationAnchor vào mọi kết quả. Mỗi anchor bao gồm node_id, page_index, một bbox đã chuẩn hóa (tọa độ trong khoảng từ 0.0 đến 1.0), và điểm confidence (0.0 đến 1.0). Những tác nhân cần nguồn gốc nên hiển thị các trường này, thay vì chỉ hiển thị riêng văn bản thô.

Máy chủ không bao giờ để ngoại lệ thoát ra tới lớp truyền tải của tác nhân. Bộ điều phối call_tool bắt mọi lỗi và trả về dưới dạng JSON TextContent, nên một lệnh gọi công cụ thất bại sẽ tạo ra payload có cấu trúc mà tác nhân có thể đọc, thay vì làm ngắt kết nối. Các dạng payload là:

Điều kiệnJSON trả về
Tên công cụ không xác định{"error": "Unknown tool: <name>"}
Thiếu tệp đầu vào{"error": "PDF file not found: <path>"}
Bất kỳ lớp con NextPDFError nào{"error": "<message>", "error_type": "<class>", "status_code": <int?>}
Bất kỳ ngoại lệ nào khác{"error": "Unexpected error: <message>"}

status_code chỉ xuất hiện khi lỗi nền tảng có mang theo giá trị đó. SDK ánh xạ các phản hồi HTTP thành một hệ phân cấp ngoại lệ có kiểu, tất cả đều bắt nguồn từ NextPDFError:

Ngoại lệTrạng thái HTTPerror_codeKhi nào
NextPDFLicenseError402license/tier-requiredEndpoint yêu cầu một bậc giấy phép phía máy chủ cao hơn cho thao tác này.
AstNoStructTreeError422ast/no-struct-treePDF chưa được gắn thẻ và phương án dự phòng heuristic chưa được bật trên máy chủ.
QuotaExceededError429quota/exceededĐã chạm giới hạn tốc độ hoặc hạn mức. Mang theo retry_after (giây) khi máy chủ gửi một header Retry-After.
AstBuildTimeoutError504ast/build-timeoutQuá trình dựng AST đã vượt quá ngân sách thời gian của máy chủ. Giảm dải trang.
NextPDFAPIError4xx/5xx khácdo máy chủ cung cấpBất kỳ lỗi nào khác ở cấp API.

Dùng hướng dẫn này khi tích hợp tác nhân:

  • Thời gian chờ. HTTP client dùng thời gian chờ mặc định cố định: tổng cộng 60 giây, với thời gian chờ kết nối là 10 giây. Một tài liệu chậm hoặc lớn sẽ biểu hiện dưới dạng AstBuildTimeoutError (máy chủ đã từ bỏ việc dựng AST) hoặc, nếu chính client hết thời gian chờ, một payload Unexpected error từ lớp truyền tải. Khi thấy ast/build-timeout, hãy yêu cầu tác nhân thu hẹp phạm vi: giảm max_pages trên nextpdf_get_ast, hoặc đặt page_index / page_startpage_end trên các công cụ trích xuất.
  • Hạn mức và lùi thời gian thử lại. Khi gặp 429, công cụ trả về error_typeQuotaExceededError với status_code 429. Giá trị retry_after nằm trên đối tượng ngoại lệ. Vì máy chủ chỉ tuần tự hóa error, error_type, và status_code, tác nhân nên coi 429 là tín hiệu để tạm dừng và thử lại sau, thay vì phân tích header thử lại từ đầu ra của công cụ. Áp đặt hạn mức tại endpoint Connect, không phải trong tác nhân.
  • PDF chưa được gắn thẻ. Một mã 422 ast/no-struct-tree có nghĩa là tệp PDF nguồn không có cây cấu trúc. Bật chế độ heuristic trên máy chủ cho những tài liệu đó, hoặc chuyển chúng tới một bước gắn thẻ trước khi trích xuất.

Bảo mật: giới hạn phạm vi khóa API và đặc quyền tối thiểu

Phần tiêu đề “Bảo mật: giới hạn phạm vi khóa API và đặc quyền tối thiểu”

Hãy coi khóa API là bí mật, với mức độ cẩn trọng như khi xử lý mật khẩu cơ sở dữ liệu.

  • Đừng bao giờ nhúng khóa vào tệp cấu hình MCP. Ví dụ JSON ở trên tham chiếu ${NEXTPDF_API_KEY} để giá trị được phân giải từ môi trường máy chủ hoặc một trình quản lý bí mật lúc khởi chạy. Tệp cấu hình có thể được đưa vào quản lý phiên bản; bí mật thì không.
  • Giới hạn phạm vi khóa chỉ ở mức trích xuất chỉ đọc. Máy chủ MCP chỉ gọi bề mặt trích xuất AST (extract_cited_text, extract_cited_tables, get_document_ast, search_ast_nodes, get_ast_diff). Máy chủ không render, ký, biên tập che hay thay đổi tài liệu. Hãy cấp cho tác nhân một khóa có phạm vi phía máy chủ giới hạn ở các đường dẫn chỉ đọc đó, để một tác nhân bị xâm phạm không thể chạm tới thao tác ghi hoặc thao tác ở bậc cao hơn.
  • Dùng một khóa riêng cho mỗi tác nhân. Khóa riêng cho từng tác nhân cho phép bạn thu hồi hoặc xoay vòng một tích hợp mà không ảnh hưởng đến các tích hợp khác, đồng thời giúp nhật ký endpoint có thể quy về một tác nhân cụ thể.
  • Ràng buộc hệ thống tệp. Vì mỗi công cụ đọc một đường dẫn tuyệt đối từ ổ đĩa cục bộ, máy chủ có thể đọc bất kỳ tệp nào mà tiến trình máy chủ có quyền đọc. Hãy chạy máy chủ dưới một người dùng không có đặc quyền, giới hạn thư mục làm việc của nó vào một thư mục tài liệu, và đừng bao giờ chạy máy chủ dưới tài khoản có đặc quyền.
  • Ưu tiên Transport Layer Security (TLS). Trỏ NEXTPDF_BASE_URL tới endpoint https:// cho mọi triển khai không phải cục bộ. SDK gửi khóa dưới dạng token Bearer trong header Authorization, nên truyền tải dạng văn bản thuần sẽ làm lộ khóa trên đường truyền.

Xem Bảo mật và vận hành Connect để biết các biện pháp kiểm soát phía endpoint hỗ trợ cho những thực hành phía client này.

Kiểm thử máy chủ cục bộ trước khi kết nối một tác nhân

Phần tiêu đề “Kiểm thử máy chủ cục bộ trước khi kết nối một tác nhân”

Hãy xác thực máy chủ một cách độc lập trước khi kết nối tác nhân. Cách kiểm tra nhanh nhất không cần PDF và không cần mạng:

Terminal window
python -c "from nextpdf.mcp import _tool_definitions; print(len(_tool_definitions()))"

Một bản cài đúng sẽ in ra 8. Nếu bạn thấy ImportError nhắc đến extra mcp, nghĩa là gói phụ thuộc tùy chọn đang bị thiếu. Cài lại bằng pip install nextpdf[mcp].

Tiếp theo, hãy chạy qua CLI chính các đường dẫn SDK mà các công cụ sử dụng. CLI giao tiếp với endpoint của bạn bằng cùng hai biến môi trường đó. Đặt chúng một lần:

Terminal window
export NEXTPDF_BASE_URL="https://connect.example.com"
export NEXTPDF_API_KEY="$(cat /run/secrets/nextpdf_api_key)"

Sau đó xác nhận phiên bản, khả năng kết nối và một lần trích xuất thực tế:

Terminal window
nextpdf version
nextpdf info /path/to/sample.pdf
nextpdf extract text /path/to/sample.pdf --headings-only

nextpdf version chạy mà không cần thông tin xác thực và xác nhận gói đã được nạp thành công. nextpdf info chạy get_document_ast, chính là lệnh gọi đứng sau nextpdf_get_astnextpdf_info. Nếu cả hai đều thành công, thông tin xác thực và endpoint là chính xác, và các công cụ MCP tương ứng sẽ hoạt động.

Để vận hành trực tiếp giao thức MCP, hãy dùng MCP Inspector từ upstream (đi kèm gói mcp). Trỏ nó tới cùng lệnh và môi trường mà tác nhân của bạn sẽ dùng, rồi liệt kê và gọi thủ công các công cụ. Xác minh rằng nextpdf_health báo cáo status: "ok". Công cụ này trả về misconfigured mỗi khi NEXTPDF_BASE_URL hoặc NEXTPDF_API_KEY chưa được đặt; đây là cách nhanh nhất để phát hiện giá trị môi trường còn thiếu trước khi tác nhân gọi một công cụ thực sự.

Giám sát và gỡ lỗi các lệnh gọi công cụ

Phần tiêu đề “Giám sát và gỡ lỗi các lệnh gọi công cụ”

Máy chủ MCP giao tiếp qua input/output chuẩn (stdio), nên đầu ra chuẩn của nó mang luồng giao thức và phải luôn sạch. Máy chủ không tự cấu hình ghi nhật ký ứng dụng. Các kênh quan sát chính của bạn là payload lỗi công cụ có cấu trúc, CLI, và nhật ký của chính endpoint của bạn.

  • Các payload lỗi công cụ là tín hiệu. Mọi lệnh gọi thất bại đều trả về đối tượng JSON với error và, đối với lỗi SDK, error_typestatus_code (xem Xử lý lỗi). Hãy để máy chủ tác nhân ghi lại các payload này. Chúng xác định công cụ bị lỗi và nguyên nhân chính xác mà không cần thêm đo đạc trên máy chủ.
  • Tái hiện qua CLI với ghi nhật ký gỡ lỗi. Bản thân máy chủ MCP không phát ra nhật ký nào, nhưng CLI chạy chính các lệnh gọi SDK đó và có ghi nhật ký. Hãy tái hiện công cụ bị lỗi qua lệnh CLI tương ứng với --log-level debug. CLI ghi nhật ký ra stderr kèm dấu thời gian và ghi lại đầy đủ traceback cho lỗi không lường trước; đây là cách trực tiếp nhất để thấy một trình xử lý đang làm gì mà không cần gắn trình gỡ lỗi.
  • Sức khỏe như một phép thăm dò. Gọi nextpdf_health để xác nhận máy chủ nhìn thấy base URL và khóa API. Kết quả báo cáo sdk_version, server_url, api_key_configured (một giá trị boolean, không bao giờ là chính khóa đó), và status.
  • Khả năng quan sát ở phía endpoint. Vì mỗi công cụ ánh xạ tới một yêu cầu Connect, hãy đối chiếu hoạt động của công cụ với nhật ký truy cập endpoint theo khóa API và dấu thời gian. Hãy chạy endpoint phía sau cùng các biện pháp kiểm soát về xác thực, hạn mức và khả năng quan sát mà bạn dùng cho các client dịch vụ khác.

Khắc phục các sự cố tích hợp tác nhân thường gặp

Phần tiêu đề “Khắc phục các sự cố tích hợp tác nhân thường gặp”
Triệu chứngNguyên nhân có khả năngCách giải quyết
Máy chủ không khởi động được, kèm một ImportError về mcp extraGói phụ thuộc tùy chọn mcp chưa được càiCài bằng pip install nextpdf[mcp].
Lệnh gọi công cụ đầu tiên trả về {"error": "NEXTPDF_BASE_URL environment variable is required..."}Khối env của MCP không truyền base URL, hoặc shell không mở rộng ${NEXTPDF_BASE_URL}Đặt biến trong môi trường máy chủ tác nhân và xác nhận trình khởi chạy mở rộng được biến đó.
nextpdf_health báo cáo "status": "misconfigured"Một trong hai biến bắt buộc đang rỗngCung cấp cả NEXTPDF_BASE_URLNEXTPDF_API_KEY.
Mọi công cụ dựa trên đường dẫn đều trả về {"error": "PDF file not found: <path>"}Tác nhân đã truyền đường dẫn tương đối hoặc đường dẫn phía máy chủ mà tiến trình máy chủ không nhìn thấy đượcTruyền một đường dẫn tuyệt đối mà người dùng của máy chủ có thể đọc; xác nhận bằng nextpdf info <path>.
Công cụ trả về error_typeNextPDFLicenseError (trạng thái 402)Thao tác cần một bậc giấy phép phía máy chủ cao hơnDùng một endpoint và khóa được phép thực hiện thao tác đó.
Công cụ trả về error_typeAstNoStructTreeError (trạng thái 422)PDF chưa được gắn thẻ và phương án dự phòng heuristic đang tắtBật chế độ heuristic trên endpoint, hoặc gắn thẻ PDF trước.
Công cụ trả về error_typeQuotaExceededError (trạng thái 429)Đã chạm tới giới hạn tốc độ hoặc hạn mứcTạm dừng và thử lại; nâng hạn mức endpoint nếu giới hạn quá thấp.
Công cụ trả về error_typeAstBuildTimeoutError (trạng thái 504), hoặc một lần hết thời gian chờ truyền tảiTài liệu quá lớn so với ngân sách thời gianThu hẹp phạm vi với max_pages, page_index, hoặc page_start/page_end.
Tác nhân không đăng ký công cụ NextPDF nàoTác nhân đã gọi python -m nextpdf (CLI) thay vì python -m nextpdf.mcpDùng python -m nextpdf.mcp làm command/args.

Đối với lỗi ở cấp endpoint và kiểm tra triển khai, xem Khắc phục sự cố Connect. Đối với các thao tác SDK mà những công cụ này bao bọc, xem tài liệu tham khảo CLItổng quan SDK.