Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este tutorial, creará un servidor de Protocolo de contexto de modelo (MCP) que expone herramientas de administración de tareas mediante FastAPI y el SDK de Python de MCP. Implemente el servidor en Azure Container Apps y conéctese a él desde GitHub Copilot Chat en VS Code.
En este tutorial, usted hará lo siguiente:
- Creación de una aplicación fastAPI que expone herramientas de MCP
- Probar el servidor MCP localmente con GitHub Copilot
- Containerización y despliegue de la aplicación en Azure Container Apps
- Conexión de GitHub Copilot al servidor MCP implementado
Prerrequisitos
- Una cuenta de Azure con una suscripción activa. cree una de forma gratuita.
- Cli de Azure versión 2.62.0 o posterior.
- Python 3.10 o posterior.
- Visual Studio Code con la extensión GitHub Copilot.
- Docker Desktop (opcional: solo es necesario para probar el contenedor localmente).
Crea el esqueleto de la aplicación
En esta sección, creará un nuevo proyecto de Python con FastAPI y el SDK de Python de MCP.
Cree el directorio del proyecto y configure un entorno virtual:
mkdir tasks-mcp-server && cd tasks-mcp-server python -m venv .venv source .venv/bin/activateCrear
requirements.txt:fastapi>=0.115.0 uvicorn>=0.30.0 mcp[cli]>=1.2.0Instale las dependencias:
pip install -r requirements.txtCree
task_store.pypara el almacén de datos en memoria:from dataclasses import dataclass, field from datetime import datetime, timezone @dataclass class TaskItem: id: int title: str description: str is_complete: bool = False created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc)) def to_dict(self) -> dict: return { "id": self.id, "title": self.title, "description": self.description, "is_complete": self.is_complete, "created_at": self.created_at.isoformat(), } class TaskStore: def __init__(self): self._tasks: list[TaskItem] = [ TaskItem(1, "Buy groceries", "Milk, eggs, bread"), TaskItem(2, "Write docs", "Draft the MCP tutorial", True), ] self._next_id = 3 def get_all(self) -> list[dict]: return [t.to_dict() for t in self._tasks] def get_by_id(self, task_id: int) -> dict | None: task = next((t for t in self._tasks if t.id == task_id), None) return task.to_dict() if task else None def create(self, title: str, description: str) -> dict: task = TaskItem(self._next_id, title, description) self._next_id += 1 self._tasks.append(task) return task.to_dict() def toggle_complete(self, task_id: int) -> dict | None: task = next((t for t in self._tasks if t.id == task_id), None) if task is None: return None task.is_complete = not task.is_complete return task.to_dict() def delete(self, task_id: int) -> bool: task = next((t for t in self._tasks if t.id == task_id), None) if task is None: return False self._tasks.remove(task) return True # For demonstration only — not thread-safe. store = TaskStore()La
TaskItemdataclass define el modelo de datos con unto_dict()método para la serialización. LaTaskStoreclase administra una lista en memoria rellenada previamente con datos de ejemplo y proporciona métodos CRUD. El singleton a nivel de módulostorese comparte en toda la aplicación por razones de simplicidad.
Definición de las herramientas de MCP
En esta sección, definirá las herramientas de MCP que el modelo de IA puede invocar y montar el servidor MCP en la aplicación FastAPI.
Crear
mcp_server.py:from mcp.server.fastmcp import FastMCP from task_store import store mcp = FastMCP("TasksMCP", stateless_http=True) @mcp.tool() async def list_tasks() -> list[dict]: """List all tasks with their ID, title, description, and completion status.""" return store.get_all() @mcp.tool() async def get_task(task_id: int) -> dict | None: """Get a single task by its numeric ID. Args: task_id: The numeric ID of the task to retrieve. """ return store.get_by_id(task_id) @mcp.tool() async def create_task(title: str, description: str) -> dict: """Create a new task with the given title and description. Returns the created task. Args: title: A short title for the task. description: A detailed description of what the task involves. """ return store.create(title, description) @mcp.tool() async def toggle_task_complete(task_id: int) -> str: """Toggle a task's completion status between complete and incomplete. Args: task_id: The numeric ID of the task to toggle. """ task = store.toggle_complete(task_id) if task: status = "complete" if task["is_complete"] else "incomplete" return f"Task {task['id']} is now {status}." return f"Task with ID {task_id} not found." @mcp.tool() async def delete_task(task_id: int) -> str: """Delete a task by its numeric ID. Args: task_id: The numeric ID of the task to delete. """ if store.delete(task_id): return f"Task {task_id} deleted." return f"Task with ID {task_id} not found."Puntos clave:
-
FastMCP("TasksMCP", stateless_http=True)crea un servidor MCP mediante el patrón HTTP sin estado en el SDK de Python. El punto de conexión HTTP transmisible tiene como valor predeterminado la subruta/mcp. - Cada
@mcp.tool()función se convierte en una herramienta invocable. Las anotaciones de parámetros y la cadena de documentación de la función ayudan al modelo de inteligencia artificial a comprender cómo usar cada herramienta.
-
Cree
app.py. Este archivo define la aplicación FastAPI que monta el servidor MCP:from contextlib import AsyncExitStack, asynccontextmanager from fastapi import FastAPI from fastapi.responses import JSONResponse from mcp_server import mcp @asynccontextmanager async def lifespan(app: FastAPI): async with AsyncExitStack() as stack: await stack.enter_async_context(mcp.session_manager.run()) yield app = FastAPI(lifespan=lifespan) app.mount("/", mcp.streamable_http_app()) @app.get("/health") async def health(): return JSONResponse({"status": "healthy"})La aplicación de servidor MCP se monta en la raíz (
/). El punto de conexión HTTP que se puede transmitir del SDK tiene/mcpcomo valor predeterminado , por lo que la ruta de acceso completa del punto de conexión es/mcp.Se usa un punto de conexión de
/healthindependiente para los sondeos de estado de las Container Apps. Los puntos de conexión de MCP esperan solicitudes POST de JSON-RPC y no son adecuados para verificaciones de estado.
Probar el servidor MCP localmente
Antes de implementar en Azure, compruebe que el servidor MCP funciona ejecutandolo localmente y conectándose desde GitHub Copilot.
Inicie la aplicación:
uvicorn app:app --reload --port 8080Abra VS Code y, a continuación, abra Chat de Copilot y seleccione Modo de agente .
Seleccione el botón Herramientas y, a continuación, seleccione Agregar más herramientas...>Agregue el servidor MCP.
Seleccione HTTP (HTTP o eventos Server-Sent).
Escriba la dirección URL del servidor:
http://localhost:8080/mcpEscriba un identificador de servidor:
tasks-mcpSeleccione Configuración del área de trabajo.
En una nueva ventana de Chat de Copilot, escribe: "Muéstrame todas las tareas"
Seleccione Continuar cuando Copilot solicite confirmación de la herramienta MCP.
Debería ver la lista de tareas devuelta desde su almacén en memoria.
Sugerencia
Pruebe otras indicaciones como "Crear una tarea para revisar la PR", "Marcar la tarea 1 como completada" o "Eliminar la tarea 2".
Contenerizar la aplicación
Empaquete la aplicación como contenedor de Docker para que pueda probarla localmente antes de implementarla en Azure.
Crear un
Dockerfile:FROM python:3.12-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8080 CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"]El Dockerfile usa una imagen base de Python 3.12 slim, instala las dependencias desde
requirements.txty, a continuación, copia el código de la aplicación. Uvicorn sirve la aplicación FastAPI en el puerto 8080.Compruebe que el contenedor se compila y se ejecuta localmente:
docker build -t tasks-mcp-server . docker run -p 8080:8080 tasks-mcp-serverConfirme que el punto de conexión de mantenimiento responde:
curl http://localhost:8080/health
Implementación en Azure Container Apps
Después de incluir la aplicación en contenedores, impleméntela en Azure Container Apps mediante la CLI de Azure. El az containerapp up comando compila la imagen de contenedor en la nube, por lo que no necesita Docker en la máquina para este paso.
Establecer variables de entorno:
RESOURCE_GROUP="mcp-tutorial-rg" LOCATION="eastus" ENVIRONMENT_NAME="mcp-env" APP_NAME="tasks-mcp-server-py"Cree un grupo de recursos y un entorno de Container Apps:
az group create --name $RESOURCE_GROUP --location $LOCATION az containerapp env create \ --name $ENVIRONMENT_NAME \ --resource-group $RESOURCE_GROUP \ --location $LOCATIONImplemente la aplicación contenedora:
az containerapp up \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --environment $ENVIRONMENT_NAME \ --source . \ --ingress external \ --target-port 8080Configurar CORS:
az containerapp ingress cors enable \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --allowed-origins "*" \ --allowed-methods "GET,POST,DELETE,OPTIONS" \ --allowed-headers "*"Nota:
Para producción, reemplace los orígenes comodín por orígenes de confianza específicos. Consulte Protección de servidores MCP en Container Apps.
Compruebe la implementación:
APP_URL=$(az containerapp show \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --query "properties.configuration.ingress.fqdn" -o tsv) curl https://$APP_URL/health
Conexión de GitHub Copilot al servidor implementado
Ahora que el servidor MCP se ejecuta en Azure, configure VS Code para conectar GitHub Copilot al punto de conexión implementado.
Crear o actualizar
.vscode/mcp.json:{ "servers": { "tasks-mcp-server": { "type": "http", "url": "https://<your-app-fqdn>/mcp" } } }Reemplace
<your-app-fqdn>por el FQDN de la salida de la implementación.En VS Code, abra El chat de Copilot en modo agente.
Compruebe que
tasks-mcp-serveraparece en la lista de herramientas. Seleccione Iniciar si es necesario.Pruebe con una sugerencia como "Crear una tarea para implementar el entorno de ensayo".
Configuración del escalado para uso interactivo
De forma predeterminada, Azure Container Apps puede escalar a cero réplicas. En el caso de los servidores MCP que sirven a clientes interactivos como Copilot, los inicios en frío provocan retrasos notables. Establezca un número mínimo de réplicas para mantener al menos una instancia en ejecución:
az containerapp update \
--name $APP_NAME \
--resource-group $RESOURCE_GROUP \
--min-replicas 1
Consideraciones de seguridad
En este tutorial se usa un servidor MCP no autenticado para simplificar. Antes de ejecutar un servidor MCP en producción, revise las siguientes recomendaciones. Cuando un agente con tecnología de modelos de lenguaje grandes (LLM) llama al servidor MCP, tenga en cuenta los ataques de inyección de solicitudes.
- Autenticación y autorización: proteja el servidor MCP con el identificador de Microsoft Entra. Consulte Protección de servidores MCP en Container Apps.
- Validación de entrada: valide siempre los parámetros de la herramienta. Use Pydantic para aplicar la validación de datos en las entradas de herramientas.
- HTTPS: Azure Container Apps aplica HTTPS de forma predeterminada con certificados TLS automáticos.
- Privilegios mínimos: exponga solo las herramientas que requiere su caso de uso. Evite herramientas que realicen operaciones destructivas sin confirmación.
- CORS: restringir orígenes permitidos a dominios de confianza en producción.
- Registro y supervisión: Registra las invocaciones de la herramienta MCP para auditoría. Utilice Azure Monitor y Log Analytics.
Limpieza de recursos
Si no tiene previsto seguir usando esta aplicación, elimine el grupo de recursos para quitar todos los recursos que creó en este tutorial:
az group delete --resource-group $RESOURCE_GROUP --yes --no-wait
Paso siguiente
Contenido relacionado
- Introducción a los servidores MCP en Azure Container Apps
- Implementación de un servidor MCP en Container Apps (.NET)
- Implementación de un servidor MCP en Container Apps (Node.js)
- Implementación de un servidor MCP en Container Apps (Java)
- Solución de problemas de servidores MCP en Container Apps
- SDK de MCP Python