Verbindung zum MCP-Server für Entwicklerwissen über MCP SDKs herstellen

Mit den offiziellen SDKs für das Model Context Protocol (MCP) können Ihre eigenen Anwendungen und KI-Agenten programmatisch eine Verbindung zum Developer Knowledge MCP-Server herstellen. Verwenden Sie ein MCP SDK, wenn Sie einen benutzerdefinierten Agenten, einen Backend-Dienst oder einen eigenen MCP-Server erstellen, der offizielle Google Developers-Entwicklerdokumentation durchsuchen und abrufen muss, anstatt eine vorhandene IDE oder Unterstützung beim Programmieren zu konfigurieren.

In diesem Leitfaden erfahren Sie, wie Sie

  • das MCP-Client-SDK für Python oder TypeScript installieren.
  • mit einem API-Schlüssel oder Standardanmeldedaten für Anwendungen (Application Default Credentials, ADC) eine Verbindung zum Developer Knowledge MCP-Server herstellen.
  • die Tools search_documents, get_documents und answer_query aufrufen.
  • Authentifizierungs-, Kontingent- und Toolfehler behandeln.

Hinweis

Bevor Sie beginnen, lesen Sie die folgenden Abschnitte.

API aktivieren und Anmeldedaten erstellen

Aktivieren Sie die Developer Knowledge API in Ihrem Google Cloud-Projekt und erstellen Sie die Anmeldedaten für Ihre Authentifizierungsmethode. Eine detaillierte Anleitung finden Sie unter siehe Authentifizierungsmethode auswählen.

In den Beispielen in diesem Leitfaden wird ein API-Schlüssel verwendet. Wenn Sie stattdessen ADC verwenden möchten, lesen Sie den Abschnitt Mit Standardanmeldedaten für Anwendungen authentifizieren.

MCP SDK installieren

Wählen Sie Ihre Programmiersprache aus, um das MCP-Client-SDK zu installieren:

Python

In diesem Leitfaden wird Version 2 des MCP Python SDK verwendet, für das Python 3.10 oder höher erforderlich ist. Version 1.x des SDK verwendet andere Klassen- und Funktionsnamen. Daher funktionieren diese Beispiele nicht damit:

pip install --upgrade "mcp>=2"

TypeScript

In diesem Leitfaden wird das MCP TypeScript SDK mit Node.js 18 oder höher verwendet:

npm install @modelcontextprotocol/sdk

API-Schlüssel festlegen

Damit Sie Ihren API-Schlüssel nicht fest im Quellcode codieren müssen, speichern Sie ihn in einer Umgebungsvariablen. Ersetzen Sie YOUR_API_KEY durch Ihren API-Schlüssel:

export DEVELOPERKNOWLEDGE_API_KEY="YOUR_API_KEY"

Verbindung zum Server herstellen

Der Developer Knowledge MCP-Server verwendet den streamfähigen HTTP-Transport am folgenden Endpunkt:

https://developerknowledge.googleapis.com/mcp

Übergeben Sie zur Authentifizierung Ihren API-Schlüssel in jeder Anfrage im HTTP-Header X-Goog-Api-Key. Übergeben Sie den API-Schlüssel nicht als URL-Abfrageparameter.

Im folgenden Beispiel wird eine Verbindung zum Server hergestellt und die verfügbaren Tools werden aufgelistet:

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();

Wenn die Verbindung erfolgreich ist, werden in der Ausgabe die drei Tools aufgeführt:

Available tools: search_documents, answer_query, get_documents

Die übrigen Beispiele in diesem Leitfaden werden im verbundenen Client aus diesem Abschnitt ausgeführt. In den TypeScript-Beispielen wird await auf oberster Ebene verwendet. Führen Sie sie daher als ES-Module aus (z. B. mit npx tsx index.ts).

Tools aufrufen

Jedes Tool gibt sein Ergebnis als strukturierte Inhalte zurück, die dem Ausgabeschema des Tools entsprechen. So können Sie Felder direkt lesen, anstatt Text zu parsen. Die vollständigen Eingabe- und Ausgabeschemas finden Sie in der MCP-Referenz.

Nach Dokumentation suchen

