mcpField
D
Document Understanding MCP Server

Document Understanding MCP Server

ローカル
github.com/jaesharp生産性279 週間前に更新

Document Understanding MCP Server について

Document Understanding MCP Serverは、AIモデルがローカルPDFを読み取り、調べるためのツールを提供します。テキスト、メタデータ、レイアウト、表、画像の抽出に加え、テキスト検索と言語検出に対応し、現在はアルファ版でローカル開発とテスト向けです。

主な機能

  1. 01OCRフォールバック付きPDFテキスト抽出
  2. 02メタデータとレイアウトの抽出
  3. 03表と画像の抽出
  4. 04ページ位置付きの完全一致検索
  5. 05言語検出

活用シーン

  1. 01スキャンPDFからテキストを抽出
  2. 02語句と掲載ページを検索
  3. 03表、画像、ページレイアウトを確認

MCP 対応

MCPを実装し、抽出、検索、言語検出などのPDF処理ツールをMCPクライアントに提供します。利用可能なツールは、JavaやTesseractの検出状況と起動フラグによって異なる場合があります。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

インストール方法は未掲載です

このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。

リポジトリ

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

ドキュメント理解 MCP サーバー

⚠️ 警告:このサーバーは現在アルファ段階であり、ローカルでの開発およびテストのみを目的としています。本番環境にデプロイしたり、信頼できないネットワークに公開したりしないでください。このサーバーを実行する前に、重要なセキュリティ上の考慮事項について SECURITY.md を確認してください。

ドキュメント(主に PDF)からテキスト、メタデータ、レイアウトを抽出し、検索するツールを提供する MCP サーバーです。このサーバーは Model Context Protocol(MCP)仕様を実装しており、AI モデルが標準化されたインターフェースを通じて PDF ドキュメントを操作できます。

概要

Document Understanding MCP Server は、PDF ドキュメントから情報を抽出するための一連のツールを提供します。以下の機能が含まれます。

  • テキストコンテンツの抽出(スキャンされたドキュメントでは OCR によるフォールバックあり)
  • メタデータの抽出(作成者、タイトル、作成日など)
  • レイアウト情報の抽出(テキストブロック、画像、描画)
  • 表の抽出
  • 画像の抽出
  • ドキュメントのアウトライン/ブックマークの抽出
  • テキスト検索機能
  • 言語の検出

これらのツールを使うと、AI モデルが PDF ドキュメントを分析して理解できるため、より高度なドキュメント処理ワークフローを実現できます。

今後の予定:PDF 以外の複数のドキュメント形式への対応拡大に取り組んでいます。今後予定されているアーキテクチャの変更については、docs/plans/README.md を参照してください。

セットアップとインストール

  1. リポジトリをクローンします:
    git clone <repo-url>
    cd document-understanding-mcp-server
    
  2. Python をインストールします: Python 3.11+ がインストールされていることを確認してください。
  3. uv をインストールします: 環境管理には uv の使用をおすすめします。
    pip install uv
    
  4. 仮想環境を作成して同期します:
    uv venv # Create .venv
    # Install core dependencies
    uv pip sync pyproject.toml
    # For development/testing, install optional extras:
    uv pip install -e '.[dev,test]'
    
  5. (表の抽出に必須)Java をインストールします: extract_tables ツールは tabula-py に依存しており、実行には Java Runtime Environment(JRE)が必要です。お使いのシステムに適した JRE(OpenJDK など)をインストールし、java がシステムの PATH から利用できることを確認してください。
  6. (OCR フォールバックに必須)Tesseract をインストールします: extract_pdf_contents の OCR フォールバックは pytesseract に依存しており、Tesseract OCR エンジン本体が必要です。お使いの OS 用の Tesseract をインストールし(Tesseract のインストールを参照)、tesseract コマンドがシステムの PATH にあることを確認してください。
  7. ベースパスを設定します(上書きしない限り必須): DOCUMENT_UNDERSTANDING_BASE_PATH 環境変数を定義します。デフォルトでは、サーバーが PDF を読み取るのはこのディレクトリのみです。例:
    export DOCUMENT_UNDERSTANDING_BASE_PATH=/path/to/your/pdf_working_directory
    

