Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Dalam tutorial ini, Anda membangun server Protokol Konteks Model (MCP) yang mengekspos alat manajemen tugas dengan menggunakan FastAPI dan MCP Python SDK. Anda menyebarkan server ke Azure Container Apps dan menghubungkannya dari GitHub Copilot Chat di VS Code.
Di tutorial ini, Anda akan:
- Membuat aplikasi FastAPI yang mengekspos alat MCP
- Menguji server MCP secara lokal dengan GitHub Copilot
- Kontainerisasi dan sebarkan aplikasi ke Azure Container Apps
- Menyambungkan GitHub Copilot ke server MCP yang disebarkan
Prasyarat
- Sebuah akun Azure dengan langganan aktif. Buat akun gratis.
- Azure CLI versi 2.62.0 atau yang lebih baru.
- Python 3.10 atau yang lebih baru.
- Visual Studio Code dengan ekstensi GitHub Copilot .
- Docker Desktop (opsional - hanya diperlukan untuk menguji kontainer secara lokal).
Membuat perancah aplikasi
Di bagian ini, Anda membuat proyek Python baru dengan FastAPI dan MCP Python SDK.
Buat direktori proyek dan siapkan lingkungan virtual:
mkdir tasks-mcp-server && cd tasks-mcp-server python -m venv .venv source .venv/bin/activateBuat
requirements.txt:fastapi>=0.115.0 uvicorn>=0.30.0 mcp[cli]>=1.2.0Instal dependensi:
pip install -r requirements.txtBuat
task_store.pyuntuk penyimpanan data dalam memori: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()Klasifikasi
TaskItemdata menentukan model data denganto_dict()metode untuk serialisasi. KelasTaskStoremengelola daftar dalam memori yang telah diisi sebelumnya dengan data sampel dan menyediakan metode CRUD. Singleton level modulstoreini dibagikan di seluruh aplikasi untuk memudahkan pengelolaan atau penggunaan.
Tentukan alat MCP
Di bagian ini, Anda menentukan alat MCP yang dapat dipanggil model AI dan memasang server MCP di aplikasi FastAPI Anda.
Buat
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."Poin utama:
-
FastMCP("TasksMCP", stateless_http=True)membuat server MCP menggunakan pola HTTP stateless di Python SDK. Titik akhir HTTP yang dapat dialirkan mengarah secara default ke subjalur/mcp. - Setiap
@mcp.tool()fungsi menjadi alat yang dapat dipanggil. Fungsi docstring dan anotasi parameter membantu model AI memahami cara menggunakan setiap alat.
-
Buat
app.py. File ini mendefinisikan aplikasi FastAPI yang memasang server 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"})Aplikasi server MCP dipasang di root (
/). Titik akhir HTTP SDK yang dapat dialirkan default ke/mcp, sehingga jalur titik akhir lengkap adalah/mcp.Titik akhir terpisah
/healthdigunakan untuk pemeriksaan kesehatan Container Apps. Titik akhir MCP mengharapkan permintaan JSON-RPC POST dan tidak cocok sebagai pemeriksaan kesehatan.
Menguji server MCP secara lokal
Sebelum menyebarkan ke Azure, verifikasi server MCP berfungsi dengan menjalankannya secara lokal dan menyambungkan dari GitHub Copilot.
Mulai aplikasi:
uvicorn app:app --reload --port 8080Buka Visual Studio Code, lalu buka Obrolan Copilot dan pilih Mode agen .
Pilih tombol Alat , lalu pilih Tambahkan Alat Lainnya...>Tambahkan Server MCP.
Pilih HTTP (HTTP atau Event Server-Sent).
Masukkan URL server:
http://localhost:8080/mcpMasukkan ID server:
tasks-mcpPilih Pengaturan Ruang Kerja.
Dalam permintaan Obrolan Copilot baru, ketik: "Tampilkan saya semua tugas"
Pilih Lanjutkan saat Copilot meminta konfirmasi alat MCP.
Anda akan melihat daftar tugas yang dikembalikan dari penyimpanan dalam memori Anda.
Petunjuk / Saran
Coba perintah lain seperti "Buat tugas untuk meninjau PR", "Tandai tugas 1 sebagai selesai", atau "Hapus tugas 2".
Menerapkan kontainer pada aplikasi
Kemas aplikasi sebagai kontainer Docker sehingga Anda dapat mengujinya secara lokal sebelum menyebarkan ke Azure.
Buat
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"]Dockerfile menggunakan gambar dasar ramping Python 3.12, menginstal dependensi dari
requirements.txt, lalu menyalin kode aplikasi. Uvicorn melayani aplikasi FastAPI di port 8080.Verifikasi pembangunan dan menjalankan kontainer secara lokal:
docker build -t tasks-mcp-server . docker run -p 8080:8080 tasks-mcp-serverPastikan endpoint kesehatan merespons:
curl http://localhost:8080/health
Menyebarkan ke Azure Container Apps
Setelah Anda membuat kontainer aplikasi, sebarkan ke Azure Container Apps dengan menggunakan Azure CLI. Perintah ini az containerapp up membangun gambar kontainer di cloud, sehingga Anda tidak memerlukan Docker di komputer Anda untuk langkah ini.
Atur variabel lingkungan:
RESOURCE_GROUP="mcp-tutorial-rg" LOCATION="eastus" ENVIRONMENT_NAME="mcp-env" APP_NAME="tasks-mcp-server-py"Buat grup sumber daya dan lingkungan Container Apps:
az group create --name $RESOURCE_GROUP --location $LOCATION az containerapp env create \ --name $ENVIRONMENT_NAME \ --resource-group $RESOURCE_GROUP \ --location $LOCATIONSebarkan aplikasi kontainer:
az containerapp up \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --environment $ENVIRONMENT_NAME \ --source . \ --ingress external \ --target-port 8080Mengonfigurasi CORS:
az containerapp ingress cors enable \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --allowed-origins "*" \ --allowed-methods "GET,POST,DELETE,OPTIONS" \ --allowed-headers "*"Nota
Untuk produksi, ganti asal wildcard dengan asal tepercaya yang spesifik. Lihat Mengamankan server MCP di Container Apps.
Verifikasi penyebaran:
APP_URL=$(az containerapp show \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --query "properties.configuration.ingress.fqdn" -o tsv) curl https://$APP_URL/health
Menyambungkan GitHub Copilot ke server yang disebarkan
Sekarang setelah server MCP berjalan di Azure, konfigurasikan VS Code untuk menyambungkan GitHub Copilot ke endpoint yang telah diterapkan.
Buat atau perbarui
.vscode/mcp.json:{ "servers": { "tasks-mcp-server": { "type": "http", "url": "https://<your-app-fqdn>/mcp" } } }Ganti
<your-app-fqdn>dengan FQDN dari output penyebaran.Di Visual Studio Code, buka Copilot Chat dalam mode Agent.
Verifikasi
tasks-mcp-servermuncul di daftar Alat. Pilih Mulai jika diperlukan.Mengujilah dengan perintah seperti "Buat tugas untuk mengimplementasikan lingkungan penahapan".
Mengonfigurasi penskalaan untuk penggunaan interaktif
Secara default, Azure Container Apps dapat menskalakan ke nol replika. Untuk server MCP yang melayani klien interaktif seperti Copilot, cold start menyebabkan penundaan yang nyata. Atur jumlah replika minimum untuk menjaga setidaknya satu instans tetap berjalan:
az containerapp update \
--name $APP_NAME \
--resource-group $RESOURCE_GROUP \
--min-replicas 1
Pertimbangan keamanan
Tutorial ini menggunakan server MCP yang tidak diaauthenticated untuk kesederhanaan. Sebelum menjalankan server MCP dalam produksi, tinjau rekomendasi berikut. Ketika agen yang didukung oleh model bahasa besar (LLM) memanggil server MCP Anda, waspadai serangan injeksi yang cepat .
- Autentikasi dan otorisasi: Amankan server MCP Anda dengan ID Microsoft Entra. Lihat Mengamankan server MCP di Container Apps.
- Validasi input: Selalu validasi parameter alat. Gunakan Pydantic untuk menerapkan validasi data pada input alat.
- HTTPS: Azure Container Apps memberlakukan HTTPS secara default dengan sertifikat TLS otomatis.
- Hak istimewa terkecil: Hanya mengekspos alat yang diperlukan kasus penggunaan Anda. Hindari alat yang melakukan operasi destruktif tanpa konfirmasi.
- CORS: Membatasi asal yang diizinkan ke domain tepercaya di lingkungan produksi.
- Pencatatan dan Pemantauan: Pemanggilan alat MCP dicatat untuk audit. Gunakan Azure Monitor dan Analitik Log.
Membersihkan sumber daya
Jika Anda tidak berencana untuk terus menggunakan aplikasi ini, hapus grup sumber daya untuk menghapus semua sumber daya yang Anda buat dalam tutorial ini:
az group delete --resource-group $RESOURCE_GROUP --yes --no-wait