Claude Code で OCR を使う — space ocr MCP サーバーに接続する
ホスト型の space ocr MCP サーバーを Claude Code に接続し、請求書や領収書の画像から位置情報付きの構造化フィールドと要確認リストを受け取り、そのまま保管・照会するまでの手順です。
Claude Code から請求書・領収書・名刺・身分証・各種フォームの画像を渡し、ばらばらのテキストではなく 名前の付いたフィールド として受け取れます。その入口が space ocr の MCP サーバーです。ホスト型のエンドポイントを一度登録すれば、以降そのツールが Claude Code 標準のツールと並び、書類が出てきた場面でアシスタントが自分で選びます。
何が変わるのかを正確に書いておきます。画像を会話に貼る方法は、毎回 同じ項目 が必要になるまで、値がページのどこにあったかの記録が必要になるまで、結果を残す場所が必要になるまでは成立します。かといって OCR エンジン・解析層・データベースを自前で立てれば、その 3 つの保守が残ります。ここでは抽出がサーバー側で走って形の決まった応答を返し、値ごとに読み取り位置の座標が付き、同じサーバーが書類をワークスペースに保管するので、2 度目からは読み直さずに照会できます。
接続する
サーバーは https://mcp.space-ocr.com/mcp にあり、Streamable HTTP 上の MCP で話します。インストールするものも常駐させるプロセスもありません。URL を登録し、API キーは各リクエストのベアラーヘッダーで渡すだけです。Claude Code ならコマンド 1 行です。
claude mcp add --transport http space-ocr https://mcp.space-ocr.com/mcp \
--header "Authorization: Bearer YOUR_API_KEY"Cursor・VS Code・Windsurf は同じ URL とヘッダーを mcp.json に書きます。ヘッダーを設定できないクライアント — claude.ai・Claude デスクトップ・Claude モバイル — では、同じ URL をカスタムコネクタとして追加すると OAuth の同意画面が開き、どの API キーで動かすかを選べます。どちらの経路でもキーはそのリクエストにのみ使われ、サーバー側には保存されません。
{
"mcpServers": {
"space-ocr": {
"url": "https://mcp.space-ocr.com/mcp",
"headers": { "Authorization": "Bearer YOUR_API_KEY" }
}
}
}キーと料金
API キーは space-ocr.com → Developer → API Keys で発行します(spocr_ で始まる文字列)。全アカウントに 毎月 100 クレジットの無料枠 があり、カード登録は不要、毎月リセットされます。それを超えた分は 1 クレジット ¥10 です。
課金の単位はページです。読み取り 3 種のいずれか、またはアップロード 1 ページが、それぞれちょうど 1 クレジット。読み取りが失敗した分は自動返金されます。それ以外は無料です — ツリーの閲覧、保管済み行の照会、セルの修正、アップロードリンクの発行。残量は space_balance が返します(無料枠、プラン枠、前払い残高の順に消費)。大きなバッチの前に一度呼んでおく価値があります。
ツールは 13 種
最初に space_guide を読ませます。サーバー自身の使い方ガイドで、6 つの短い項目(start・upload・schemas・verification・queries・workflows)がそのまま会話に読み込まれます。ネットワークもクレジットも使いません。
読み取りは 3 種、いずれも保存しません。
ocr_extract— 名前付きフィールドの抽出。fieldsスキーマを宣言するか、autoFields: trueでモデルに提案させます。ocr_markdown— レイアウトを保った Markdown。見出し・箇条書き・表(セルごとにrow/col)に、要素単位の座標が付きます。ocr_text— 読み順を復元したプレーンテキスト。段組みのページが混線せず、ブロック単位の座標が付きます。
残り 10 種がワークスペースを動かします。space_list はツリーの閲覧、space_view はアイテムの読み取りと照会、space_create はフォルダ/シート/ドキュメント束/メモの作成、space_inbox はアップロードリンクの発行、space_upload はすでに URL になっている画像の投入、space_job はアップロードジョブの確認、space_edit はセル値やメモ本文の修正、space_balance は残量、space_delete は 2 段階での削除です。各ツールの背後にある REST ルートまで含めた一覧は API ドキュメント にあります。
画像の入れ方
ツール呼び出しに画像のバイト列は載せられません。最初の 1 回がここで止まりがちです。space_upload が受け取るのは、すでに公開 https:// URL になっている画像だけ(1 回に最大 20 枚、1 枚 20MB まで)。それ以外はすべて space_inbox を通ります — 手元のファイル、この会話に添付された写真、これから撮るスキャン。シートや束を 1 つ指定して有効期限付きのアップロードリンクを発行し、バイト列はその端末から space ocr へ直接送られ、会話を経由しません。応答には両方の結末が入っています。シェルコマンドを実行できるなら curl 行を、できないならユーザーに見せるリンクを使います。
アップロードは非同期です。space_upload は即座にジョブを返し、1 ページおよそ 20 秒。space_job で追ってもよいし、少し置いてから space_view で対象を読んでも同じ行が入っています。扱えるのは画像だけです。PDF はエラーも出さずにアップロードされたまま読まれないので、ページを画像にしてから送ってください。
使い捨ての読み取りか、残す行か
ocr_* は何も保存しません。二度と繰り返さない参照や、シートの列を設計する前に未知の書類を autoFields で下見する用途に向きます。ユーザーが後でまた見るものは、ワークスペースに入れます。
作るのは space_create です。フォルダはまとめる箱で、ルート直下に置けるのはフォルダだけ。シートは投入した画像すべてから決まった columns を抽出し、画像 1 枚が 1 行になります — 比較や絞り込みをする値はここへ。ドキュメント束は各ページを markdown(読む散文)または text(検索する語)に変換し、ページをひとまとまりに保ちます。メモは素のテキストです。
アドレスの規則を 1 つ覚えておくと半日を節約できます。フォルダは名前で指定できますが、それ以外は一覧や作成の呼び出しが返した path で指定します。その末尾は表示名ではなく uniqueKey です — 「March」という名前のシートは /invoices/March にはありません。受け取った path をそのまま持ち回り、表示名から組み立て直さないでください。
行が溜まったら、照会も space_view の仕事です。where で絞り(繰り返すと AND、演算子は = != > >= < <= と包含の ~)、sort で並べ替え、select で列を射影し、limit / offset で分割します。座標は応答を軽く保つため既定では省かれるので、ページ上の位置を示したいときやセルごとの判定を読みたいときに boxes: true を付けます。読み取りは無料なので、絞り込みをサーバーに任せることが、そのまま回答とコンテキストを小さく保つ方法になります。
返ってくるもの
読み取り 3 種も、アップロードが生む行も、応答の形はひとつです。data.values は宣言したスキーマそのままのデータ。data.cells は path をキーにしたフラットなマップで(total、items[0].price)、項目ごとに読み取り位置の軸並行 box と 4 点の quad、判定 verified、review、その根拠の evidence が入ります。data.review は 1 枚分の集計で、flagged に確認すべき path と reasons が並びます。data.normalized はスカラー型を宣言したときだけ付き、印字された値の隣に解釈済みの値を置きます。data.image は 0〜1000 の正規化座標をピクセルに戻す基準です。
{
"status": "success",
"data": {
"values": {
"store_name": "スーパー ABC",
"date": "2025-04-10",
"invoice_no": "",
"total": "¥548"
},
"cells": {
"total": {
"box": { "xmin": 380, "ymin": 720, "xmax": 530, "ymax": 742 },
"quad": [{"x":380,"y":720},{"x":530,"y":720},{"x":530,"y":742},{"x":380,"y":742}],
"verified": true,
"review": null,
"evidence": { "text_match": true, "source": "vision_symbol_match", "match_ratio": 1.0 },
"normalized": { "value": 548, "type": "number", "method": "deterministic" }
}
},
"review": {
"unit": "field",
"declared": 4,
"returned": 3,
"boxed": 3,
"verified": 3,
"flagged": [ { "path": "invoice_no", "reasons": ["missing"] } ],
"by_reason": { "missing": 1 }
},
"normalized": { "total": 548 },
"image": { "width": 1654, "height": 2339 }
}
}なぜ値を検証できるのか。 座標は LLM が推測した位置ではありません。ページ上で実際に検出された OCR シンボルに再アンカーされ、0〜1000 の正規化グリッドで返り、ピクセル換算の基準は data.image です。位置が実在するので、値をドキュメント上に描いて、読み取られた場所と目で照合できます。あわせて verified が判定を示し(検討理由が立てば false、照合が走って何も立たなければ true、照合する対象がなければ null)、文字照合そのものは evidence.text_match が報告します。したがって「宣言した規則で立ったが文字は一致している」は矛盾ではなく正常な組み合わせです。どちらも証拠であって証明ではありません — 2 つのエンジンが同じ誤読で一致することはあり得るので、業務側の検算は残してください。
削除は 2 回の呼び出し
space_delete は 1 回目の呼び出しでは決して削除しません。confirm なしで呼ぶと、そのパスが抱えているもの — 対象、配下のフォルダ/シート/束/メモ/画像の件数、サンプル — を返し、あわせて約 10 分有効な署名付き confirm トークンを発行します。エージェントはその要約を見せ、明確な同意を待ってから、トークンを付けて呼び直します。トークンは呼び出し側のキーとそのパスに紐づく署名なので作り出せず、シートに対して発行したトークンでその行を消すこともできません。
この手続きがあるのは、削除がカスケードして取り消せないからです。フォルダを消せば中の画像も一緒に消えます。行の削除でスキャンは返金されません — そのページはアップロード時に読まれ、課金済みです。
4 つの習慣
サーバー自身が運用ルールを明示しています。安く済んで根拠を示せるエージェントと、クレジットを焼いて当て推量するエージェントを分けるのがこの 4 つです。
- 溜める、垂れ流さない。 2 枚目からは直接
ocr_*を呼ばず、space_create→space_inboxへ。重いデータは会話に貼り戻さず API の背後に置きます。 - スキャン前に確認。 バッチの前に
space_balance、2 枚目のシートを作る前にspace_list。すでに行になっている書類に二重に払う必要はありません。 - 保管済みの行から答える。 全行をコンテキストに引き込まず、
where/sort/select/limitでシートに問い合わせます。読み取りは無料、画像の読み取りは無料ではありません。 - 位置を引用し、不確かなものは印を付ける。 値には読み取り位置と判定が付いています。
data.review.flaggedに挙がったものは断定せず「要確認」として差し出し、値は印字どおりに求めます — ページにない値はページに紐づけられません。