設定

  • DOCUMENT_UNDERSTANDING_BASE_PATH(環境変数、必須):* サーバーが PDF の読み取りのためにアクセスできるディレクトリの絶対パスを指定します。--allow-any-path を使用しない限り、これが設定されていない場合、サーバーは起動を拒否します。
  • DOCUMENT_UNDERSTANDING_LOG_LEVEL(環境変数): コンソール出力の最小ログレベル(例:DEBUG、INFO、WARNING)を設定します。デフォルトはINFOです。
  • DOCUMENT_UNDERSTANDING_LOG_FORMAT(環境変数): コンソールログの形式(plain または json)を設定します。デフォルトはplainです。
  • DOCUMENT_UNDERSTANDING_LOG_FILE(環境変数): 設定すると、構造化された JSON ログの書き込み先パス(例:.tmp/logs/server.log)を指定します。ディレクトリは作成されます。デフォルトでは無効です。
  • DOCUMENT_UNDERSTANDING_LOG_FILE_LEVEL(環境変数): ファイルログの最小レベル(例:DEBUG、INFO)を設定します。デフォルトはINFOです。
  • DOCUMENT_UNDERSTANDING_DEFAULT_LANG(環境変数): デフォルトの OCR 言語(例:eng、fra)を設定します。設定されていない場合は、デフォルトでengになります。
  • ENABLE_SAVE_IMAGES_TO_FILES(環境変数): true に設定すると、output_directory パラメーターを指定して extract_images ツールを使用した際に、抽出した画像をファイルに保存できるようになります。デフォルトはfalseです。
  • SAFE_OUTPUT_DIRECTORIES(環境変数): ENABLE_SAVE_IMAGES_TO_FILES=true かつ ALLOW_ANY_PATH=false の場合に画像を保存できるディレクトリを、コロン区切りで列挙します。例:/tmp:/var/output:/data/images。
  • 機能の上書き/有効化フラグ(コマンドライン):
    • --allow-no-java:extract_tables に必要な Java ランタイムが見つからない場合、通常はサーバーが終了します。このフラグを使用すると起動できますが、extract_tables ツールは無効になります。
    • --allow-no-tesseract:OCR フォールバックに必要な Tesseract 実行ファイルが見つからない場合、通常はサーバーが終了します。このフラグを使用すると起動できますが、extract_pdf_contents の OCR フォールバックは無効になります。
    • --enable-experimental:デフォルトで無効になっている実験的なツール(find_nearby_content など)を有効にします。
    • --allow-any-path:(セキュリティリスク) 設定すると、PDF_SERVER_BASE_PATH による制限を無効にし、ツールの引数で指定された任意のパスからファイルを読み取ろうとすることをサーバーに許可します。十分に注意し、信頼できる環境でのみ使用してください。

機能/依存関係マトリックス

一部のツールの利用可否やすべての機能を利用できるかどうかは、外部依存関係またはフラグによって決まります。

ツール名機能依存関係/トリガーチェック実行時点制御フラグ
extract_tablesjava_runtimeJava ランタイム(JRE)サーバー起動時--allow-no-java
extract_pdf_contentstesseract_ocr(任意)Tesseract OCRサーバー起動時--allow-no-tesseract
(Other Tools)(None)Python パッケージインストール時(N/A)

**注: Tesseract OCR が利用できず(かつ --allow-no-tesseract が使用されている場合)、OCR フォールバックは無効になります。

ツール

サーバーは以下のツールを実装しています。list_tools 呼び出しを通じて LLM に提示されるリストは、検出された機能(Java が利用可能かどうかなど)と起動フラグに応じて動的に変化します。 レスポンススキーマ(TextContentResponse、MetadataResponse など)については、src/document_understanding/models.py を参照してください。エラーレスポンスは ErrorResponse スキーマに従います。

ガイダンス: すべてのツールの pdf_path 引数には、サーバーの環境内でアクセス可能なファイルパスを指定する必要があります。

