1. Введение
Обзор
В этой лабораторной работе вы создадите и развернете сервер протокола контекста модели (MCP) . Серверы MCP полезны для предоставления студентам магистратуры доступа к внешним инструментам и сервисам. Вы настроите его как безопасный, готовый к использованию в производственной среде сервис в Cloud Run, к которому можно будет получить доступ с нескольких клиентов. Затем вы подключитесь к удаленному серверу MCP из командной строки Gemini.
Что вы будете делать
Мы будем использовать FastMCP для создания MCP-сервера для зоопарка , который будет содержать два инструмента: get_animals_by_species и get_animal_details . FastMCP предоставляет быстрый и понятный с точки зрения Python способ создания MCP-серверов и клиентов.

Что вы узнаете
- Разверните сервер MCP в Cloud Run.
- Защитите конечную точку вашего сервера, требуя аутентификации для всех запросов, чтобы гарантировать, что только авторизованные клиенты и агенты могут взаимодействовать с ним.
- Подключитесь к защищенной конечной точке вашего сервера MCP из Gemini CLI.
2. Настройка проекта
- Если у вас еще нет учетной записи Google, вам необходимо ее создать .
- Используйте личный аккаунт вместо рабочего или учебного. Рабочие и учебные аккаунты могут иметь ограничения, которые не позволят вам включить API, необходимые для этой лабораторной работы.
- Войдите в консоль Google Cloud .
- Включите выставление счетов в облачной консоли.
- Выполнение этой лабораторной работы должно обойтись менее чем в 1 доллар США в виде облачных ресурсов.
- В конце этой лабораторной работы вы можете выполнить действия по удалению ресурсов, чтобы избежать дальнейших списаний средств.
- Новые пользователи могут воспользоваться бесплатной пробной версией стоимостью 300 долларов США .
- Создайте новый проект или выберите вариант повторного использования существующего проекта.
- Если вы видите ошибку, связанную с квотой проекта, используйте существующий проект повторно или удалите существующий проект, чтобы создать новый.
3. Откройте редактор Cloud Shell.
- Нажмите на эту ссылку, чтобы перейти непосредственно в редактор Cloud Shell.
- Если сегодня вам будет предложено авторизоваться, нажмите «Авторизовать» , чтобы продолжить.

- Если терминал не отображается внизу экрана, откройте его:
- Нажмите «Просмотреть».
- Нажмите «Терминал»

- В терминале настройте свой проект с помощью этой команды:
- Формат:
gcloud config set project [PROJECT_ID] - Пример:
gcloud config set project lab-project-id-example - Если вы не помните идентификатор своего проекта:
- Вы можете вывести список всех идентификаторов ваших проектов с помощью:
gcloud projects list | awk '/PROJECT_ID/{print $2}'

