
Pythonで作成したOCR機能をFastMCPでMCPサーバー化してみました
はじめに
こんにちは、DIVX R&Dエンジニア兼広報室室長のyasunaです。
私の所属するR&D部では、画像から文字を読み取るOCR機能や、その結果をLLMで解釈する機能など、AIを活用した便利なソリューションを開発しています。
しかし、これらのシステムは、それ単体でローカルマシンで動くだけでは十分ではありません。他のシステム、例えば弊社のAIエンジン「GAI Engine」などから、ネットワーク経由で「サービス」として呼び出せる必要がありました。
今回は、その「MCPサーバー化」の手段として FastMCP というライブラリを選びました。この記事では、私たちがアプリケーションを、どのようにしてFastMCPサーバーへと移行していったのか、その「サーバー化」のプロセスと考え方を中心に整理します。
FastMCPについては以下のGitHubが参考になります。今回は最新版のv2ではなくて安定版のv1を使って構築しました。
https://github.com/jlowin/fastmcp
この記事を読んで分かること
この記事を読むと、すでにあるPythonのOCR機能を、FastMCP を使ってネットワークから呼び出し可能な「ツール」としてサーバー化するまでの、具体的な手順と考え方が分かります。
背景
私たちのチームが開発したOCRやLLMの機能は、最終的に他のシステムと連携することが前提です。そのためには、これらの機能を独立したマイクロサービスとして動かし、標準化されたインターフェースで呼び出せるようにする必要がありました。
FastMCP を選んだのは、AIの機能を「ツール(Tool)」として定義し、それをMCPというプロトコルで公開する、という考え方が良いなと感じたからです。
アプリケーションを「ツール」としてMCPサーバー化する手順
ここでは、既存のPython関数をMCPサーバー化するためにやったことを紹介します。
1. MCPサーバー用の「ラッパー関数」を定義する
最初のステップは、既存のAI関数(run_ocr など)を直接サーバーに登録するのではなく、一度「ラップ」する(包み込む)関数(run_ocr_tool)を新しく作ることでした。
なぜなら、元のOCR関数は、Numpy配列のようなPython特有のデータ形式を引数として期待していることが多いからです。しかし、サーバーがネットワークから受け取るのは、JSON形式のBase64文字列や画像URLです。
この「ラッパー関数」の役割は、関数が理解できるように、入力を「翻訳」することです。具体的には、Base64文字列をデコードしたり、URLから画像をダウンロードしたりして、Numpy配列に変換してから元の関数を呼び出します。
同時に、関数からの戻り値(Numpy配列など、JSONで送れないデータ)を、クライアントが受け取れるようにJSON形式に「翻訳」し直すのも、このラッパー関数の役割になります。
2. FastMCPサーバーのインスタンスを作成する
次に、FastMCP を使って、サーバー本体を作ります。FastMCP(...) という呼び出しでサーバーインスタンスを作成し、name(サーバー名)や version(バージョン情報)などを設定します。この時点では、サーバーはまだ空っぽです。
3. MCPサーバーに「ツール」を登録する
空のサーバーに、私たちが作った機能を「ツール」として追加していきます。FastMCP の便利な点は、server.add_tool() というメソッドを使うだけで、ステップ1で定義したラッパー関数(run_ocr_tool)を、ネットワークから呼び出し可能なAPIエンドポイントとして簡単に登録できることでした。
Tool.from_function() という機能を使って、Python関数をそのままツールとして登録できるため、HTTPのルーティングなどを自分で細かく書く必要がありませんでした。
4. 実運用に必要なものを整備する
サーバーとして動かすには、機能が動くだけでなく、セキュリティや監視の仕組みも必要です。
まず、誰でもAPIを呼び出せないように、APIキーによる認証を組み込みました。FastMCP が提供する AuthProvider という仕組みを使い、リクエストヘッダーに含まれる Authorization トークンを検証する ApiKeyAuthProvider という独自のクラスを定義しました。この認証クラスをステップ2のサーバー作成時に渡すことで、許可されたリクエストだけを受け付けるようになります。
次に、サーバーが正常に動いているかを外部(例えばAWSのALB=ロードバランサー)から監視するための「ヘルスチェック」機能を追加しました。
health_check_tool という、単純に {"status": "ok"} と返すだけのツールをサーバーに登録しました。さらに、ALBのヘルスチェックはMCPプロトコルではなく、単純なHTTP GETリクエストで行われることが多いため、@server.custom_route というデコレータを使い、/mcp/tools というパスにGETリクエストが来た場合もOKを返す、特別なエンドポイントも用意しました。
5. MCPサーバーを起動する
最後に、これらすべてをまとめたMCPサーバーを起動します。main() 関数の中で、CORS(オリジン間リソース共有)の設定や、環境変数からホスト名(HOST)とポート番号(PORT)を読み込む設定を行います。
そしてサーバーを呼び出すことで、FastMCP は、私たちが定義したツール、認証、ヘルスチェック機能を持ったHTTPサーバーとして起動します。
考察
今回の作業を通して、「アプリケーションをMCPサーバー化する」ということは、単にPythonスクリプトをWebフレームワークで動かすことではないなと感じました。
ネットワーク(Base64, JSON)とロジック(Numpy配列)の間で、データ形式を相互に翻訳する必要がありました。
また、元の関数にはなかった「責務」を追加することでもありました。認証(セキュリティ)、ヘルスチェック(監視)、CORS設定(連携)といった、サービスとしてネットワーク上で「振る舞う」ために必要な責務です。
FastMCP は、これらの責務を実装するための基盤と、「ツール」として機能を登録する簡単な方法を提供してくれていると感じました。
まとめ
今回は、ローカルで動作するOCR機能からスタートし、FastMCP を用いて、セキュリティや監視機能を備えたネットワークサービスを構築するまでを振り返りました。
OCRのロジックそのものを開発することと、それを「ツール」として誰もが使えるサービスに仕立て上げること、その両方を考える良い機会になりました。ぜひ参考にしていただけると嬉しいです。


