1. Introdução
Visão geral
Neste laboratório, você vai criar e implantar um servidor de protocolo de contexto de modelo (MCP). Os servidores MCP são úteis para dar aos LLMs acesso a ferramentas e serviços externos. Você vai configurá-lo como um serviço seguro e pronto para produção no Cloud Run, que pode ser acessado de vários clientes. Em seguida, você se conectará ao servidor MCP remoto na CLI do Gemini.
Atividades deste laboratório
Vamos usar o FastMCP para criar um servidor MCP de zoológico com duas ferramentas: get_animals_by_species
e get_animal_details
. O FastMCP oferece uma maneira rápida e em Python de criar servidores e clientes MCP.
O que você vai aprender
- Implante o servidor MCP no Cloud Run.
- Proteja o endpoint do servidor exigindo autenticação para todas as solicitações, garantindo que apenas clientes e agentes autorizados possam se comunicar com ele.
- Conectar-se ao endpoint do servidor MCP seguro na CLI do Gemini
2. Configuração do projeto
- Se você ainda não tiver uma Conta do Google, crie uma.
- Use uma conta pessoal em vez de uma conta escolar ou de trabalho. As contas escolares e de trabalho podem ter restrições que impedem a ativação das APIs necessárias para este laboratório.
- Faça login no Console do Google Cloud.
- Ative o faturamento no Console do Cloud.
- A conclusão deste laboratório custa menos de US $1 em recursos do Cloud.
- Siga as etapas no final deste laboratório para excluir recursos e evitar mais cobranças.
- Novos usuários podem aproveitar a avaliação sem custo financeiro de US$300.
- Crie um projeto ou reutilize um projeto existente.
3. Abrir editor do Cloud Shell
- Clique neste link para acessar diretamente o editor do Cloud Shell.
- Se for preciso autorizar em algum momento hoje, clique em Autorizar para continuar.
- Se o terminal não aparecer na parte de baixo da tela, abra-o:
- Clique em Visualizar.
- Clique em Terminal
.
- No terminal, defina o projeto com este comando:
- Formato:
gcloud config set project [PROJECT_ID]
- Exemplo:
gcloud config set project lab-project-id-example
- Se você não se lembrar do ID do projeto:
- Para listar todos os IDs de projeto, use:
gcloud projects list | awk '/PROJECT_ID/{print $2}'
- Para listar todos os IDs de projeto, use:
- Formato:
- Você vai receber esta mensagem:
Se você vir umUpdated property [core/project].
WARNING
e for perguntadoDo you want to continue (Y/n)?
, provavelmente inseriu o ID do projeto incorretamente. Pressionen
,Enter
e tente executar o comandogcloud config set project
novamente.
4. Ativar APIs
No terminal, ative as APIs:
gcloud services enable \
run.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com
Se for preciso autorizar, clique em Autorizar para continuar.
Esse comando pode levar alguns minutos para ser concluído, mas vai gerar uma mensagem de sucesso semelhante a esta:
Operation "operations/acf.p2-73d90d00-47ee-447a-b600" finished successfully.
5. Preparar seu projeto Python
- Crie uma pasta chamada
mcp-on-cloudrun
para armazenar o código-fonte da implantação:mkdir mcp-on-cloudrun && cd mcp-on-cloudrun
- Crie um projeto em Python com a ferramenta
uv
para gerar um arquivopyproject.toml
: O comandouv init --description "Example of deploying an MCP server on Cloud Run" --bare --python 3.13
uv init
cria um arquivopyproject.toml
para seu projeto.Para ver o conteúdo do arquivo, execute o seguinte: A saída será semelhante a esta: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. Criar o servidor MCP do zoológico
Para fornecer um contexto valioso e melhorar o uso de LLMs com o MCP, configure um servidor MCP de zoológico com o FastMCP, um framework padrão para trabalhar com o Protocolo de contexto de modelo. O FastMCP oferece uma maneira rápida de criar servidores e clientes MCP com Python. Esse servidor MCP fornece dados sobre animais em um zoológico fictício. Para simplificar, armazenamos os dados na memória. Para um servidor MCP de produção, provavelmente você vai querer fornecer dados de fontes como bancos de dados ou APIs.
- Execute o comando a seguir para adicionar o FastMCP como uma dependência no arquivo
pyproject.toml
: Isso vai adicionar um arquivouv add fastmcp==2.11.1 --no-sync
uv.lock
ao seu projeto. - Crie e abra um novo arquivo
server.py
para o código-fonte do servidor MCP: O comandocloudshell edit server.py
cloudshell edit
vai abrir o arquivoserver.py
no editor acima do terminal. - Adicione o seguinte código-fonte do servidor MCP do zoológico ao arquivo
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__": logger.info(f"🚀 MCP server started on port {os.getenv('PORT', 8080)}") asyncio.run( mcp.run_async( transport="http", host="0.0.0.0", port=os.getenv("PORT", 8080), ) )
Seu código está completo! É hora de implantar o servidor MCP no Cloud Run.
7. Como implantar no Cloud Run
Agora implante um servidor MCP no Cloud Run diretamente do código-fonte.
- Crie e abra um novo
Dockerfile
para implantação no Cloud Run:cloudshell edit Dockerfile
- Inclua o código a seguir no Dockerfile para usar a ferramenta
uv
e executar o arquivoserver.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"]
- Execute o comando
gcloud
para implantar o aplicativo no Cloud Run. Use a flaggcloud run deploy zoo-mcp-server \ --no-allow-unauthenticated \ --region=europe-west1 \ --source=. \ --labels=dev-tutorial=codelab-mcp
--no-allow-unauthenticated
para exigir autenticação. Isso é importante por motivos de segurança. Se você não exigir autenticação, qualquer pessoa poderá chamar o servidor MCP e causar danos ao sistema. - Confirme a criação de um novo repositório do Artifact Registry. Como é a primeira vez que você implanta no Cloud Run usando o código-fonte, vai aparecer o seguinte:
DigiteDeploying 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
e pressioneEnter
. Isso vai criar um repositório do Artifact Registry para sua implantação. Isso é necessário para armazenar o contêiner Docker do servidor MCP para o serviço do Cloud Run. - Depois de alguns minutos, você vai ver uma mensagem como esta:
Service [zoo-mcp-server] revision [zoo-mcp-server-12345-abc] has been deployed and is serving 100 percent of traffic.
Você implantou o servidor MCP. Agora você pode usar.
8. Adicionar o servidor MCP remoto à CLI do Gemini
Agora que você implantou um servidor MCP remoto, é possível se conectar a ele usando vários aplicativos, como o Google Code Assist ou a CLI do Gemini. Nesta seção, vamos estabelecer uma conexão com o novo servidor MCP remoto usando a CLI do Gemini.
- Conceda à sua conta de usuário permissão para chamar o servidor MCP remoto
gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \ --member=user:$(gcloud config get-value account) \ --role='roles/run.invoker'
- Salve as credenciais e o número do projeto do Google Cloud em variáveis de ambiente para usar no arquivo de configurações do Gemini:
export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)") export ID_TOKEN=$(gcloud auth print-identity-token)
- Abra o arquivo de configurações da CLI do Gemini
cloudshell edit ~/.gemini/settings.json
- Substitua o arquivo de configurações da CLI do Gemini para adicionar o servidor MCP do Cloud Run
{ "mcpServers": { "zoo-remote": { "httpUrl": "https://zoo-mcp-server-$PROJECT_NUMBER.europe-west1.run.app/mcp/", "headers": { "Authorization": "Bearer $ID_TOKEN" } } }, "selectedAuthType": "cloud-shell", "hasSeenIdeIntegrationNudge": true }
- Iniciar a CLI do Gemini no Cloud Shell
Talvez seja necessário pressionargemini
Enter
para aceitar algumas configurações padrão. - Pedir para o Gemini listar as ferramentas do MCP disponíveis no contexto
/mcp
- Peça ao Gemini para encontrar algo no zoológico
A CLI do Gemini sabe usar o servidor MCPWhere can I find penguins?
zoo-remote
e vai perguntar se você quer permitir a execução do MCP. - Use a seta para baixo e pressione
Enter
para selecionar.Yes, always allow all tools from server "zoo-remote"
A saída precisa mostrar a resposta correta e uma caixa de exibição indicando que o servidor MCP foi usado.
Você conseguiu! Você implantou um servidor MCP remoto no Cloud Run e o testou usando a CLI do Gemini.
Quando quiser encerrar a sessão, digite /quit
e pressione Enter
para sair da CLI do Gemini.
Depuração
Se você receber um erro como este:
🔍 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.
É provável que o token de ID tenha expirado e precise ser definido novamente.ID_TOKEN
- Digite
/quit
e pressioneEnter
para sair da CLI do Gemini. - Definir o projeto no terminal
gcloud config set project [PROJECT_ID]
- Reinicie na etapa 2 acima
9. (Opcional) Verificar chamadas de função nos registros do servidor
Para verificar se o servidor MCP do Cloud Run foi chamado, confira os registros do serviço.
gcloud run services logs read zoo-mcp-server --region europe-west1 --limit=5
Você vai ver um registro de saída que confirma que uma chamada de função foi feita. 🛠️
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. (Opcional) Adicionar solicitação de MCP ao servidor
Um comando do MCP pode acelerar seu fluxo de trabalho para comandos que você executa com frequência, criando uma abreviação para um comando mais longo.
A CLI do Gemini converte automaticamente os comandos do MCP em comandos de barra personalizados para que você possa invocar um comando do MCP digitando /prompt_name
, em que prompt_name
é o nome do comando do MCP.
Crie um comando de MCP para encontrar rapidamente um animal no zoológico digitando /find animal
na CLI do Gemini.
- Adicione este código ao arquivo
server.py
acima da proteção principal (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." )
- Reimplantar o aplicativo no Cloud Run
gcloud run deploy zoo-mcp-server \ --no-allow-unauthenticated \ --region=europe-west1 \ --source=. \ --labels=dev-tutorial=codelab-mcp
- Atualize o ID_TOKEN do seu servidor MCP remoto
export ID_TOKEN=$(gcloud auth print-identity-token)
- Depois que a nova versão do aplicativo for implantada, inicie a CLI do Gemini.
gemini
- No comando, use o novo comando personalizado que você criou:
/find --animal="lions"
Você vai notar que a CLI do Gemini chama a ferramenta get_animals_by_species
e formata a resposta conforme instruído pelo comando do 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.
Metas extras para testar seus conhecimentos
Para um desafio extra, siga as mesmas etapas para criar um comando que retorne curiosidades sobre espécies específicas de animais no zoológico.
Ou, para testar ainda mais o que você aprendeu, crie uma ideia de ferramenta que usaria com frequência e implante um segundo servidor MCP remoto. Em seguida, adicione-o às configurações da CLI Gemini para ver se funciona.
11. Conclusão
Parabéns! Você implantou e se conectou a um servidor MCP remoto seguro.
Continuar para o próximo laboratório
Este é o primeiro laboratório de uma série de três partes. No segundo laboratório, você vai usar o servidor do MCP criado com um agente do ADK.
Usar um servidor MCP no Cloud Run com um agente ADK
(Opcional) Limpar
Se você não vai continuar para o próximo laboratório e quer limpar o que criou, exclua o projeto do Cloud para evitar cobranças adicionais.
O Cloud Run não gera custos quando o serviço não está em uso, mas você ainda pode receber cobranças pelo armazenamento da imagem de contêiner no Artifact Registry. A exclusão do projeto do Cloud interrompe o faturamento de todos os recursos usados nele.
Se quiser, exclua o projeto:
gcloud projects delete $GOOGLE_CLOUD_PROJECT
Você também pode excluir recursos desnecessários do disco do Cloud Shell. Você pode:
- Exclua o diretório do projeto do codelab:
rm -rf ~/mcp-on-cloudrun
- Aviso: Não é possível desfazer a próxima ação. Se você quiser excluir tudo no Cloud Shell para liberar espaço, exclua todo o diretório principal. Verifique se tudo o que você quer manter está salvo em outro lugar.
sudo rm -rf $HOME