Azure Functions(MCP)×最新Microsoft Foundryで柔軟にAI Agentを構築する

本記事では、Azure Functions 上で Model Context Protocol (MCP) に準拠したツールをホストする最小構成の例を紹介します。

MCP は、「AI Agent」機能から利用できる汎用ツール呼び出しプロトコルで、定義したツール(function)を JSON ベースで呼び出す仕組みを提供します。

またMS Ignite2025で発表されたMicrosoft Foundry を用いて、Pythonソースコード経由でAgentを操作する方法を提供します。

リファレンス情報

今回はMicrosoft Foundryと、Azure Functionsを使用してAgentを構築します。

Functions×MCP Serverの最新情報はこちらをご参照ください。

learn.microsoft.com

作成する関数とファイル

このサンプルでは、次の 2 種類の MCP ツールを定義します:

  • repos_list — 固定のリポジトリ一覧を返すダミーツール
  • echo — 入力文字列をそのまま返すシンプルなツール

このサンプルは以下の 3 ファイルで構成されます。

  • function_app.py
  • requirements.txt
  • host.json

事前準備

ローカル実行環境

python3.11以上の環境で、以下のコマンドを実行してパッケージを導入してください。

pip install openai>=2.0.0
pip install azure-identity
pip install azure-ai-projects>=2.0.0b2
pip install azure-ai-agents>=1.2.0b5

AI Foundryの設定

エンドポイントの取得

デプロイしたMicrosoft Foundryの情報を取得します。概要ページから「Project endpoint」を控えておきます。

※ 今回の記事ではAPIキーではなく、EntraID認証を使用してアクセスします。

Azure Functionsのキー作成

Azure Functionsは、今回はBasic B1プランで作成しました。

作成後、以下の通りCloud Shellなどでコマンドを実行してキーを取得します。

az account set --subscription <サブスクリプションID>
az functionapp keys set  --name <リソース名> --resource-group <リソースグループ> --key-type systemKeys --key-name mcp_extension --key-value $(openssl rand -hex 32)

上記のコマンドを実行し、システムキーを作成しておきます。

Azure Functions(MCP)ソースコード

host.json

基本的に下記をコピーして使用することができます。 MCP 拡張の定義部分に注目してください。

  • extensions.mcp に、MCP サーバーとしてのメタデータ(名前・バージョン・説明)を記述します。
  • extensionBundleのバージョンは4.29.0以上である必要があります。
{
  "version": "2.0",
  "logging": {
    "logLevel": {
      "Microsoft.Azure.WebJobs.Extensions.OpenAI": "Information"
    },
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle.Preview",
    "version": "[4.29.0, 5.0.0)"
  },
  "extensions": {
    "mcp": {
      "instructions": "Snippy is an intelligent code snippet service with AI-powered analysis. Available tools: save_snippet (save code with vector embeddings), get_snippet (retrieve saved snippets by name), code_style (generate style guides from snippets), and deep_wiki (create comprehensive documentation). Use save_snippet with 'snippetname' and 'snippet' parameters, optionally include 'projectid'. Retrieve snippets using get_snippet with 'snippetname'. Generate documentation with code_style or deep_wiki, optionally providing 'chathistory' and 'userquery' for context.",
      "serverName": "Snippy",
      "serverVersion": "2.1.0",
      "messageOptions": {
        "useAbsoluteUriForEndpoint": false
      }
    }    
  }
}

requirements.txt

Azure Functions の Python 環境に必要なパッケージを記述します。

azure-functions>=1.24.0
agent-framework-azurefunctions
azure-identity 
packaging

function_app.py

Azure Functions の標準エントリポイントを定義します。

import json
import logging
import azure.functions as func

# Azure Functions アプリインスタンスを作成
app = func.FunctionApp()


# =============================================================================
# HTTP ヘルスチェック(オプション)
# =============================================================================
@app.route(route="health", methods=["GET"], auth_level=func.AuthLevel.ANONYMOUS)
def health_check(req: func.HttpRequest) -> func.HttpResponse:
    """ヘルスチェックエンドポイント."""
    return func.HttpResponse(
        body=json.dumps({"status": "healthy", "service": "echobot"}),
        mimetype="application/json",
        status_code=200
    )
1. MCP ツール:引数なしの例

固定のリポジトリ情報を返すシンプルなツールです。

# =============================================================================
# MCP ツール: repos_list(引数なし)
# =============================================================================
@app.mcp_tool_trigger(
    arg_name="context",
    tool_name="repos_list",
    description="固定リポジトリ一覧を返す",
    tool_properties="[]",  # 引数なしの場合は空配列
)
def mcp_repos_list(context: str) -> str:
    """MCP ツール: 固定のリポジトリ一覧を返す."""
    logging.info("repos_list called")
    repos = [
        {"name": "foo/bar", "stars": 42},
        {"name": "foo/baz", "stars": 17}
    ]
    return json.dumps(repos, ensure_ascii=False)
2. MCP ツール:引数付きの例

入力文字列をそのまま返す echo ツールです。 引数スキーマを JSON 定義として明示します。

