Instrumenta un server MCP autogestito con OpenTelemetry

Questo documento descrive i passaggi per instrumentare ed eseguire il deployment di un server Model Context Protocol (MCP) self-hosted, consentendo la raccolta di dati di telemetria. L' esempio in questo documento crea un server MCP utilizzando FastMCP ed esegue il deployment del server MCP utilizzando Cloud Run. FastMCP include l'instrumentazione OpenTelemetry che raccoglie i dati di telemetria da tutte le operazioni MCP.

Questo documento descrive i seguenti passaggi:

  1. Prepara il progetto Python con il gestore di pacchetti uv.
  2. Crea un server MCP per le operazioni matematiche.
  3. Esegui il deployment in Cloud Run.
  4. Autentica il client MCP.
  5. Testa il server MCP self-hosted.
  6. Visualizza i dati di telemetria.

Prima di iniziare

  1. Accedi al tuo Google Cloud account. Se non hai mai utilizzato Google Cloud, crea un account per valutare il rendimento dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti senza costi per l'esecuzione, il test e il deployment dei workload.
  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. Abilita le API Artifact Registry, Cloud Run, Cloud Build, Telemetry, Cloud Logging, Cloud Monitoring e Cloud Trace.

    Ruoli richiesti per abilitare le API

    Per abilitare le API, devi disporre del ruolo IAM Amministratore utilizzo servizi (roles/serviceusage.serviceUsageAdmin), che contiene l'autorizzazione serviceusage.services.enable. Scopri come concedere i ruoli.

    Abilita le API

  7. Configura l'ambiente di sviluppo di Cloud Run nel tuo Google Cloud progetto.
  8. Assicurati di disporre delle autorizzazioni appropriate per eseguire il deployment dei servizi e dei ruoli Amministratore di Cloud Run (roles/run.admin) e Utente account di servizio (roles/iam.serviceAccountUser) concessi al tuo account.
  9. Concedi il ruolo Cloud Run Invoker (roles/run.invoker) al tuo account. Questo ruolo consente al server MCP self-hosted di accedere al servizio Cloud Run.
  10. Scopri come concedere i ruoli

    Console

    1. Nella Google Cloud console vai alla pagina IAM.

      Vai a IAM
    2. Seleziona il progetto.
    3. Fai clic su Concedi l'accesso.
    4. Nel campo Nuove entità, inserisci il tuo identificatore dell'utente. In genere si tratta dell'indirizzo email utilizzato per eseguire il deployment del servizio Cloud Run.

    5. Nell'elenco Seleziona un ruolo, seleziona un ruolo.
    6. Per concedere ruoli aggiuntivi, fai clic su Aggiungi un altro ruolo e aggiungi ogni ruolo aggiuntivo.
    7. Fai clic su Salva.

    gcloud

    Per concedere i ruoli IAM richiesti al tuo account nel tuo progetto:

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

    Sostituisci:

    • PROJECT_ID: l'identificatore del progetto.
    • PRINCIPAL: un identificatore per l'entità a cui vuoi concedere il ruolo. Gli identificatori principali in genere hanno il seguente formato: PRINCIPAL-TYPE:ID. Ad esempio, user:my-user@example.com. Per un elenco completo dei formati che PRINCIPAL può avere, consulta Identificatori delle entità.
    • ROLE: un ruolo IAM.
  11. Se sei soggetto a un criterio dell'organizzazione di restrizione del dominio policy che limita le chiamate non autenticate per il tuo progetto, devi accedere al servizio di cui hai eseguito il deployment come descritto in Testare i servizi privati.

  12. Installa Uv, un gestore di pacchetti e progetti Python.

Prepara il progetto Python

I seguenti passaggi descrivono come configurare il progetto Python con il gestore di pacchetti uv.

  1. Crea una cartella denominata mcp-on-cloudrun per archiviare il codice sorgente per il deployment:

      mkdir mcp-on-cloudrun
      cd mcp-on-cloudrun
    
  2. Crea un progetto Python con lo strumento uv per generare un file pyproject.toml:

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

    Il comando uv init crea il seguente file 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 i seguenti nuovi file aggiuntivi:

    • server.py per il codice sorgente del server MCP.
    • otel_setup.py per configurare OpenTelemetry.
    • test_server.py per testare il server self-hosted.
    • Un Dockerfile per il deployment in Cloud Run.
    touch server.py otel_setup.py test_server.py Dockerfile
    

    La directory del progetto deve contenere la seguente struttura:

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

Crea un server MCP per le operazioni matematiche

In questa sezione configurerai un server MCP matematico con FastMCP. FastMCP offre un modo rapido per creare server e client MCP con Python.

