Python MCP 서버
Python MCP 서버
섹션 제목: “Python MCP 서버”NextPDF Python SDK는 PDF 추출 작업을 네이티브 에이전트 도구로 노출하는 Model Context Protocol(MCP) 서버를 제공합니다. MCP를 지원하는 에이전트(예: Claude Code)는 서버를 한 번 등록한 뒤, 다른 도구를 호출할 때와 같은 방식으로 NextPDF 도구를 호출합니다.
이 서버는 가벼운 어댑터 역할을 합니다. 각 도구는 로컬 디스크에서 PDF를 읽고, NextPDF Connect 엔드포인트에 비동기 클라이언트를 호출한 다음, 결과를 JSON 문자열로 반환합니다. 서버 자체에는 비즈니스 로직이 없으며 호출 사이에 어떤 데이터도 저장하지 않습니다.
MCP extra와 함께 SDK를 설치하십시오:
pip install nextpdf[mcp]이 mcp extra는 업스트림 mcp 패키지를 추가합니다(제약 조건 mcp>=1.0,<2.0). 이 서버에는 Python 3.10 이상이 필요합니다.
MCP 클라이언트 구성에서 서버 모듈을 실행하십시오. 아래 예제는 구성 파일에 비밀 값을 넣지 않고 호스트 환경에서 두 연결 값을 모두 읽습니다(보안 참조):
{ "mcpServers": { "nextpdf": { "command": "python", "args": ["-m", "nextpdf.mcp"], "env": { "NEXTPDF_BASE_URL": "https://connect.example.com", "NEXTPDF_API_KEY": "${NEXTPDF_API_KEY}" } } }}이 python -m nextpdf.mcp 진입점은 main()을 실행하며, asyncio.run(serve())를 통해 표준 입출력(stdio)으로 서버를 시작합니다. 이를 python -m nextpdf와 혼동하지 마십시오. python -m nextpdf는 MCP 서버가 아니라 명령줄 인터페이스(CLI)를 실행합니다.
NEXTPDF_BASE_URL과 NEXTPDF_API_KEY는 둘 다 필수입니다. 서버는 첫 번째 도구 호출 시 클라이언트를 지연 생성합니다. 두 변수 중 하나라도 비어 있으면 RuntimeError를 발생시키며, 프로세스를 중단시키는 대신 도구 오류로 에이전트에 반환됩니다.
도구 카탈로그 및 SDK 매핑
섹션 제목: “도구 카탈로그 및 SDK 매핑”서버는 여덟 개의 도구를 등록합니다. 모든 도구 이름에는 nextpdf_ 접두사가 붙습니다. 각 도구는 비동기 클라이언트의 ast 네임스페이스(AsyncNextPDF.ast)에 있는 메서드에 매핑됩니다. 다만 아래에 언급된 두 개의 복합 도구는 예외이며, 이들은 하위 수준 호출을 서버 내부에서 조합해 만듭니다.
| MCP 도구 | SDK 호출 | 참고 |
|---|---|---|
nextpdf_extract_text | ast.extract_cited_text(pdf_data, page_index=..., headings_only=...) | 이 도구는 CitedTextBlock 목록을 반환합니다. |
nextpdf_extract_tables | ast.extract_cited_tables(pdf_data, page_range=...) | 이 도구는 ExtractCitedTablesResponse를 반환합니다. |
nextpdf_get_ast | ast.get_document_ast(pdf_data, page_range_start=0, page_range_end=..., token_budget=...) | 이 도구는 AstDocument를 반환합니다. |
nextpdf_info | ast.get_document_ast(pdf_data) | 서버가 메타데이터 요약으로 변환해 제공합니다. 전용 엔드포인트는 없습니다. |
nextpdf_health | 없음 | 환경 변수만 검사하며, 네트워크 호출은 수행하지 않습니다. |
nextpdf_search | ast.search_ast_nodes(pdf_data, node_type=..., page_index=..., text_query=..., max_results=...) | 이 도구는 SearchAstNodesResponse를 반환합니다. |
nextpdf_get_outline | ast.search_ast_nodes(pdf_data, node_type="heading", max_results=500) | 서버가 제목 노드를 개요로 재구성합니다. |
nextpdf_diff | ast.get_ast_diff(original_pdf_data, modified_pdf_data) | 이 도구는 GetAstDiffResponse를 반환합니다. |
에이전트를 연결하기 전에 알아 둘 도구 입력 관련 참고 사항은 다음과 같습니다:
- 모든 경로 입력(
pdf_path,original_pdf_path,modified_pdf_path)은 서버를 실행하는 머신에 있는 파일의 절대 경로입니다. 에이전트가 경로를 전달하면 서버가 로컬에서 바이트를 읽습니다. 업로드 도구는 없습니다. nextpdf_extract_text는 입력 스키마에max_pages필드를 선언하지만, 텍스트 핸들러는 이를 SDK로 전달하지 않습니다. 텍스트의 페이지 범위 지정은page_index(0부터 시작하는 단일 페이지)로 이루어집니다. 문서 전체 순회를 제한해야 할 때는nextpdf_get_ast를max_pages와 함께 사용하십시오.nextpdf_get_ast는max_pages를[0, max_pages - 1]의 양끝을 포함하는 페이지 범위로 변환합니다(기본값max_pages는 50). 반환되는 트리의 크기를 제한하려면token_budget을 전달하십시오.nextpdf_info는schema_version,source_hash,page_count,estimated_tokens,root_node_type및root_children_count를 반환합니다. 이들은AstDocument모델에서 가져오며, 여기서estimated_tokens는 계산된 속성입니다(토큰당 대략 4자).nextpdf_get_outline는 각 제목에 대해id,page_index,text및depth(노드의attributes["level"]에서 읽으며, 기본값은 1)를 포함하는 항목 하나를 반환하고, 여기에 더해heading_count,total_matches및truncated를 반환합니다.
인용 추출 도구는 모든 결과에 CitationAnchor를 첨부합니다. 각 앵커는 node_id, page_index, 정규화된 bbox(0.0에서 1.0 범위의 좌표) 및 confidence 점수(0.0에서 1.0)를 포함합니다. 출처가 필요한 에이전트는 원시 텍스트뿐 아니라 이러한 필드도 노출해야 합니다.
오류 처리, 타임아웃 및 할당량
섹션 제목: “오류 처리, 타임아웃 및 할당량”서버는 예외가 에이전트 전송 계층으로 전파되도록 절대 허용하지 않습니다. call_tool 디스패처는 모든 오류를 포착해 JSON TextContent로 반환하므로, 실패한 도구 호출은 연결 끊김이 아니라 에이전트가 읽을 수 있는 구조화된 페이로드를 생성합니다. 페이로드 형식은 다음과 같습니다:
| 조건 | 반환되는 JSON |
|---|---|
| 알 수 없는 도구 이름 | {"error": "Unknown tool: <name>"} |
| 누락된 입력 파일 | {"error": "PDF file not found: <path>"} |
모든 NextPDFError 하위 클래스 | {"error": "<message>", "error_type": "<class>", "status_code": <int?>} |
| 기타 모든 예외 | {"error": "Unexpected error: <message>"} |
status_code는 기반 오류가 이를 포함할 때만 포함됩니다. SDK는 HTTP 응답을 NextPDFError를 루트로 하는 타입화된 예외 계층 구조에 매핑합니다:
| 예외 | HTTP 상태 | error_code | 상황 |
|---|---|---|---|
NextPDFLicenseError | 402 | license/tier-required | 엔드포인트가 해당 작업에 대해 더 높은 서버 측 라이선스 등급을 요구합니다. |
AstNoStructTreeError | 422 | ast/no-struct-tree | PDF 에 태그가 없고 서버에서 휴리스틱 폴백이 활성화되어 있지 않습니다. |
QuotaExceededError | 429 | quota/exceeded | 속도 제한 또는 할당량에 도달했습니다. retry_after(초)를 포함하며, 서버가 Retry-After 헤더를 보낼 때 제공됩니다. |
AstBuildTimeoutError | 504 | ast/build-timeout | AST 빌드가 서버의 시간 예산을 초과했습니다. 페이지 범위를 줄이십시오. |
NextPDFAPIError | 기타 4xx/5xx | 서버 제공 | 기타 모든 API 수준 실패. |
에이전트 통합을 위한 실용적 지침:
- 타임아웃. HTTP 클라이언트는 고정된 기본 타임아웃을 사용합니다. 총 60초, 연결 타임아웃 10초입니다. 느리거나 큰 문서는
AstBuildTimeoutError(서버가 AST 빌드를 포기함)로 나타나거나, 클라이언트 자체가 타임아웃되는 경우 전송 계층에서Unexpected error페이로드로 나타납니다.ast/build-timeout가 보이면 에이전트에 범위를 좁히도록 지시하십시오:nextpdf_get_ast에서max_pages를 낮추거나, 추출 도구에page_index/page_start와page_end를 설정하십시오. - 할당량 및 백오프. 429에서 도구는
error_type으로QuotaExceededError를,status_code로 429를 반환합니다. 예외 객체에는retry_after값이 있습니다. 서버는error,error_type및status_code만 직렬화하므로, 에이전트는 도구 출력에서 재시도 헤더를 파싱하기보다는 429를 잠시 멈췄다가 나중에 재시도하라는 신호로 취급해야 합니다. 할당량은 에이전트가 아니라 Connect 엔드포인트에서 시행하십시오. - 태그 없는 PDF. 422
ast/no-struct-tree는 원본 PDF에 구조 트리가 없음을 의미합니다. 해당 문서에 대해 서버에서 휴리스틱 모드를 활성화하거나, 추출 전에 태그 지정 단계로 라우팅하십시오.
보안: API 키 범위 지정 및 최소 권한
섹션 제목: “보안: API 키 범위 지정 및 최소 권한”API 키는 데이터베이스 비밀번호와 동일한 수준의 주의를 기울여 비밀로 취급하십시오.
- MCP 구성 파일에 키를 절대 포함하지 마십시오. 위의 JSON 예제는
${NEXTPDF_API_KEY}를 참조하므로 값은 시작 시점에 호스트 환경 또는 비밀 관리자에서 확인됩니다. 구성 파일은 소스 제어에 커밋될 수 있지만, 비밀은 그렇게 해서는 안 됩니다. - 키 범위를 읽기 전용 추출로 한정하십시오. MCP 서버는 AST 추출 영역(
extract_cited_text,extract_cited_tables,get_document_ast,search_ast_nodes,get_ast_diff)만 호출합니다. 렌더링, 서명, 편집(redaction), 문서 변경은 수행하지 않습니다. 서버 측 범위가 해당 읽기 경로로 제한된 키를 에이전트에 발급하여, 침해된 에이전트가 쓰기 또는 더 높은 등급의 작업에 도달할 수 없도록 하십시오. - 에이전트별 전용 키를 사용하십시오. 에이전트별 키를 사용하면 다른 통합에 영향을 주지 않고 한 통합을 폐기하거나 교체할 수 있으며, 엔드포인트 로그를 특정 에이전트에 귀속시킬 수 있습니다.
- 파일 시스템을 제한하십시오. 모든 도구가 로컬 디스크에서 절대 경로를 읽으므로, 서버는 호스트 프로세스가 읽을 수 있는 모든 파일을 읽을 수 있습니다. 권한이 낮은 사용자로 실행하고, 작업 디렉터리를 문서 폴더로 제한하며, 고권한 계정으로 절대 실행하지 마십시오.
- 전송 계층 보안(TLS)을 선호하십시오. 로컬이 아닌 모든 배포에서
NEXTPDF_BASE_URL을https://엔드포인트로 지정하십시오. SDK는 키를Bearer토큰으로Authorization헤더에 담아 보내므로, 평문 전송은 키를 통신 경로에 노출시킵니다.
이러한 클라이언트 측 실무 지침을 뒷받침하는 엔드포인트 측 제어에 대해서는 Connect 보안 및 운영을 참조하십시오.
에이전트를 연결하기 전에 로컬에서 서버 테스트하기
섹션 제목: “에이전트를 연결하기 전에 로컬에서 서버 테스트하기”에이전트를 연결하기 전에 서버를 독립적으로 검증하십시오. 가장 빠른 점검에는 PDF도 네트워크도 필요하지 않습니다:
python -c "from nextpdf.mcp import _tool_definitions; print(len(_tool_definitions()))"올바르게 설치되었다면 8을 출력합니다. ImportError가 mcp extra를 언급하며 나타나면, 선택적 의존성이 누락된 것입니다. pip install nextpdf[mcp]로 다시 설치하십시오.
다음으로, 도구가 사용하는 것과 동일한 SDK 경로를 CLI를 통해 실행하십시오. CLI는 동일한 두 환경 변수로 엔드포인트와 통신합니다. 한 번 설정하십시오:
export NEXTPDF_BASE_URL="https://connect.example.com"export NEXTPDF_API_KEY="$(cat /run/secrets/nextpdf_api_key)"그런 다음 버전, 연결성 및 실제 추출을 확인하십시오:
nextpdf versionnextpdf info /path/to/sample.pdfnextpdf extract text /path/to/sample.pdf --headings-onlynextpdf version은 자격 증명 없이 실행되며 패키지 가져오기를 확인합니다. nextpdf info는 get_document_ast를 실행하며, 이는 nextpdf_get_ast와 nextpdf_info 뒤에 있는 동일한 호출입니다. 후자의 두 명령이 모두 성공하면 자격 증명과 엔드포인트가 올바르며 해당 MCP 도구가 작동합니다.
MCP 프로토콜을 직접 구동하려면 업스트림 MCP Inspector(mcp 패키지에 포함됨)를 사용하십시오. 에이전트가 사용할 것과 동일한 명령 및 환경을 가리키도록 설정한 다음, 도구를 수동으로 나열하고 호출하십시오. nextpdf_health가 status: "ok"를 보고하는지 확인하십시오. misconfigured를 반환하는 경우는 NEXTPDF_BASE_URL 또는 NEXTPDF_API_KEY가 설정되지 않았다는 뜻이며, 이는 에이전트가 실제 도구를 호출하기 전에 누락된 환경 값을 잡아내는 가장 빠른 방법입니다.
도구 호출 모니터링 및 디버깅
섹션 제목: “도구 호출 모니터링 및 디버깅”MCP 서버는 stdio를 통해 통신하므로, 표준 출력은 프로토콜 스트림을 전달하며 깨끗하게 유지되어야 합니다. 서버는 자체 애플리케이션 로깅을 구성하지 않으므로, 주요 관측 가능성 채널은 구조화된 도구 오류 페이로드, CLI 및 엔드포인트 자체의 로그입니다.
- 도구 오류 페이로드가 신호입니다. 모든 실패한 호출은
error를, SDK 오류의 경우error_type과status_code를 포함하는 JSON 객체를 반환합니다(오류 처리 참조). 에이전트 호스트가 이러한 페이로드를 기록하게 하십시오. 이 페이로드는 서버에 추가 계측을 하지 않고도 실패한 도구와 정확한 원인을 식별할 수 있게 합니다. - 디버그 로깅과 함께 CLI를 통해 재현하십시오. MCP 서버 자체는 로그를 내보내지 않지만, CLI는 동일한 SDK 호출을 실행하며 로그를 남깁니다. 실패한 도구를 해당 CLI 명령으로
--log-level debug와 함께 재현하십시오. CLI는 타임스탬프와 함께 stderr에 로그를 남기고 예기치 않은 오류에 대해 전체 트레이스백을 기록하므로, 디버거를 연결하지 않고도 핸들러가 무엇을 하고 있는지 확인하는 가장 직접적인 방법입니다. - 프로브로 사용하는 상태 점검. 서버가 기본 URL과 API 키를 인식하는지 확인하려면
nextpdf_health를 호출하십시오. 결과는sdk_version,server_url,api_key_configured(불리언이며, 키 자체는 절대 아님) 및status를 보고합니다. - 엔드포인트 측 관측 가능성. 각 도구가 하나의 Connect 요청에 매핑되므로, 도구 활동을 API 키와 타임스탬프로 엔드포인트 액세스 로그와 상관시키십시오. 다른 서비스 클라이언트에 사용하는 것과 동일한 인증, 할당량, 관측 가능성 제어 뒤에서 엔드포인트를 실행하십시오.
흔한 에이전트 통합 문제 해결
섹션 제목: “흔한 에이전트 통합 문제 해결”| 증상 | 유력한 원인 | 해결책 |
|---|---|---|
서버가 ImportError와 함께 시작에 실패하고, 오류가 mcp extra에 관한 것임 | 이 mcp 선택적 의존성이 설치되지 않음 | 다음을 실행해 설치하십시오: pip install nextpdf[mcp]. |
첫 번째 도구 호출이 다음 응답을 반환함: {"error": "NEXTPDF_BASE_URL environment variable is required..."} | MCP env 블록이 기본 URL을 전달하지 않았거나, 셸이 ${NEXTPDF_BASE_URL}을 확장하지 않음 | 에이전트 호스트 환경에서 변수를 설정하고 런처가 이를 확장하는지 확인하십시오. |
nextpdf_health가 "status": "misconfigured"를 보고함 | 두 필수 변수 중 하나가 비어 있음 | NEXTPDF_BASE_URL과 NEXTPDF_API_KEY를 모두 제공하십시오. |
모든 경로 기반 도구가 다음 응답을 반환함: {"error": "PDF file not found: <path>"} | 에이전트가 서버 프로세스가 볼 수 없는 상대 경로 또는 호스트 측 경로를 전달함 | 서버 사용자가 읽을 수 있는 절대 경로를 전달하고, nextpdf info <path>로 확인하십시오. |
도구가 error_typeNextPDFLicenseError(상태 402)를 반환함 | 작업에 더 높은 서버 측 라이선스 등급이 필요함 | 작업 권한이 있는 엔드포인트와 키를 사용하십시오. |
도구가 error_typeAstNoStructTreeError(상태 422)를 반환함 | PDF에 태그가 없고 휴리스틱 폴백이 꺼져 있음 | 엔드포인트에서 휴리스틱 모드를 활성화하거나, 먼저 PDF에 태그를 지정하십시오. |
도구가 error_typeQuotaExceededError(상태 429)를 반환함 | 속도 제한 또는 할당량에 도달함 | 잠시 멈췄다가 재시도하십시오. 제한이 너무 낮으면 엔드포인트 할당량을 높이십시오. |
도구가 error_typeAstBuildTimeoutError(상태 504) 또는 전송 타임아웃을 반환함 | 문서가 시간 예산에 비해 너무 큼 | max_pages, page_index 또는 page_start/page_end를 사용해 범위를 좁히십시오. |
| 에이전트가 NextPDF 도구를 전혀 등록하지 않음 | 에이전트가 python -m nextpdf(CLI)를 호출하고, python -m nextpdf.mcp를 사용하지 않음 | python -m nextpdf.mcp를 command/args로 사용하십시오. |
엔드포인트 수준 실패 및 배포 점검에 대해서는 Connect 문제 해결을 참조하십시오. 이러한 도구가 래핑하는 기반 SDK 작업에 대해서는 CLI 참조와 SDK 개요를 참조하십시오.