本記事では、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の最新情報はこちらをご参照ください。
作成する関数とファイル
このサンプルでは、次の 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連携を一歩前へ進めるきっかけになれば幸いです。