Conectar-se ao servidor MCP de conhecimento do desenvolvedor usando SDKs do MCP

Os SDKs oficiais do Protocolo de Contexto de Modelo (MCP) permitem que seus aplicativos e agentes de IA se conectem ao servidor MCP do Developer Knowledge de forma programática. Use um SDK do MCP ao criar um agente personalizado, um serviço de back-end ou seu próprio servidor MCP que precisa pesquisar e recuperar a documentação para desenvolvedores oficial do Google Developers, em vez de configurar um ambiente de desenvolvimento integrado ou uma assistência de programação.

Neste guia, você vai aprender a:

  • Instalar o SDK do cliente do MCP para Python ou TypeScript.
  • Conectar-se ao servidor MCP do Developer Knowledge com uma chave de API ou o Application Default Credentials (ADC).
  • Chamar as ferramentas search_documents, get_documents e answer_query.
  • Resolver erros de autenticação, cota e ferramentas.

Antes de começar

Antes de começar, conclua as seções a seguir.

Ativar a API e criar credenciais

Ative a API Developer Knowledge no seu projeto na nuvem do Google Cloud e crie as credenciais para o método de autenticação. Para instruções detalhadas, consulte Escolher seu método de autenticação.

Os exemplos neste guia usam uma chave de API. Para usar o ADC, consulte Autenticar com o Application Default Credentials.

Instalar o SDK do MCP

Selecione sua linguagem de programação para instalar o SDK do cliente do MCP:

Python

Este guia usa a versão 2 do SDK do MCP para Python, que exige o Python 3.10 ou mais recente. A versão 1.x do SDK usa nomes de classe e função diferentes. Portanto, esses exemplos não funcionam com ela:

pip install --upgrade "mcp>=2"

TypeScript

Este guia usa o SDK do MCP para TypeScript com o Node.js 18 ou mais recente:

npm install @modelcontextprotocol/sdk

Definir sua chave de API

Para evitar a codificação da chave de API no código-fonte, armazene-a em uma variável de ambiente. Substitua YOUR_API_KEY pela sua chave de API:

export DEVELOPERKNOWLEDGE_API_KEY="YOUR_API_KEY"

Conexão com o servidor

O servidor MCP do Developer Knowledge usa o transporte HTTP transmissível no endpoint a seguir:

https://developerknowledge.googleapis.com/mcp

Para autenticar, transmita sua chave de API no cabeçalho HTTP X-Goog-Api-Key em cada solicitação. Não transmita a chave de API como um parâmetro de consulta de URL.

O exemplo a seguir se conecta ao servidor e lista as ferramentas disponíveis:

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 a conexão for bem-sucedida, a saída vai listar as três ferramentas:

Available tools: search_documents, answer_query, get_documents

Os exemplos restantes neste guia são executados no cliente conectado desta seção. Os exemplos do TypeScript usam await de nível superior. Portanto, execute-os como módulos ES (por exemplo, com npx tsx index.ts).

Chamar as ferramentas

Cada ferramenta retorna o resultado como conteúdo estruturado que corresponde ao esquema de saída da ferramenta. Assim, é possível ler os campos diretamente em vez de analisar o texto. Para conferir os esquemas de entrada e saída completos, consulte a referência do MCP.

Pesquisar documentação

Chame search_documents com uma string query para recuperar os blocos de documentação mais relevantes. Cada resultado contém o content do bloco e o nome do recurso parent do documento de origem:

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

Recuperar documentos completos

Se um bloco não contiver contexto suficiente, transmita um ou mais valores parent para get_documents para recuperar o conteúdo completo do Markdown de cada página. É possível solicitar até 20 documentos em uma única chamada. Como vários blocos podem vir do mesmo documento, remova os valores parent duplicados primeiro:

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

Os documentos completos podem ser grandes. Portanto, chame get_documents somente quando os blocos de pesquisa não forem suficientes. Para saber mais, consulte Otimizar a janela de contexto e o uso de tokens.

Gerar uma resposta

Chame answer_query para gerar uma resposta com base no corpus do Developer Knowledge. O resultado contém o answerText e as references usadas para gerá-lo:

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

O campo references contém nomes de recursos de documentos que podem ser transmitidos para get_documents. O mesmo documento pode aparecer mais de uma vez. Portanto, remova as duplicatas antes de recuperar os documentos. A ferramenta answer_query tem uma cota menor do que as outras ferramentas. Para saber mais, consulte Cotas e limites.

Autenticar com o Application Default Credentials

Em vez de uma chave de API, é possível autenticar com o Application Default Credentials (ADC). O ADC funciona com suas credenciais de usuário durante o desenvolvimento local e com contas de serviço quando o código é executado no Google Cloud.

Ao usar o ADC, envie os seguintes cabeçalhos em cada solicitação:

  • Authorization: um token de acesso Bearer do OAuth 2.0 com o escopo https://www.googleapis.com/auth/cloud-platform.
  • X-Goog-User-Project: o ID do projeto que tem a API Developer Knowledge ativada e é faturado pela cota. Sua conta precisa da permissão serviceusage.services.use nesse projeto.

Os tokens de acesso expiram. Portanto, os clientes de longa duração precisam atualizá-los. Os exemplos a seguir usam as bibliotecas de autenticação do Google para adicionar um token atual a cada solicitação.

  1. Configure o ADC para desenvolvimento local seguindo as etapas na guia ADC em Escolher seu tipo de credencial OAuth.

  2. Defina a variável de ambiente GOOGLE_CLOUD_PROJECT para o projeto que tem a API Developer Knowledge ativada. Os exemplos enviam esse ID do projeto no cabeçalho X-Goog-User-Project:

    export GOOGLE_CLOUD_PROJECT="PROJECT_ID"
    
  3. Instale a biblioteca do Google Authenticator para sua linguagem:

    Python

    pip install --upgrade google-auth requests
    

    TypeScript

    npm install google-auth-library
    
  4. Crie o cliente com o 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);
    

Solucionar erros

Os erros do servidor MCP do Developer Knowledge chegam ao seu código de duas maneiras:

  • Erros de solicitação: erros de autenticação, permissão e cota são retornados com um status de erro de HTTP, como 400, 403, ou 429. Os SDKs geram essas exceções: MCPError no Python e StreamableHTTPError no TypeScript. Capture essas exceções nas chamadas de ferramentas.
  • Erros de ferramenta: quando uma ferramenta é executada, mas não consegue concluir a solicitação, o resultado tem is_error (Python) ou isError (TypeScript) definido como true, e o campo content contém uma descrição de texto do problema. Verifique esse campo antes de ler o conteúdo estruturado.

O exemplo a seguir processa os dois tipos de erro:

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 retornar um erro de cota (429 RESOURCE_EXHAUSTED), volte para search_documents, que tem uma cota maior. Para estratégias de nova tentativa, incluindo espera exponencial, consulte Tratamento de erros e gerenciamento de cotas. Para conferir as causas comuns de erros de autenticação, consulte Erros de chave de API e Erros de OAuth e ADC.

A seguir