Transforme linguagem natural em ações reais do Google Cloud com o Gemini e o MCP no Cloud Run

1. Introdução

Este codelab orienta você na criação de um servidor MCP (Protocolo de Contexto de Modelo) personalizado usando Python, na implantação dele no Google Cloud Run e na conexão com a CLI do Gemini para executar operações reais do Google Cloud Storage usando linguagem natural.

Fluxo arquitetônico:CLI do Gemini → Cloud Run → MCP

e149713a547f4157.png

Imagine o seguinte: você abre o terminal e digita um comando simples em um agente de IA, como os mostrados abaixo:

  • List my GCS buckets
  • Create a GCS bucket named <bucket-name>
  • Tell me about the metadata of my GCS object

Em segundos, sua nuvem ouve e executa. Sem comandos complicados. Sem troca de guias sem fim. Apenas linguagem simples se transformando em ações reais na nuvem.

O que você aprenderá

Você vai criar e implantar um servidor MCP personalizado que conecta a CLI do Gemini ao Google Cloud Storage.

Você vai:

  • Criar um servidor MCP baseado em Python
  • Colocar o aplicativo em um contêiner
  • Implantar no Cloud Run
  • Protegê-lo usando o IAM e tokens de identidade
  • Conectá-lo à CLI do Gemini
  • Executar operações do GCS em tempo real usando linguagem natural

O que você aprenderá

  • O que é o MCP (Protocolo de Contexto de Modelo) e como ele funciona
  • Como criar recursos de chamada de ferramentas usando Python
  • Como implantar aplicativos conteinerizados no Cloud Run
  • Como a CLI do Gemini se integra a servidores MCP externos
  • Como autenticar serviços do Cloud Run com segurança
  • Como executar operações reais do Google Cloud Storage usando IA

O que é necessário

  • Navegador da Web Google Chrome
  • Uma conta do Gmail
  • Um projeto do Google Cloud com o faturamento ativado
  • CLI do Gemini (pré-instalada no Google Cloud Shell)
  • Conhecimento básico do Python e do Google Cloud

Este codelab espera que o usuário tenha conhecimento básico de Python

2. Antes de começar

Criar um projeto

  1. No console do Google Cloud, na página de seletor de projetos, selecione ou crie um projeto do Google Cloud.
  2. Verifique se o faturamento está ativado para seu projeto na nuvem. Saiba como verificar se o faturamento está ativado em um projeto .
  3. Você vai usar o Cloud Shell, um ambiente de linha de comando executado no Google Cloud que vem pré-carregado com bq. Clique em Ativar o Cloud Shell na parte de cima do console do Google Cloud.

Imagem do botão &quot;Ativar o Cloud Shell&quot;

  1. Depois de se conectar ao Cloud Shell, verifique se sua conta já está autenticada e se o projeto está configurado com o ID do seu projeto usando o comando a seguir:
gcloud auth list
  1. Execute o comando a seguir no Cloud Shell para confirmar se o comando gcloud sabe sobre seu projeto.
gcloud config list project
  1. Se o projeto não estiver definido, use este comando:
gcloud config set project <YOUR_PROJECT_ID>
  1. Ative as APIs necessárias usando o comando mostrado abaixo. Isso pode levar alguns minutos. Aguarde.
gcloud services enable \
  run.googleapis.com \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com

Se for solicitado, clique em Autorizar para continuar.

5e681903144bdfbe.png

Após a execução do comando, uma mensagem semelhante à mostrada abaixo será exibida:

Operation "operations/..." finished successfully.

Se alguma API for perdida, você sempre poderá ativá-la durante a implementação.

Consulte a documentação para ver o uso e os comandos gcloud.

Preparar seu projeto do Python

Nesta seção, você vai criar o projeto do Python que vai hospedar o servidor MCP e configurar as dependências dele para implantação no Cloud Run.

Criar o diretório do projeto

Comece criando uma nova pasta chamada mcp-on-cloudrun para armazenar o código-fonte:

mkdir gcs-mcp-server && cd gcs-mcp-server

Criar requirements.txt

touch requirements.txt
cloudshell edit ~/gcs-mcp-server/requirements.txt