1. extract_pdf_contents
  • 説明:ローカル PDF ファイルの指定したページからテキストコンテンツを抽出します。直接テキストを抽出し、スキャンされたページや画像の多いページでは OCR にフォールバックします。
  • 引数:
    • pdf_path (string, required):ローカル PDF ファイルへのパスです。
    • pages (string, optional):ページ指定(1 始まり、範囲、負のインデックス)。例:"1, 3-5, -1"。デフォルト=すべて。
    • ocr_language (string, optional):Tesseract の OCR 言語(例:"eng"、"fra+eng")。デフォルト='eng'。
    • password (string, optional):暗号化された PDF のパスワードです。
  • 戻り値:TextContentResponse JSON。
  • 使い方:ページの生テキストを取得するのに最適です。必要に応じて OCR を自動的に処理します。特定のセクションには pages を使用します。英語以外の言語でスキャンされたテキストを扱う場合は、ocr_language を設定してください。
2. extract_pdf_metadata
  • 説明:メタデータ(作成者、タイトル、日付)を抽出し、PDF 内の画像や図面を確認します。
  • 引数:
    • pdf_path (string, required):ローカル PDF ファイルへのパスです。
    • password (string, optional):暗号化された PDF のパスワードです。
  • 戻り値:MetadataResponse JSON。
  • 使い方:まずこれを使用して、PDF の構造やプロパティ(ページ数、タイトル、作成者など)の概要を把握し、画像や図面が含まれているかどうかのヒントを得ます。
3. search_pdf_text
  • 説明:指定したページ内で完全一致するテキストを検索し、バウンディングボックスを返します。
  • 引数:
    • pdf_path (string, required):ローカル PDF ファイルへのパスです。
    • query (string, required):検索するテキスト(大文字と小文字を区別します)。
    • pages (string, optional):ページ指定です。デフォルト=すべて。
    • password (string, optional):暗号化された PDF のパスワードです。
  • 戻り値:ページ番号と矩形の座標を含む一致項目のリストを格納した SearchResponse JSON。
  • 使い方:特定の用語やフレーズとその位置を見つけるのに便利です。
4. extract_pdf_layout
  • 説明:テキストブロック、図面、画像の配置(座標を含む)など、詳細なレイアウト情報を抽出します。
  • 引数:
    • pdf_path (string, required):ローカル PDF ファイルへのパスです。
    • pages (string, optional):ページ指定です。デフォルト=すべて。
    • include_images (boolean, optional):画像情報(xref、bbox、サイズ)を含めます。デフォルト=False。
    • include_drawings (boolean, optional):ベクター図面の情報を含めます。デフォルト=False。
    • detail_level (string, optional):テキストの詳細レベル('blocks'、'lines'、'words')。デフォルト='blocks'。
    • password (string, optional):暗号化された PDF のパスワードです。
  • 戻り値:ページごとのレイアウト詳細を含む LayoutResponse JSON。
  • 使い方:空間的な関係が重要な場合や、ページ構造を把握する場合に使用します。テキスト、画像、ベクター図面の座標を取得できます。複雑なページでは、応答が大きくなることがあります。
5. extract-images
  • 説明:画像(ラスター画像、一部の Form XObjects など)の情報を抽出します。
  • 引数:
    • pdf_path(文字列、必須):ローカルの PDF ファイルへのパスです。
    • pages(文字列、任意):ページ指定です。デフォルトは全ページです。
    • include_data(ブール値、任意):true の場合、base64 形式の画像データを含めます。デフォルトは false です。
    • min_width(整数、任意):結果に含める画像の最小幅です。
    • min_height(整数、任意):結果に含める画像の最小高さです。
    • filter_bbox(配列、任意):画像を絞り込む境界ボックス [x0, y0, x1, y1] です。
    • password(文字列、任意):暗号化された PDF のパスワードです。
    • output_directory(文字列、任意):抽出した画像の保存先ディレクトリです。ENABLE_SAVE_IMAGES_TO_FILES=true 環境変数が必要です。
    • save_without_returning_data(ブール値、任意):true の場合、レスポンスに base64 データを含めず、画像をファイルに保存します。デフォルトは false です。
  • 戻り値:ImageExtractionResponse JSON。
  • ガイダンス:画像の寸法、ページ番号、内部参照(xref)を返します。境界ボックス(bbox)は任意で、検出に失敗した場合(例:Form XObjects)は含まれないことがあります。非常に大きなレスポンスが返される可能性があるため、include_data=True の使用には注意してください。output_directory が指定され、ENABLE_SAVE_IMAGES_TO_FILES=true の場合、画像はディスクに保存され、レスポンスにファイルパスが含まれます。save_without_returning_data=True を指定すると、レスポンスにサイズが大きくなる可能性のある base64 データを含めずに、画像をファイルに保存できます。
