在 Cloud Run 上构建和部署远程 MCP 服务器

本教程介绍了如何使用可流式传输的 HTTP 传输在 Cloud Run 上构建和部署远程 Model Context Protocol (MCP) 服务器。借助可流式传输的 HTTP 传输,MCP 服务器可以作为独立进程运行,处理多个客户端连接。

目标

在此教程中,您将学习以下操作:

  1. 使用 uv 软件包管理系统准备 Python 项目
  2. 创建用于数学运算的 MCP 服务器
  3. 部署到 Cloud Run
  4. 对 MCP 客户端进行身份验证
  5. 测试远程 MCP 服务器

费用

在本文档中,您将使用 Google Cloud的以下收费组件:

如需根据您的预计使用量来估算费用,请使用价格计算器

新 Google Cloud 用户可能有资格申请免费试用

准备工作

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  5. Verify that billing is enabled for your Google Cloud project.

  6. Enable the Artifact Registry, Cloud Run Admin API, and Cloud Build APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  7. 在 Google Cloud 项目中设置 Cloud Run 开发环境
  8. 确保您拥有部署服务的相应权限,并且您的账号已被授予 Cloud Run Admin (roles/run.admin) 和 Service Account User (roles/iam.serviceAccountUser) 角色。
  9. 向您的账号授予 Cloud Run Invoker (roles/run.invoker) 角色。此角色允许远程 MCP 服务器访问 Cloud Run 服务。
  10. 了解如何授予角色

    控制台

    1. 在 Google Cloud 控制台中,前往 IAM 页面。

      前往 IAM
    2. 选择相应项目。
    3. 点击 授予访问权限
    4. 新的主账号字段中,输入您的用户标识符。这通常是用于部署 Cloud Run 服务的电子邮件地址。

    5. 选择角色列表中,选择一个角色。
    6. 如需授予其他角色,请点击 添加其他角色,然后依次添加所需角色。
    7. 点击保存

    gcloud

    如需向您在项目中的账号授予所需的 IAM 角色,请执行以下操作:

       gcloud projects add-iam-policy-binding PROJECT_ID \
           --member=PRINCIPAL \
           --role=ROLE
       

    您需要进行如下替换:

    • PROJECT_NUMBER:您的 Google Cloud 项目编号。
    • PROJECT_ID:您的 Google Cloud 项目 ID。
    • PRINCIPAL:您要向其授予角色的账号的邮箱。
    • ROLE:您要添加到部署者账号的角色。
  11. 如果您通过网域限制组织政策来限制项目的未经身份验证的调用,则您需要按照测试专用服务中的说明访问已部署的服务。

  12. 安装 Uv(Python 软件包和项目管理器)。

准备 Python 项目

以下步骤介绍了如何使用 uv 软件包管理器设置 Python 项目

  1. 创建一个名为 mcp-on-cloudrun 的文件夹,用于存储要部署的源代码:

      mkdir mcp-on-cloudrun
      cd mcp-on-cloudrun
    
  2. 使用 uv 工具创建一个 Python 项目,以生成 pyproject.toml 文件:

      uv init --name "mcp-on-cloudrun" --description "Example of deploying an MCP server on Cloud Run" --bare --python 3.10
    

    uv init 命令会创建以下 pyproject.toml 文件:

    [project]
    name = "mcp-server"
    version = "0.1.0"
    description = "Example of deploying an MCP server on Cloud Run"
    readme = "README.md"
    requires-python = ">=3.10"
    dependencies = []
    
  3. 创建以下其他新文件:

    • server.py(适用于 MCP 服务器源代码)
    • test_server.py 以测试远程服务器
    • 用于部署到 Cloud Run 的 Dockerfile
    touch server.py test_server.py Dockerfile
    

    您的项目目录应包含以下结构:

    ├── mcp-on-cloudrun
    │   ├── pyproject.toml
    │   ├── server.py
    │   ├── test_server.py
    │   └── Dockerfile
    

创建用于数学运算的 MCP 服务器

为了提供有价值的背景信息,以便改进 LLM 与 MCP 的搭配使用,请使用 FastMCP 设置数学 MCP 服务器。FastMCP 提供了一种使用 Python 快速构建 MCP 服务器和客户端的方法。

请按照以下步骤创建用于执行加法和减法等数学运算的 MCP 服务器。

  1. 运行以下命令,将 FastMCP 添加为 pyproject.toml 文件中的依赖项:

    uv add fastmcp==2.8.0 --no-sync
    
  2. server.py 文件中添加以下数学 MCP 服务器源代码:

    import asyncio
    import logging
    import os
    
    from fastmcp import FastMCP 
    
    logger = logging.getLogger(__name__)
    logging.basicConfig(format="[%(levelname)s]: %(message)s", level=logging.INFO)
    
    mcp = FastMCP("MCP Server on Cloud Run")
    
    @mcp.tool()
    def add(a: int, b: int) -> int:
        """Use this to add two numbers together.
    
        Args:
            a: The first number.
            b: The second number.
    
        Returns:
            The sum of the two numbers.
        """
        logger.info(f">>> 🛠️ Tool: 'add' called with numbers '{a}' and '{b}'")
        return a + b
    
    @mcp.tool()
    def subtract(a: int, b: int) -> int:
        """Use this to subtract two numbers.
    
        Args:
            a: The first number.
            b: The second number.
    
        Returns:
            The difference of the two numbers.
        """
        logger.info(f">>> 🛠️ Tool: 'subtract' called with numbers '{a}' and '{b}'")
        return a - b
    
    if __name__ == "__main__":
        logger.info(f"🚀 MCP server started on port {os.getenv('PORT', 8080)}")
        # Could also use 'sse' transport, host="0.0.0.0" required for Cloud Run.
        asyncio.run(
            mcp.run_async(
                transport="streamable-http",
                host="0.0.0.0",
                port=os.getenv("PORT", 8080),
            )
        )
    
  3. 在 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"]
    

