AIエージェント向けパスポートOCR MCPサーバー

アシスタントに、パスポート、身分証明書、渡航文書を読み取る能力を与えます。返ってくるのはただのテキストの塊ではなく、構造化されたフィールドです。サーバーは2つの方法でModel Context Protocolを話します。npmからインストールしてクライアントがコマンドとして起動するstdio版と、mcp.doc.cheapでホストされるStreamable HTTP版です。どちらも公開HTTP APIの薄いクライアントであり、独自のデータは一切保持しません。

npx -y @doc-cheap/mcp

npmでは@doc-cheap/mcpとして、公式MCPレジストリではcheap.doc/mcpとして公開しています。ソースコードはGitLabの公開ミラーにあります。

公式MCPレジストリSmitherycursor.directorynpmに掲載されています。

エージェントが受け取るもの

ここが重要な違いです。1ページ分のテキストを返すOCRツールは、モデルに再解析の作業を渡すことになり、日付の再解析を任されたモデルは、いずれ日付をでっち上げます。このツールは、すでに分割されたフィールドを返します。

  • 所持人:名、姓、生年月日、性別、国籍。
  • 書類:種類、国、発行国、番号、シリーズ、発行日、有効期限、期限切れかどうか、残り日数。
  • 見つかったすべてのフィールド。それぞれに信頼度が付き、機械読み取りゾーン(MRZ)と印字された視覚ゾーンから別々に読み取られます。そのため、モデルは2つの読み取り結果が一致していると仮定するのではなく、一致していることを確認できます。
  • 判定付きの機械読み取りゾーン。判定は合格、不合格、なしのいずれかで、理由と、読み取った行そのものが付きます。
  • 作業中にアシスタントが表示できる1行の要約。

失敗は、空の結果として黙って返されることはなく、エラーブロック内の読みやすい1行として返ります。アシスタントはそれに基づいて対応でき、ユーザーに表示することもできます。APIからの拒否は、API自身の文言、エラーコード、説明ページへのリンクをそのまま保持します。

クライアントにインストールする

Claude Desktop

claude_desktop_config.json

{
  "mcpServers": {
    "doc-cheap": {
      "command": "npx",
      "args": [
        "-y",
        "@doc-cheap/mcp"
      ],
      "env": {
        "DOC_CHEAP_API_KEY": "sk_live_your_key"
      }
    }
  }
}

Claude Code

プロジェクトディレクトリでコマンドを1つ実行

claude mcp add-json doc-cheap '{"command":"npx","args":["-y","@doc-cheap/mcp"],"env":{"DOC_CHEAP_API_KEY":"sk_live_your_key"}}'

Cursor

~/.cursor/mcp.json、またはプロジェクト内の .cursor/mcp.json

{
  "mcpServers": {
    "doc-cheap": {
      "command": "npx",
      "args": [
        "-y",
        "@doc-cheap/mcp"
      ],
      "env": {
        "DOC_CHEAP_API_KEY": "sk_live_your_key"
      }
    }
  }
}

VS Code

.vscode/mcp.json – mcpServers ではなく servers の下に入れる点に注意

{
  "servers": {
    "doc-cheap": {
      "command": "npx",
      "args": [
        "-y",
        "@doc-cheap/mcp"
      ],
      "type": "stdio",
      "env": {
        "DOC_CHEAP_API_KEY": "sk_live_your_key"
      }
    }
  }
}

Gemini CLI

~/.gemini/settings.json

{
  "mcpServers": {
    "doc-cheap": {
      "command": "npx",
      "args": [
        "-y",
        "@doc-cheap/mcp"
      ],
      "env": {
        "DOC_CHEAP_API_KEY": "sk_live_your_key"
      }
    }
  }
}

Windsurf

~/.codeium/windsurf/mcp_config.json

