Instrumenta un servidor de MCP autohospedado con OpenTelemetry

En este documento, se describen los pasos para instrumentar y, luego, implementar un servidor de Protocolo de contexto del modelo (MCP) autoalojado, lo que permite la recopilación de telemetría. En el ejemplo de este documento, se compila un servidor de MCP con FastMCP y se implementa el servidor de MCP con Cloud Run. FastMCP incluye la instrumentación de OpenTelemetry que recopila telemetría de todas las operaciones de MCP.

En este documento, se describen los siguientes pasos:

  1. Prepara tu proyecto de Python con el administrador de paquetes uv.
  2. Crea un servidor de MCP para operaciones matemáticas.
  3. Implementa en Cloud Run.
  4. Autentica el cliente de MCP.
  5. Prueba el servidor de MCP autoalojado.
  6. Visualiza tus datos de telemetría.

Antes de comenzar

  1. Accede a tu Google Cloud cuenta de. Si eres nuevo en Google Cloud, crea una cuenta para evaluar el rendimiento de nuestros productos en situaciones reales. Los clientes nuevos también obtienen $300 en créditos gratuitos para ejecutar, probar y, además, implementar cargas de trabajo.
  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 role (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 role (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. Habilita las APIs de Artifact Registry, Cloud Run, Cloud Build, Telemetry, Cloud Logging, Cloud Monitoring y Cloud Trace.

    Roles necesarios para habilitar las APIs

    Para habilitar las APIs, necesitas el rol de IAM de administrador de Service Usage (roles/serviceusage.serviceUsageAdmin), que contiene el permiso serviceusage.services.enable. Obtén más información para otorgar roles.

    Habilitar las API

  7. Configura tu entorno de desarrollo de Cloud Run en tu Google Cloud proyecto.
  8. Asegúrate de tener los permisos adecuados para implementar servicios y los roles de administrador de Cloud Run (roles/run.admin) y usuario de cuenta de servicio (roles/iam.serviceAccountUser) otorgados a tu cuenta.
  9. Otorga el rol de invocador de Cloud Run (roles/run.invoker) a tu cuenta. Este rol permite que el servidor de MCP autoalojado acceda al servicio de Cloud Run.
  10. Obtén información para otorgar los roles

    Console

    1. En la Google Cloud consola de, dirígete a la página IAM.

      Ir a IAM
    2. Selecciona el proyecto.
    3. Haz clic en Grant access.
    4. En el campo Principales nuevas, ingresa tu identificador de usuario. Por lo general, es la dirección de correo electrónico que se usa para implementar el servicio de Cloud Run.

    5. En la lista Seleccionar un rol, elige uno.
    6. Para otorgar roles adicionales, haz clic en Agregar otro rol y agrega cada rol adicional.
    7. Haz clic en Guardar.

    gcloud

    Para otorgar los roles de IAM necesarios a tu cuenta en tu proyecto, haz lo siguiente:

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

    Reemplaza lo siguiente:

    • PROJECT_ID: Es el identificador del proyecto.
    • PRINCIPAL: Es un identificador de la entidad principal a la que deseas otorgar el rol. Por lo general, los identificadores principales tienen el siguiente formato: PRINCIPAL-TYPE:ID. Por ejemplo, user:my-user@example.com. Para obtener una lista completa de los formatos que PRINCIPAL puede tener, consulta Identificadores principales.
    • ROLE: Es un rol de IAM.
  11. Si estás bajo una política de la organización de restricción de dominios que restringe las invocaciones no autenticadas para tu proyecto, deberás acceder a tu servicio implementado como se describe en Prueba servicios privados.

  12. Instala Uv, un administrador de proyectos y paquetes de Python.

Prepara tu proyecto de Python

En los siguientes pasos, se describe cómo configurar tu proyecto de Python con el administrador de paquetes uv.

  1. Crea una carpeta llamada mcp-on-cloudrun para almacenar el código fuente de la implementación:

      mkdir mcp-on-cloudrun
      cd mcp-on-cloudrun
    
  2. Crea un proyecto de Python con la herramienta uv para generar un archivo pyproject.toml:

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

    El comando uv init crea el siguiente archivo 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. Crea los siguientes archivos nuevos adicionales:

    • server.py para el código fuente del servidor de MCP
    • otel_setup.py para configurar OpenTelemetry
    • test_server.py para probar el servidor autoalojado
    • Un Dockerfile para implementar en Cloud Run
    touch server.py otel_setup.py test_server.py Dockerfile
    

    El directorio de tu proyecto debe contener la siguiente estructura:

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

Crea un servidor de MCP para operaciones matemáticas

En esta sección, configurarás un servidor de MCP de matemáticas con FastMCP. FastMCP proporciona una forma rápida de compilar servidores y clientes de MCP con Python.

Sigue estos pasos para crear un servidor de MCP para operaciones matemáticas, como sumas y restas.

  1. Ejecuta el siguiente comando para agregar FastMCP como una dependencia en el archivo pyproject.toml:

    uv add fastmcp==2.13.1 --no-sync
    
  2. Agrega el siguiente código de configuración de OpenTelemetry en el archivo otel_setup.py:

    import logging
    import google.auth
    import google.auth.transport.requests
    import grpc
    from google.auth.transport.grpc import AuthMetadataPlugin
    from opentelemetry import trace
    from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
        OTLPSpanExporter,
    )
    from opentelemetry.sdk.resources import SERVICE_NAME, Resource
    from opentelemetry.sdk.trace import TracerProvider
    from opentelemetry.sdk.trace.export import BatchSpanProcessor
    
    logger = logging.getLogger(__name__)
    
    
    def setup_opentelemetry(service_name: str) -> None:
        """Sets up OpenTelemetry to send traces to Google Cloud Observability."""
        credentials, project_id = google.auth.default()
        if not project_id:
            raise Exception("Could not determine Google Cloud project ID.")
    
        resource = Resource.create(
            attributes={
                SERVICE_NAME: service_name,
                "gcp.project_id": project_id,
            }
        )
    
        # Set up OTLP auth
        request = google.auth.transport.requests.Request()
        auth_metadata_plugin = AuthMetadataPlugin(credentials=credentials, request=request)
        channel_creds = grpc.composite_channel_credentials(
            grpc.ssl_channel_credentials(),
            grpc.metadata_call_credentials(auth_metadata_plugin),
        )
    
        # Set up OpenTelemetry Python SDK
        tracer_provider = TracerProvider(resource=resource)
        tracer_provider.add_span_processor(
            BatchSpanProcessor(
                OTLPSpanExporter(
                    credentials=channel_creds,
                    endpoint="https://telemetry.googleapis.com:443/v1/traces",
                )
            )
        )
        trace.set_tracer_provider(tracer_provider)
        logger.info("OpenTelemetry successfully initialized.")
    
    
  3. Agrega el siguiente código fuente del servidor de MCP de matemáticas en el archivo server.py:

    from otel_setup import setup_opentelemetry
    setup_opentelemetry("mcp-server")
    
    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),
            )
        )
    
  4. Incluye el siguiente código en el Dockerfile para usar la herramienta uv para ejecutar el archivo 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"]
    