- Вы можете вывести список всех идентификаторов ваших проектов с помощью:
- Формат:
- Вы должны увидеть следующее сообщение:
Если вы видитеUpdated property [core/project].
WARNINGи вас спрашиваютDo you want to continue (Y/n)?, то, скорее всего, вы неправильно ввели идентификатор проекта. Нажмитеn, затемEnterи попробуйте снова выполнить командуgcloud config set project.
4. Включите API.
В терминале включите API:
gcloud services enable \
run.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com
Если появится запрос на авторизацию, нажмите «Авторизовать» , чтобы продолжить. 
Выполнение этой команды может занять несколько минут, но в итоге должно отобразиться сообщение об успешном завершении, похожее на это:
Operation "operations/acf.p2-73d90d00-47ee-447a-b600" finished successfully.
5. Подготовьте свой проект на Python.
- Создайте папку с именем
mcp-on-cloudrunдля хранения исходного кода, необходимого для развертывания:mkdir mcp-on-cloudrun && cd mcp-on-cloudrun - Создайте проект Python с помощью инструмента
uv, чтобы сгенерировать файлpyproject.toml: Командаuv init --description "Example of deploying an MCP server on Cloud Run" --bare --python 3.13uv initсоздает файл `pyproject.tomlдля вашего проекта. Чтобы просмотреть содержимое файла, выполните следующую команду: Результат должен выглядеть следующим образом:cat pyproject.toml[project] name = "mcp-on-cloudrun" version = "0.1.0" description = "Example of deploying an MCP server on Cloud Run" requires-python = ">=3.13" dependencies = []
6. Создайте сервер MCP для зоопарка.
Чтобы обеспечить ценный контекст для улучшения использования LLM с MCP, настройте сервер MCP для зоопарка с помощью FastMCP — стандартной платформы для работы с протоколом контекста модели. FastMCP предоставляет быстрый способ создания серверов и клиентов MCP с помощью Python. Этот сервер MCP предоставляет данные о животных в вымышленном зоопарке. Для простоты мы храним данные в памяти. Для производственного сервера MCP вам, вероятно, потребуется предоставлять данные из таких источников, как базы данных или API.
- Выполните следующую команду, чтобы добавить FastMCP в качестве зависимости в файл
pyproject.toml: Это добавит файлuv add fastmcp==2.12.4 --no-syncuv.lockв ваш проект. - Создайте и откройте новый файл
server.pyс исходным кодом сервера MCP: Командаcloudshell edit ~/mcp-on-cloudrun/server.pycloudshell editоткроет файлserver.pyв редакторе, расположенном над терминалом. - Добавьте следующий исходный код сервера zoo MCP в файл
server.py:import asyncio import logging import os from typing import List, Dict, Any from fastmcp import FastMCP logger = logging.getLogger(__name__) logging.basicConfig(format="[%(levelname)s]: %(message)s", level=logging.INFO) mcp = FastMCP("Zoo Animal MCP Server 🦁🐧🐻") # Dictionary of animals at the zoo ZOO_ANIMALS = [ { "species": "lion", "name": "Leo", "age": 7, "enclosure": "The Big Cat Plains", "trail": "Savannah Heights" }, { "species": "lion", "name": "Nala", "age": 6, "enclosure": "The Big Cat Plains", "trail": "Savannah Heights" }, { "species": "lion", "name": "Simba", "age": 3, "enclosure": "The Big Cat Plains", "trail": "Savannah Heights" }, { "species": "lion", "name": "King", "age": 8, "enclosure": "The Big Cat Plains", "trail": "Savannah Heights" }, { "species": "penguin", "name": "Waddles", "age": 2, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "penguin", "name": "Pip", "age": 4, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "penguin", "name": "Skipper", "age": 5, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "penguin", "name": "Chilly", "age": 3, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "penguin", "name": "Pingu", "age": 6, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "penguin", "name": "Noot", "age": 1, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "elephant", "name": "Ellie", "age": 15, "enclosure": "The Pachyderm Sanctuary", "trail": "Savannah Heights" }, { "species": "elephant", "name": "Peanut", "age": 12, "enclosure": "The Pachyderm Sanctuary", "trail": "Savannah Heights" }, { "species": "elephant", "name": "Dumbo", "age": 5, "enclosure": "The Pachyderm Sanctuary", "trail": "Savannah Heights" }, { "species": "elephant", "name": "Trunkers", "age": 10, "enclosure": "The Pachyderm Sanctuary", "trail": "Savannah Heights" }, { "species": "bear", "name": "Smokey", "age": 10, "enclosure": "The Grizzly Gulch", "trail": "Polar Path" }, { "species": "bear", "name": "Grizzly", "age": 8, "enclosure": "The Grizzly Gulch", "trail": "Polar Path" }, { "species": "bear", "name": "Barnaby", "age": 6, "enclosure": "The Grizzly Gulch", "trail": "Polar Path" }, { "species": "bear", "name": "Bruin", "age": 12, "enclosure": "The Grizzly Gulch", "trail": "Polar Path" }, { "species": "giraffe", "name": "Gerald", "age": 4, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "giraffe", "name": "Longneck", "age": 5, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "giraffe", "name": "Patches", "age": 3, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "giraffe", "name": "Stretch", "age": 6, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "antelope", "name": "Speedy", "age": 2, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "antelope", "name": "Dash", "age": 3, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "antelope", "name": "Gazelle", "age": 4, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "antelope", "name": "Swift", "age": 5, "enclosure": "The Tall Grass Plains", "trail": "Savannah Heights" }, { "species": "polar bear", "name": "Snowflake", "age": 7, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "polar bear", "name": "Blizzard", "age": 5, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "polar bear", "name": "Iceberg", "age": 9, "enclosure": "The Arctic Exhibit", "trail": "Polar Path" }, { "species": "walrus", "name": "Wally", "age": 10, "enclosure": "The Walrus Cove", "trail": "Polar Path" }, { "species": "walrus", "name": "Tusker", "age": 12, "enclosure": "The Walrus Cove", "trail": "Polar Path" }, { "species": "walrus", "name": "Moby", "age": 8, "enclosure": "The Walrus Cove", "trail": "Polar Path" }, { "species": "walrus", "name": "Flippers", "age": 9, "enclosure": "The Walrus Cove", "trail": "Polar Path" } ] @mcp.tool() def get_animals_by_species(species: str) -> List[Dict[str, Any]]: """ Retrieves all animals of a specific species from the zoo. Can also be used to collect the base data for aggregate queries of animals of a specific species - like counting the number of penguins or finding the oldest lion. Args: species: The species of the animal (e.g., 'lion', 'penguin'). Returns: A list of dictionaries, where each dictionary represents an animal and contains details like name, age, enclosure, and trail. """ logger.info(f">>> 🛠️ Tool: 'get_animals_by_species' called for '{species}'") return [animal for animal in ZOO_ANIMALS if animal["species"].lower() == species.lower()] @mcp.tool() def get_animal_details(name: str) -> Dict[str, Any]: """ Retrieves the details of a specific animal by its name. Args: name: The name of the animal. Returns: A dictionary with the animal's details (species, name, age, enclosure, trail) or an empty dictionary if the animal is not found. """ logger.info(f">>> 🛠️ Tool: 'get_animal_details' called for '{name}'") for animal in ZOO_ANIMALS: if animal["name"].lower() == name.lower(): return animal return {} if __name__ == "__main__": port = int(os.getenv("PORT", 8080)) logger.info(f"🚀 MCP server started on port {port}") asyncio.run( mcp.run_async( transport="http", host="0.0.0.0", port=port, ) )
Ваш код готов! Теперь пора развернуть сервер MCP в Cloud Run.
7. Развертывание в облаке
Теперь разверните сервер MCP в Cloud Run непосредственно из исходного кода.
- Создайте и откройте новый
Dockerfileдля развертывания в Cloud Run:cloudshell edit ~/mcp-on-cloudrun/Dockerfile - Добавьте следующий код в Dockerfile, чтобы использовать инструмент
uvдля запуска файлаserver.py:# Use the official Python image FROM python:3.13-slim # Install uv COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ # Install the project into /app COPY . /app WORKDIR /app # Allow statements and log messages to immediately appear in the logs ENV PYTHONUNBUFFERED=1 # Install dependencies RUN uv sync EXPOSE $PORT # Run the FastMCP server CMD ["uv", "run", "server.py"] - Создайте учетную запись службы с именем
mcp-server-sa:gcloud iam service-accounts create mcp-server-sa --display-name="MCP Server Service Account" - Выполните команду
gcloud, чтобы развернуть приложение в Cloud Run. Используйте флагcd ~/mcp-on-cloudrun gcloud run deploy zoo-mcp-server \ --service-account=mcp-server-sa@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \ --no-allow-unauthenticated \ --region=europe-west1 \ --source=. \ --labels=dev-tutorial=codelab-mcp--no-allow-unauthenticatedчтобы потребовать аутентификацию. Это важно по соображениям безопасности. Если аутентификация не требуется, любой может обратиться к вашему MCP-серверу и потенциально нанести ущерб вашей системе. - Подтвердите создание нового репозитория Artifact Registry. Поскольку вы впервые развертываете приложение в Cloud Run из исходного кода, вы увидите следующее:
ВведитеDeploying from source requires an Artifact Registry Docker repository to store built containers. A repository named [cloud-run-source-deploy] in region [europe-west1] will be created. Do you want to continue (Y/n)?
Yи нажмитеEnter. Это создаст репозиторий Artifact Registry для вашего развертывания. Это необходимо для хранения контейнера Docker сервера MCP для службы Cloud Run. - Через несколько минут вы увидите сообщение следующего вида:
Service [zoo-mcp-server] revision [zoo-mcp-server-12345-abc] has been deployed and is serving 100 percent of traffic.
Вы развернули свой MCP-сервер. Теперь вы можете им пользоваться.
8. Добавьте удаленный сервер MCP в Gemini CLI.
Теперь, когда вы успешно развернули удаленный сервер MCP, вы можете подключиться к нему с помощью различных приложений, таких как Google Code Assist или Gemini CLI. В этом разделе мы установим соединение с вашим новым удаленным сервером MCP с помощью Gemini CLI .
- Предоставьте вашей учетной записи пользователя разрешение на обращение к удаленному серверу MCP.
gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \ --member=user:$(gcloud config get-value account) \ --role='roles/run.invoker' - Сохраните свои учетные данные Google Cloud и номер проекта в переменных среды для использования в файле настроек Gemini:
export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)") export ID_TOKEN=$(gcloud auth print-identity-token) - Создайте папку
.gemini, если она еще не создана.mkdir -p ~/.gemini - Откройте файл настроек Gemini CLI.
cloudshell edit ~/.gemini/settings.json - Замените файл настроек Gemini CLI, чтобы добавить сервер Cloud Run MCP.
{ "ide": { "hasSeenNudge": true }, "mcpServers": { "zoo-remote": { "httpUrl": "https://zoo-mcp-server-$PROJECT_NUMBER.europe-west1.run.app/mcp", "headers": { "Authorization": "Bearer $ID_TOKEN" } } }, "security": { "auth": { "selectedType": "cloud-shell" } } } - Запустите интерфейс командной строки Gemini в Cloud Shell.
Возможно, вам потребуется нажатьgeminiEnter, чтобы принять некоторые настройки по умолчанию.
- Пусть Gemini перечислит доступные ей инструменты MCP в контексте её деятельности.
/mcp - Попросите Близнецов найти что-нибудь в зоопарке.
Интерфейс командной строки Gemini должен знать, что нужно использовать сервер MCPWhere can I find penguins?zoo-remote, и спросит, хотите ли вы разрешить выполнение MCP. - Воспользуйтесь стрелкой вниз, затем нажмите
Enter, чтобы выбратьYes, always allow all tools from server "zoo-remote"

В результате должен отобразиться правильный ответ и окно, указывающее на использование сервера MCP.

У вас получилось! Вы успешно развернули удаленный сервер MCP в Cloud Run и протестировали его с помощью Gemini CLI.
Когда вы будете готовы завершить сессию, введите /quit и нажмите Enter , чтобы выйти из Gemini CLI.
Отладка
Если вы видите ошибку подобного рода:
🔍 Attempting OAuth discovery for 'zoo-remote'... ❌ 'zoo-remote' requires authentication but no OAuth configuration found Error connecting to MCP server 'zoo-remote': MCP server 'zoo-remote' requires authentication. Please configure OAuth or check server settings.
Вероятно, срок действия ID-токена истек, и требуется повторная установка значения ID_TOKEN .
- Введите
/quitи нажмитеEnter, чтобы выйти из Gemini CLI. - Настройте свой проект в терминале.
gcloud config set project [PROJECT_ID] - Начните заново с шага 2, описанного выше.
9. (Необязательно) Проверьте вызовы инструментов в журналах сервера.
Чтобы убедиться, что ваш сервер Cloud Run MCP был вызван, проверьте журналы службы.
gcloud run services logs read zoo-mcp-server --region europe-west1 --limit=5
Вы должны увидеть сообщение в журнале, подтверждающее, что был выполнен вызов инструмента. 🛠️
2025-08-05 19:50:31 INFO: 169.254.169.126:39444 - "POST /mcp HTTP/1.1" 200 OK 2025-08-05 19:50:31 [INFO]: Processing request of type CallToolRequest 2025-08-05 19:50:31 [INFO]: >>> 🛠️ Tool: 'get_animals_by_species' called for 'penguin'
10. (Необязательно) Добавить приглашение MCP на сервер.
Использование командной строки MCP может ускорить рабочий процесс для часто используемых вами запросов, создавая сокращенную запись для более длинных запросов.
Gemini CLI автоматически преобразует приглашения командной строки MCP в пользовательские команды со слэшем , так что вы можете вызвать приглашение командной строки MCP, набрав /prompt_name где prompt_name — это имя вашего приглашения командной строки MCP.
Создайте командную строку MCP, чтобы быстро находить животных в зоопарке, вводя команду /find animal в Gemini CLI.
- Добавьте этот код в файл
server.pyперед основным блоком guard (if __name__ == "__main__":)@mcp.prompt() def find(animal: str) -> str: """ Find which exhibit and trail a specific animal might be located. """ return ( f"Please find the exhibit and trail information for {animal} in the zoo. " f"Respond with '[animal] can be found in the [exhibit] on the [trail].'" f"Example: Penguins can be found in The Arctic Exhibit on the Polar Path." ) - Переразверните приложение в Cloud Run.
gcloud run deploy zoo-mcp-server \ --region=europe-west1 \ --source=. \ --labels=dev-tutorial=codelab-mcp - Обновите значение ID_TOKEN для вашего удаленного сервера MCP.
export ID_TOKEN=$(gcloud auth print-identity-token) - После развертывания новой версии вашего приложения запустите Gemini CLI.
gemini - В командной строке используйте созданную вами новую пользовательскую команду:
ИЛИ/find --animal="lions"/find lions
Вы должны увидеть, что Gemini CLI вызывает инструмент get_animals_by_species и форматирует ответ в соответствии с указаниями командной строки MCP!
╭───────────────────────────╮
│ > /find --animal="lion" │
╰───────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✔ get_animals_by_species (zoo-remote MCP Server) get_animals_by_species (zoo-remote MCP Server) │
│ │
│ [{"species":"lion","name":"Leo","age":7,"enclosure":"The Big Cat │
│ Plains","trail":"Savannah │
│ Heights"},{"species":"lion","name":"Nala","age":6,"enclosure":"The Big Cat │
│ Plains","trail":"Savannah │
│ Heights"},{"species":"lion","name":"Simba","age":3,"enclosure":"The Big Cat │
│ Plains","trail":"Savannah │
│ Heights"},{"species":"lion","name":"King","age":8,"enclosure":"The Big Cat │
│ Plains","trail":"Savannah Heights"}] │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ Lions can be found in The Big Cat Plains on the Savannah Heights.
11. (Необязательно) Используйте Gemini Flash Lite для более быстрой реакции.
Gemini CLI позволяет выбрать используемую модель.
- Gemini 2.5 Pro — это передовая модель мышления от Google, способная рассуждать над сложными задачами в области программирования, математики и STEM-дисциплин, а также анализировать большие наборы данных, кодовые базы и документы, используя подробный контекст.
- Gemini 2.5 Flash — лучшая модель Google по соотношению цены и производительности, предлагающая широкий спектр возможностей. 2.5 Flash лучше всего подходит для крупномасштабной обработки, задач с низкой задержкой и большим объемом данных, требующих интеллектуального анализа, а также для агентских сценариев использования.
- Gemini 2.5 Flash Lite — это самая быстрая модель Flash от Google, оптимизированная для экономичности и высокой пропускной способности.
Поскольку запросы, связанные с поиском животных в зоопарке, не требуют размышлений или логического мышления, попробуйте ускорить процесс, используя более быструю модель.
Создайте командную строку MCP, чтобы быстро находить животных в зоопарке, вводя команду /find animal в Gemini CLI.
- После развертывания новой версии вашего приложения запустите Gemini CLI.
gemini --model=gemini-2.5-flash-lite - В командной строке используйте созданную вами новую пользовательскую команду:
/find lions
Вы по-прежнему должны видеть, что Gemini CLI вызывает инструмент get_animals_by_species и форматирует ответ в соответствии с указаниями командной строки MCP, но ответ должен появиться гораздо быстрее!
╭───────────────────────────╮
│ > /find --animal="lion" │
╰───────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✔ get_animals_by_species (zoo-remote MCP Server) get_animals_by_species (zoo-remote MCP Server) │
│ │
│ [{"species":"lion","name":"Leo","age":7,"enclosure":"The Big Cat │
│ Plains","trail":"Savannah │
│ Heights"},{"species":"lion","name":"Nala","age":6,"enclosure":"The Big Cat │
│ Plains","trail":"Savannah │
│ Heights"},{"species":"lion","name":"Simba","age":3,"enclosure":"The Big Cat │
│ Plains","trail":"Savannah │
│ Heights"},{"species":"lion","name":"King","age":8,"enclosure":"The Big Cat │
│ Plains","trail":"Savannah Heights"}] │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ Lions can be found in The Big Cat Plains on the Savannah Heights.
Отладка
Если вы видите ошибку подобного рода:
✕ Unknown command: /find --animal="lions"
Попробуйте запустить команду /mcp , и если она выдаст сообщение zoo-remote - Disconnected , возможно, потребуется повторно развернуть систему или снова выполнить следующие команды:
gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
--member=user:$(gcloud config get-value account) \
--role='roles/run.invoker'
export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)")
export ID_TOKEN=$(gcloud auth print-identity-token)
12. Заключение
Поздравляем! Вы успешно развернули и подключились к защищенному удаленному серверу MCP.
Переходите к следующей лабораторной работе.
Эта лабораторная работа — первая в серии из трех частей. Во второй лабораторной работе вы будете использовать сервер MCP, который вы создали с помощью агента ADK.
Используйте сервер MCP в Cloud Run с агентом ADK.
(Необязательно) Уборка
Если вы не собираетесь переходить к следующей лабораторной работе и хотите удалить созданный вами проект, вы можете удалить его из облачного хранилища, чтобы избежать дополнительных расходов.
Хотя Cloud Run не взимает плату, когда услуга не используется, с вас все равно может взиматься плата за хранение образа контейнера в реестре артефактов. Удаление вашего проекта Cloud прекращает выставление счетов за все ресурсы, используемые в этом проекте.
При желании вы можете удалить проект:
gcloud projects delete $GOOGLE_CLOUD_PROJECT
Также вы можете удалить ненужные ресурсы с диска Cloudshell. Для этого выполните следующие действия:
- Удалите каталог проекта codelab:
rm -rf ~/mcp-on-cloudrun - Внимание! Следующее действие необратимо! Если вы хотите удалить все данные в Cloud Shell, чтобы освободить место, вы можете удалить всю свою домашнюю директорию . Будьте внимательны и убедитесь, что все, что вы хотите сохранить, сохранено в другом месте.
sudo rm -rf $HOME