Segui questi passaggi per creare un server MCP per operazioni matematiche come addizione e sottrazione.

  1. Esegui il seguente comando per aggiungere FastMCP come dipendenza nel file pyproject.toml:

    uv add fastmcp==2.13.1 --no-sync
    
  2. Aggiungi il seguente codice di configurazione di OpenTelemetry nel file 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. Aggiungi il seguente codice sorgente del server MCP matematico nel file 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. Includi il seguente codice nel Dockerfile per utilizzare lo strumento uv per eseguire il file 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"]
    

Esegui il deployment in Cloud Run

Puoi eseguire il deployment del server MCP come immagine container o come codice sorgente:

Immagine container

Per eseguire il deployment di un server MCP incluso in un pacchetto come immagine container, segui queste istruzioni.

  1. Crea un repository Artifact Registry per archiviare l'immagine container:

    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. Crea l'immagine container ed eseguine il push su 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. Esegui il deployment dell'immagine contenitore del server MCP in 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
    

Origine

Puoi eseguire il deployment dei server MCP self-hosted in Cloud Run dalle relative origini.

Esegui il deployment dall'origine eseguendo il seguente comando:

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

Autentica il client MCP

Se hai eseguito il deployment del servizio con il flag --no-allow-unauthenticated, qualsiasi client MCP che si connette al server MCP self-hosted deve eseguire l'autenticazione.

  1. Concedi il ruolo Cloud Run Invoker (roles/run.invoker) al account di servizio. Questo binding dei criteri di Identity and Access Management garantisce l'utilizzo di un meccanismo di sicurezza efficace per autenticare il client MCP locale.

  2. Esegui il proxy Cloud Run per creare un tunnel autenticato al server MCP self-hosted sulla tua macchina locale machine:

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

    Se il proxy Cloud Run non è ancora installato, questo comando ti chiede di scaricarlo. Segui le istruzioni per scaricare e installare il proxy.

Cloud Run autentica tutto il traffico verso http://127.0.0.1:8080 e inoltra le richieste al server MCP self-hosted.

Testa il server MCP self-hosted

Puoi testare e connetterti al server MCP self-hosted utilizzando il client FastMCP e accedendo all'URL http://127.0.0.1:8080/mcp.

Per testare e richiamare il meccanismo di addizione e sottrazione:

  1. Prima di eseguire il server di test, esegui il proxy Cloud Run.

  2. Crea un file di test denominato test_server.py e aggiungi il seguente codice:

    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. In un nuovo terminale, esegui il server di test:

    uv run test_server.py
    

    Dovresti vedere l'output seguente:

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

Visualizza i dati di telemetria

Questa sezione descrive come visualizzare i dati di log, metriche e tracce generati dal server MCP self-hosted.

Prima di iniziare

Per ottenere le autorizzazioni necessarie per visualizzare i dati di log, metriche e tracce, chiedi all'amministratore di concederti i seguenti ruoli IAM sul tuo progetto:

Per saperne di più sulla concessione dei ruoli, consulta Gestisci l'accesso a progetti, cartelle e organizzazioni.

Potresti anche riuscire a ottenere le autorizzazioni richieste tramite i ruoli personalizzati o altri ruoli predefiniti.

Visualizza i dati di telemetria

Per scoprire come visualizzare i dati di log, metriche e tracce, consulta quanto segue:

Dati di log

Nella Google Cloud console, vai alla pagina Esplora log:

Vai a Esplora log

Se utilizzi la barra di ricerca per trovare questa pagina, seleziona il risultato con il sottotitolo Logging.

Per ulteriori informazioni sull'utilizzo della pagina Esplora log, consulta Visualizzare e analizzare i log.

Dati delle metriche

Nella Google Cloud console, vai alla  Esplora metriche pagina:

Vai a Esplora metriche

Se utilizzi la barra di ricerca per trovare questa pagina, seleziona il risultato con il sottotitolo Monitoring.

Per ulteriori informazioni sull'utilizzo della pagina Esplora metriche, consulta Creare grafici con Esplora metriche.

Dati di Trace

Nella Google Cloud console, vai alla Esplora tracce pagina:

Vai a Esplora tracce

Puoi trovare questa pagina anche utilizzando la barra di ricerca.

Lo screenshot seguente illustra il riquadro Dettagli nella pagina Esplora tracce, che mostra gli intervalli di traccia generati dalle operazioni tools/call:

Il riquadro dei dettagli mostra una traccia e i relativi intervalli associati.

Per ulteriori informazioni sull'utilizzo della pagina Esplora tracce, consulta Trovare ed esplorare le tracce.

Passaggi successivi