Connettiti al server MCP per Developer Knowledge utilizzando gli SDK MCP

Gli SDK ufficiali Model Context Protocol (MCP) consentono alle tue applicazioni e ai tuoi agenti AI di connettersi al server MCP per Developer Knowledge a livello di programmazione. Utilizza un SDK MCP quando crei un agente personalizzato, un servizio di backend o un server MCP che deve cercare e recuperare la documentazione per lo sviluppo ufficiale di Google Developers, anziché configurare un IDE o un'assistenza al coding esistente.

In questa guida imparerai a:

  • Installare l'SDK client MCP per Python o TypeScript.
  • Connetterti al server MCP per Developer Knowledge con una chiave API o le Credenziali predefinite dell'applicazione (ADC).
  • Chiamare gli strumenti search_documents, get_documents e answer_query.
  • Gestire l'autenticazione, la quota e gli errori degli strumenti.

Prima di iniziare

Prima di iniziare, completa le seguenti sezioni.

Abilitare l'API e creare le credenziali

Abilita l'API Developer Knowledge nel tuo progetto cloud Google Cloud e crea le credenziali per il metodo di autenticazione. Per istruzioni passo passo, consulta Scegliere il metodo di autenticazione.

Gli esempi in questa guida utilizzano una chiave API. Per utilizzare ADC, consulta Autenticarsi con le Credenziali predefinite dell'applicazione.

Installare l'SDK MCP

Seleziona il linguaggio di programmazione per installare l'SDK client MCP:

Python

Questa guida utilizza la versione 2 dell' SDK MCP Python, che richiede Python 3.10 o versioni successive. La versione 1.x dell'SDK utilizza nomi di classi e funzioni diversi, quindi questi esempi non funzionano:

pip install --upgrade "mcp>=2"

TypeScript

Questa guida utilizza l' SDK MCP TypeScript con Node.js 18 o versioni successive:

npm install @modelcontextprotocol/sdk

Impostare la chiave API

Per evitare di codificare la chiave API nel codice sorgente, archiviala in una variabile di ambiente. Sostituisci YOUR_API_KEY con la tua chiave API:

export DEVELOPERKNOWLEDGE_API_KEY="YOUR_API_KEY"

Connettersi al server

Il server MCP per Developer Knowledge utilizza il trasporto HTTP Streamable al seguente endpoint:

https://developerknowledge.googleapis.com/mcp

Per autenticarti, passa la chiave API nell'intestazione HTTP X-Goog-Api-Key in ogni richiesta. Non passare la chiave API come parametro di query dell'URL.

L'esempio seguente si connette al server ed elenca gli strumenti disponibili:

Python

import asyncio
import os

from mcp import Client
from mcp.client.streamable_http import (
    create_mcp_http_client,
    streamable_http_client,
)

MCP_URL = "https://developerknowledge.googleapis.com/mcp"

async def main() -> None:
    headers = {"X-Goog-Api-Key": os.environ["DEVELOPERKNOWLEDGE_API_KEY"]}

    async with create_mcp_http_client(headers=headers) as http_client:
        transport = streamable_http_client(MCP_URL, http_client=http_client)
        async with Client(transport) as client:
            tools = await client.list_tools()
            names = ", ".join(tool.name for tool in tools.tools)
            print("Available tools:", names)

if __name__ == "__main__":
    asyncio.run(main())

TypeScript

import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import {
  StreamableHTTPClientTransport,
} from '@modelcontextprotocol/sdk/client/streamableHttp.js';

const apiKey = process.env.DEVELOPERKNOWLEDGE_API_KEY;
if (!apiKey) {
  throw new Error('Set the DEVELOPERKNOWLEDGE_API_KEY variable.');
}

const transport = new StreamableHTTPClientTransport(
  new URL('https://developerknowledge.googleapis.com/mcp'),
  { requestInit: { headers: { 'X-Goog-Api-Key': apiKey } } },
);

const client = new Client({ name: 'my-docs-agent', version: '1.0.0' });
await client.connect(transport);

const { tools } = await client.listTools();
console.log('Available tools:', tools.map((tool) => tool.name).join(', '));

await client.close();

Se la connessione va a buon fine, l'output elenca i tre strumenti:

Available tools: search_documents, answer_query, get_documents

Gli esempi rimanenti in questa guida vengono eseguiti all'interno del client connesso da questa sezione. Gli esempi di TypeScript utilizzano await di primo livello, quindi eseguili come moduli ES (ad esempio, con npx tsx index.ts).

Chiamare gli strumenti

Ogni strumento restituisce il risultato come contenuti strutturati che corrispondono allo schema di output dello strumento, in modo da poter leggere i campi direttamente anziché analizzare il testo. Per gli schemi di input e output completi, consulta il riferimento MCP.

