如何在 Cloud Run 上部署安全的 MCP 服务器

1. 简介

概览

在本实验中,您将构建并部署 Model Context Protocol (MCP) 服务器。MCP 服务器可用于为 LLM 提供对外部工具和服务的访问权限。您将它配置为 Cloud Run 上可供多个客户端访问的安全的生产就绪型服务。然后,您将从 Gemini CLI 连接到远程 MCP 服务器。

您将执行的操作

我们将使用 FastMCP 创建一个包含两个工具(get_animals_by_speciesget_animal_details)的 zoo MCP 服务器。FastMCP 提供了一种快速、Python 式的方法来构建 MCP 服务器和客户端。

动物园 MCP 服务器图形

学习内容

  • 将 MCP 服务器部署到 Cloud Run。
  • 通过要求对所有请求进行身份验证来保护服务器的端点,确保只有经过授权的客户端和代理才能与该端点通信。
  • 通过 Gemini CLI 连接到安全的 MCP 服务器端点

2. 项目设置

  1. 如果您还没有 Google 账号,则必须先创建一个 Google 账号
    • 请改用个人账号,而不是工作账号或学校账号。工作账号和学校账号可能存在限制,导致您无法启用本实验所需的 API。
  2. 登录 Google Cloud 控制台
  3. 在 Cloud 控制台中启用结算功能
    • 完成本实验的 Cloud 资源费用应不到 1 美元。
    • 您可以按照本实验结束时的步骤删除资源,以避免产生更多费用。
    • 新用户符合参与 $300 USD 免费试用计划的条件。
  4. 创建新项目或选择重复使用现有项目。

3. 打开 Cloud Shell Editor

  1. 点击此链接可直接前往 Cloud Shell 编辑器
  2. 如果系统在今天任何时间提示您进行授权,请点击授权继续。点击以授权 Cloud Shell
  3. 如果终端未显示在屏幕底部,请打开它:
    • 点击查看
    • 点击终端在 Cloud Shell 编辑器中打开新终端
  4. 在终端中,使用以下命令设置项目:
    • 格式:
      gcloud config set project [PROJECT_ID]
      
    • 示例:
      gcloud config set project lab-project-id-example
      
    • 如果您不记得项目 ID,请执行以下操作:
      • 您可以使用以下命令列出所有项目 ID:
        gcloud projects list | awk '/PROJECT_ID/{print $2}'
        
      在 Cloud Shell 编辑器终端中设置项目 ID
  5. 您应会看到以下消息:
    Updated property [core/project].
    
    如果您看到 WARNING 并被问到 Do you want to continue (Y/n)?,则很可能是您输入的项目 ID 有误。按 n,按 Enter,然后尝试再次运行 gcloud config set project 命令。

4. 启用 API

在终端中,启用以下 API:

gcloud services enable \
  run.googleapis.com \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com

如果系统提示您进行授权,请点击授权继续。点击以授权 Cloud Shell

此命令可能需要几分钟时间才能完成,但最终应会生成类似如下所示的成功消息:

Operation "operations/acf.p2-73d90d00-47ee-447a-b600" finished successfully.

5. 准备 Python 项目

  1. 创建一个名为 mcp-on-cloudrun 的文件夹,用于存储要部署的源代码:
    mkdir mcp-on-cloudrun && cd mcp-on-cloudrun
    
  2. 使用 uv 工具创建一个 Python 项目,以生成 pyproject.toml 文件:
    uv init --description "Example of deploying an MCP server on Cloud Run" --bare --python 3.13
    
    uv 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 的搭配使用,请使用 FastMCP(一种用于处理 Model Context Protocol 的标准框架)设置动物园 MCP 服务器。FastMCP 提供了一种使用 Python 快速构建 MCP 服务器和客户端的方法。此 MCP 服务器提供有关虚构动物园中动物的数据。为简单起见,我们将数据存储在内存中。对于生产 MCP 服务器,您可能需要提供来自数据库或 API 等来源的数据。

  1. 运行以下命令,将 FastMCP 添加为 pyproject.toml 文件中的依赖项:
    uv add fastmcp==2.12.4 --no-sync
    
    这会将 uv.lock 文件添加到您的项目中。
  2. 为 MCP 服务器源代码创建并打开新的 server.py 文件:
    cloudshell edit ~/mcp-on-cloudrun/server.py
    
    cloudshell edit 命令会在终端上方的编辑器中打开 server.py 文件。
  3. server.py 文件中添加以下动物园 MCP 服务器源代码:
    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. 部署到 Cloud Run