6. extract_tables
  • 説明:指定した PDF ページから表を抽出し、リストのリストとして返します。
  • 引数:
    • pdf_path(文字列、必須):ローカルの PDF ファイルへのパスです。
    • pages(文字列、任意):'all' またはカンマ区切りのページ番号(1 始まり)です。デフォルトは全ページです。
    • password(文字列、任意):暗号化された PDF のパスワードです。
  • 戻り値:TableExtractionResponse JSON。(注:現在の実装では辞書のリストを返します。詳しくはdocs/KNOWN_ISSUES.mdを参照してください。)
  • ガイダンス:tabula-py を使用して、可能な範囲で表を検出します。結果は表の書式(罫線、間隔)に大きく左右される場合があります。時間がかかることがあります。注: このツールには Java ランタイムが必要です。サーバーの起動時に Java が検出されず、--allow-no-java フラグが使用されていた場合、このツールは利用できません。
7. detect-language
  • 説明:指定したページ(デフォルトは 1 ページ目)からサンプリングしたテキストコンテンツの言語を検出します。
  • 引数:
    • pdf_path(文字列、必須):ローカルの PDF ファイルへのパスです。
    • pages(文字列、任意):サンプリング対象のページ指定です。デフォルトは '1' です。
    • sample_size(整数、任意):サンプリングする最大文字数です。デフォルトは 2000 です。
    • password(文字列、任意):暗号化された PDF のパスワードです。
  • 戻り値:LanguageDetectionResponse JSON。
  • ガイダンス:処理や翻訳の前に、主要な言語を特定するのに役立ちます。
8. extract_pdf_outline
  • 説明:PDF から文書のアウトライン(ブックマーク/目次)を抽出します。
  • 引数:
    • pdf_path(文字列、必須):ローカルの PDF ファイルへのパスです。
    • password(文字列、任意):暗号化された PDF のパスワードです。
  • 戻り値:階層構造のアウトラインを含む OutlineExtractionResponse JSON。
  • ガイダンス:文書の目次またはブックマーク構造の抽出に使用します。文書にアウトラインがない場合は、空のリストを返します。
9. get_pdf_working_directory
  • 説明:PDF ファイルを処理用に配置するための指定ディレクトリパスを返します。
  • 引数:なし。
  • 戻り値:status、working_directory(文字列または null)、および任意の message を含む JSON。
  • ガイダンス:pdf_path が必要な他のツールを呼び出す前に、PDF ファイルのアップロード先/配置先を確認するためにこのツールを呼び出してください。サーバーが --allow-any-path を指定して起動された場合、working_directory は null になります。

テスト

テストスイートでは、すべてのテストに動的に生成される PDF を使用します。リポジトリには静的な PDF ファイルは保存されていません。tests/conftest.py のテストフィクスチャは、次のような必要なテスト用 PDF をすべて実行時に生成します。

  • シンプルなテキストドキュメント
  • 画像を含むドキュメント
  • 図形を含むドキュメント
  • 表を含むドキュメント
  • アウトライン/ブックマークを含むドキュメント
  • 空のドキュメント
  • 暗号化されたドキュメント

この方法により、外部ファイルを必要とせずにすべてのテストを実行でき、テストスイートの移植性と自己完結性が高まります。

テストの実行
# Run all tests
python -m pytest

# Run specific test categories
python -m pytest tests/unit
python -m pytest tests/integration

# Run tests with coverage
python -m pytest --cov=src
テストアーキテクチャ

テストスイートには、次のような複数の種類のテストが含まれています。

  • ユニットテスト:個々のコンポーネントを分離してテストします
  • 統合テスト:コンポーネント間の相互作用をテストします
  • エンドツーエンドテスト:ユーザーの視点からシステム全体をテストします

