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 fornecer 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 por vários clientes. Em seguida, você vai se conectar ao servidor MCP remoto na CLI do Antigravity.
Atividades deste laboratório
Vamos usar o FastMCP para criar um servidor MCP de zoológico que tenha duas ferramentas: get_animals_by_species e get_animal_details. O FastMCP oferece uma maneira rápida e Pythonica de criar servidores e clientes MCP.

O que você vai aprender
- Implantar 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 Antigravity
2. Configuração do projeto
- Se você ainda não tiver uma Conta do Google, deverá criar uma Conta do Google.
- 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.
- Crie um projeto ou reutilize um projeto atual.
- Se você receber um erro sobre a cota do projeto, reutilize ou exclua um projeto atual para criar um novo.
3. Abrir editor do Cloud Shell
- Clique neste link para navegar diretamente até o editor do Cloud Shell.
- Se você receber uma solicitação de autorização a qualquer momento, 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:
- É possível listar todos os IDs de projeto com:
gcloud projects list | awk '/PROJECT_ID/{print $2}'

- É possível listar todos os IDs de projeto com:
- Formato:
- Você vai receber esta mensagem:
Se você receber umUpdated property [core/project].
WARNINGe a perguntaDo you want to continue (Y/n)?, provavelmente inseriu o ID do projeto incorretamente. Pressionen, pressioneEntere tente executar o comandogcloud config set projectnovamente.
4. Ativar APIs
No terminal, ative as APIs:
gcloud services enable \
run.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com
Se você receber uma solicitação de autorização, clique em Autorizar para continuar. 
Esse comando pode levar alguns minutos para ser concluído, mas ele vai gerar uma mensagem de sucesso semelhante a esta:
Operation "operations/acf.p2-73d90d00-47ee-447a-b600" finished successfully.
5. Preparar o projeto Python
- Crie uma pasta chamada
mcp-on-cloudrunpara armazenar o código-fonte da implantação:mkdir mcp-on-cloudrun && cd mcp-on-cloudrun - Crie um projeto Python com a ferramenta
uvpara gerar um arquivopyproject.toml: O comandouv init --description "Example of deploying an MCP server on Cloud Run" --bare --python 3.13uv initcria um arquivopyproject.tomlpara o projeto.Para conferir 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 para melhorar o uso de LLMs com MCP, configure um servidor MCP de zoológico com 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 seguinte comando para adicionar o FastMCP como uma dependência no arquivo
pyproject.toml: Isso vai adicionar um arquivouv add fastmcp==2.12.4 --no-syncuv.lockao projeto. - Crie e abra um novo arquivo
server.pypara o código-fonte do servidor MCP: O comandocloudshell edit ~/mcp-on-cloudrun/server.pycloudshell editvai abrir o arquivoserver.pyno editor acima do terminal. - Adicione o seguinte código-fonte do servidor MCP do zoológico no 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__": 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, ) )
Seu código está concluído. É 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
Dockerfilepara implantação no Cloud Run:cloudshell edit ~/mcp-on-cloudrun/Dockerfile - Inclua o código a seguir no Dockerfile para usar a ferramenta
uvpara 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"] - Crie uma conta de serviço chamada
mcp-server-sa:gcloud iam service-accounts create mcp-server-sa --display-name="MCP Server Service Account" - Execute o comando
gcloudpara implantar o aplicativo no Cloud Run Use a flagcd ~/mcp-on-cloudrun gcloud run deploy zoo-mcp-server \ --service-account=mcp-server-sa@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \ --no-allow-unauthenticated \ --region=us-west1 \ --source=. \ --labels=dev-tutorial=codelab-mcp--no-allow-unauthenticatedpara 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 a partir do código-fonte, você vai ver:
DigiteDeploying from source requires an Artifact Registry Docker repository to store built containers. A repository named [cloud-run-source-deploy] in region [us-west1] will be created. Do you want to continue (Y/n)?
Ye pressioneEnter. Isso vai criar um repositório do Artifact Registry para sua implantação. Isso é necessário para armazenar o contêiner do Docker do servidor MCP para o serviço do Cloud Run. - Depois de alguns minutos, você vai receber 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 usá-lo.
8. Adicionar o servidor MCP remoto à CLI do Antigravity
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 Antigravity. Nesta seção, vamos estabelecer uma conexão com o novo servidor MCP remoto usando a CLI do Antigravity.
- Conceda permissão à sua conta de usuário 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 suas credenciais do Google Cloud e o número do projeto em variáveis de ambiente para usar no arquivo de configurações do Antigravity:
export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)") export ID_TOKEN=$(gcloud auth print-identity-token) - Crie uma pasta
.gemini/antigravity-clise ela ainda não tiver sido criada.mkdir -p ~/.gemini/antigravity-cli - Grave o servidor MCP remoto no arquivo de configuração do MCP da CLI do Antigravity:
cat > ~/.gemini/antigravity-cli/mcp_config.json << EOF { "mcpServers": { "zoo-remote": { "serverUrl": "https://zoo-mcp-server-${PROJECT_NUMBER}.us-west1.run.app/mcp", "headers": { "Authorization": "Bearer ${ID_TOKEN}" } } } } EOF - Inicie a CLI do Antigravity:
agy
- Autentique-se com a CLI do Antigravity: a autenticação é necessária durante a inicialização. Selecione OAuth (pressionando
Enter).
- Clique no link (se não for clicável, destaque o URL no Cloud Shell para copiá-lo e cole-o no navegador).
- Faça login na sua Conta do Google
- Copiar o código
- Cole o código no terminal do editor do Cloud Shell.
- Pressione
Enter.
- Pressione
Enterpara aceitar algumas configurações padrão. - Peça à CLI do Antigravity para listar as ferramentas MCP disponíveis no contexto dela.
Pressione/mcpESCpara voltar à caixa de comando. - Peça à CLI do Antigravity para encontrar algo no zoológico.
A CLI do Antigravity deve saber usar o servidor MCPWhere can I find penguins?zoo-remotee vai perguntar se você quer permitir a execução do MCP. - Use a seta para baixo e pressione
Enterpara selecionar.Yes, always allow all tools from server "zoo-remote"

