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는 MCP 서버와 클라이언트를 빌드하는 빠르고 Pythonic한 방법을 제공합니다.

동물원 MCP 서버 그래픽

학습할 내용

  • Cloud Run에 MCP 서버를 배포합니다.
  • 모든 요청에 인증을 요구하여 승인된 클라이언트와 에이전트만 서버의 엔드포인트와 통신할 수 있도록 서버의 엔드포인트를 보호하세요.
  • Gemini CLI에서 보안 MCP 서버 엔드포인트에 연결

2. 프로젝트 설정

  1. 아직 Google 계정이 없다면 Google 계정을 만들어야 합니다.
    • 직장 또는 학교 계정 대신 개인 계정을 사용하세요. 직장 및 학교 계정에는 이 실습에 필요한 API를 사용 설정하지 못하도록 하는 제한이 있을 수 있습니다.
  2. Google Cloud 콘솔에 로그인합니다.
  3. Cloud 콘솔에서 결제를 사용 설정합니다.
    • 이 실습을 완료하는 데 드는 Cloud 리소스 비용은 미화 1달러 미만입니다.
    • 이 실습이 끝나면 단계에 따라 리소스를 삭제하여 추가 요금이 발생하지 않도록 할 수 있습니다.
    • 신규 사용자는 미화$300 상당의 무료 체험판을 사용할 수 있습니다.
  4. 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다.

3. Cloud Shell 편집기 열기

  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 서버 만들기

MCP로 LLM 사용을 개선하기 위한 유용한 컨텍스트를 제공하려면 Model Context Protocol 작업용 표준 프레임워크인 FastMCP를 사용하여 동물원 MCP 서버를 설정하세요. FastMCP는 Python으로 MCP 서버와 클라이언트를 빠르게 빌드하는 방법을 제공합니다. 이 MCP 서버는 가상의 동물원에 있는 동물에 관한 데이터를 제공합니다. 간단하게 하기 위해 메모리에 데이터를 저장합니다. 프로덕션 MCP 서버의 경우 데이터베이스나 API와 같은 소스의 데이터를 제공하는 것이 좋습니다.

  1. 다음 명령어를 실행하여 pyproject.toml 파일에 FastMCP를 종속 항목으로 추가합니다.
    uv add fastmcp==2.11.1 --no-sync
    
    그러면 프로젝트에 uv.lock 파일이 추가됩니다.
  2. MCP 서버 소스 코드의 새 server.py 파일을 만들고 엽니다.
    cloudshell edit 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__":
        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),
            )
        )
    

코드가 완성되었습니다. 이제 MCP 서버를 Cloud Run에 배포할 시간입니다.

7. Cloud Run에 배포

이제 소스 코드에서 직접 Cloud Run에 MCP 서버를 배포합니다.

  1. Cloud Run에 배포할 새 Dockerfile를 만들고 엽니다.
    cloudshell edit Dockerfile
    
  2. uv 도구를 사용하여 server.py 파일을 실행하려면 Dockerfile에 다음 코드를 포함하세요.
    # 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에 애플리케이션 배포
    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. Gemini CLI에 원격 MCP 서버 추가

이제 원격 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. Gemini 설정 파일에서 사용할 Google Cloud 사용자 인증 정보와 프로젝트 번호를 환경 변수에 저장합니다.
    export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)")
    export ID_TOKEN=$(gcloud auth print-identity-token)
    
  3. Gemini CLI 설정 파일 열기
    cloudshell edit ~/.gemini/settings.json
    
  4. Gemini CLI 설정 파일을 바꿔 Cloud Run MCP 서버 추가
    {
      "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
    }
    

  1. Cloud Shell에서 Gemini CLI 시작하기
    gemini
    
    일부 기본 설정을 수락하려면 Enter 키를 눌러야 할 수 있습니다.Gemini CLI 초기 뷰
  2. Gemini가 컨텍스트 내에서 사용할 수 있는 MCP 도구를 나열하도록 합니다.
    /mcp
    
  3. Gemini에게 동물원에서 무언가를 찾아 달라고 요청
    Where can I find penguins?
    
    Gemini CLI는 zoo-remote MCP 서버를 사용해야 하며 MCP 실행을 허용할지 묻습니다.
  4. 아래쪽 화살표를 사용한 다음 Enter를 눌러 선택합니다.
    Yes, always allow all tools from server "zoo-remote"
    
    Gemini CLI에서 동물원 원격 도구 허용

출력에는 정답과 MCP 서버가 사용되었음을 보여주는 표시 상자가 표시되어야 합니다.

Gemini CLI show zoo mcp server result

완료되었습니다. 원격 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가 MCP 프롬프트의 이름인 경우 /prompt_name를 입력하여 MCP 프롬프트를 호출할 수 있습니다.

Gemini CLI에 /find animal를 입력하여 동물원에서 동물을 빠르게 찾을 수 있도록 MCP 프롬프트를 만듭니다.

  1. if __name__ == "__main__": 위의 server.py 파일에 다음 코드를 추가합니다.
    @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"
    

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.

자신을 테스트하기 위한 스트레치 목표

추가로 도전해 보려면 동일한 단계를 따라 동물원의 특정 동물 종에 관한 재미있는 사실을 반환하는 프롬프트를 만들어 보세요.

또는 학습한 내용을 테스트하기 위해 자주 사용할 도구에 대한 아이디어를 떠올리고 두 번째 원격 MCP 서버를 배포해 보세요. 그런 다음 Gemini CLI 설정에 추가하여 작동하는지 확인합니다.

11. 결론

축하합니다. 보안 원격 MCP 서버를 성공적으로 배포하고 연결했습니다.

다음 실습으로 계속 진행

이 실습은 3부로 구성된 시리즈의 첫 번째 실습입니다. 두 번째 실습에서는 ADK 에이전트로 만든 MCP 서버를 사용합니다.

ADK 에이전트와 함께 Cloud Run의 MCP 서버 사용

(선택사항) 정리

다음 실습으로 계속 진행하지 않고 생성한 항목을 정리하려면 클라우드 프로젝트를 삭제하여 추가 요금이 발생하지 않도록 하면 됩니다.

Cloud Run에서는 서비스를 사용하지 않을 때 비용이 청구되지 않지만 Artifact Registry에 컨테이너 이미지를 저장하는 데 요금이 부과될 수 있습니다. Cloud 프로젝트를 삭제하면 해당 프로젝트 내에서 사용되는 모든 리소스에 대한 청구가 중단됩니다.

원하는 경우 프로젝트를 삭제합니다.

gcloud projects delete $GOOGLE_CLOUD_PROJECT

cloudshell 디스크에서 불필요한 리소스를 삭제하는 것이 좋습니다. 다음과 같은 작업을 할 수 있습니다.

  1. Codelab 프로젝트 디렉터리를 삭제합니다.
    rm -rf ~/mcp-on-cloudrun
    
  2. 경고 이 작업은 되돌릴 수 없습니다. 공간을 확보하기 위해 Cloud Shell의 모든 항목을 삭제하려면 전체 홈 디렉터리를 삭제하면 됩니다. 보관할 모든 항목이 다른 곳에 저장되어 있는지 확인하세요.
    sudo rm -rf $HOME