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

404 lines
17 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "b8c57858",
"metadata": {},
"source": [
"# Agentes de Azure AI con Soporte para el Protocolo de Contexto del Modelo (MCP) - Python\n",
"\n",
"Este cuaderno demuestra cómo usar los Agentes de Azure AI con herramientas del Protocolo de Contexto del Modelo (MCP) en Python. Muestra cómo crear un agente inteligente que puede aprovechar servidores MCP externos (como Microsoft Learn) para capacidades mejoradas utilizando autenticación sin claves.\n"
]
},
{
"cell_type": "markdown",
"id": "2e6e4234",
"metadata": {},
"source": [
"## Instalar los Paquetes de Python Requeridos\n",
"\n",
"Primero, necesitamos instalar los paquetes de Python necesarios:\n",
"- **azure-ai-projects**: SDK principal de Azure AI Projects\n",
"- **azure-ai-agents**: SDK de Azure AI Agents para crear y gestionar agentes\n",
"- **azure-identity**: Proporciona autenticación sin claves utilizando DefaultAzureCredential\n",
"- **mcp**: Implementación del Protocolo de Contexto de Modelos para Python\n"
]
},
{
"cell_type": "markdown",
"id": "6a2e9a05",
"metadata": {},
"source": [
"## Beneficios de la Autenticación Sin Claves\n",
"\n",
"Este cuaderno demuestra la **autenticación sin claves**, que ofrece varias ventajas:\n",
"- ✅ **Sin claves de API que gestionar** - Utiliza autenticación basada en identidad de Azure\n",
"- ✅ **Mayor seguridad** - No se almacenan secretos en el código ni en archivos de configuración\n",
"- ✅ **Rotación automática de credenciales** - Azure gestiona el ciclo de vida de las credenciales\n",
"- ✅ **Control de acceso basado en roles** - Utiliza Azure RBAC para permisos detallados\n",
"- ✅ **Soporte para múltiples entornos** - Funciona sin problemas tanto en desarrollo como en producción\n",
"\n",
"`DefaultAzureCredential` selecciona automáticamente la mejor fuente de credenciales disponible:\n",
"1. **Identidad Administrada** (cuando se ejecuta en Azure)\n",
"2. Credenciales de **Azure CLI** (durante el desarrollo local)\n",
"3. Credenciales de **Visual Studio**\n",
"4. **Variables de entorno** (si están configuradas)\n",
"5. Autenticación mediante **navegador interactivo** (como último recurso)\n"
]
},
{
"cell_type": "markdown",
"id": "43efa94d",
"metadata": {},
"source": [
"## Configuración de Autenticación Sin Claves\n",
"\n",
"**Requisitos previos para la autenticación sin claves:**\n",
"\n",
"### Para Desarrollo Local:\n",
"```bash\n",
"# Install Azure CLI and login\n",
"az login\n",
"# Verify your identity\n",
"az account show\n",
"```\n",
"\n",
"### Para Entornos de Azure:\n",
"- Habilita la **Identidad Administrada Asignada por el Sistema** en tu recurso de Azure\n",
"- Asigna los **roles RBAC** apropiados a la identidad administrada:\n",
" - `Cognitive Services OpenAI User` para acceso a Azure OpenAI\n",
" - `AI Developer` para acceso a Proyectos de Azure AI\n",
"\n",
"### Variables de Entorno (Opcional):\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",
"**¡No se necesitan claves API ni cadenas de conexión!** 🔐\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": [
"## Importar Bibliotecas Necesarias\n",
"\n",
"Importa los módulos de Python necesarios: \n",
"- **os, time**: Bibliotecas estándar de Python para variables de entorno y retrasos \n",
"- **AIProjectClient**: Cliente principal para Proyectos de IA de Azure \n",
"- **DefaultAzureCredential**: Autenticación sin claves para servicios de Azure \n",
"- **Clases relacionadas con MCP**: Para crear y gestionar herramientas MCP y manejar aprobaciones \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": [
"## Configurar la configuración del servidor MCP\n",
"\n",
"Configura la configuración del servidor MCP utilizando variables de entorno con valores predeterminados como respaldo:\n",
"- **MCP_SERVER_URL**: La URL del servidor MCP (por defecto, la API de Microsoft Learn)\n",
"- **MCP_SERVER_LABEL**: Una etiqueta para identificar el servidor MCP (por defecto, \"mslearn\")\n",
"\n",
"Este enfoque permite una configuración flexible en diferentes entornos.\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": [
"## Crear Cliente de Proyecto de Azure AI (Autenticación sin Claves)\n",
"\n",
"Inicializa el cliente del proyecto de Azure AI utilizando **autenticación sin claves**:\n",
"- **endpoint**: La URL del endpoint del proyecto de Azure AI Foundry\n",
"- **credential**: Usa `DefaultAzureCredential()` para una autenticación segura y sin claves\n",
"- **No se requieren claves de API**: Descubre y utiliza automáticamente la mejor credencial disponible\n",
"\n",
"**Flujo de Autenticación:**\n",
"1. Verifica la Identidad Administrada (en entornos de Azure)\n",
"2. Recurre a las credenciales de Azure CLI (para desarrollo local)\n",
"3. Utiliza otras fuentes de credenciales disponibles según sea necesario\n",
"\n",
"Este enfoque elimina la necesidad de gestionar claves de API o cadenas de conexión en tu código.\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": [
"## Crear Definición de Herramienta MCP\n",
"\n",
"Crea una herramienta MCP que se conecte al servidor MCP de Microsoft Learn:\n",
"- **server_label**: Identificador para el servidor MCP\n",
"- **server_url**: Punto de acceso URL del servidor MCP\n",
"- **allowed_tools**: Lista opcional para restringir qué herramientas pueden ser utilizadas (una lista vacía permite todas las herramientas)\n",
"\n",
"Esta herramienta permitirá al agente acceder a la documentación y recursos de 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": [
"## Crear Agente y Ejecutar Conversación (Flujo sin Claves)\n",
"\n",
"Esta sección completa demuestra el **flujo de trabajo de agente sin claves**:\n",
"\n",
"1. **Crear Agente de IA**: Configura un agente con el modelo GPT-4.1 nano y herramientas MCP.\n",
"2. **Crear Hilo**: Establece un hilo de conversación para la comunicación.\n",
"3. **Enviar Mensaje**: Pregunta al agente sobre las diferencias entre Azure OpenAI y OpenAI.\n",
"4. **Gestionar Aprobaciones de Herramientas**: Aprueba automáticamente las llamadas a herramientas MCP cuando sea necesario.\n",
"5. **Supervisar la Ejecución**: Monitorea el progreso del agente y gestiona cualquier acción requerida.\n",
"6. **Mostrar Resultados**: Presenta los detalles de la conversación y el uso de herramientas.\n",
"\n",
"**Características sin Claves:**\n",
"- ✅ **Sin secretos codificados** - Toda la autenticación se gestiona mediante la identidad de Azure.\n",
"- ✅ **Seguro por defecto** - Utiliza control de acceso basado en roles.\n",
"- ✅ **Despliegue simplificado** - No se requiere gestión de credenciales.\n",
"- ✅ **Amigable con auditorías** - Todo el acceso se rastrea a través de la identidad de Azure.\n",
"\n",
"El agente usará herramientas MCP para acceder a recursos de Microsoft Learn con total seguridad y sin necesidad de gestionar claves 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**Descargo de responsabilidad**: \nEste documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción.\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:20:29+00:00",
"source_file": "05-AdvancedTopics/mcp-foundry-agent-integration/mcp_support_python.ipynb",
"language_code": "es"
}
},
"nbformat": 4,
"nbformat_minor": 5
}