部署到 Cloud Run

您可以将 MCP 服务器部署为容器映像源代码

容器映像

如需部署已打包为容器映像的 MCP 服务器,请按以下说明操作。

  1. 创建 Artifact Registry 制品库以存储容器映像:

    gcloud artifacts repositories create remote-mcp-servers \
    --repository-format=docker \
    --location=us-central1 \
    --description="Repository for remote MCP servers" \
    --project=PROJECT_ID
    
  2. 使用 Cloud Build 构建容器映像并将其推送到 Artifact Registry:

    gcloud builds submit --region=us-central1 --tag us-central1-docker.pkg.dev/PROJECT_ID/remote-mcp-servers/mcp-server:latest
    
  3. 将 MCP 服务器容器映像部署到 Cloud Run:

    gcloud run deploy mcp-server \
    --image us-central1-docker.pkg.dev/PROJECT_ID/remote-mcp-servers/mcp-server:latest \
    --region=us-central1 \
    --no-allow-unauthenticated
    

源代码

您可以从远程 MCP 服务器的来源将其部署到 Cloud Run。

通过运行以下命令从源代码进行部署:

gcloud run deploy mcp-server --no-allow-unauthenticated --region=us-central1 --source .

对 MCP 客户端进行身份验证

如果您使用 --no-allow-unauthenticated 标志部署了服务,则连接到远程 MCP 服务器的任何 MCP 客户端都必须进行身份验证。

  1. 向该服务账号授予 Cloud Run Invoker (roles/run.invoker) 角色。此 Identity and Access Management 政策绑定可确保使用强大的安全机制来验证本地 MCP 客户端的身份。

  2. 运行 Cloud Run 代理,以在本地计算机上创建通往远程 MCP 服务器的经过身份验证的隧道:

    gcloud run services proxy mcp-server --region=us-central1
    

    如果尚未安装 Cloud Run 代理,此命令会提示您下载该代理。按照提示下载并安装代理。

Cloud Run 会对所有流向 http://127.0.0.1:8080 的流量进行身份验证,并将请求转发到远程 MCP 服务器。

测试远程 MCP 服务器

您可以使用 FastMCP 客户端并访问网址 http://127.0.0.1:8080/mcp 来测试并连接到远程 MCP 服务器。

如需测试和调用加减机制,请按以下步骤操作:

  1. 在运行测试服务器之前,请运行 Cloud Run 代理

  2. 创建一个名为 test_server.py 的测试文件,并添加以下代码:

    import asyncio
    
    from fastmcp import Client
    
    async def test_server():
        # Test the MCP server using streamable-http transport.
        # Use "/sse" endpoint if using sse transport.
        async with Client("http://localhost:8080/mcp") as client:
            # List available tools
            tools = await client.list_tools()
            for tool in tools:
                print(f">>> 🛠️  Tool found: {tool.name}")
            # Call add tool
            print(">>> 🪛  Calling add tool for 1 + 2")
            result = await client.call_tool("add", {"a": 1, "b": 2})
            print(f"<<< ✅ Result: {result[0].text}")
            # Call subtract tool
            print(">>> 🪛  Calling subtract tool for 10 - 3")
            result = await client.call_tool("subtract", {"a": 10, "b": 3})
            print(f"<<< ✅ Result: {result[0].text}")
    
    if __name__ == "__main__":
        asyncio.run(test_server())
  3. 在新终端中,运行测试服务器:

    uv run test_server.py
    

    您应该会看到以下输出内容:

     🛠️ Tool found: add
     🛠️ Tool found: subtract
     🪛 Calling add tool for 1 + 2
     ✅ Result: 3
     🪛 Calling subtract tool for 10 - 3
     ✅ Result: 7
    

清理

为避免您的 Google Cloud 账号产生额外费用,请删除您在本教程中部署的所有资源。

删除项目

如果您为本教程创建了一个新项目,请删除项目。 如果您使用的是某个现有项目,并且需要保留此项目但不保留在本教程中所做的更改,请删除为本教程创建的资源

为了避免产生费用,最简单的方法是删除您为本教程创建的项目。

要删除项目,请执行以下操作:

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

删除教程资源

  1. 删除您在本教程中部署的 Cloud Run 服务。Cloud Run 服务在收到请求之前不会产生费用。

    如需删除 Cloud Run 服务,请运行以下命令:

    gcloud run services delete SERVICE-NAME

    SERVICE-NAME 替换为服务的名称。

    您还可以通过Google Cloud 控制台删除 Cloud Run 服务。

  2. 移除您在教程设置过程中添加的 gcloud 默认区域配置:

     gcloud config unset run/region
    
  3. 移除项目配置:

     gcloud config unset project