A saída vai mostrar a resposta correta e uma caixa de exibição mostrando que o servidor MCP foi usado.

Você conseguiu! Você implantou um servidor MCP remoto no Cloud Run e o testou usando a CLI do Antigravity.
Quando estiver tudo pronto para encerrar a sessão, digite /exit e pressione Enter para sair da CLI do Antigravity.
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 exija a configuração do ID_TOKEN novamente.
- Digite
/exite pressioneEnterpara sair da CLI do Antigravity. - Defina o projeto no terminal.
gcloud config set project [PROJECT_ID] - Execute novamente o comando de credenciais do Google Cloud para receber um novo
ID_TOKEN, já que o seu pode ter expirado, e reescreva o arquivo de configuração:export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)") export ID_TOKEN=$(gcloud auth print-identity-token) cat > ~/.gemini/antigravity-cli/mcp_config.json << EOF
{ "mcpServers": { "zoo-remote": { "serverUrl": "https://zoo-mcp-server-${PROJECT_NUMBER}.us-west1.run.app/mcp", "headers": { "Authorization": "Bearer ${ID_TOKEN}" } } } } EOF ```
9. (Opcional) Verificar chamadas de ferramentas nos registros do servidor
Para verificar se o servidor MCP do Cloud Run foi chamado, confira os registros de serviço.
gcloud run services logs read zoo-mcp-server --region us-west1 --limit=5
Você vai receber um registro de saída que confirma que foi feita uma chamada de ferramenta. 🛠️
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 comando MCP ao servidor
Um comando MCP pode acelerar o fluxo de trabalho para comandos que você executa com frequência, criando um atalho para um comando mais longo.
A CLI do Antigravity converte automaticamente os comandos MCP em comandos de barra personalizados para que você possa invocar um comando MCP digitando /prompt_name, em que prompt_name é o nome do comando MCP.
Crie um comando MCP para encontrar rapidamente um animal no zoológico digitando /find animal na CLI do Antigravity.
- Adicione este código ao arquivo
server.pyacima do guarda 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." ) - Reimplante o aplicativo no Cloud Run.
gcloud run deploy zoo-mcp-server \ --region=us-west1 \ --source=. \ --labels=dev-tutorial=codelab-mcp - Atualize o ID_TOKEN e recrie o arquivo de configuração:
export ID_TOKEN=$(gcloud auth print-identity-token) export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)") cat > ~/.gemini/antigravity-cli/mcp_config.json << EOF
{ "mcpServers": { "zoo-remote": { "serverUrl": "https://zoo-mcp-server-${PROJECT_NUMBER}.us-west1.run.app/mcp", "headers": { "Authorization": "Bearer ${ID_TOKEN}" } } } } EOF ```
- Depois que a nova versão do aplicativo for implantada, inicie a CLI do Antigravity.
agy - No comando, use o novo comando personalizado que você criou:
/find lions
Você vai notar que a CLI do Antigravity chama a ferramenta get_animals_by_species e formata a resposta conforme as instruções do comando MCP.
╭───────────────────────────╮
│ > /find lions │
╰───────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✔ 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. (Opcional) Usar o Gemini Flash Lite para respostas mais rápidas
A CLI do Antigravity permite escolher o modelo e o esforço que você está usando.
Como as solicitações relacionadas à localização dos animais do zoológico não exigem pensamento ou raciocínio, tente acelerar as coisas usando um modelo mais rápido.
Na seção anterior, você criou um comando MCP para encontrar rapidamente um animal no zoológico digitando /find animal na CLI do Antigravity.
- Depois que a nova versão do aplicativo for implantada, inicie a CLI do Antigravity.
agy --model=gemini-3.6-flash --effort=low - No comando, use o novo comando personalizado que você criou:
/find lions
Você ainda vai notar que a CLI do Antigravity chama a ferramenta get_animals_by_species e formata a resposta conforme as instruções do comando MCP, mas a resposta vai aparecer muito mais rápido.
╭───────────────────────────╮
│ > /find lions │
╰───────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✔ 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.
Depuração
Se você receber um erro como este:
✕ Unknown command: /find lions
Tente executar /mcp e, se ele gerar zoo-remote - Disconnected, talvez seja necessário reimplantar ou executar os seguintes comandos novamente:
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)
cat > ~/.gemini/antigravity-cli/mcp_config.json << EOF
{
"mcpServers": {
"zoo-remote": {
"serverUrl": "https://zoo-mcp-server-${PROJECT_NUMBER}.us-west1.run.app/mcp",
"headers": {
"Authorization": "Bearer ${ID_TOKEN}"
}
}
}
}
EOF
12. Conclusão
Parabéns! Você implantou e se conectou a um servidor MCP remoto seguro.
Continuar para o próximo laboratório
Este laboratório é o primeiro de uma série de três partes. No segundo laboratório, você vai usar o servidor MCP criado com um agente ADK.
Usar um servidor MCP no Cloud Run com um agente ADK
(Opcional) Limpar
Se você não quiser continuar para o próximo laboratório e quiser limpar o que criou, exclua o projeto na nuvem para evitar cobranças adicionais.
Ainda que o Cloud Run não gere custos quando o serviço não estiver em uso, é possível que receba cobranças pelo armazenamento da imagem do contêiner no Artifact Registry. A exclusão do projeto na nuvem interrompe o faturamento de todos os recursos usados nele.
Se quiser, exclua o projeto:
gcloud projects delete $GOOGLE_CLOUD_PROJECT
Talvez você também queira excluir recursos desnecessários do disco do Cloud Shell. Você pode:
- Exclua o diretório do projeto do codelab:
rm -rf ~/mcp-on-cloudrun - Alerta! essa próxima ação não pode ser desfeita. Se você quiser excluir tudo no Cloud Shell para liberar espaço, você pode excluir seu diretório inicial inteiro. Tenha cuidado para que tudo o que você quer manter seja salvo em outro lugar.
sudo rm -rf $HOME