Implementa en Cloud Run

Puedes implementar el servidor de MCP como una imagen de contenedor o como código fuente:

Imagen de contenedor

Para implementar un servidor de MCP empaquetado como una imagen de contenedor, sigue estas instrucciones.

  1. Crea un repositorio de Artifact Registry para almacenar la imagen de contenedor:

    gcloud artifacts repositories create self-hosted-mcp-servers \
    --repository-format=docker \
    --location=us-central1 \
    --description="Repository for self-hosted MCP servers" \
    --project=PROJECT_ID
    
  2. Compila la imagen de contenedor y envíala a Artifact Registry con Cloud Build:

    gcloud builds submit --region=us-central1 --tag us-central1-docker.pkg.dev/PROJECT_ID/self-hosted-mcp-servers/mcp-server:latest
    
  3. Implementa la imagen de contenedor del servidor de MCP en Cloud Run:

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

Fuente

Puedes implementar servidores de MCP autoalojados en Cloud Run desde sus fuentes.

Para realizar la implementación desde la fuente, ejecuta el siguiente comando:

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

Autentica el cliente de MCP

Si implementaste tu servicio con la marca --no-allow-unauthenticated, cualquier cliente de MCP que se conecte a tu servidor de MCP autoalojado debe autenticarse.

  1. Otorga el rol de invocador de Cloud Run (roles/run.invoker) a la cuenta de servicio. Esta vinculación de políticas de Identity and Access Management garantiza que se use un mecanismo de seguridad sólido para autenticar tu cliente de MCP local.

  2. Ejecuta el proxy de Cloud Run para crear un túnel autenticado al servidor de MCP autoalojado en tu máquina local:

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

    Si aún no está instalado el proxy de Cloud Run, este comando te solicitará que lo descargues. Sigue las indicaciones para descargar e instalar el proxy.