Cercare la documentazione

Chiama search_documents con una stringa query per recuperare i blocchi di documentazione più pertinenti. Ogni risultato contiene il content del blocco e il nome della risorsa parent del documento da cui proviene:

Python

search = await client.call_tool(
    "search_documents",
    {"query": "How do I create a Cloud Storage bucket?"},
)
results = search.structured_content["results"]
for chunk in results[:3]:
    print(f"{chunk['parent']}\n{chunk['content'][:200]}...\n")

TypeScript

const search = await client.callTool({
  name: 'search_documents',
  arguments: { query: 'How do I create a Cloud Storage bucket?' },
});
const { results } = search.structuredContent as {
  results: { parent: string; id: string; content: string }[];
};
for (const chunk of results.slice(0, 3)) {
  console.log(`${chunk.parent}\n${chunk.content.slice(0, 200)}...\n`);
}

Recuperare i documenti completi

Se un blocco non contiene un contesto sufficiente, passa uno o più valori parent a get_documents per recuperare il contenuto Markdown completo di ogni pagina. Puoi richiedere fino a 20 documenti in una singola chiamata. Poiché più blocchi possono provenire dallo stesso documento, rimuovi prima i valori parent duplicati:

Python

names = list(dict.fromkeys(chunk["parent"] for chunk in results[:3]))
get = await client.call_tool("get_documents", {"names": names})
for document in get.structured_content["documents"]:
    print(f"{document['title']} ({document['uri']})")
    print(document["content"])

TypeScript

const names = [...new Set(results.slice(0, 3).map((c) => c.parent))];
const get = await client.callTool({
  name: 'get_documents',
  arguments: { names },
});
const { documents } = get.structuredContent as {
  documents: {
    name: string;
    uri: string;
    title: string;
    content: string;
  }[];
};
for (const document of documents) {
  console.log(`${document.title} (${document.uri})`);
  console.log(document.content);
}

I documenti completi possono essere di grandi dimensioni, quindi chiama get_documents solo quando i blocchi di ricerca non sono sufficienti. Per saperne di più, consulta Ottimizzare la finestra di contesto e l'utilizzo dei token.

Generare una risposta

Chiama answer_query per generare una risposta basata sul corpus di Developer Knowledge. Il risultato contiene answerText e i references utilizzati per generarlo:

Python

answer = await client.call_tool(
    "answer_query",
    {"query": "How do I create a Cloud Storage bucket?"},
)
print(answer.structured_content["answerText"])
for reference in answer.structured_content["references"]:
    print(reference)

TypeScript

const answer = await client.callTool({
  name: 'answer_query',
  arguments: { query: 'How do I create a Cloud Storage bucket?' },
});
const { answerText, references } = answer.structuredContent as {
  answerText: string;
  references: string[];
};
console.log(answerText);
console.log(references.join('\n'));

Il campo references contiene i nomi delle risorse dei documenti che puoi passare a get_documents. Lo stesso documento può essere visualizzato più di una volta, quindi rimuovi i duplicati prima di recuperare i documenti. Lo strumento answer_query ha una quota inferiore rispetto agli altri strumenti. Per saperne di più, consulta Quote e limiti.

Autenticarsi con le Credenziali predefinite dell'applicazione

Anziché una chiave API, puoi autenticarti con le Credenziali predefinite dell'applicazione (ADC). ADC funziona con le credenziali utente durante lo sviluppo locale e con gli account di servizio quando il codice viene eseguito su Google Cloud.

Quando utilizzi ADC, invia le seguenti intestazioni in ogni richiesta:

  • Authorization: un token di accesso OAuth 2.0 Bearer con l'ambito https://www.googleapis.com/auth/cloud-platform.
  • X-Goog-User-Project: l'ID del progetto in cui è abilitata l'API Developer Knowledge e per cui viene addebitata la quota. Il tuo account deve disporre dell'autorizzazione serviceusage.services.use per questo progetto.

