スポンサーリンク

FastMCP で実装した MCP サーバーを AWS Lambda で稼働させる方法

最近はエンジニアにとどまらず多くの人が AI ツールを使い、MCP(Model Context Protocol)サーバーと接続して仕事などをしている人が多いと思います。

MCP サーバーが登場した頃はローカルマシンで稼働させるのが基本でした。

であるが故にマシンスペック次第では重たくなったり、技術的な面でエンジニアではない人がMCPサーバーを使うことが難しいものもありました。

MCP サーバーを使うためにマシンに uvx が入っていることが前提になっていることもしばしばありました。

ただ最近では Remote MCP サーバーも登場し、多くの AI ツールがそれに対応し始めたので、今回 AWS Lambda で MCP サーバーを構築することに挑戦しました。

この記事では FastMCP ライブラリを利用し、AWS Lambda上でスケーラブルかつ低コストな MCP サーバーを構築する方法を紹介します。

FastMCP で実装したMCPサーバーを Lambda にデプロイする

クライアントからのリクエストは、ストリーミングが有効化された Function URL を通じて Lambda に送られ、コンテナ内で FastAPI ベースのアプリケーションがリクエストを処理します。

主な使用技術スタック

多くの開発者にとっては特別準備するものはないとは思いますが、 AWS SAM CLI は開発マシンにインストールしておくと便利です。

ディレクトリ構成

最終的なディレクトリ構成は下記のようになる想定です。

my-lambda-mcp/
├── Dockerfile
├── pyproject.toml
├── README.md
├── src/
│   └── app.py
└── template.yaml

ステップ1: プロジェクトのセットアップ

まず、プロジェクト用のディレクトリを作成し、必要なライブラリを定義します。

uv init --lib my-lambda-mcp

プロジェクトを作成した、ディレクトリ移動して必要なライブラリの追加をします。

cd my-lambda-mcp

最低限必要なライブラリは下記です。

  • fastmcp
  • uvicorn

uv add を使って追加していきます。

uv add fastmcp uvicorn

セットアップは以上です。

ステップ2: アプリケーションの作成 (app.py)

次に、アプリケーションの心臓部となるコードを作成します。プロジェクトルートに app.py という名前でファイルを作成します。

FastMCP をステートレスモードで初期化することが、Lambda で正しく動作させるための最重要ポイントです。

from fastmcp import FastMCP

mcp = FastMCP("Demo 🚀")

@mcp.tool
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b

# ⚠️⚠️ ここで stateless_http=True にすることが重要 ⚠️⚠️
app = mcp.http_app(
    stateless_http=True,
) 

ステップ3: コンテナの定義 (Dockerfile)

aws-lambda-adapter を組み込み、Uvicorn を起動するための Dockerfile をプロジェクトルートに作成します。

FROM ghcr.io/astral-sh/uv:python3.13-bookworm

# aws-lambda-adapterをコンテナにコピー
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.1 /lambda-adapter /opt/extensions/lambda-adapter

WORKDIR /app
COPY pyproject.toml README.md /app/
RUN uv sync

COPY src/ ./src/

ENV UV_CACHE_DIR=/tmp/uv-cache
ENV UV_NO_SYNC=1  # uv のビルド速度を上げる 

ENV AWS_LAMBDA_ADAPTER_BUFFER_OFF=1
ENV AWS_LAMBDA_ADAPTER_CALLBACK_PATH="/callback"
ENV AWS_LAMBDA_ADAPTER_HTTP_PROXY_BUFFERING="off"

ENV PYTHONPATH=/app
ENV PATH="/app/.venv/bin:$PATH"


CMD ["uvicorn", "src.app:app", "--host", "0.0.0.0", "--port", "8080"]

補足 – uv関連の環境変数

環境変数の設定の目的に一応触れておきます。興味ない人は飛ばしてください。

uv関連の環境変数

UV_CACHE_DIR=/tmp/uv-cache

uv のキャッシュディレクトリを /tmp/uv-cache に指定しています。

  • Docker コンテナ内でuvがパッケージをキャッシュする際の保存場所を明示的に設定
  • /tmp を使うことで、コンテナの一時的な領域にキャッシュを配置
  • ビルド時のパフォーマンス向上とディスク使用量の最適化を図る

UV_NO_SYNC=1

uv の自動同期機能を無効化します。

  • 通常uvは依存関係の変更を検出して自動的に同期を行う
  • Docker ビルド時や Lambda 実行時には不要な処理となるため無効化
  • 起動時間の短縮とパフォーマンスの向上を実現
AWS Lambda Adapter関連の環境変数

AWS_LAMBDA_ADAPTER_BUFFER_OFF=1

AWS Lambda Web Adapter のバッファリング機能を無効化します。

  • レスポンスのバッファリングを行わず、ストリーミングでレスポンスを返す
  • リアルタイム性を重視したアプリケーションに適用
  • メモリ使用量の削減効果も期待できる