Adicione o seguinte conteúdo ao arquivo:

fastmcp
google-cloud-storage
google-api-core
pydantic

Salve o arquivo.

3. Criar o servidor MCP

Nesta seção, você vai criar o servidor MCP que expõe as operações do Google Cloud Storage como ferramentas chamáveis.

Este servidor vai:

  • Registrar ferramentas do MCP
  • Conectar-se ao Google Cloud Storage
  • Executar sobre HTTP
  • Ser implantável no Cloud Run

Agora, vamos criar nossa lógica principal do MCP em main.py.

Confira abaixo o código completo que define várias ferramentas para gerenciar o Google Cloud Storage, desde a listagem e criação de buckets até o upload, download e gerenciamento de blobs.

Criar o arquivo do aplicativo principal

No diretório mcp-on-cloudrun, crie um novo arquivo chamado main.py:

touch main.py

Abra o arquivo usando o editor do Cloud Shell:

cloudshell edit ~/gcs-mcp-server/main.py

Adicione a origem a seguir ao conteúdo do arquivo main.py:

import asyncio
import logging
import os
from datetime import timedelta
from typing import List, Dict, Any
from fastmcp import FastMCP
from google.cloud import storage
from google.api_core import exceptions

# ---------------------------------------------------------
# 🌐 Initialize MCP
# ---------------------------------------------------------
logging.basicConfig(format="[%(levelname)s]: %(message)s", level=logging.INFO)
logger = logging.getLogger(__name__)

mcp = FastMCP(name="MyEnhancedGCSMCPServer")
# ---------------------------------------------------------
# 1️⃣ Simple Greeting
# ---------------------------------------------------------
@mcp.tool
def sayhi(name: str) -> str:
  """Returns a friendly greetings"""
  return f"Hello {name}! It's a pleasure to connect from your enhanced MCP Server."

# ---------------------------------------------------------
# 2️⃣ List all GCS buckets
# ---------------------------------------------------------
@mcp.tool
def list_gcs_buckets() -> List[str]:
  """Lists all GCS buckets in the project."""
  try:
      storage_client = storage.Client()
      buckets = storage_client.list_buckets()
      return [bucket.name for bucket in buckets]
  except exceptions.Forbidden as e:
      return [f"Error: Permission denied to list buckets. Details: {e}"]
  except Exception as e:
      return [f"An unexpected error occurred: {e}"]

# ---------------------------------------------------------
# 3️⃣ Create a new bucket
# ---------------------------------------------------------
@mcp.tool
def create_bucket(bucket_name: str, location: str = "US") -> str:
  """Creates a new GCS bucket. Bucket names must be globally unique."""
  try:
      storage_client = storage.Client()
      bucket = storage_client.bucket(bucket_name)
      bucket.location = location
      storage_client.create_bucket(bucket)
      return f"✅ Bucket '{bucket_name}' created successfully in '{location}'."
  except exceptions.Conflict:
      return f"⚠️ Error: Bucket '{bucket_name}' already exists."
  except exceptions.Forbidden as e:
      return f"❌ Error: Permission denied to create bucket. Details: {e}"
  except Exception as e:
      return f"❌ Unexpected error: {e}"

# ---------------------------------------------------------
# 4️⃣ Delete a bucket
# ---------------------------------------------------------
@mcp.tool
def delete_bucket(bucket_name: str) -> str:
  """Deletes a GCS bucket."""
  try:
      storage_client = storage.Client()
      bucket = storage_client.bucket(bucket_name)
      bucket.delete(force=True)
      return f"🗑️ Bucket '{bucket_name}' deleted successfully."
  except exceptions.NotFound:
      return f"⚠️ Error: Bucket '{bucket_name}' not found."
  except exceptions.Forbidden as e:
      return f"❌ Error: Permission denied to delete bucket. Details: {e}"
  except Exception as e:
      return f"❌ Unexpected error: {e}"