I token di accesso scadono, quindi i client a lunga esecuzione devono aggiornarli. Gli esempi seguenti utilizzano le librerie di autenticazione Google per aggiungere un token corrente a ogni richiesta.

  1. Configura ADC per lo sviluppo locale seguendo i passaggi nella scheda ADC in Scegliere il tipo di credenziale OAuth.

  2. Imposta la variabile di ambiente GOOGLE_CLOUD_PROJECT sul progetto in cui è abilitata l'API Developer Knowledge. Gli esempi inviano questo ID progetto nell'intestazione X-Goog-User-Project:

    export GOOGLE_CLOUD_PROJECT="PROJECT_ID"
    
  3. Installa la libreria di autenticazione Google per il tuo linguaggio:

    Python

    pip install --upgrade google-auth requests
    

    TypeScript

    npm install google-auth-library
    
  4. Crea il client con ADC:

    Python

    import os
    
    import google.auth
    import google.auth.transport.requests
    import httpx2  # Installed automatically with mcp>=2
    from mcp import Client
    from mcp.client.streamable_http import (
        create_mcp_http_client,
        streamable_http_client,
    )
    
    MCP_URL = "https://developerknowledge.googleapis.com/mcp"
    
    class GoogleCredentialsAuth(httpx2.Auth):
        """Adds a current ADC access token and quota project to requests."""
    
        def __init__(self, project_id: str) -> None:
            self.credentials, _ = google.auth.default(
                scopes=["https://www.googleapis.com/auth/cloud-platform"]
            )
            self.project_id = project_id
    
        def auth_flow(self, request):
            if not self.credentials.valid:
                self.credentials.refresh(
                    google.auth.transport.requests.Request()
                )
            request.headers["Authorization"] = (
                f"Bearer {self.credentials.token}"
            )
            request.headers["X-Goog-User-Project"] = self.project_id
            yield request
    
    async def main() -> None:
        auth = GoogleCredentialsAuth(os.environ["GOOGLE_CLOUD_PROJECT"])
        async with create_mcp_http_client(auth=auth) as http_client:
            transport = streamable_http_client(
                MCP_URL, http_client=http_client
            )
            async with Client(transport) as client:
                ...
    

    TypeScript

    import { GoogleAuth } from 'google-auth-library';
    import { Client } from '@modelcontextprotocol/sdk/client/index.js';
    import {
      StreamableHTTPClientTransport,
    } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
    
    const auth = new GoogleAuth({
      scopes: 'https://www.googleapis.com/auth/cloud-platform',
    });
    const projectId = process.env.GOOGLE_CLOUD_PROJECT;
    if (!projectId) {
      throw new Error('Set the GOOGLE_CLOUD_PROJECT variable.');
    }
    
    const transport = new StreamableHTTPClientTransport(
      new URL('https://developerknowledge.googleapis.com/mcp'),
      {
        // Add a current access token and the quota project to each request.
        fetch: async (url, init) => {
          const headers = new Headers(init?.headers);
          for (const [name, value] of await auth.getRequestHeaders()) {
            headers.set(name, value);
          }
          headers.set('X-Goog-User-Project', projectId);
          return fetch(url, { ...init, headers });
        },
      },
    );
    
    const client = new Client({ name: 'my-docs-agent', version: '1.0.0' });
    await client.connect(transport);
    

Gestire gli errori

Gli errori del server MCP per Developer Knowledge raggiungono il codice in due modi:

  • Errori di richiesta: gli errori di autenticazione, autorizzazione e quota vengono restituiti con uno stato di errore HTTP, ad esempio 400, 403, o 429. Gli SDK li generano come eccezioni: MCPError in Python e StreamableHTTPError in TypeScript. Rileva queste eccezioni intorno alle chiamate degli strumenti.
  • Errori degli strumenti: quando uno strumento viene eseguito ma non riesce a completare la richiesta, il risultato ha is_error (Python) o isError (TypeScript) impostato su true e il campo content contiene una descrizione testuale del problema. Controlla questo campo prima di leggere i contenuti strutturati.

L'esempio seguente gestisce entrambi i tipi di errore:

Python

from mcp import MCPError

try:
    result = await client.call_tool(
        "search_documents", {"query": "Cloud Storage buckets"}
    )
except MCPError as error:
    print(f"Request failed ({error.code}): {error.message}")
else:
    if result.is_error:
        print("Tool error:", result.content)
    else:
        results = result.structured_content["results"]

TypeScript

import {
  StreamableHTTPError,
} from '@modelcontextprotocol/sdk/client/streamableHttp.js';

try {
  const result = await client.callTool({
    name: 'search_documents',
    arguments: { query: 'Cloud Storage buckets' },
  });
  if (result.isError) {
    console.error('Tool error:', result.content);
  } else {
    const { results } = result.structuredContent as {
      results: { parent: string; id: string; content: string }[];
    };
  }
} catch (error) {
  if (error instanceof StreamableHTTPError) {
    console.error(`Request failed (${error.code}): ${error.message}`);
  } else {
    throw error;
  }
}

Se answer_query restituisce un errore di quota (429 RESOURCE_EXHAUSTED), esegui il fallback a search_documents, che ha una quota più elevata. Per le strategie di nuovi tentativi, incluso il backoff esponenziale, consulta Gestione degli errori e della quota. Per le cause comuni degli errori di autenticazione, consulta Errori delle chiavi API e errori di OAuth e ADC.

Passaggi successivi