AWS_LAMBDA_ADAPTER_CALLBACK_PATH="/callback"

Lambda Web Adapter がコールバック用に使用するパスを /callback に設定します。

  • Lambda の実行完了を通知するためのエンドポイントを指定
  • アダプター内部での処理フローを制御する重要な設定

AWS_LAMBDA_ADAPTER_HTTP_PROXY_BUFFERING="off"

HTTP プロキシのバッファリング機能を無効化します。

  • リアルタイムでのデータ転送を優先する設定
  • 大きなレスポンスや長時間の処理において効果的
  • Lambda 関数のタイムアウト制限を考慮した最適化
Python関連の環境変数

PYTHONPATH=/app

Pythonのモジュール検索パスに /app を追加します。

  • アプリケーションのルートディレクトリからモジュールをインポート可能にする
  • 相対インポートの問題を解決
  • コンテナ内での Python アプリケーションの実行を安定化

PATH="/app/.venv/bin:$PATH"

システムの PATH 環境変数に仮想環境の bin ディレクトリを追加します。

  • uv で作成した仮想環境内の Python やパッケージのコマンドを直接実行可能にする
  • 仮想環境を明示的にアクティベートせずに Python スクリプトを実行
  • コンテナ起動時の利便性を向上

ステップ4: サーバーレスインフラの定義 (template.yaml)

AWS SAM を使い、Lambda 関数や Function URL をコードで定義します。プロジェクトルートに template.yaml を作成してください。

AWSTemplateFormatVersion:'2010-09-09'
Transform:AWS::Serverless-2016-10-31
Description:A serverless MCP server using FastMCP on AWS Lambda.

Globals:
 Function:
   Timeout:120
   MemorySize:256

Resources:
 MyLambdaMcpFunction:# 任意の名前でOK
   Type:AWS::Serverless::Function
   Properties:
     FunctionName:MyLambdaMcpFunction# 任意の名前でOK
     PackageType:Image
     FunctionUrlConfig:
       AuthType:NONE# 本番運用するときは必ず認証を有効にしてください
       InvokeMode:RESPONSE_STREAM# ストリーミング応答を有効化(重要)
       Cors:
         AllowOrigins:
           -'*'
         AllowHeaders:
           -Content-Type
           -Authorization
         AllowMethods:
           -POST
   Metadata:
     DockerTag:my-lambda-mcp-v1# 任意の名前でOK
     Dockerfile:Dockerfile
     DockerContext:.

Outputs:
 MyLambdaMcpFunctionUrl:
   Description:"The URL for the MCP Server Lambda function"
   Value:!GetAttMyLambdaMcpFunctionUrl.FunctionUrl

これは最小限の設定です。

⚠️ 認証認可に関してもガバガバなので、本番運用する時は必ず然るべき設定に変更してください。

ステップ5: デプロイ

準備が整いました。以下のコマンドで AWS にデプロイします。

まずはビルドをします。

sam build --use-container

ビルドができたらデプロイをします。

sam deploy \
  --capabilities CAPABILITY_IAM \
  --stack-name my-mcp-server \
  --image-repository ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.ap-northeast-1.amazonaws.com/my-app \
  --no-confirm-changeset

Docker レジストリーの設定などは各個人の環境に合わせて設定してください。

また AWS CLI の設定次第では profile の指定が必要だったりしますが、ここの詳細は割愛します。

ステップ6: 動作確認

デプロイが完了すると、Outputs に Lambda Function URL が表示されます。その URL を使って MCP サーバーの設定をします。

おそらくこのような感じで表示されると思います。

CloudFormation outputs from deployed stack
----------------------------------------------------------------
Outputs                                                         
----------------------------------------------------------------
Key                 MyLambdaMcpFunctionUrl                          
Description         The URL for the MCP Server Lambda function
Value               https://xxxxxxxxxxxxxxxxxxxxxxxx
----------------------------------------------------------------

Value が関数 URL になります。今回は Cursor を例に紹介します。

Cursor の場合、mcp.json に下記を追加するだけです。

{
  "mcpServers": {
    "my-lambda-mcp": { # 任意の名前でOKです。
      "url": "https://xxxxxxxxxxxxxxxxxxxxxxxx/mcp/" # ⚠️ /mcp/ が必要です
    }
  }
}

⚠️ 注意点としては URL の最後に /mcp/ が必要なことです。末尾のスラッシュも必要なので注意です。

おわりに

これで、サーバー管理不要で、利用した分だけ課金されるスケーラブルな MCP サーバーが完成しました。この構成をベースに、ツール登録ロジックを充実させたり、認証を強化したりと、自由にカスタマイズしてみてください。

ステートレスモードで起動することが肝だと思います。

みなさまの役に立ちますと幸いです。

AI AgentAWSDockerMCPPython
スポンサーリンク
ibukishをフォローする
スポンサーリンク
ibukish Lab+
タイトルとURLをコピーしました