エンドツーエンドテストでは、MCP コマンドラインインターフェースを使用してサーバーとやり取りし、実際の使用状況をシミュレーションします。この方法により、さまざまなシナリオや種類の PDF でサーバーが正しく動作することを確認できます。

サーバーの実行/起動

このサーバーは、標準の MCP stdio 通信を使用して実行されます。サーバーを実行する方法はいくつかあります。

方法 1:付属の実行ファイルを使用する(推奨)
# Set required base path (if not using sandbox mode)
export DOCUMENT_UNDERSTANDING_BASE_PATH=/path/to/pdf/storage

# Run with default settings (sandbox mode)
bin/document-understanding-mcp-server

# Run with sandbox mode disabled (less restricted)
DOCUMENT_UNDERSTANDING_SANDBOX=false bin/document-understanding-mcp-server

# Run with additional arguments
bin/document-understanding-mcp-server --enable-experimental --port 8000

document-understanding-mcp-server 実行ファイルは、次の機能を備えた安全な環境を自動的に設定します。

  • サンドボックスモード(デフォルト)での、ユーザーごとに分離されたディレクトリ
  • セキュリティコンテキストに基づく適切な権限
  • 環境に応じたインテリジェントな引数処理
方法 2:インストール済みパッケージのエントリーポイントを使用する

パッケージを pip でインストールすると、エントリーポイントを直接使用できます。

# Run with default settings
document-understanding-mcp-server

# Run with custom arguments
document-understanding-mcp-server --allow-any-path --enable-experimental
方法 3:standalone_server.py を直接使用する
# Activate environment
source .venv/bin/activate

# Set required base path
export DOCUMENT_UNDERSTANDING_BASE_PATH=/path/to/pdf/storage

# Run directly (will fail if Java/Tesseract missing and flags not used)
python standalone_server.py

# Run allowing missing Java/Tesseract but restricting path
python standalone_server.py --allow-no-java --allow-no-tesseract

# Run allowing ANY path access (UNSAFE)
# DOCUMENT_UNDERSTANDING_BASE_PATH is ignored here
python standalone_server.py --allow-any-path

# Enable experimental features
python standalone_server.py --enable-experimental
サンドボックスモード

このサーバーは、デフォルトで有効になっている安全なサンドボックスモードに対応しており、次の処理を行います。

  1. ファイル出力用にユーザーごとに分離されたディレクトリを作成します
  2. より厳格なファイル権限を設定します(700 - ユーザーのみアクセス可能)
  3. セキュリティを強化するため、--allow-any-path フラグを無効にします

サンドボックスモードを無効にするには(本番環境では推奨されません)。

export DOCUMENT_UNDERSTANDING_SANDBOX=false
起動コマンド(mcp.json の例)
例 1:基本設定
{
  "mcpServers": {
    "document-understanding": {
      "command": "/path/to/document-understanding-mcp-server",
      "args": [
        "--enable-experimental"
      ]
    }
  }
}
例 2:Python モジュールを直接使用する
{
  "mcpServers": {
    "document-understanding": {
      "command": "/path/to/your/.venv/bin/python",
      "args": [
        "-m", "document_understanding.cli"
      ],
      "env": {
        "DOCUMENT_UNDERSTANDING_BASE_PATH": "/path/to/pdf/storage"
      }
    }
  }
}