Rufen Sie search_documents mit einem query-String auf, um die relevantesten Dokumentationsblöcke abzurufen. Jedes Ergebnis enthält den Block content und den parent-Ressourcennamen des Dokuments, aus dem er stammt:

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`);
}

Vollständige Dokumente abrufen

Wenn ein Block nicht genügend Kontext enthält, übergeben Sie einen oder mehrere parent-Werte an get_documents, um den vollständigen Markdown-Inhalt jeder Seite abzurufen. Sie können bis zu 20 Dokumente in einem einzigen Aufruf anfordern. Da mehrere Blöcke aus demselben Dokument stammen können, entfernen Sie zuerst doppelte parent-Werte:

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);
}

Vollständige Dokumente können groß sein. Rufen Sie get_documents daher nur auf, wenn die Suchblöcke nicht ausreichen. Weitere Informationen finden Sie unter Kontextfenster und Tokennutzung optimieren.

Antwort generieren

Rufen Sie answer_query auf, um eine Antwort zu generieren, die auf dem Developer Knowledge-Korpus basiert. Das Ergebnis enthält den answerText und die references, die zum Generieren verwendet wurden:

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'));

Das Feld references enthält Dokumentressourcennamen, die Sie an get_documents übergeben können. Dasselbe Dokument kann mehrmals vorkommen. Entfernen Sie daher Duplikate, bevor Sie die Dokumente abrufen. Das Tool answer_query hat ein niedrigeres Kontingent als die anderen Tools. Weitere Informationen finden Sie unter Kontingente und Limits.

Mit Standardanmeldedaten für Anwendungen authentifizieren

Anstelle eines API-Schlüssels können Sie sich mit Standardanmeldedaten für Anwendungen (Application Default Credentials, ADC) authentifizieren. ADC funktioniert mit Ihren Nutzeranmeldedaten bei der lokalen Entwicklung und mit Dienstkonten, wenn Ihr Code in Google Cloud ausgeführt wird.

Wenn Sie ADC verwenden, senden Sie bei jeder Anfrage die folgenden Header:

  • Authorization: ein Bearer-OAuth 2.0-Zugriffstoken mit dem Bereich https://www.googleapis.com/auth/cloud-platform.
  • X-Goog-User-Project: die ID des Projekts, in dem die Developer Knowledge API aktiviert ist und das für das Kontingent in Rechnung gestellt wird. Ihr Konto benötigt die Berechtigung serviceusage.services.use für dieses Projekt.

Zugriffstokens laufen ab. Daher müssen sie von Clients mit langer Laufzeit aktualisiert werden. In den folgenden Beispielen werden die Google-Authentifizierungsbibliotheken verwendet, um jeder Anfrage ein aktuelles Token hinzuzufügen.

  1. Richten Sie ADC für die lokale Entwicklung ein. Folgen Sie dazu der Anleitung auf dem ADC unter OAuth-Anmeldedatentyp auswählen.

  2. Legen Sie die Umgebungsvariable GOOGLE_CLOUD_PROJECT auf das Projekt fest, in dem die Developer Knowledge API aktiviert ist. In den Beispielen wird diese Projekt-ID im Header X-Goog-User-Project gesendet:

    export GOOGLE_CLOUD_PROJECT="PROJECT_ID"
    
  3. Installieren Sie die Google-Authentifizierungsbibliothek für Ihre Sprache:

    Python

    pip install --upgrade google-auth requests
    

    TypeScript

    npm install google-auth-library
    
  4. Erstellen Sie den Client mit 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);
    

Fehler verarbeiten

Fehler vom Developer Knowledge MCP-Server erreichen Ihren Code auf zwei Arten:

  • Anfragefehler: Authentifizierungs-, Berechtigungs- und Kontingentfehler werden mit einem HTTP-Fehlerstatus wie 400, 403, oder 429 zurückgegeben. Die SDKs lösen diese als Ausnahmen aus: MCPError in Python und StreamableHTTPError in TypeScript. Fangen Sie diese Ausnahmen um Ihre Toolaufrufe ab.
  • Toolfehler: Wenn ein Tool ausgeführt wird, die Anfrage aber nicht abgeschlossen werden kann, ist für das Ergebnis is_error (Python) oder isError (TypeScript) auf true gesetzt und das Feld content enthält eine Textbeschreibung des Problems. Prüfen Sie dieses Feld, bevor Sie die strukturierten Inhalte lesen.

Im folgenden Beispiel werden beide Fehlertypen behandelt:

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;
  }
}

Wenn answer_query einen Kontingentfehler (429 RESOURCE_EXHAUSTED) zurückgibt, greifen Sie auf search_documents zurück, das ein höheres Kontingent hat. Informationen zu Wiederholungsstrategien, einschließlich exponentiellem Backoff, finden Sie unter Fehlerbehandlung und Kontingentverwaltung. Häufige Ursachen für Authentifizierungsfehler finden Sie unter API-Schlüsselfehler und OAuth- und ADC-Fehler.

Nächste Schritte