🧠

Azure FunctionでMCPサーバーのデプロイのやり方:その1

に公開

今日はAzure Functionを使って最近の話題のMCPサーバーの立て方についてお話しします。MCPサーバーに馴染みのない方はModel Context Protocolの公式ドキュメントを参考にして下さい。
Azure FunctionでMCPサーバーのデプロイに二つのステップがあります。

  1. Azure上でAzure Functionの設定
  2. 設定されたAzure FunctionにMCPサーバーのコードをデプロイ

Azure 上でAzure Functionの設定

画像を使用して詳細を話しませんが、設定のステップを以下に述べますので、Azure Portal上それぞれの具体的な設定のやり方をGoogle検索などで調べて下さい。

  1. Azure FunctionのPlan typeをFlex Consumption, Instance Memory
    を512MB(例えば)に選択して下さい。Linux環境だとFlex Consumptionの方が便利です。
  2. 忘れてはいけないのはAzure FunctionにAzure Storageを追加することです。Blob Storageに空のContainerを作成しておいてください。後で、ここにzipされたAzure Functionのコードをデプロイします。
  3. 可能だったら、Application Insightsのリソースも追加して下さい。Azure上で簡単にできます。
  4. 下記の画像の「環境変数」を追加されているかを「設定>環境変数」から確認して下さい。環境変数の画像
  5. Azure Function に適切な名前にして下さい。
  6. 設定完了すると「Overview」画面のDefault domainに<your-function-name>.azurewebsites.net, Operating System: Linuxを見れます。
  7. Networkingのところで、Public network accessを防止できるのですが、今日は省略します。

設定されたAzure FunctionにMCPサーバーのコードをデプロイ

まずは、Azure Functionの基本的なディレクトリ構造を見よう。

<project-root>/  
│  
├── .venv/                     # Python の仮想環境(任意だが推奨)  
│  
├── .gitignore                 # Git で不要なファイルを無視するための設定ファイル  
├── host.json                  # Azure Functions ホストの設定を構成するファイル  
├── local.settings.json        # ローカル環境のアプリ設定やシークレット(デプロイされない)  
├── requirements.txt           # 関数アプリの Python 依存関係を記述するファイル  
├── function_app.py            # V2 プログラミングモデルでルートやトリガーを定義するファイル
├── .funcignore                # Azure にアップロードしないファイルを指定
│   
└── README.md                  # オプションのドキュメント  

こちらで、最も重要なのは5つのファイルです。

  1. requirements.txt
  2. host.json
  3. local.settings.json
  4. function_app.py
  5. .funcignore

host.jsonファイルの形式が以下になります。

{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle.Experimental",
    "version": "[4.*, 5.0.0)"
  }
}

デバッグ付きにしたければ、

{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    },
    "logLevel": {
          "default": "Debug"
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle.Experimental",
    "version": "[4.*, 5.0.0)"
  }
}

Azure公式のhost.json のリファレンスがこちらにあります。

local.settings.jsonの形式

{
    "IsEncrypted": false,
    "Values": {
      "FUNCTIONS_WORKER_RUNTIME": "python",
      "AzureWebJobsStorage": "UseDevelopmentStorage=true"
    }
}

詳しい説明はこちらを参考にして下さい。

ローカルのAzure FunctionにMCPサーバーのコードをデプロイ

仮想ストレージの起動

Azure FunctionにAzure Storageを入れないといけないですので、ローカル環境でも「仮想」のストレージを立ち上げるのが必要です。
このために、podmanを使用します。podmanのインストールや使い方にはこちらを参考にして下さい。

  1. podmanの起動:
podman machine start
  1. Azuriteのイメージをダウンロードする
podman run -d --name azurite \
-p 10000:10000 \
-p 10001:10001 \
-p 10002:10002 \
mcr.microsoft.com/azure-storage/azurite
  1. イメージ起動の確認:podman ps -a。STATUSを確認するとazuriteが起動しているのが見えます。

Python 環境の構築

仮想環境パッケージのuvを使用します。こちらのやり方でインストール下さい。Porject Directoryで以下のコマンドを実行して下さい。

uv init
uv venv
source .venv/bin/activate
uv add azure-functions

MCP Inspectorのインストール

