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 della telemetria. L'esempio in questo documento crea un server MCP utilizzando FastMCP ed esegue il deployment del server MCP utilizzando Cloud Run. FastMCP include la strumentazione OpenTelemetry che raccoglie la telemetria da tutte le operazioni MCP.

Questo documento descrive i seguenti passaggi:

  1. Prepara il tuo 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 autogestito.
  6. Visualizza i dati di telemetria.

Prima di iniziare

  1. Accedi al tuo account Google Cloud . Se non conosci Google Cloud, crea un account per valutare le prestazioni 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 dei servizi (roles/serviceusage.serviceUsageAdmin), che include l'autorizzazione serviceusage.services.enable. Scopri come concedere i ruoli.

    Abilita le API

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

    Console

    1. Nella console Google Cloud 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 il deployment del servizio Cloud Run.

    5. Nell'elenco Seleziona un ruolo, seleziona un ruolo.
    6. Per concedere altri ruoli, 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 può avere PRINCIPAL, consulta Identificatori delle entità.
    • ROLE: un ruolo IAM.
  11. Se la tua organizzazione è soggetta a una norma di restrizione di dominio che limita le chiamate non autenticate per il tuo progetto, devi accedere al servizio di cui è stato 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 passaggi seguenti descrivono come configurare il progetto Python con il uv package manager.

  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 autogestito.
    • 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 configuri 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 questo comando per aggiungere FastMCP e le dipendenze OpenTelemetry richieste nel file pyproject.toml:

    uv add fastmcp==3.2.0 opentelemetry-api==1.40.0 opentelemetry-sdk==1.40.0 opentelemetry-exporter-otlp-proto-grpc==1.40.0 --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 al 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'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 su 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 su Cloud Run dalle relative origini.

Esegui il deployment dall'origine eseguendo questo comando:

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

Autenticare il client MCP

Se hai eseguito il deployment del servizio con il flag --no-allow-unauthenticated, qualsiasi client MCP che si connette al tuo server MCP autogestito deve autenticarsi.

  1. Concedi il ruolo Cloud Run Invoker (roles/run.invoker) al account di servizio. Questo binding dei criteri Identity and Access Management garantisce che venga utilizzato 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 autogestito sulla tua macchina locale:

    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 autogestito.

Testare il server MCP autogestito

Per testare e connetterti al tuo server MCP autogestito, utilizza il client FastMCP e accedi all'URL http://127.0.0.1:8080/mcp.

Per testare e richiamare il meccanismo di aggiunta e sottrazione, segui questi passaggi:

  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
    

Visualizzare i dati di telemetria

Questa sezione descrive come visualizzare i dati di log, metriche e traccia 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 nel 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.

Visualizzare la telemetria

Per scoprire come visualizzare i dati di log, metriche e traccia, consulta le seguenti risorse:

Dati di log

Nella console Google Cloud , 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 saperne di più sull'utilizzo della pagina Esplora log, vedi Visualizzare e analizzare i log.

Dati delle metriche

Nella console Google Cloud , vai alla pagina  Esplora metriche:

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 Crea grafici con Esplora metriche.

Dati di Trace

Nella console Google Cloud , vai alla pagina Esplora tracce:

Vai a Esplora tracce

Puoi trovare questa pagina anche utilizzando la barra di ricerca.

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

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

Per saperne di più sull'utilizzo della pagina Esplora tracce, vedi Trovare ed esplorare le tracce.

Passaggi successivi