Oktatóanyag: Python MCP-kiszolgáló üzembe helyezése az Azure Container Appsben

Ebben az oktatóanyagban létrehoz egy Model Context Protocol (MCP) kiszolgálót, amely a FastAPI és az MCP Python SDK használatával teszi elérhetővé a feladatkezelő eszközöket. Üzembe helyezheti a kiszolgálót az Azure Container Appsben, és csatlakozhat hozzá a GitHub Copilot Chatből a VS Code-ban.

Ebben az útmutatóban Ön:

  • Olyan FastAPI-alkalmazás létrehozása, amely mcp-eszközöket tesz elérhetővé
  • Az MCP-kiszolgáló helyi tesztelése a GitHub Copilottal
  • Az alkalmazás tárolóba helyezése és üzembe helyezése az Azure Container Appsben
  • A GitHub Copilot csatlakoztatása az üzembe helyezett MCP-kiszolgálóhoz

Előfeltételek

Az alkalmazásállvány létrehozása

Ebben a szakaszban egy új Python-projektet hoz létre a FastAPI és az MCP Python SDK használatával.

  1. Hozza létre a projektkönyvtárat, és állítson be egy virtuális környezetet:

    mkdir tasks-mcp-server && cd tasks-mcp-server
    python -m venv .venv
    source .venv/bin/activate
    
  2. Létrehoz requirements.txt:

    fastapi>=0.115.0
    uvicorn>=0.30.0
    mcp[cli]>=1.2.0
    
  3. Telepítse a függőségeket:

    pip install -r requirements.txt
    
  4. Létrehozás task_store.py a memóriában lévő adattárhoz:

    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()
    

    Az TaskItem adatosztály szerializálási to_dict() módszerrel határozza meg az adatmodellt. Az TaskStore osztály a mintaadatokkal előre feltöltött memóriabeli listát kezeli, és CRUD-metódusokat biztosít. A modulszintű store singleton az egyszerűség kedvéért meg van osztva az alkalmazáson belül.

Az MCP-eszközök definiálása

Ebben a szakaszban definiálja azokat az MCP-eszközöket, amelyeket az AI-modell meghívhat és csatlakoztathat az MCP-kiszolgálóhoz a FastAPI-alkalmazásban.

  1. Létrehoz 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."
    

    Összefoglalás:

    • FastMCP("TasksMCP", stateless_http=True) egy MCP-kiszolgálót hoz létre az állapot nélküli HTTP-minta használatával a Python SDK-ban. A streamelhető HTTP-végpont alapértelmezés szerint a /mcp mellékútra irányul.
    • Minden @mcp.tool() függvény visszavonhatatlan eszköz lesz. A függvényi leírások és a paraméter annotációk segítik a mesterséges intelligencia modellnek megérteni az egyes eszközök használatát.
  2. Hozz létre app.py. Ez a fájl határozza meg az MCP-kiszolgálót csatlakoztató FastAPI-alkalmazást:

    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"})
    

    Az MCP-kiszolgálóalkalmazás a gyökérnél (/) csatlakozik. Az SDK streamelhető HTTP-végpontjának alapértelmezett beállítása /mcp, így a teljes végpont elérési útja /mcp.

    A Container Apps állapottesztjeihez külön /health végpontot használunk. Az MCP-végpontok JSON-RPC POST-kéréseket várnak, és nem alkalmasak állapot-ellenőrzésekre.

Az MCP-kiszolgáló helyi tesztelése

Az Azure-ban való üzembe helyezés előtt ellenőrizze, hogy az MCP-kiszolgáló működik-e helyileg futtatva és a GitHub Copilotból való csatlakozással.

  1. Indítsa el az alkalmazást:

    uvicorn app:app --reload --port 8080
    
  2. Nyissa meg a VS Code-ot, majd nyissa meg a Copilot-csevegést , és válassza az Ügynök módot.

  3. Válassza az Eszközök gombot, majd válassza a További eszközök hozzáadása...>Adja hozzá az MCP-kiszolgálót.

  4. Válassza a HTTP (HTTP vagy Server-Sent események) lehetőséget.

  5. Adja meg a kiszolgáló URL-címét: http://localhost:8080/mcp

  6. Adjon meg egy kiszolgálóazonosítót: tasks-mcp

  7. Válassza a Munkaterület beállításai lehetőséget.

  8. Egy új Copilot-csevegési üzenetbe írja be a következőt: "Az összes feladat megjelenítése"

  9. Válassza a Folytatás lehetőséget, amikor a Copilot az MCP-eszköz megerősítését kéri.

Látnia kell a memóriabeli tárolóból visszaadott feladatlistát.

Jótanács

Próbálkozzon más kérdésekkel, például a "Feladat létrehozása a kérelem áttekintéséhez", az "1. tevékenység megjelölése befejezettként" vagy a "2. tevékenység törlése" kérdésekkel.

Az alkalmazás tárolóba helyezése

Csomagolja be az alkalmazást Docker-tárolóként, hogy helyileg tesztelhesse, mielőtt üzembe helyezené az Azure-ban.

  1. Hozzon létre egy 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"]
    

    A Dockerfile egy Python 3.12 vékony alaprendszerképet használ, telepíti a függőségeket requirements.txt, majd átmásolja az alkalmazáskódot. Az Uvicorn a FastAPI alkalmazást a 8080-ás porton szolgálja ki.

  2. Ellenőrizze, hogy a konténer helyben épül és fut.

    docker build -t tasks-mcp-server .
    docker run -p 8080:8080 tasks-mcp-server
    

    Ellenőrizze, hogy az állapotvégpont válaszol-e: curl http://localhost:8080/health