Node js, npmの設定はこちらに従って下さい。
npxのインストール:

npm install -g npx

MCP Inspectorの立ちがり方:

npx @modelcontextprotocol/inspector

以下の出力をターミナルで確認ください。

Starting MCP inspector...
⚙️ Proxy server listening on port 6277
🔍 MCP Inspector is up and running at http://127.0.0.1:6274 🚀

hello_mcpツールの追加

今、以下のようにfunction_app.pyhello_mcpという関数を書きます。

# Azure Functions SDK をインポート
import azure.functions as func

# 関数アプリケーションを初期化(FUNCTIONレベルの認証を設定)
app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)


# 汎用トリガーを定義(独自のトリガータイプ "mcpToolTrigger" を使用)
@app.generic_trigger(
    arg_name="context",          # 引数名(トリガー情報を含む)
    type="mcpToolTrigger",       # トリガータイプ名
    toolName="hello_mcp",        # 呼び出されるツール名
    description="Hello world.",  # ツールの説明
    toolProperties="[]",         # 必要なパラメータ(ここではなし)
)
def hello_mcp(context) -> str:
    """
    単純な関数で、「こんにちは」メッセージを返します。

    引数:
        context: トリガーコンテキスト(ここでは使用しません)

    戻り値:
        str: 「Hello I am MCPTool!」という文字列
    """
    return "Hello I am MCPTool!"

ローカルでのAzure Functionの起動

*podmanでazuriteが起動しているのかを確認して下さい。
Project Directory で以下のコマンド

source .venv/bin/activate
func start

を実行すると、以下のようにツールが見えるはずです(他のログを省略)。

Found Python version 3.12.8 (python3).

Azure Functions Core Tools
Core Tools Version:       4.0.7030 Commit hash: N/A +bb4c949899cd5659d6bfe8b92cc923453a2e8f88 (64-bit)
Function Runtime Version: 4.1037.0.23568

[2025-05-23T09:58:29.911Z] MCP server SSE endpoint: http://localhost:7071/runtime/webhooks/mcp/sse
[2025-05-23T09:58:29.956Z] Worker process started and initialized.

Functions:

	hello_mcp: mcpToolTrigger

つまり、http://localhost:7071/runtime/webhooks/mcp/sse にmcpサーバーが立ち上がっています。

MCP Inspectorから確認

  1. 上記に立ち上げたアドレス(http://127.0.0.1:6274)にアクセスし、URLのところにhttp://localhost:7071/runtime/webhooks/mcp/sseを入力し、Connectしてください。
  2. List Toolsをするとhello_mcpが見れます。
  3. hello_mcpをクリックし、Run Toolをすると、以下のように表示されます。

では、ローカルでAzure Function MCPサーバーの起動確認できました。

Azure Function (Cloud上)にデプロイ

Azure CLIをインストールして下さい。 インストールのやり方

Project Directoryのデプロイ用のファイルをzipにして下さい。

zip -r testFunc.zip .  -x "./.venv/*" -x "*.git*" -x ./.vscode -x .env -x "*__pycache__/*" -x "*/__pycache__/*"

Azure CLIにログイン:

az login

zipファイルをAzure CLIでアップロード:

az functionapp deployment source config-zip --src testFunc.zip --name <function-name> --resource-group <group_name>  --build-remote true

では、デプロイされたのかをAzure portal上の、OverViewページのFunctionsから確認下さい。

Cloud上のMCPサーバーの動作確認

Overview,サイドバーのFunctions>App keysからmcp_extensionのキーを受け取り下さい。mcp_extension key

この関数のDomain Nameが<your-function-name>.azurewebsites.netで、https:///<your-function-name>.azurewebsites.net/runtime/webhooks/mcp/sseでMCPサーバーをアクセスできます。

但し、mcp_extensionキーを入れる必要がありますので、URIはhttps:///<your-function-name>.azurewebsites.net/runtime/webhooks/mcp/sse?code=<mcp_extensionキー>になります。

このURIをMCP Inspectorに入力すると上記と同じようにhello_mcpツールを使えます。

最後に

今回は簡単なツールを使っていますが、次回のブローぐでもっと機能のツールを導入しますので、お待ち下さい。

DXC Lab

Discussion