Criar e implantar um servidor MCP remoto no Cloud Run

Este tutorial mostra como criar e implantar um servidor do Protocolo de Contexto de Modelo (MCP) remoto no Cloud Run usando o transporte HTTP transmissível. Com o transporte HTTP transmissível, o servidor MCP opera como um processo independente que pode processar várias conexões de clientes.

Objetivos

Com este tutorial, você vai:

  1. Preparar seu projeto Python com o gerenciador de pacotes uv.
  2. Criar um servidor MCP para operações matemáticas.
  3. Implantar no Cloud Run.
  4. Autenticar o cliente MCP.
  5. Testar o servidor MCP remoto.

Custos

Neste documento, você usa os seguintes componentes faturáveis do Cloud de Confiance by S3NS:

Antes de começar

  1. In the Cloud de Confiance console, on the project selector page, select or create a Cloud de Confiance 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 role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  2. Verify that billing is enabled for your Cloud de Confiance project.

  3. Ative o Artifact Registry, a API Cloud Run Admin e as APIs Cloud Build.

    Funções necessárias para ativar APIs

    Para ativar as APIs, é necessário ter a permissão serviceusage.services.enable. Se você criou o projeto, provavelmente já tem essa permissão com o papel de proprietário (roles/owner). Caso contrário, você pode receber essa permissão pelo papel Administrador de uso do serviço (roles/serviceusage.serviceUsageAdmin). Saiba como conceder papéis.

    Ativar as APIs

  4. Configure o ambiente de desenvolvimento do Cloud Run no seu Cloud de Confiance projeto do.
  5. Verifique se você tem as permissões adequadas para implantar serviços e os papéis Administrador do Cloud Run (roles/run.admin) e Usuário da conta de serviço (roles/iam.serviceAccountUser) concedidos à sua conta.
  6. Conceda o papel de Invocador do Cloud Run (roles/run.invoker) à sua conta. Esse papel permite que o servidor MCP remoto acesse o serviço do Cloud Run.
  7. Saiba como conceder os papéis

    Console

    1. No Cloud de Confiance console, acesse a página IAM.

      Acessar IAM
    2. Selecione o projeto.
    3. Clique em CONCEDER ACESSO.
    4. No campo Novos principais, digite seu identificador de usuário. Normalmente, esse é o endereço de e-mail usado para implantar o serviço do Cloud Run.

    5. Na lista Selecionar papel, escolha um.
    6. Para conceder outros papéis, adicione-os clicando em Adicionar outro papel.
    7. Clique em Salvar.

    gcloud

    Para conceder os papéis necessários do IAM à sua conta no seu projeto:

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

    Substitua:

    • PROJECT_NUMBER: o Cloud de Confiance número do projeto.
    • PROJECT_ID: o Cloud de Confiance ID do projeto.
    • PRINCIPAL: o endereço de e-mail da conta a que você está concedendo o papel.
    • ROLE: o papel que você está adicionando à conta do implantador.
  8. Se você precisa seguir uma política da organização de restrição de domínio que restringe invocações não autenticadas para seu projeto, será necessário acessar o serviço implantado, conforme descrito em Como testar serviços particulares.

  9. Instale o Uv, um gerenciador de projetos e pacotes Python.

Preparar seu projeto Python

As etapas a seguir descrevem como configurar seu projeto Python com o gerenciador de pacotes uv.

  1. Crie uma pasta chamada mcp-on-cloudrun para armazenar o código-fonte da implantação:

      mkdir mcp-on-cloudrun
      cd mcp-on-cloudrun
    
  2. Crie um projeto Python com a ferramenta uv para gerar um arquivo pyproject.toml:

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

    O comando uv init cria o seguinte arquivo 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. Crie os seguintes novos arquivos adicionais:

    • server.py para o código-fonte do servidor MCP
    • test_server.py para testar o servidor remoto
    • Um Dockerfile para implantação no Cloud Run
    touch server.py test_server.py Dockerfile
    

    O diretório do projeto precisa conter a seguinte estrutura:

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

Criar um servidor MCP para operações matemáticas

Para fornecer um contexto valioso para melhorar o uso de LLMs com MCP, configure um servidor MCP matemático com FastMCP. O FastMCP oferece uma maneira rápida de criar servidores e clientes MCP com Python.

