コンテンツにスキップ

Python MCP サーバー

NextPDF Python SDK には、PDF 抽出操作をエージェントのネイティブツールとして公開する Model Context Protocol(MCP)サーバーが付属しています。MCP 対応のエージェント(たとえば Claude Code)は、このサーバーを一度登録すれば、以後は他のツールと同じ方法で NextPDF ツールを呼び出せます。

このサーバーは軽量なアダプターです。各ツールはローカルディスクから PDF を読み込み、NextPDF Connect エンドポイントに非同期クライアントで問い合わせ、結果を JSON 文字列として返します。サーバー自体にビジネスロジックはなく、呼び出し間でデータを保存しません。

MCP エクストラ付きで SDK をインストールします。

Terminal window
pip install nextpdf[mcp]

インストールされる mcp エクストラは、アップストリームの mcp パッケージ(制約 mcp>=1.0,<2.0)を追加します。サーバーには Python 3.10 以降が必要です。

MCP クライアントの構成からサーバーモジュールを実行します。次の例では、構成ファイルにシークレットを埋め込まず、2 つの接続値をどちらもホスト環境から読み込みます(セキュリティを参照)。

{
"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 と混同しないでください。こちらは MCP サーバーではなく、コマンドラインインターフェイス(CLI)を実行します。

NEXTPDF_BASE_URLNEXTPDF_API_KEY はどちらも必須です。サーバーは最初のツール呼び出し時にクライアントを遅延初期化します。いずれかの変数が空の場合は RuntimeError を送出し、プロセスをクラッシュさせるのではなく、ツールエラーとしてエージェントへ返します。

サーバーは 8 個のツールを登録します。すべてのツール名には nextpdf_ プレフィックスが付きます。各ツールは非同期クライアントの ast 名前空間(AsyncNextPDF.ast)のメソッドにマップされます。ただし、下に示す 2 つの複合ツールは例外で、下位レベルの呼び出しをサーバー内部で組み立てます。

MCP ツールSDK 呼び出し備考
nextpdf_extract_textast.extract_cited_text(pdf_data, page_index=..., headings_only=...)返却値は CitedTextBlock のリスト。
nextpdf_extract_tablesast.extract_cited_tables(pdf_data, page_range=...)応答は ExtractCitedTablesResponse
nextpdf_get_astast.get_document_ast(pdf_data, page_range_start=0, page_range_end=..., token_budget=...)応答は AstDocument
nextpdf_infoast.get_document_ast(pdf_data)サーバー側で組み立てるメタデータ要約。専用エンドポイントなし。
nextpdf_healthなし環境変数のみの検査。ネットワーク呼び出しなし。
nextpdf_searchast.search_ast_nodes(pdf_data, node_type=..., page_index=..., text_query=..., max_results=...)応答は SearchAstNodesResponse
nextpdf_get_outlineast.search_ast_nodes(pdf_data, node_type="heading", max_results=500)サーバー側で見出しノードをアウトライン化。
nextpdf_diffast.get_ast_diff(original_pdf_data, modified_pdf_data)応答は GetAstDiffResponse

エージェントを接続する前に、ツール入力について次の点を把握しておいてください。

  • すべてのパス入力(pdf_pathoriginal_pdf_pathmodified_pdf_path)は、サーバーを実行しているマシン上のファイルへの絶対パスです。エージェントはパスを渡し、サーバーは該当ファイルのバイト列をローカルで読み込みます。アップロード用のツールはありません。
  • nextpdf_extract_text は入力スキーマで max_pages フィールドを宣言しますが、テキストハンドラーはこれを SDK に渡しません。テキスト抽出の対象ページは page_index(0 始まりの単一ページ)で指定します。ドキュメント全体の走査を制限する必要がある場合は、max_pages を指定して nextpdf_get_ast を使用してください。
  • nextpdf_get_astmax_pages を、両端を含むページ範囲 [0, max_pages - 1] に変換します(max_pages の既定値は 50 です)。返されるツリーのサイズを制限するには token_budget を渡します。
  • nextpdf_infoschema_versionsource_hashpage_countestimated_tokensroot_node_type、および root_children_count を返します。これらは AstDocument モデルに由来し、estimated_tokens は計算済みプロパティです(トークンあたりおおよそ 4 文字)。
  • nextpdf_get_outline は見出しごとに 1 エントリを返し、各エントリには idpage_indextext、および depth(ノードの attributes["level"] から読み取られ、既定値は 1)が含まれます。さらに heading_counttotal_matches、および truncated も返します。

引用抽出ツールは、すべての結果に CitationAnchor を付加します。各アンカーは node_idpage_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発生条件
NextPDFLicenseError402license/tier-requiredエンドポイントで、より高いサーバー側ライセンスティアが必要な操作。
AstNoStructTreeError422ast/no-struct-treeタグのない PDF で、サーバー側のヒューリスティックフォールバックが無効。
QuotaExceededError429quota/exceededレート制限またはクォータ到達。サーバーが Retry-After ヘッダーを送信した場合のみ、retry_after(秒)を保持。
AstBuildTimeoutError504ast/build-timeoutAST 構築がサーバーの時間予算を超過。ページ範囲の縮小が必要。
NextPDFAPIErrorその他の 4xx/5xxサーバー提供その他の API レベルの障害。

エージェント連携での実践的なガイダンスを示します。

  • タイムアウト。 HTTP クライアントは固定の既定タイムアウト(合計 60 秒、接続タイムアウト 10 秒)を使用します。低速または大容量のドキュメントでは、AstBuildTimeoutError(サーバーが AST の構築を断念した場合)として現れることがあります。クライアント自体がタイムアウトした場合は、トランスポート層からの Unexpected error ペイロードとして現れます。ast/build-timeout が表示された場合は、エージェントにスコープを絞るよう指示してください。max_pagesnextpdf_get_ast で下げるか、抽出ツールで page_index / page_startpage_end を設定します。
  • クォータとバックオフ。 429 が発生すると、ツールは error_type として QuotaExceededError を、status_code として 429 を返します。retry_after の値は例外オブジェクト上に存在します。サーバーは errorerror_type、および status_code のみをシリアライズするため、エージェントはツール出力から再試行ヘッダーを解析しようとせず、429 を一時停止して後で再試行するシグナルとして扱うべきです。クォータはエージェントではなく、Connect エンドポイントで適用してください。
  • タグなし PDF。 422 ast/no-struct-tree は、ソース PDF に構造ツリーがないことを意味します。このようなドキュメントでは、サーバーでヒューリスティックモードを有効にするか、抽出前にタグ付けステップへ回してください。

API キーは、データベースパスワードと同じ注意が必要なシークレットとして扱ってください。

  • MCP 構成ファイルにキーを絶対に埋め込まないでください。 上記の JSON 例は ${NEXTPDF_API_KEY} を参照しており、値は起動時にホスト環境またはシークレットマネージャーから resolve(解決)されます。構成ファイルはソース管理にコミットされても、シークレットはコミットされてはなりません。
  • キーを読み取り専用の抽出にスコープ設定してください。 MCP サーバーは AST 抽出のサーフェス(extract_cited_textextract_cited_tablesget_document_astsearch_ast_nodesget_ast_diff)のみを呼び出します。レンダリング、署名、墨消し、ドキュメントの変更は一切行いません。エージェントには、サーバー側スコープがこれらの読み取りパスに限定されたキーを発行してください。そうすれば、侵害されたエージェントが書き込みや上位ティアの操作へアクセスできなくなります。
  • エージェントごとに専用のキーを使用してください。 エージェントごとのキーを使うと、他の連携に影響を与えずに 1 つの連携だけを失効またはローテーションでき、エンドポイントのログを特定のエージェントに帰属させられます。
  • ファイルシステムを制約してください。 すべてのツールはローカルディスクから絶対パスを読み込むため、サーバーはホストプロセスが読み取れる任意のファイルを読み取れます。非特権ユーザーとして実行し、作業ディレクトリをドキュメントフォルダーに制限し、特権アカウントでは決して実行しないでください。
  • Transport Layer Security(TLS)を優先してください。 ローカル以外のデプロイでは、NEXTPDF_BASE_URLhttps:// エンドポイントに向けてください。SDK はキーを Bearer トークンとして Authorization ヘッダーで送信するため、平文トランスポートでは通信経路上でキーが露出します。

これらのクライアント側プラクティスを支えるエンドポイント側の制御については、Connect のセキュリティと運用を参照してください。

エージェントを接続する前に、サーバー単体で検証してください。最も速いチェックには PDF もネットワークも不要です。

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

正しくインストールされていれば 8 が出力されます。ImportError が表示され、mcp エクストラに言及している場合は、オプション依存関係が不足しています。pip install nextpdf[mcp] で再インストールしてください。

次に、ツールが使用するものと同じ SDK パスを CLI 経由で実行します。CLI は同じ 2 つの環境変数を使ってエンドポイントと通信します。これらを一度設定します。

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

次に、バージョン、接続性、実際の抽出を確認します。

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

nextpdf version は資格情報なしで実行でき、パッケージをインポートできることを確認します。nextpdf infoget_document_ast を実行します。これは nextpdf_get_astnextpdf_info の背後にある呼び出しと同じです。両方が成功すれば、資格情報とエンドポイントは正しく、対応する MCP ツールも動作します。

MCP プロトコルを直接操作するには、アップストリームの MCP Inspector(mcp パッケージに同梱)を使用します。エージェントが使用するのと同じコマンドと環境に向けて、ツールを手動で一覧表示し、呼び出します。nextpdf_healthstatus: "ok" を報告することを確認してください。misconfigured を返すのは、NEXTPDF_BASE_URL または NEXTPDF_API_KEY が未設定のときで、これはエージェントが実際のツールを呼び出す前に環境値の不足を捉える最も手早い方法です。

MCP サーバーは stdio 上で通信するため、その標準出力はプロトコルストリームを運び、クリーンに保つ必要があります。サーバーは独自のアプリケーションロギングを構成しません。つまり、主要な可観測性チャネルは、構造化されたツールエラーペイロード、CLI、エンドポイント自身のログです。

  • ツールエラーペイロードがシグナルです。 失敗した呼び出しはすべて、error を含み、SDK エラーの場合は error_typestatus_code も含む JSON オブジェクトを返します(エラー処理を参照)。エージェントホストにこれらのペイロードを記録させてください。サーバーに追加の計装を行わなくても、失敗しているツールと正確な原因を特定できます。
  • デバッグロギングを有効にし、CLI で再現してください。 MCP サーバー自体はログを出力しませんが、CLI は同じ SDK 呼び出しを実行し、ログを出力します。失敗するツールを、対応する CLI コマンドで --log-level debug を付けて再現してください。CLI はタイムスタンプ付きで stderr にログを出力し、予期しないエラーについては完全なトレースバックを記録します。これは、デバッガーをアタッチせずにハンドラーの動作を確認する最も直接的な方法です。
  • プローブとしてのヘルス。 nextpdf_health を呼び出して、サーバーがベース URL と API キーを認識していることを確認します。結果は sdk_versionserver_urlapi_key_configured(ブール値であり、キー自体ではありません)、および status を報告します。
  • エンドポイント側の可観測性。 各ツールは 1 つの Connect リクエストにマップされるため、API キーとタイムスタンプを使って、ツールのアクティビティをエンドポイントのアクセスログと関連付けます。他のサービスクライアントで使っているのと同じ認証、クォータ、可観測性の制御下でエンドポイントを実行してください。
症状考えられる原因解決策
サーバーが ImportError で起動に失敗し、mcp エクストラに言及オプション依存関係の mcp が未インストールpip install nextpdf[mcp] の実行。
最初のツール呼び出しの返却値:{"error": "NEXTPDF_BASE_URL environment variable is required..."}MCP の env ブロックがベース URL を渡していない、またはシェルによる ${NEXTPDF_BASE_URL} の未展開エージェントホスト環境での変数設定と、ランチャーによる展開の確認。
nextpdf_health"status": "misconfigured" を報告2 つの必須変数のいずれかが空NEXTPDF_BASE_URLNEXTPDF_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_pagespage_index、または page_start/page_end によるスコープ縮小。
エージェントが NextPDF ツールを 1 つも登録しないエージェントが python -m nextpdf(CLI)を起動しており、本来必要なのは python -m nextpdf.mcppython -m nextpdf.mcpcommand/args として使用。

エンドポイントレベルの障害とデプロイのチェックについては、Connect のトラブルシューティングを参照してください。これらのツールがラップする基盤の SDK 操作については、CLI リファレンスSDK の概要を参照してください。