LLM の使用に関するアドバイス

  • ファイルパス: PDF を処理する前に、get_pdf_working_directory を使用して許可されているディレクトリを確認してください。指定する pdf_path 引数が、そのディレクトリ内(またはサブディレクトリ内)のファイルを参照していることを確認してください。パストラバーサルの試み(../)や、作業ディレクトリ外の絶対パスは、サーバーが --allow-any-path を指定して安全でない方法で起動されていない限り、拒否されます。
  • パスワード: 現在、サーバーは(テーブル抽出を除く)ほとんどのツールでパスワード保護された PDF を処理できません。暗号化されたファイルの処理は失敗する可能性が高いです。docs/KNOWN_ISSUES.md を参照してください。
  • ツールの利用可否: 利用可能なツールの一覧は、サーバーの環境によって変わることがあります(たとえば、Java がなく、--allow-no-java が使用された場合、extract_tables は一覧に表示されません)。現在利用できるツールを確認するには、list_tools の応答を参照してください。
  • 具体的なツールを使用する: 特定の箇所だけが必要な場合は、すべての内容を抽出するのではなく、search_pdf_text を優先してください。メタデータだけが必要な場合は、extract_pdf_metadata を使用してください。
  • JSON の処理: JSON の応答を想定してください。ToolResponseContent の text フィールドを JSON として解析します。
  • status の確認: JSON 応答の status フィールドを必ず確認してください。値が "error" の場合は、診断に message フィールドと error_code フィールドを使用してください(注:エラーは通常、サーバーによって例外として発生し、MCP クライアントがこれを変換します)。
  • レイアウト情報: extract_pdf_layout ツールは、豊富な構造情報(テキストの座標、図形、画像の位置)を提供します。複雑な分析(たとえば、find_nearby_content を使用する場合)に活用できますが、応答が大きくなります。
  • ページの指定: 必要に応じて pages パラメーター(例:「1-3, 5, -1」)を効果的に使い、処理対象を絞り込んでください。
  • OCR 言語: 英語以外の文書を処理する場合は、精度を高めるために ocr_language を使って言語を指定してください(例:フランス語と英語の場合は "fra+eng")。
  • エラー処理: pdf_path が正しくない場合の FileNotFoundError や、ページ指定が無効な場合、または処理上の問題がある場合の ValueError に備えてください。暗号化されたファイルでは、さまざまなエラーが発生する可能性があります。サーバーは例外を発生させるため、MCP クライアントがそれを表面化する必要があります。

複雑な使用例

  1. スキャンされた 2 ページ目と 3 ページ目からフランス語のテキストを抽出する:

    • get_pdf_working_directory -> 応答で working_directory を確認します。
    • (LLM/ユーザーが mydoc.pdf を作業ディレクトリに配置します)
    • pdf_path="mydoc.pdf"、pages="2-3"、ocr_language="fra" を指定して extract_pdf_contents を実行します。
    • 応答を解析し、pages リストからテキストを処理します。
  2. 画像の近くにあるテキストを検索する:

    • get_pdf_working_directory -> working_directory を取得します。
    • (LLM/ユーザーが report.pdf を配置します)
    • pdf_path="report.pdf"、pages="5" を指定して extract_pdf_layout を実行します(画像が 5 ページ目にあると仮定)。
    • レイアウト応答を解析します。xref、サイズ、またはおおよその bbox を基に、目的の画像を特定します。
    • pdf_path="report.pdf"、pages="5" を指定し、target_bbox に画像の bbox を設定して、content_type="text_block"、direction="below" として find_nearby_content を実行します(有効な場合。たとえば、キャプションを検索する場合)。
    • 近傍検索の応答を解析し、キャプションのテキストを取得します。
  3. メタデータ確認後に特定のテーブルを抽出する:

    • get_pdf_working_directory -> working_directory を取得します。
    • (LLM/ユーザーが data.pdf を配置します)
    • pdf_path="data.pdf" を指定して extract_pdf_metadata を実行します。
    • 応答を確認し、page_count を確認してメタデータフィールドを参照します。
    • pdf_path="data.pdf"、pages="2, 4" を指定して extract_tables を実行します(例:2 ページ目と 4 ページ目のみ)。
    • 応答を解析します。

重要な使用手順

  1. 特定のページを抽出する:
    • pdf_path と pages="2-3" を指定して extract_pdf_contents を呼び出します。
    • JSON 応答を解析し、status を確認して抽出した内容を処理します。

既知の問題と制限事項

現在の既知の問題と制限事項の一覧については、docs/KNOWN_ISSUES.mdをご覧ください。

これまでに解決された問題の一覧については、docs/SOLVED_ISSUES.mdをご覧ください。

今後の予定

予定されている機能強化と今後の開発については、plans directoryをご覧ください。

貢献

このプロジェクトへの貢献方法については、CONTRIBUTING.mdファイルをご覧ください。

ライセンス

このプロジェクトは、LICENSEファイルに記載された条件に基づいてライセンスされています。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。