Siga estas etapas para criar um servidor MCP para operações matemáticas, como adição e subtração.

  1. Execute o seguinte comando para adicionar o FastMCP como uma dependência no arquivo pyproject.toml:

    uv add fastmcp==2.13.1 --no-sync
    
  2. Adicione o seguinte código-fonte do servidor MCP matemático no arquivo server.py:

    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. Inclua o código a seguir no Dockerfile para usar a ferramenta uv para executar o arquivo server.py:

    # Use the official Python image
    FROM python:3.14-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"]
    

Implantar no Cloud Run

É possível implantar o servidor MCP como uma imagem do contêiner:

Imagem do contêiner

Para implantar um servidor MCP empacotado como uma imagem de contêiner, siga estas instruções.

  1. Crie um repositório do Artifact Registry para armazenar a imagem do contêiner:

    gcloud artifacts repositories create remote-mcp-servers \
    --repository-format=docker \
    --location=us-central1 \
    --description="Repository for remote MCP servers" \
    --project=PROJECT_ID
    
  2. Crie a imagem do contêiner e envie-a para o Artifact Registry com o Cloud Build:

    gcloud builds submit --region=us-central1 --tag us-central1-docker.pkg.dev/PROJECT_ID/remote-mcp-servers/mcp-server:latest
    
  3. Implante a imagem do contêiner do servidor MCP no 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
    

Autenticar o cliente MCP

Se você implantou o serviço com a flag --no-allow-unauthenticated, qualquer cliente MCP que se conectar ao servidor MCP remoto precisará ser autenticado.

  1. Conceda o papel de Invocador do Cloud Run (roles/run.invoker) à conta de serviço. Essa vinculação de política do Identity and Access Management garante que um mecanismo de segurança forte seja usado para autenticar o cliente MCP local.

  2. Execute o proxy do Cloud Run para criar um túnel autenticado para o servidor MCP remoto na máquina local:

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

    Se o proxy do Cloud Run ainda não estiver instalado, esse comando vai pedir que você faça o download do proxy. Siga as instruções para fazer o download e instalar o proxy.

O Cloud Run autentica todo o tráfego para http://127.0.0.1:8080 e encaminha solicitações para o servidor MCP remoto.

Testar o servidor MCP remoto

Você testa e se conecta ao servidor MCP remoto usando o cliente FastMCP e acessando o URL http://127.0.0.1:8080/mcp.

Para testar e invocar o mecanismo de adição e subtração, siga estas etapas:

  1. Antes de executar o servidor de teste, execute o proxy do Cloud Run.

  2. Crie um arquivo de teste chamado test_server.py e adicione o seguinte código:

    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.content[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.content[0].text}")
    
    
    if __name__ == "__main__":
        asyncio.run(test_server())
  3. Em um novo terminal, execute o servidor de teste:

    uv run test_server.py
    

    Você verá esta resposta:

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

Limpar

Para evitar cobranças extras na sua Cloud de Confiance by S3NS conta, exclua todos os recursos implantados com este tutorial.

Excluir o projeto

Se você criou um novo projeto para este tutorial, exclua-o. Se você usou um projeto atual e precisa mantê-lo sem as alterações adicionadas neste tutorial, exclua os recursos criados para o tutorial.

O jeito mais fácil de evitar cobranças é excluindo o projeto que você criou para o tutorial.

Para excluir o projeto:

  1. No Cloud de Confiance console, acesse a página Gerenciar recursos.

    Acessar "Gerenciar recursos"

  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir.
  3. Na caixa de diálogo, digite o ID do projeto e clique em Desligar para excluir o projeto.

Excluir recursos do tutorial

  1. Exclua o serviço do Cloud Run que você implantou neste tutorial. Os serviços do Cloud Run não geram custos até receberem solicitações.

    Para excluir o serviço do Cloud Run, execute o seguinte comando:

    gcloud run services delete SERVICE-NAME

    Substitua SERVICE-NAME pelo nome do serviço.

    Também é possível excluir os serviços do Cloud Run no Cloud de Confiance console.

  2. Remova a configuração da região padrão da gcloud que você adicionou durante a configuração do tutorial:

     gcloud config unset run/region
    
  3. Remova a configuração do projeto:

     gcloud config unset project