Files
2026-07-13 13:31:35 +08:00

404 lines
18 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"cells": [
{
"cell_type": "markdown",
"id": "b8c57858",
"metadata": {},
"source": [
"# Azure AI Agents with Model Context Protocol (MCP) Support - Python\n",
"\n",
"このノートブックでは、PythonでAzure AI AgentsをModel Context Protocol (MCP) ツールと共に使用する方法を示します。外部のMCPサーバー(例えばMicrosoft Learn)を活用し、キー不要の認証を使用して機能を強化するインテリジェントエージェントを作成する方法を紹介します。\n"
]
},
{
"cell_type": "markdown",
"id": "2e6e4234",
"metadata": {},
"source": [
"## 必要なPythonパッケージのインストール\n",
"\n",
"まず、必要なPythonパッケージをインストールします:\n",
"- **azure-ai-projects**: Azure AI ProjectsのコアSDK\n",
"- **azure-ai-agents**: エージェントの作成と管理用Azure AI Agents SDK\n",
"- **azure-identity**: DefaultAzureCredentialを使用したキー不要の認証を提供\n",
"- **mcp**: Python向けのModel Context Protocol実装\n"
]
},
{
"cell_type": "markdown",
"id": "6a2e9a05",
"metadata": {},
"source": [
"## キーレス認証のメリット\n",
"\n",
"このノートブックでは、**キーレス認証**のデモを行います。これには以下のような多くの利点があります:\n",
"- ✅ **APIキーの管理が不要** - Azureのアイデンティティベース認証を使用\n",
"- ✅ **セキュリティの向上** - コードや設定ファイルに秘密情報を保存しない\n",
"- ✅ **資格情報の自動ローテーション** - Azureが資格情報のライフサイクル管理を担当\n",
"- ✅ **ロールベースのアクセス制御** - Azure RBACを使用して細かい権限設定が可能\n",
"- ✅ **マルチ環境対応** - 開発環境と本番環境の両方でシームレスに動作\n",
"\n",
"`DefaultAzureCredential` は、利用可能な最適な資格情報ソースを自動的に選択します:\n",
"1. **マネージドID**Azure上で実行されている場合)\n",
"2. **Azure CLI** の資格情報(ローカル開発時)\n",
"3. **Visual Studio** の資格情報\n",
"4. **環境変数**(設定されている場合)\n",
"5. **インタラクティブブラウザ**認証(フォールバックとして)\n"
]
},
{
"cell_type": "markdown",
"id": "43efa94d",
"metadata": {},
"source": [
"## キーレス認証のセットアップ\n",
"\n",
"**キーレス認証の前提条件:**\n",
"\n",
"### ローカル開発の場合:\n",
"```bash\n",
"# Install Azure CLI and login\n",
"az login\n",
"# Verify your identity\n",
"az account show\n",
"```\n",
"\n",
"### Azure環境の場合:\n",
"- Azureリソースで**システム割り当てマネージドID**を有効化する\n",
"- マネージドIDに適切な**RBACロール**を割り当てる:\n",
" - Azure OpenAIアクセス用の`Cognitive Services OpenAI User`\n",
" - Azure AIプロジェクトアクセス用の`AI Developer`\n",
"\n",
"### 環境変数 (オプション):\n",
"```python\n",
"# These are automatically detected by DefaultAzureCredential\n",
"# AZURE_CLIENT_ID=<your-client-id>\n",
"# AZURE_CLIENT_SECRET=<your-client-secret>\n",
"# AZURE_TENANT_ID=<your-tenant-id>\n",
"```\n",
"\n",
"**APIキーや接続文字列は不要です!** 🔐\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2e21387d",
"metadata": {},
"outputs": [],
"source": [
"! pip install azure-ai-projects -U\n",
"! pip install azure-ai-agents==1.1.0b4 -U\n",
"! pip install azure-identity -U\n",
"! pip install mcp==1.11.0 -U"
]
},
{
"cell_type": "markdown",
"id": "b31c8873",
"metadata": {},
"source": [
"## 必要なライブラリのインポート\n",
"\n",
"必要なPythonモジュールをインポートします:\n",
"- **os, time**: 環境変数や遅延処理のための標準Pythonライブラリ\n",
"- **AIProjectClient**: Azure AI Projectsのメインクライアント\n",
"- **DefaultAzureCredential**: Azureサービスのキー不要認証\n",
"- **MCP関連クラス**: MCPツールの作成と管理、承認処理のため\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "43667b32",
"metadata": {},
"outputs": [],
"source": [
"import os, time\n",
"from azure.ai.projects import AIProjectClient\n",
"from azure.identity import DefaultAzureCredential\n",
"from azure.ai.agents.models import McpTool, RequiredMcpToolCall, SubmitToolApprovalAction, ToolApproval\n"
]
},
{
"cell_type": "markdown",
"id": "721355e5",
"metadata": {},
"source": [
"## MCPサーバー設定の構成\n",
"\n",
"環境変数を使用してMCPサーバーの設定を構成し、デフォルト値をフォールバックとして設定します:\n",
"- **MCP_SERVER_URL**: MCPサーバーのURL (デフォルトはMicrosoft Learn API)\n",
"- **MCP_SERVER_LABEL**: MCPサーバーを識別するためのラベル (デフォルトは \"mslearn\")\n",
"\n",
"この方法により、異なる環境で柔軟な構成が可能になります。\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "189f3d55",
"metadata": {},
"outputs": [],
"source": [
"mcp_server_url = os.environ.get(\"MCP_SERVER_URL\", \"https://learn.microsoft.com/api/mcp\")\n",
"mcp_server_label = os.environ.get(\"MCP_SERVER_LABEL\", \"mslearn\")"
]
},
{
"cell_type": "markdown",
"id": "20612d9a",
"metadata": {},
"source": [
"## Azure AI プロジェクトクライアントの作成(キー不要の認証)\n",
"\n",
"**キー不要の認証**を使用して Azure AI プロジェクトクライアントを初期化します:\n",
"- **endpoint**: Azure AI Foundry プロジェクトのエンドポイント URL\n",
"- **credential**: `DefaultAzureCredential()` を使用して安全なキー不要の認証を実現\n",
"- **API キーは不要**: 利用可能な最適な資格情報を自動的に検出して使用\n",
"\n",
"**認証フロー:**\n",
"1. マネージド ID を確認(Azure 環境内)\n",
"2. Azure CLI 資格情報にフォールバック(ローカル開発用)\n",
"3. 必要に応じて他の利用可能な資格情報ソースを使用\n",
"\n",
"このアプローチにより、コード内で API キーや接続文字列を管理する必要がなくなります。\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "36b1dbd8",
"metadata": {},
"outputs": [],
"source": [
"project_client = AIProjectClient(\n",
" endpoint=\"Your Azure AI Foundry Endpoint\",\n",
" credential=DefaultAzureCredential(),\n",
")"
]
},
{
"cell_type": "markdown",
"id": "cdb6ab8c",
"metadata": {},
"source": [
"## MCPツール定義の作成\n",
"\n",
"Microsoft Learn MCPサーバーに接続するMCPツールを作成します:\n",
"- **server_label**: MCPサーバーの識別子\n",
"- **server_url**: MCPサーバーのURLエンドポイント\n",
"- **allowed_tools**: 使用可能なツールを制限するためのオプションのリスト(空のリストの場合、すべてのツールが許可されます)\n",
"\n",
"このツールを使用することで、エージェントがMicrosoft Learnのドキュメントやリソースにアクセスできるようになります。\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "51e7e136",
"metadata": {},
"outputs": [],
"source": [
"mcp_tool = McpTool(\n",
" server_label=mcp_server_label,\n",
" server_url=mcp_server_url,\n",
" allowed_tools=[], # Optional: specify allowed tools\n",
")\n"
]
},
{
"cell_type": "markdown",
"id": "6e894b0b",
"metadata": {},
"source": [
"## エージェントの作成と会話の実行(キー不要のワークフロー)\n",
"\n",
"この包括的なセクションでは、**キー不要のエージェントワークフロー**の全体像を示します:\n",
"\n",
"1. **AIエージェントの作成**: GPT-4.1 nanoモデルとMCPツールを使用してエージェントを設定\n",
"2. **スレッドの作成**: コミュニケーション用の会話スレッドを確立\n",
"3. **メッセージの送信**: Azure OpenAIとOpenAIの違いについてエージェントに質問\n",
"4. **ツール承認の処理**: 必要に応じてMCPツールの呼び出しを自動承認\n",
"5. **実行の監視**: エージェントの進捗を追跡し、必要なアクションを処理\n",
"6. **結果の表示**: 会話内容とツール使用の詳細を表示\n",
"\n",
"**キー不要の特徴:**\n",
"- ✅ **ハードコードされた秘密情報なし** - すべての認証はAzure IDで処理\n",
"- ✅ **デフォルトで安全** - ロールベースのアクセス制御を使用\n",
"- ✅ **簡素化されたデプロイ** - 資格情報管理が不要\n",
"- ✅ **監査対応** - すべてのアクセスはAzure IDを通じて追跡\n",
"\n",
"エージェントはMCPツールを使用してMicrosoft Learnリソースにアクセスし、完全なセキュリティとAPIキー管理不要の状態を実現します。\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "68c49af5",
"metadata": {},
"outputs": [],
"source": [
"with project_client:\n",
" agents_client = project_client.agents\n",
"\n",
" # Create a new agent with keyless authentication\n",
" # NOTE: To reuse existing agent, fetch it with get_agent(agent_id)\n",
" agent = agents_client.create_agent(\n",
" model=\"Your Azure OpenAI Model Deployment Name\",\n",
" name=\"my-mcp-agent\",\n",
" instructions=\"You are a helpful agent that can use MCP tools to assist users. Use the available MCP tools to answer questions and perform tasks.\",\n",
" tools=mcp_tool.definitions,\n",
" )\n",
" print(f\"Created agent, ID: {agent.id}\")\n",
" print(f\"MCP Server: {mcp_tool.server_label} at {mcp_tool.server_url}\")\n",
"\n",
" # Create thread for communication\n",
" thread = agents_client.threads.create()\n",
" print(f\"Created thread, ID: {thread.id}\")\n",
"\n",
" # Create message to thread\n",
" message = agents_client.messages.create(\n",
" thread_id=thread.id,\n",
" role=\"user\",\n",
" content=\"What's difference between Azure OpenAI and OpenAI?\",\n",
" )\n",
" print(f\"Created message, ID: {message.id}\")\n",
"\n",
" # KEYLESS APPROACH: Handle tool approvals without hardcoded secrets\n",
" \n",
" # Option 1: Completely keyless (recommended for Azure identity-enabled MCP servers)\n",
" # run = agents_client.runs.create(thread_id=thread.id, agent_id=agent.id, tool_resources=mcp_tool.resources)\n",
" \n",
" # Option 2: With minimal headers (if MCP server requires specific headers)\n",
" # For demonstration purposes, using a placeholder header\n",
" mcp_tool.update_headers(\"SuperSecret\", \"123456\") # Replace with actual auth if needed\n",
" \n",
" # Set approval mode - uncomment next line to disable approval requirement completely\n",
" # mcp_tool.set_approval_mode(\"never\") # Fully automated, no approval needed\n",
" \n",
" run = agents_client.runs.create(thread_id=thread.id, agent_id=agent.id, tool_resources=mcp_tool.resources)\n",
" print(f\"Created run, ID: {run.id}\")\n",
"\n",
" while run.status in [\"queued\", \"in_progress\", \"requires_action\"]:\n",
" time.sleep(1)\n",
" run = agents_client.runs.get(thread_id=thread.id, run_id=run.id)\n",
"\n",
" if run.status == \"requires_action\" and isinstance(run.required_action, SubmitToolApprovalAction):\n",
" tool_calls = run.required_action.submit_tool_approval.tool_calls\n",
" if not tool_calls:\n",
" print(\"No tool calls provided - cancelling run\")\n",
" agents_client.runs.cancel(thread_id=thread.id, run_id=run.id)\n",
" break\n",
"\n",
" tool_approvals = []\n",
" for tool_call in tool_calls:\n",
" if isinstance(tool_call, RequiredMcpToolCall):\n",
" try:\n",
" print(f\"Approving tool call: {tool_call}\")\n",
" \n",
" # KEYLESS APPROVAL OPTIONS:\n",
" \n",
" # Option 1: No headers (fully keyless)\n",
" # tool_approvals.append(\n",
" # ToolApproval(\n",
" # tool_call_id=tool_call.id,\n",
" # approve=True,\n",
" # headers={} # No headers needed for keyless\n",
" # )\n",
" # )\n",
" \n",
" # Option 2: With headers (if MCP server requires them)\n",
" tool_approvals.append(\n",
" ToolApproval(\n",
" tool_call_id=tool_call.id,\n",
" approve=True,\n",
" headers=mcp_tool.headers, # Uses configured headers if needed\n",
" )\n",
" )\n",
" except Exception as e:\n",
" print(f\"Error approving tool_call {tool_call.id}: {e}\")\n",
"\n",
" print(f\"tool_approvals: {tool_approvals}\")\n",
" if tool_approvals:\n",
" agents_client.runs.submit_tool_outputs(\n",
" thread_id=thread.id, run_id=run.id, tool_approvals=tool_approvals\n",
" )\n",
"\n",
" print(f\"Current run status: {run.status}\")\n",
"\n",
" print(f\"Run completed with status: {run.status}\")\n",
" if run.status == \"failed\":\n",
" print(f\"Run failed: {run.last_error}\")\n",
"\n",
" # Display run steps and tool calls\n",
" run_steps = agents_client.run_steps.list(thread_id=thread.id, run_id=run.id)\n",
"\n",
" # Loop through each step\n",
" for step in run_steps:\n",
" print(f\"Step {step['id']} status: {step['status']}\")\n",
"\n",
" # Check if there are tool calls in the step details\n",
" step_details = step.get(\"step_details\", {})\n",
" tool_calls = step_details.get(\"tool_calls\", [])\n",
"\n",
" if tool_calls:\n",
" print(\" MCP Tool calls:\")\n",
" for call in tool_calls:\n",
" print(f\" Tool Call ID: {call.get('id')}\")\n",
" print(f\" Type: {call.get('type')}\")\n",
"\n",
" print() # add an extra newline between steps\n",
"\n",
" # Fetch and log all messages\n",
" messages = agents_client.messages.list(thread_id=thread.id)\n",
" print(\"\\nConversation:\")\n",
" print(\"-\" * 50)\n",
" for msg in messages:\n",
" if msg.text_messages:\n",
" last_text = msg.text_messages[-1]\n",
" print(f\"{msg.role.upper()}: {last_text.text.value}\")\n",
" print(\"-\" * 50)\n",
"\n",
" # Example of dynamic tool management (keyless)\n",
" print(f\"\\nDemonstrating keyless dynamic tool management:\")\n",
" print(f\"Current allowed tools: {mcp_tool.allowed_tools}\")\n",
" print(\"✅ All operations completed using keyless authentication!\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**免責事項**: \nこの文書はAI翻訳サービス[Co-op Translator](https://github.com/Azure/co-op-translator)を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があります。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解について、当社は責任を負いません。\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "demo",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.15"
},
"coopTranslator": {
"original_hash": "39a035fea0d10767dfcb0662bd3528fa",
"translation_date": "2025-08-26T21:25:47+00:00",
"source_file": "05-AdvancedTopics/mcp-foundry-agent-integration/mcp_support_python.ipynb",
"language_code": "ja"
}
},
"nbformat": 4,
"nbformat_minor": 5
}