现在,直接从源代码将 MCP 服务器部署到 Cloud Run。

  1. 创建并打开新的 Dockerfile 以部署到 Cloud Run:
    cloudshell edit ~/mcp-on-cloudrun/Dockerfile
    
  2. 在 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"]
    
  3. 运行 gcloud 命令,将应用部署到 Cloud Run
    cd ~/mcp-on-cloudrun
    gcloud run deploy zoo-mcp-server \
        --no-allow-unauthenticated \
        --region=europe-west1 \
        --source=. \
        --labels=dev-tutorial=codelab-mcp
    
    使用 --no-allow-unauthenticated 标志可要求进行身份验证。这对于确保安全性至关重要。如果您不需要进行身份验证,则任何人都可以调用您的 MCP 服务器,并可能会对您的系统造成损害。
  4. 确认已创建新的 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 代码库。这是存储 Cloud Run 服务的 MCP 服务器 Docker 容器所必需的。
  5. 几分钟后,您会看到类似以下内容的消息:
    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)连接到该服务器。在本部分中,我们将使用 Gemini CLI 建立与新远程 MCP 服务器的连接。

  1. 向您的用户账号授予调用远程 MCP 服务器的权限
    gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
        --member=user:$(gcloud config get-value account) \
        --role='roles/run.invoker'
    
  2. 将您的 Google Cloud 凭据和项目编号保存在环境变量中,以便在 Gemini 设置文件中使用:
    export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)")
    export ID_TOKEN=$(gcloud auth print-identity-token)
    
  3. 创建 .gemini 文件夹(如果尚未创建)
    mkdir -p ~/.gemini
    
  4. 打开 Gemini CLI 设置文件
    cloudshell edit ~/.gemini/settings.json
    
  5. 替换 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"
            }
        }
    }
    
  6. 在 Cloud Shell 中启动 Gemini CLI
    gemini
    
    您可能需要按 Enter 接受某些默认设置。Gemini CLI 初始视图
  7. 让 Gemini 列出其上下文中可用的 MCP 工具
    /mcp
    
  8. 让 Gemini 在动物园中寻找某样东西
    Where can I find penguins?
    
    Gemini CLI 应该知道要使用 zoo-remote MCP 服务器,并会询问您是否要允许执行 MCP。
  9. 使用向下键,然后按 Enter 选择
    Yes, always allow all tools from server "zoo-remote"
    
    Gemini CLI 允许使用 Zoo 远程工具

输出应显示正确答案,以及一个显示 MCP 服务器已使用的显示框。

Gemini CLI 显示了 Zoo 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

  1. 输入 /quit,然后按 Enter 退出 Gemini CLI。
  2. 在终端中设置项目
    gcloud config set project [PROJECT_ID]
    
  3. 从上述第 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 提示转换为自定义斜杠命令,以便您可以通过输入 /prompt_name(其中 prompt_name 是 MCP 提示的名称)来调用 MCP 提示。

创建 MCP 提示,以便您通过在 Gemini CLI 中输入 /find animal 快速找到动物园中的动物。

  1. 将此代码添加到 server.py 文件中的主保护机制 (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."
        )
    
  2. 将应用重新部署到 Cloud Run
    gcloud run deploy zoo-mcp-server \
        --no-allow-unauthenticated \
        --region=europe-west1 \
        --source=. \
        --labels=dev-tutorial=codelab-mcp
    
  3. 刷新远程 MCP 服务器的 ID_TOKEN
    export ID_TOKEN=$(gcloud auth print-identity-token)
    
  4. 部署应用的新版本后,启动 Gemini CLI。
    gemini
    
  5. 在提示中使用您创建的新自定义命令:
    /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 是 Google 速度最快的 Flash 模型,经过优化,可实现高成本效益和高吞吐量。

由于与寻找动物园动物相关的请求不需要思考或推理,因此可以尝试使用速度更快的模型来加快处理速度。

创建 MCP 提示,以便您通过在 Gemini CLI 中输入 /find animal 快速找到动物园中的动物。

  1. 部署应用的新版本后,启动 Gemini CLI。
    gemini --model=gemini-2.5-flash-lite
    
  2. 在提示中使用您创建的新自定义命令:
    /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 服务器。

继续执行下一个实验

本实验是三部分系列实验中的第一个实验。在第二个实验中,您将使用通过 ADK 智能体创建的 MCP 服务器。

将 Cloud Run 上的 MCP 服务器与 ADK 代理搭配使用

(可选)清理

如果您不打算继续学习下一个实验,并且想要清理已创建的内容,可以删除您的 Cloud 项目,以免产生额外费用。

虽然 Cloud Run 不会对未在使用中的服务计费,但您可能仍然需要支付将容器映像存储在 Artifact Registry 中而产生的相关费用。删除 Cloud 项目后,系统即会停止对该项目中使用的所有资源计费。

如果您愿意,可以删除项目:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

您可能还需要从 Cloud Shell 磁盘中删除不必要的资源。您可以:

  1. 删除 Codelab 项目目录:
    rm -rf ~/mcp-on-cloudrun
    
  2. 警告!接下来要执行的操作无法撤消!如果您想删除 Cloud Shell 中的所有内容以释放空间,可以删除整个主目录。请务必将要保留的所有内容保存到其他位置。
    sudo rm -rf $HOME