# ---------------------------------------------------------
# 5️⃣ List objects in a bucket
# ---------------------------------------------------------
@mcp.tool
def list_objects(bucket_name: str) -> List[str]:
  """Lists all objects in a specified GCS bucket."""
  try:
      storage_client = storage.Client()
      blobs = storage_client.list_blobs(bucket_name)
      return [blob.name for blob in blobs]
  except exceptions.NotFound:
      return [f"⚠️ Error: Bucket '{bucket_name}' not found."]
  except Exception as e:
      return [f"❌ Unexpected error: {e}"]
# ---------------------------------------------------------
# Delete file from a bucket
# ---------------------------------------------------------
@mcp.tool
def delete_blob(bucket_name: str, blob_name: str) -> str:
  """Deletes a blob from a GCS bucket."""
  try:
      storage_client = storage.Client()
      bucket = storage_client.bucket(bucket_name)
      blob = bucket.blob(blob_name)
      blob.delete()
      return f"🗑️ Blob '{blob_name}' deleted from bucket '{bucket_name}'."
  except exceptions.NotFound:
      return f"⚠️ Error: Bucket '{bucket_name}' or blob '{blob_name}' not found."
  except exceptions.Forbidden as e:
      return f" Permission denied. Details: {e}"
  except Exception as e:
      return f" Unexpected error: {e}"

# ---------------------------------------------------------
# Get bucket metadata
# ---------------------------------------------------------
@mcp.tool
def get_bucket_metadata(bucket_name: str) -> Dict[str, Any]:
  """Retrieves metadata for a GCS bucket."""
  try:
      storage_client = storage.Client()
      bucket = storage_client.get_bucket(bucket_name)
      return {
          "id": bucket.id,
          "name": bucket.name,
          "location": bucket.location,
          "storage_class": bucket.storage_class,
          "created": bucket.time_created.isoformat() if bucket.time_created else None,
          "updated": bucket.updated.isoformat() if bucket.updated else None,
          "versioning_enabled": bucket.versioning_enabled,
      }
  except exceptions.NotFound:
      return {"error": f" Bucket '{bucket_name}' not found."}
  except Exception as e:
      return {"error": f" Unexpected error: {e}"}

# ---------------------------------------------------------
# Get object metadata
# ---------------------------------------------------------
@mcp.tool
def get_blob_metadata(bucket_name: str, blob_name: str) -> Dict[str, Any]:
  """Retrieves metadata for a specific blob."""
  try:
      storage_client = storage.Client()
      bucket = storage_client.bucket(bucket_name)
      blob = bucket.get_blob(blob_name)
      if not blob:
          return {"error": f" Blob '{blob_name}' not found in '{bucket_name}'."}
      return {
          "name": blob.name,
          "bucket": blob.bucket.name,
          "size": blob.size,
          "content_type": blob.content_type,
          "updated": blob.updated.isoformat() if blob.updated else None,
          "storage_class": blob.storage_class,
          "crc32c": blob.crc32c,
          "md5_hash": blob.md5_hash,
      }
  except exceptions.NotFound:
      return {"error": f" Bucket '{bucket_name}' not found."}
  except Exception as e:
      return {"error": f" Unexpected error: {e}"}

# ---------------------------------------------------------
# 🚀 Entry Point
# ---------------------------------------------------------
if __name__ == "__main__":
  port = int(os.getenv("PORT", 8080))
  logger.info(f"🚀 Starting Enhanced GCS MCP Server on port {port}")
  asyncio.run(
      mcp.run_async(
          transport="http",
          host="0.0.0.0",
          port=port,
      )
  )

Salve o arquivo depois de adicionar o código.

Sua estrutura de projeto agora será assim:

gcs-mcp-server/
├── requirements.txt
└── main.py

Vamos entender o código brevemente:

Importações e configuração:

O código começa importando as bibliotecas necessárias.

  • Bibliotecas padrão: asyncio para execução assíncrona, logging para gerar mensagens de status e os para variáveis de ambiente.
  • FastMCP: a estrutura principal usada para criar o servidor de Protocolo de Contexto de Modelo.
  • Google Cloud Storage: a biblioteca google.cloud.storage é importada para interagir com o GCS, juntamente com exceptions para tratamento de erros.

Inicialização:

Configuramos o formato de registro para ajudar a depurar e rastrear a identidade do servidor. Além disso, configuramos uma instância de FastMCP chamada MyEnhancedGCSMCPServer. Esse objeto (mcp) será usado para registrar todas as ferramentas (funções) que o servidor expõe. Definimos as seguintes ferramentas:

  • list_gcs_buckets: recupera uma lista de todos os buckets de armazenamento no projeto na nuvem do Google Cloud associado.
  • create_bucket: cria um novo bucket com um nome e local específicos.
  • delete_bucket: exclui um bucket atual.
  • list_objects: lista todos os arquivos (blobs) dentro de um bucket específico.
  • delete_blob: exclui um arquivo específico de um bucket.
  • get_bucket_metadata: retorna detalhes técnicos sobre um bucket (local, classe de armazenamento, status de controle de versão, hora de criação).
  • get_blob_metadata: retorna detalhes técnicos sobre um arquivo específico (tamanho, tipo de conteúdo, hash MD5, última atualização).

Ponto de entrada :

Isso configura a porta, que é definida como 8080 por padrão se não estiver definida. Em seguida, ele usa asyncio.run() para iniciar o servidor de forma assíncrona com mcp.run_async. Por fim, ele configura o servidor para ser executado por HTTP (host 0.0.0.0), tornando-o acessível para solicitações de rede recebidas.

4. Colocar o servidor MCP em um contêiner

Nesta seção, você vai criar um Dockerfile para que o servidor MCP possa ser implantado no Cloud Run.

O Cloud Run requer um aplicativo conteinerizado. Você vai definir como o aplicativo é criado e iniciado.

Criar o Dockerfile

Crie um novo arquivo chamado Dockerfile:

touch Dockerfile

Abra-o no editor do Cloud Shell:

cloudshell edit ~/gcs-mcp-server/Dockerfile

Adicionar configuração do Docker

Cole o conteúdo mostrado a seguir no Dockerfile:

