Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом руководстве вы создадите сервер протокола Model Context Protocol (MCP), открывающий средства управления задачами с помощью FastAPI и пакета MCP Python SDK. Вы развертываете сервер в приложениях контейнеров Azure и подключаетесь к нему из чата GitHub Copilot в VS Code.
Изучив это руководство, вы:
- Создание приложения FastAPI, предоставляющего средства MCP
- Тестирование сервера MCP локально с помощью GitHub Copilot
- Контейнеризация и развертывание приложения в приложениях контейнеров Azure
- Подключите GitHub Copilot к развернутому серверу MCP
Предпосылки
- Учетная запись Azure с активной подпиской. Создайте его бесплатно.
- Azure CLI версии 2.62.0 или более поздней.
- Python 3.10 или более поздней версии.
- Visual Studio Code с расширением GitHub Copilot .
- Docker Desktop (необязательно) требуется только для локального тестирования контейнера.
Создайте каркас приложения
В этом разделе вы создаете новый проект на Python с FastAPI и SDK MCP для Python.
Создайте каталог проекта и настройте виртуальную среду:
mkdir tasks-mcp-server && cd tasks-mcp-server python -m venv .venv source .venv/bin/activateСоздание
requirements.txt:fastapi>=0.115.0 uvicorn>=0.30.0 mcp[cli]>=1.2.0Установите зависимости:
pip install -r requirements.txtСоздайте
task_store.pyдля хранилища данных в памяти: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()Класс
TaskItemданных определяет модель данных с методомto_dict()сериализации. КлассTaskStoreуправляет списком в памяти, предварительно заполненным примерами данных и предоставляет методы CRUD. Одноэлементный объект уровня модуляstoreиспользуется во всем приложении для простоты.
Определение средств MCP
В этом разделе описаны средства MCP, которые модель ИИ может вызывать и подключать сервер MCP в приложении FastAPI.
Создание
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."Основные моменты:
-
FastMCP("TasksMCP", stateless_http=True)создает сервер MCP с помощью шаблона HTTP без отслеживания состояния в пакете SDK для Python. По умолчанию потоковое подключение HTTP указывает на/mcpподпуть. - Каждая
@mcp.tool()функция становится вызываемым инструментом. Документация по функциям и заметки параметров помогают модели ИИ понять, как использовать каждое средство.
-
Создайте
app.py. Этот файл определяет приложение FastAPI, которое подключает сервер 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"})Приложение сервера MCP монтируется на корневой директории (
/). Потоковая конечная точка HTTP пакета SDK по умолчанию имеет/mcpзначение, поэтому полный путь к конечной точке равен/mcp./healthОтдельная конечная точка используется для проверок работоспособности контейнерных приложений. Конечные точки MCP ожидают JSON-RPC запросов POST и не подходят для проверки работоспособности.
Тестирование сервера MCP локально
Перед развертыванием в Azure убедитесь, что сервер MCP работает, запустив его локально и подключившись к нему с помощью GitHub Copilot.
Запустите приложение:
uvicorn app:app --reload --port 8080Откройте VS Code, а затем откройте чат Copilot и выберите режим агента .
Нажмите кнопку "Сервис" , а затем нажмите кнопку "Добавить дополнительные инструменты" ...>Добавьте СЕРВЕР MCP.
Выберите HTTP (HTTP или Server-Sent события).
Введите URL-адрес сервера:
http://localhost:8080/mcpВведите идентификатор сервера:
tasks-mcpВыберите параметры рабочей области.
В новом запросе чата Copilot введите "Показать мне все задачи"
Нажмите кнопку "Продолжить", когда Copilot запрашивает подтверждение средства MCP.
Вы увидите список задач, возвращенный из выделенного в памяти хранилища.
Подсказка
Попробуйте использовать другие запросы, такие как "Создать задачу для проверки pr", "Пометить задачу 1 как завершенную" или "Удалить задачу 2".
Помещение приложения в контейнер
Упаковайте приложение как контейнер Docker, чтобы протестировать его локально перед развертыванием в Azure.
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 использует базовый образ Python 3.12, устанавливает зависимости из
requirements.txt, а затем копирует код приложения. Uvicorn обслуживает приложение FastAPI через порт 8080.Проверьте сборку контейнера и выполняется локально:
docker build -t tasks-mcp-server . docker run -p 8080:8080 tasks-mcp-serverУбедитесь, что точка проверки работоспособности отвечает:
curl http://localhost:8080/health
Развертывание в приложениях контейнеров Azure
После контейнеризации приложения разверните его в приложениях контейнеров Azure с помощью Azure CLI. Команда az containerapp up создает образ контейнера в облаке, поэтому для этого шага не требуется Docker.
Задайте переменные среды:
RESOURCE_GROUP="mcp-tutorial-rg" LOCATION="eastus" ENVIRONMENT_NAME="mcp-env" APP_NAME="tasks-mcp-server-py"Создайте группу ресурсов и среду для контейнерных приложений:
az group create --name $RESOURCE_GROUP --location $LOCATION az containerapp env create \ --name $ENVIRONMENT_NAME \ --resource-group $RESOURCE_GROUP \ --location $LOCATIONРазверните приложение контейнера:
az containerapp up \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --environment $ENVIRONMENT_NAME \ --source . \ --ingress external \ --target-port 8080Настройка CORS:
az containerapp ingress cors enable \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --allowed-origins "*" \ --allowed-methods "GET,POST,DELETE,OPTIONS" \ --allowed-headers "*"Замечание
Для продакшна замените подстановочные знаки определенными доверенными источниками. См. раздел "Безопасные серверы MCP" в приложениях контейнеров.
Проверьте развертывание:
APP_URL=$(az containerapp show \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --query "properties.configuration.ingress.fqdn" -o tsv) curl https://$APP_URL/health
Подключите GitHub Copilot к развернутому серверу
Теперь, когда сервер MCP запущен в Azure, настройте VS Code для подключения GitHub Copilot к развернутой конечной точке.
Создание или обновление
.vscode/mcp.json:{ "servers": { "tasks-mcp-server": { "type": "http", "url": "https://<your-app-fqdn>/mcp" } } }Замените
<your-app-fqdn>полным доменным именем из выходных данных развертывания.В VS Code откройте чат Copilot в режиме агента.
Убедитесь, что
tasks-mcp-serverотображается в списке инструментов. При необходимости нажмите кнопку "Пуск ".Проверьте запрос, например "Создать задачу для развертывания промежуточной среды".
Настройка масштабирования для интерактивного использования
По умолчанию приложения контейнеров Azure могут масштабироваться до нуля реплик. Для серверов MCP, которые обслуживают интерактивных клиентов, таких как Copilot, холодные запуски вызывают заметные задержки. Задайте минимальное число реплик для поддержания по крайней мере одного экземпляра:
az containerapp update \
--name $APP_NAME \
--resource-group $RESOURCE_GROUP \
--min-replicas 1
Вопросы безопасности
В этом руководстве для простоты используется неавтоентизованный сервер MCP. Перед запуском сервера MCP в рабочей среде ознакомьтесь со следующими рекомендациями. Когда агент, работающий на больших языковых моделях (LLM), вызывает сервер MCP, учитывайте атаки инъекции команд.
- Проверка подлинности и авторизация. Защита сервера MCP с помощью идентификатора Microsoft Entra. См. раздел "Безопасные серверы MCP" в приложениях контейнеров.
- Проверка входных данных: всегда проверяйте параметры средства. Используйте Pydantic для принудительной валидации входных данных инструментов.
- HTTPS: приложения контейнеров Azure по умолчанию применяют ПРОТОКОЛ HTTPS с автоматическими сертификатами TLS.
- Минимальные привилегии: предоставляйте только те инструменты, которые требуются для вашего случая. Избегайте средств, выполняющих разрушительные операции без подтверждения.
- CORS: ограничение разрешенных источников доверенным доменам в рабочей среде.
- Ведение журнала и мониторинг: Запись вызовов инструментов MCP для аудита. Используйте Azure Monitor и Log Analytics.
Очистите ресурсы
Если вы не планируете продолжать использовать это приложение, удалите группу ресурсов, чтобы удалить все ресурсы, созданные в этом руководстве:
az group delete --resource-group $RESOURCE_GROUP --yes --no-wait
Следующий шаг
Связанный контент
- Общие сведения о серверах MCP в приложениях контейнеров Azure
- Развертывание сервера MCP в приложениях-контейнерах (.NET)
- Развертывание сервера MCP в контейнерных приложениях (Node.js)
- Развертывание сервера MCP в приложениях контейнеров (Java)
- Устранение неполадок серверов MCP в приложениях контейнеров
- MCP Python SDK