{
  "mcpServers": {
    "doc-cheap": {
      "command": "npx",
      "args": [
        "-y",
        "@doc-cheap/mcp"
      ],
      "env": {
        "DOC_CHEAP_API_KEY": "sk_live_your_key"
      }
    }
  }
}

Kiro

ワークスペースの .kiro/settings/mcp.json、または ~/.kiro/settings/mcp.json

{
  "mcpServers": {
    "doc-cheap": {
      "command": "npx",
      "args": [
        "-y",
        "@doc-cheap/mcp"
      ],
      "disabled": false,
      "autoApprove": [
        "check_balance",
        "search_docs"
      ],
      "env": {
        "DOC_CHEAP_API_KEY": "sk_live_your_key"
      }
    }
  }
}

Kiroならワンクリック

クライアント自身のインストールリンクです。何かを書き込む前に確認を求め、コマンドと引数のリストを表示します。

Kiroに追加

  • ブロックを追加したら、クライアントを再起動してください。サーバーはクライアントが起動するため、変更した設定や環境変数は、起動し直したときにしか反映されません。
  • DOC_CHEAP_API_KEY を設定しない場合、サーバーは公開サンドボックスキーを使います。スキャンはその無料枠の範囲内で実行され、報告する残高はありません。動作を確認するには、これが最も手早い方法です。
  • オプション設定:DOC_CHEAP_DOCS_BASE(検索結果のリンク先)、DOC_CHEAP_DOCS_DIR(検索対象にするドキュメントのコピー)、DOC_CHEAP_IMAGE_ROOT(下記の安全策を参照)。

またはホスト型サーバーに接続する

同じ3つのツールが https://mcp.doc.cheap/mcp でStreamable HTTP経由でホストされているため、URLに接続するタイプのクライアントなら何もインストールする必要はありません。ログインも不要です。キーは X-Doc-Cheap-Api-Key または Authorization: Bearer として送信します(両方送った場合は名前付きのヘッダーが優先されます)。何も送らなければ公開サンドボックスキーが使われます。ホスト型サーバーはお使いのマシン上のファイルを読めないため、画像はbase64またはhttpsのURLで受け取ります。

https://mcp.doc.cheap/mcp

Claude Code

コマンドを1つ実行

claude mcp add --transport http doc-cheap https://mcp.doc.cheap/mcp --header "Authorization: Bearer sk_live_your_key"

Cursor

~/.cursor/mcp.json

{
  "mcpServers": {
    "doc-cheap": {
      "url": "https://mcp.doc.cheap/mcp",
      "headers": {
        "Authorization": "Bearer sk_live_your_key"
      }
    }
  }
}

VS Code

.vscode/mcp.json

{
  "servers": {
    "doc-cheap": {
      "type": "http",
      "url": "https://mcp.doc.cheap/mcp",
      "headers": {
        "Authorization": "Bearer sk_live_your_key"
      }
    }
  }
}

Claude Desktopとclaude.aiでは、Settings、Connectorsからカスタムコネクタとして、URL https://mcp.doc.cheap/mcp を指定して追加します。キーがなければサンドボックスキーで動作します。

3つのツール