# =============================================================================
# MCP ツール: echo
# =============================================================================
@app.mcp_tool_trigger(
    arg_name="context",
    tool_name="echo",
    description="ユーザーが入力したメッセージをそのまま返すエコーボット。'message' パラメータに返してほしいテキストを指定してください。",
    tool_properties='[{"propertyName": "message", "propertyType": "string", "description": "エコーバックするメッセージ"}]',
)
def mcp_echo(context: str) -> str:
    """MCP エコーツール: 受け取ったメッセージをそのまま返す."""
    try:
        # コンテキストから引数を抽出
        mcp_data = json.loads(context)
        args = mcp_data.get("arguments", {})
        message = args.get("message", "")

        if not message:
            return json.dumps({"error": "メッセージが指定されていません"})

        logging.info(f"Echo: {message}")

        # メッセージをそのまま返す
        return json.dumps({
            "echo": message,
            "status": "success"
        })

    except json.JSONDecodeError:
        return json.dumps({"error": "無効なJSONコンテキスト"})
    except Exception as e:
        logging.error(f"Error in mcp_echo: {str(e)}")
        return json.dumps({"error": str(e)})

これら作製した関数を、Azure Functionsにデプロイします。

今回は単純な例でしたが、このFunctionsでデータを処理させたり、さらに別なAPIを呼び出したりすることで、複雑な情報を処理するMCPサーバーを自分で構築することができます。

ローカル環境からの回答生成

Agentの作成

まずはプログラム経由でAgentを作成します。

最初に、以下の変数情報を設定します。

# Azure AI Projects 接続文字列
PROJECT_CONNECTION_STRING = ""
# Azure AI Projects 接続文字列
PROJECT_CONNECTION_STRING = ""

# MCP Server URL
MCP_SERVER_URL = ""
FUNC_KEY = ""
SERVER_LABEL = "test_mcp_server"

Agentを作成する際に、同時にMCPのツールを設定します。AgentにはGPT-4.1を使用しています。

この際、AgentのInstructionsにツールの種類や使い方を書いておくと、想定通りの挙動を出しやすくなりました。

from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import (
    PromptAgentDefinition, MCPTool
)
from azure.identity import DefaultAzureCredential, ClientSecretCredential

# Azure 認証情報の設定
cred = DefaultAzureCredential()
## アプリ認証を使用する場合
# cred = ClientSecretCredential(
#     tenant_id="",
#     client_id="", 
#     client_secret="",
# ) 


# Azure AI Projects クライアントの初期化
# 環境変数または認証情報を設定してください

project_client = AIProjectClient(
    endpoint=PROJECT_CONNECTION_STRING,
    credential=cred
)

openai_client = project_client.get_openai_client()


# MCP ツールの設定
mcp_tool =MCPTool(
    server_label=SERVER_LABEL,
    server_url=f"{MCP_SERVER_URL}/runtime/webhooks/mcp/sse",
    allowed_tools=["echo", "repos_list"],
    headers={"x-functions-key":FUNC_KEY}
)

# Agentの作成
agent = project_client.agents.create_version( 
agent_name="MCP",
  definition= PromptAgentDefinition(
    model="gpt-4.1",
    instructions="You are a helpful assistant that can call MCP server functions. Tool list: echo: Echoes the input text. repos_list: Lists repositories.",
    tools=[mcp_tool],
  ) 
) 
print(f"created agent: {agent.id}")

Agentを使用した回答生成

Agentはユーザーの承認を待つことがあるため、このサンプルでは自動で承認するように設定します。

def handle_mcp_approvals(response, conversation, openai_client, agent):
    while True:
        approvals = []
        for item in (response.output or []):
            if getattr(item, "type", "") == "mcp_approval_request":
                print(f"[MCP] approve request: {item.id} ({item.server_label}:{getattr(item, 'name', '')})")
                approvals.append({
                    "type": "mcp_approval_response",          # 必要ならここで yes/no を分岐。サンプルではYes固定
                    "approve": True,    
                    "approval_request_id": item.id,
                })
        if not approvals:
            return response

        response = openai_client.responses.create(
            conversation=conversation.id,
            extra_body={
                "agent": {
                    "type": "agent_reference",
                    "name": agent.name,
                    "version": agent.version,
                }
            },
            input=approvals,
        )

実際に会話する際は以下の通りです。必要に応じてAgentがMCPサーバーの機能を呼び出します。

conversation = openai_client.conversations.create( 
    items=[], 
) 
try:
    while True:
        user_input = input("You: ")
        if user_input.lower() in ["exit", "quit"]:
            break

        response = openai_client.responses.create( 
            conversation=conversation.id,
            extra_body={"agent": {"type": "agent_reference", "name": agent.name, "version": agent.version}},
            input = user_input
        ) 
        response = handle_mcp_approvals(response, conversation, openai_client, agent)
        print("Assistant:", response.output_text)

except Exception as e:
    print(f"An error occurred: {e}")
finally:
    print(f"process finished.")

おわりに

本記事では、Azure Functions 上に MCP 準拠のツールを最小構成でホストし、最新のMicrosoft Foundryを用いたAgent からの呼び出しまで一連の流れを確認しました。repos_list と echo の2つのツールを通じて、Agent への登録・実行の具体例を示しています。

MCP を使うことで、社内 API のラッパー化やデータ検索、ドキュメント生成など、既存資産の活用を段階的に進められます。

MCP×Azure Functions は小さく始めて大きく育てられる構成です。今回のサンプルが、みなさまのAgent連携を一歩前へ進めるきっかけになれば幸いです。

執筆担当者プロフィール
西野 佑基

西野 佑基(日本ビジネスシステムズ株式会社)

機械学習系ソリューション開発、業務Webアプリ開発、開発環境自動化などを担当。

担当記事一覧