Üzembe helyezés az Azure Container Appsben

Az alkalmazás tárolóba helyezése után helyezze üzembe az Azure Container Appsben az Azure CLI használatával. A az containerapp up parancs létrehozza a tárolórendszerképet a felhőben, így ehhez a lépéshez nincs szükség a Dockerre a gépen.

  1. Környezeti változók beállítása:

    RESOURCE_GROUP="mcp-tutorial-rg"
    LOCATION="eastus"
    ENVIRONMENT_NAME="mcp-env"
    APP_NAME="tasks-mcp-server-py"
    
  2. Erőforráscsoport és Container Apps-környezet létrehozása:

    az group create --name $RESOURCE_GROUP --location $LOCATION
    
    az containerapp env create \
        --name $ENVIRONMENT_NAME \
        --resource-group $RESOURCE_GROUP \
        --location $LOCATION
    
  3. A tárolóalkalmazás üzembe helyezése:

    az containerapp up \
        --name $APP_NAME \
        --resource-group $RESOURCE_GROUP \
        --environment $ENVIRONMENT_NAME \
        --source . \
        --ingress external \
        --target-port 8080
    
  4. CORS konfigurálása:

    az containerapp ingress cors enable \
        --name $APP_NAME \
        --resource-group $RESOURCE_GROUP \
        --allowed-origins "*" \
        --allowed-methods "GET,POST,DELETE,OPTIONS" \
        --allowed-headers "*"
    

    Megjegyzés:

    A gyártásban cserélje le a helyettesítő eredeteket meghatározott, megbízható eredetekre. Lásd: Biztonságos MCP-kiszolgálók a Container Appsben.

  5. Ellenőrizze az üzembe helyezést:

    APP_URL=$(az containerapp show \
        --name $APP_NAME \
        --resource-group $RESOURCE_GROUP \
        --query "properties.configuration.ingress.fqdn" -o tsv)
    
    curl https://$APP_URL/health
    

A GitHub Copilot csatlakoztatása az üzembe helyezett kiszolgálóhoz

Most, hogy az MCP-kiszolgáló az Azure-ban fut, konfigurálja a VS Code-ot a GitHub Copilot üzembe helyezett végponthoz való csatlakoztatásához.

  1. Létrehozás vagy frissítés .vscode/mcp.json:

    {
        "servers": {
            "tasks-mcp-server": {
                "type": "http",
                "url": "https://<your-app-fqdn>/mcp"
            }
        }
    }
    

    Cserélje le <your-app-fqdn> a központi telepítési kimenet teljes tartománynevét.

  2. A VS Code-ban nyissa meg a Copilot-csevegést ügynök módban.

  3. Az Ellenőrzés tasks-mcp-server megjelenik az Eszközök listában. Szükség esetén válassza a Start lehetőséget.

  4. Teszteljen egy " Feladat létrehozása az előkészítési környezet üzembe helyezéséhez" üzenettel.

Skálázás konfigurálása interaktív használatra

Az Azure Container Apps alapértelmezés szerint nulla replikára skálázható. Az olyan interaktív ügyfeleket kiszolgáló MCP-kiszolgálók esetében, mint a Copilot, a hidegindítások észrevehető késéseket okoznak. Állítson be egy minimális replikaszámot, hogy legalább egy példány fusson:

az containerapp update \
    --name $APP_NAME \
    --resource-group $RESOURCE_GROUP \
    --min-replicas 1

Biztonsági szempontok

Ez az oktatóanyag egy nem hitelesített MCP-kiszolgálót használ az egyszerűség kedvéért. Mielőtt éles környezetben futtat egy MCP-kiszolgálót, tekintse át az alábbi javaslatokat. Amikor egy nagy nyelvi modellekkel (LLM-ekkel) rendelkező ügynök meghívja az MCP-kiszolgálót, vegye figyelembe a gyors injektálási támadásokat.

  • Hitelesítés és engedélyezés: Az MCP-kiszolgáló védelme a Microsoft Entra-azonosítóval. Lásd: Biztonságos MCP-kiszolgálók a Container Appsben.
  • Bemeneti ellenőrzés: Mindig ellenőrizze az eszköz paramétereit. A Pydantic használatával kényszerítheti az adatérvényesítést az eszközbemeneteken.
  • HTTPS: Az Azure Container Apps alapértelmezés szerint automatikus TLS-tanúsítványokkal kényszeríti a HTTPS-t.
  • Minimális jogosultság: Csak azokat az eszközöket tegye elérhetővé, amelyet a használati eset igényel. Kerülje azokat az eszközöket, amelyek megerősítés nélkül végeznek romboló műveleteket.
  • CORS: Az engedélyezett források korlátozása az éles környezetben megbízható tartományokra.
  • Naplózás és figyelés: Az MCP-eszközök meghívásainak naplózása audit céljából. Használja az Azure Monitort és a Log Analyticset.

Erőforrások tisztítása

Ha nem tervezi folytatni az alkalmazás használatát, törölje az erőforráscsoportot az oktatóanyagban létrehozott összes erőforrás eltávolításához:

az group delete --resource-group $RESOURCE_GROUP --yes --no-wait

Következő lépés