Cloud Run autentica todo el tráfico a http://127.0.0.1:8080 y reenvía las solicitudes al servidor de MCP autoalojado.

Prueba el servidor de MCP autoalojado

Para probar y conectarte a tu servidor de MCP autoalojado, usa el cliente de FastMCP y accede a la URL http://127.0.0.1:8080/mcp.

Para probar e invocar el mecanismo de suma y resta, sigue estos pasos:

  1. Antes de ejecutar el servidor de prueba, ejecuta el proxy de Cloud Run.

  2. Crea un archivo de prueba llamado test_server.py y agrega el siguiente código:

    from otel_setup import setup_opentelemetry
    setup_opentelemetry("test-server")
    
    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. En una terminal nueva, ejecuta el servidor de prueba:

    uv run test_server.py
    

    Deberías ver el siguiente resultado:

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

Visualiza tus datos de telemetría

En esta sección, se describe cómo puedes ver los datos de registro, métricas y seguimiento que genera tu servidor de MCP autoalojado.

Antes de comenzar

Para obtener los permisos que necesitas para ver tus datos de registro, métricas y seguimiento, pídele a tu administrador que te otorgue los siguientes roles de IAM en tu proyecto:

Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.

También puedes obtener los permisos necesarios a través de roles personalizados o cualquier otro rol predefinido.

Visualiza la telemetría

Para obtener información sobre cómo ver tus datos de registro, métricas y seguimiento, consulta lo siguiente:

Datos de registros

En la Google Cloud consola de, ve a la Explorador de registros del segmento:

Ir al Explorador de registros

Si usas la barra de búsqueda para encontrar esta página, selecciona el resultado cuyo subtítulo es Logging.

Para obtener más información sobre el uso de la página Explorador de registros, consulta Visualiza y analiza registros.

Datos de métricas

En la Google Cloud consola de, accede a la  Explorador de métricas página:

Acceder al Explorador de métricas

Si usas la barra de búsqueda para encontrar esta página, selecciona el resultado cuyo subtítulo es Monitoring.

Para obtener más información sobre el uso de la página Explorador de métricas, consulta Crea gráficos con el Explorador de métricas.

Datos de seguimiento

En la Google Cloud consola de, ve a la página Explorador de seguimiento:

Ve al Explorador de seguimiento

También puedes usar la barra de búsqueda para encontrar esta página.

En la siguiente captura de pantalla, se ilustra el panel Details en la página Trace Explorer , que muestra los intervalos de seguimiento generados a partir de las operaciones tools/call:

Panel de detalles que muestra un registro y sus intervalos asociados.

Para obtener más información sobre el uso de la página Explorador de seguimiento, consulta Busca y explora seguimientos.

¿Qué sigue?