FROM python:3.11-slim
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /app
RUN apt-get update && apt-get install -y \
   build-essential \
   gcc \
   && rm -rf /var/lib/apt/lists/*
RUN pip install --upgrade pip
COPY . .
RUN pip install -r requirements.txt
ENV PORT=8080
EXPOSE 8080
CMD ["python", "main.py"]

Salve o arquivo depois de adicionar o conteúdo. Sua estrutura de projeto agora será assim:

gcs-mcp-server/
├── requirements.txt
├── main.py
└── Dockerfile

5. Como implantar no Cloud Run

Agora implante o servidor MCP diretamente da origem.

Execute o comando a seguir no Cloud Shell:

gcloud run deploy gcs-mcp-server \
   --no-allow-unauthenticated \
   --region=us-central1 \
   --source=. \
   --labels=session=buildersdayblr

Quando solicitado a

  • Permitir invocações não autenticadas? → Não

O Cloud Build vai:

  • Crie a imagem do contêiner
  • Envie para o Artifact Registry
  • Implante no Cloud Run

Insira Y para confirmar que o repositório do Artifact Registry pode ser criado.

Deploying from source requires an Artifact Registry Docker repository to store built containers. A repository named [cloud-run-source-deploy] in region [us-central1] will be created.

Do you want to continue (Y/n)?  Y

Após a implantação, uma mensagem de sucesso será exibida com o URL do serviço do Cloud Run.

Também é possível verificar a implantação no console do Google Cloud em Cloud Run → Services.

53f95a2aa7a169d6.png

6. Configuração da CLI do Gemini

Até agora, criamos e implantamos nosso servidor MCP no Cloud Run.

Agora é hora da parte divertida: conectá-lo à CLI do Gemini e transformar seus comandos de linguagem natural em ações reais na nuvem.

Conceder permissão de invocador do Cloud Run

Como nosso serviço do Cloud Run é particular, vamos autenticar usando um token de identidade e atribuir as permissões corretas do IAM.

Implantamos o serviço com --no-allow-unauthenticated. Portanto, você precisa conceder permissão para invocá-lo.

Configure o ID do projeto:

export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)

Conceda a você o papel de invocador do Cloud Run:

gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
  --member=user:$(gcloud config get-value account) \
  --role='roles/run.invoker'

Isso permite que sua conta invoque o serviço do Cloud Run com segurança.

Gerar um token de identidade

O Cloud Run requer um token de identidade para acesso autenticado.

Gere um:

export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)")
export ID_TOKEN=$(gcloud auth print-identity-token)

Verifique:

echo $PROJECT_NUMBER
echo $ID_TOKEN

Você vai usar esse token na configuração da CLI do Gemini.

Configurar o servidor MCP na CLI do Gemini

Abra o arquivo de configurações da CLI do Gemini:

cloudshell edit ~/.gemini/settings.json

Adicione a seguinte configuração:

{
 "ide": {
   "enabled": true,
   "hasSeenNudge": true
 },
 "mcpServers": {
   "my-cloudrun-server": {
     "httpUrl": "https://gcs-mcp-server-$PROJECT_NUMBER.asia-south1.run.app/mcp",
     "headers": {
       "Authorization": "Bearer $ID_TOKEN"
     }
   }
 },
 "security": {
   "auth": {
     "selectedType": "cloud-shell"
   }
 }
}

Validar os servidores MCP configurados na CLI do Gemini

Inicie a CLI do Gemini no terminal do Cloud Shell usando o comando a seguir:

gemini

A saída abaixo será exibida

193224319056d340.png

Na CLI do Gemini, execute:

/mcp refresh
/mcp list

Agora você verá o gcs-cloudrun-server registrado. Confira abaixo uma captura de tela de exemplo:

726738c48290fc30.png

7. Invocar operações do Google Storage usando linguagem natural

Criar bucket

Create a bucket named my-ai-bucket in asia-south1 region

Isso vai solicitar sua permissão para invocar a ferramenta create_bucket do servidor MCP.

5ab2225295285077.png

Clique em "Permitir uma vez" e o bucket será criado na região específica solicitada.

Listar buckets

Para listar os buckets, insira o comando abaixo:

List all my GCS buckets

Excluir bucket

Para excluir um bucket, insira o comando abaixo (substitua <your_bucket_name> pelo nome do bucket):

Delete the bucket <your_bucket_name>

Acessar os metadados do bucket

Para acessar os metadados de um bucket, insira o comando abaixo (substitua <your_bucket_name> pelo nome do bucket):

Give me metadata of the <your_bucket_name>

8. Liberar espaço

Leia toda esta seção antes de decidir excluir o projeto do Google Cloud, já que essa ação normalmente não é reversível.

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados neste codelab, siga estas etapas:

  • No console do Google Cloud, acesse a página "Gerenciar recursos".
  • Na lista de projetos, selecione o que você quer excluir.
  • Clique em Excluir.

Na caixa de diálogo, digite o ID do projeto e clique em desligar para excluí-lo permanentemente.

A exclusão do projeto interrompe o faturamento de todos os recursos usados nele, incluindo serviços do Cloud Run e imagens de contêiner armazenadas no Artifact Registry.

Como alternativa, se você quiser manter o projeto, mas remover o serviço implantado:

  1. Acesse o Cloud Run no console do Google Cloud.
  2. Selecione o serviço gcs-mcp-server.
  3. Clique em Excluir para remover o serviço.

Ou insira o comando gcloud a seguir no terminal do Cloud Shell.

gcloud run services delete gcs-mcp-server --region=us-central1

9. Conclusão

🎉 Parabéns! Você acabou de criar seu primeiro fluxo de trabalho de nuvem com tecnologia de IA.

Você implementou:

  • Um servidor MCP personalizado baseado em Python
  • Recursos de chamada de ferramentas para o Google Cloud Storage
  • Conteinerização usando o Docker
  • Implantação segura no Cloud Run
  • Autenticação baseada em identidade
  • Integração com a CLI do Gemini

Agora você pode estender essa arquitetura para oferecer suporte a outros serviços do Google Cloud, como BigQuery, Pub/Sub ou Compute Engine.

Esse padrão demonstra como os sistemas de IA podem interagir com a infraestrutura em nuvem com segurança por meio da invocação de ferramentas estruturadas.