MCP・バイナリアップロードで心が折れた話
はじめに
SaaS「Suidasu」をひとりで開発しています。開発歴15年、直近はITコンサルが長かったですが、久しぶりにゴリゴリ書いてます。
この記事はMCPサーバーを実装する中で、バイナリファイルのアップロードという一見シンプルな要件に振り回され、Google Drive審査で消耗し、最終的にREST APIを並行実装するに至った経緯をまとめたものです。
これからMCPサーバーを開発しようとしている方、特に画像やファイルを扱うサービスを考えている方の参考になれば幸いです。
MCPサーバーの普及
2024年末にAnthropicが発表したMCP(Model Context Protocol)は、AIエージェントに外部ツールとの連携機能を付与するための標準プロトコルです。
LLM単体では「テキストを生成する」ことしかできませんが、MCPを通じてデータベース検索、ファイル操作、API呼び出しなど、実世界のアクションを実行できるようになります。いわばAIエージェントの「武器を増やす」仕組みです。
Claude、ChatGPT、Geminiなど主要なAIプラットフォームがMCP対応を進めており、MCPサーバーの需要は急速に高まっています。自社サービスをMCP対応にすれば、ユーザーは普段使っているAIエージェントから直接サービスの機能を呼び出せるようになります。
モチベーション — なぜMCPに注力するのか
AIサービスの世界では、OpenAI・Google・Anthropicという「Big3」がしのぎを削っています。彼らと同じ土俵で戦うのは現実的ではありません。
私が考えたのは、MCPサーバーとして優れたツールを提供すること。つまりAIエージェントの「武器」として選ばれるポジションを取る戦略です。ユーザーがどのAIエージェントを使っていても、MCPを通じて私たちのサービスを呼び出せる。プラットフォームに依存しない立ち位置です。
背景 — Suidasuが生まれた理由
業界によっては、手書きやFAXによる業務が現在も残っています。
- 暗号のような手書きの受注伝票
- 省略だらけの記述
- 積載量によるざっくり見積もりなど、担当者の感覚に依存した数値
こうしたデータを起こすと、担当者によるブレが大きい。しかし一般的なOCRの導入は費用が高く、中小企業では手が出しにくい。画像認識の独自実装も開発費用がかかります。
低コストで、可能な限り業務負荷を下げたい。
このモチベーションから、画像・PDFからAI(Gemini)でデータを抽出するSaaS「Suidasu」を開発しました。カスタムレイアウトを定義すれば、業務に特化した項目でデータを抽出できます。
「SaaSはオワコン」と言われることもありますが、AI支援・AI統合を前提とした新しいSaaSの形として、仕様を固定するのではなく、AIが柔軟にデータを解釈するアプローチで開発しています。
経験談 — MCPバイナリアップロードとの戦い
MCPのバイナリ制約
SuidasuのMCPサーバーには extract_data というツールがあります。画像をアップロードし、AIがデータを抽出して返す——サービスの根幹機能です。
しかし、ここで壁にぶつかりました。
MCPはJSON-RPCベースのプロトコルであり、multipart/form-dataによるバイナリ送信をサポートしていません。
つまり画像を送るには、Base64エンコードしてJSONの文字列フィールドに入れるしかない。Base64にすると元データの約1.33倍にサイズが膨張します。
最新のスマートフォンで撮影した写真は3〜5MB程度。Base64にすると4〜7MB。MCP SDKのデフォルトメッセージサイズ上限は4MBです。
普通にスマホで撮った写真が送れない。
この問題はMCPコミュニティでも認識されており、複数のissueが立っています。
| Issue | 内容 | 状態 |
|---|---|---|
| #155 | クライアント→サーバーへのファイル送信手段がない | Open(2025年2月〜) |
| #527 | Base64 in JSON-RPCはスケールしない | Open(2025年5月〜) |
| SEP-1306 | バイナリモードElicitation提案 | Draft/探索段階 |
| SEP-1597 | HTTP RESTトランスポート提案 | 提案段階 |
SEP-1306ではElicitation機能を拡張してファイルアップロードを可能にする提案、SEP-1597ではJSON-RPCの代わりにHTTP RESTトランスポートを追加する提案がされていますが、いずれもまだ実装には程遠い状況です。
プロトコル仕様レベルでのバイナリアップロードのネイティブサポートは、2026年4月現在、まだ存在しません。
代替案① — クラウドストレージ連携(Google Drive)
MCPで直接画像を送れないなら、Google Driveに画像を置いて、そのURLを渡せばいいのでは?
この発想でGoogle Drive連携の実装を検討しました。しかし、ここからが長い戦いの始まりでした。
drive.readonly — CASA審査の壁
ユーザーのGoogle Driveからファイルを読み取るには drive.readonly スコープが必要です。しかしこれは**restricted scope(制限付きスコープ)**に分類されます。
制限付きスコープを使うには、Googleの審査を通過した上で、**CASA(Cloud Application Security Assessment)**というサードパーティによるセキュリティ評価を受ける必要があります。
- サービス仕様を動画で説明する必要がある
- 何度もやり取りが発生する
- そしてCASA審査は年次更新が必要
- 費用は年間数十万円
個人開発・小規模チームにとって、この負担は重すぎます。
drive.file — UXの悪化
審査の結果、Googleから drive.file スコープの使用を提案されました。
"The drive.file scope allows the user to create Drive files, and select and modify any file from their Drive that they want to share with your application"
drive.file は制限付きスコープではないため、CASA審査は不要です。しかし、このスコープではユーザーがGoogle Pickerを使って明示的にファイルを選択する必要があります。
MCPの文脈で考えてみてください。ユーザーはAIエージェントとの会話の中で「この画像を分析して」と言いたいだけです。そこに「まずGoogle Pickerでファイルを選択してください」というステップが入ると、MCPの手軽さが失われます。
結局、Google Drive連携は断念しました。OneDrive、Boxなども同様の審査要件があり、クラウドストレージ連携という方向性自体を諦めることになりました。
代替案② — REST API(OpenAPI)の並行実装
最終的にたどり着いた答えは、MCPと同等の機能をREST APIとしても提供することでした。
REST APIなら multipart/form-data で画像を直接アップロードできます。サイズ制限もサーバー側で自由に設定可能。当たり前のHTTPの世界です。
SuidasuではMCPの全21ツールと同等の機能をREST APIとして実装し、OpenAPI仕様書とSwagger UIも提供しています。
# MCP(JSON-RPC)— 画像URLを渡す方式に制限
POST /mcp
{"method": "tools/call", "params": {"name": "extract_data", "arguments": {"image_url": "https://...", "project_id": "..."}}}
# REST API — multipart/form-dataで直接アップロード可能
POST /v1/api/extract
Content-Type: multipart/form-data
file: (バイナリデータ)
project_id: "..."
MCPサーバー側は、Base64入力を廃止し、HTTPS URLからの画像ダウンロード方式に切り替えました。ユーザーが画像をどこかにホストし、そのURLを渡す形です。
完璧な解決策ではありませんが、現時点ではこれがもっとも現実的なアプローチだと考えています。
まとめ
MCPは素晴らしいプロトコルですが、万能ではありません。
特にバイナリファイルのアップロードが必要なサービスでは、JSON-RPCの制約が大きなボトルネックになります。仕様レベルでの解決はまだ先の話です。
クラウドストレージ連携は技術的には可能でも、審査コスト・UXの観点から小規模サービスには現実的ではありませんでした。
これからMCPサーバーを開発する方へ、私の経験から言えることは:
- ファイルアップロードが必要なら、REST APIの並行実装を最初から計画に入れる
- MCPはテキストベースのツール(検索、CRUD操作、データ取得)には最適
- バイナリデータを扱う部分はREST APIに任せ、MCPからはURL参照で連携する設計が現実的
MCPのエコシステムは急速に発展しています。将来的にはバイナリアップロートのネイティブサポートが実現するかもしれません。でも、今日サービスを届けるためには、現実的な選択をする必要があります。
心が折れても、代替案を見つけて前に進む。開発ってそういうものですよね。