MCPサーバーが公開する3つのツール
ツール機能返す内容宣言している動作
scan_document Recognise a passport or ID document書類の画像を認識する構造化された結果全体と1行の要約読み取り専用ではありません(クレジットを消費する場合があります)。破壊的ではありません。冪等キーを送った場合に限り冪等です。オープンワールド:回答はリモートサービスから返ります。
check_balance Check remaining creditsアカウントの利用状況を読み取る残高と今期のカウンター読み取り専用、かつオープンワールド:数値はアカウントのリアルタイムの状況です。
search_docs Search the doc.cheap API documentationドキュメントを検索する一致したセクションをタイトル、リンク、抜粋付きで返す(オフライン)読み取り専用、かつクローズドワールド:検索対象はサーバーと一緒に配布されるドキュメントのコピーなので、ネットワークなしで、同じクエリには同じ回答が返ります。
  • scan_document は画像を image_base64、image_path、image_url のいずれかで受け取り、直接呼び出しと同じオプション(expect_country、return_portrait、reference、idempotency_key など)を受け付けます。
  • search_docs はサーバーと一緒に配布されるドキュメントのコピーを読むため、ネットワークなしで回答します。つまりエージェントは、呼び出しを消費せずにフィールドの一覧やエラーコードを調べられます。
  • check_balance には、アカウントに紐づいたキーが必要です。公開サンドボックスキーでは、実際の値のように見えるゼロを返すのではなく、残高がないことをはっきり伝えます。
  • すべてのツールが出力スキーマを宣言し、それに沿った構造化コンテンツを返すため、エージェントはテキストを解析せずにフィールドを利用できます。
  • ドキュメントの各ページは、エージェントが読めるリソースでもあります。また、4つのプロンプト(書類をJSONに読み取る、有効期限を確認する、まとめてスキャンする、エラーコードを説明する)で、よくある作業を1ステップで始められます。

料金

認識できた書類1件あたり$0.01。定額で、すべてのアカウントに、どの処理量でも同じです。料金は1つだけで、交渉の余地もありません。課金されるのは書類を認識できた場合だけです。何も見つからない、画像を読み取れない、種類を識別できないスキャンは、判定結果を返すだけで料金はかかりません。すべての結果にどちらだったかが示されるため、エージェントもあなたも、その呼び出しで料金が発生したかどうかを常に把握できます。

アカウントを作る前でも、公開サンドボックスキーでIPアドレスごとに合計10件の書類を無料で認識できます。リクエストは結果にかかわらず1時間あたり最大10件です。登録すると20クレジットが追加されます。1クレジットは1セントで、1セントは書類1件です。

本番環境での認識時間は中央値で約275 msです。各結果には処理時間が含まれるため、エージェントのループは実際の数値をもとに時間の見積もりを立てられます。

サーバーが送信する情報

デフォルトでは、サーバーはどこにも何も報告しません。障害の報告は、ご自身で報告先を設定しない限りオフで、設定がなければトラッカーのライブラリは読み込まれることすらありません。

知っておきたい2つの安全策

サーバーはお使いのマシン上で、あなたの権限で動作し、その引数はモデルが選びます。そのため、2つの引数には制限を設けています。

ディレクトリを1つ開放するまで、ローカルファイルは無効

image_path は、DOC_CHEAP_IMAGE_ROOT でディレクトリを指定するまで一切動作せず、代わりに image_base64 を送るようアシスタントに伝えます。変数を設定すると、ディレクトリと要求されたファイルの両方についてシンボリックリンクを解決してから、ファイルがディレクトリ内にあるかを確認します。.. を含むパスも、外部を指すリンクも拒否され、相対パスはクライアントがたまたまプロセスを起動した場所ではなく、そのディレクトリを基準に解釈されます。ルート外のパスと存在しないパスには同じメッセージを返します。別々のメッセージにすると、マシン上のあらゆるパスについて「このファイルは存在するか」という問いに答えてしまうからです。

リモート画像は公開されたhttpsのみ

image_url はサーバーが取得するため、スキームは https: でなければならず、ホストは公開インターネットのアドレスにのみ解決される必要があります。ループバック、プライベート、リンクローカル、キャリアグレードNAT、マルチキャスト、予約済みの範囲は、IPv6にマッピングされた表記も含めて拒否されます。公開されていないアドレスが1つでも返れば、URL全体を拒否します。リダイレクトは手動で最大3回まで追跡し、その都度改めて確認します。本文は25 MBが上限で、ヘッダーの値を信用するのではなく、受信しながら数えます。

image_base64 にはこれらの制約がありません。呼び出し側がすでにバイト列を持っているからです。上記のどの拒否も image_base64 を案内するのはそのためです。

ガイドを読む