ערכות ה-SDK הרשמיות של Model Context Protocol (MCP) מאפשרות לאפליקציות ולסוכני ה-AI שלכם להתחבר לשרת ה-MCP של Developer Knowledge באופן פרוגרמטי. השתמשו ב-MCP SDK כשאתם יוצרים סוכן בהתאמה אישית, שירות לקצה העורפי או שרת MCP משלכם שצריך לחפש ולאחזר מאמרי עזרה רשמיים למפתחים של Google, במקום להגדיר IDE קיים או עוזר דיגיטלי לתכנות.
במדריך הזה תלמדו איך:
- מתקינים את ערכת ה-SDK של לקוח MCP ל-Python או ל-TypeScript.
- מתחברים לשרת ה-MCP של Developer Knowledge באמצעות מפתח API או Application Default Credentials (ADC).
- מפעילים את הכלים
search_documents,get_documentsו-answer_query. - לטפל בשגיאות שקשורות לאימות, למכסות ולכלים.
לפני שמתחילים
לפני שמתחילים, צריך להשלים את הקטעים הבאים.
הפעלת ה-API ויצירת פרטי כניסה
מפעילים את Developer Knowledge API בפרויקט בענן ב-Google Cloud ויוצרים את פרטי הכניסה לשיטת האימות. הוראות מפורטות מופיעות במאמר בחירה של שיטת האימות.
בדוגמאות שבמדריך הזה נעשה שימוש במפתח API. כדי להשתמש ב-ADC, קראו את המאמר אימות באמצעות Application Default Credentials.
התקנת ה-SDK של MCP
בוחרים את שפת התכנות כדי להתקין את ערכת ה-SDK של לקוח ה-MCP:
Python
במדריך הזה נעשה שימוש בגרסה 2 של MCP Python SDK, שנדרשת בה Python 3.10 ואילך. בגרסה 1.x של ה-SDK נעשה שימוש בשמות שונים של מחלקות ופונקציות, ולכן הדוגמאות האלה לא פועלות בה:
pip install --upgrade "mcp>=2"
TypeScript
במדריך הזה משתמשים ב-MCP TypeScript SDK עם Node.js מגרסה 18 ואילך:
npm install @modelcontextprotocol/sdk
הגדרת מפתח ה-API
כדי להימנע מהטמעת מפתח ה-API בקוד המקור, כדאי לאחסן אותו במשתנה סביבה. מחליפים את הערך YOUR_API_KEY במפתח ה-API שלכם:
export DEVELOPERKNOWLEDGE_API_KEY="YOUR_API_KEY"
התחברות לשרת
שרת ה-MCP של Developer Knowledge משתמש בתעבורת נתונים ב-HTTP שניתנת להעברה בסטרימינג בנקודת הקצה הבאה:
https://developerknowledge.googleapis.com/mcp
כדי לבצע אימות, צריך להעביר את מפתח ה-API בכותרת ה-HTTP X-Goog-Api-Key בכל בקשה. אל תעבירו את מפתח ה-API כפרמטר של שאילתה בכתובת URL.
בדוגמה הבאה מתבצע חיבור לשרת ומוצגת רשימה של הכלים הזמינים:
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();
אם החיבור מצליח, הפלט מציג את שלושת הכלים:
Available tools: search_documents, answer_query, get_documents
שאר הדוגמאות במדריך הזה פועלות בתוך הלקוח המחובר מהקטע הזה. בדוגמאות של TypeScript נעשה שימוש ב-await ברמה העליונה, לכן צריך להריץ אותן כמודולים של ES (לדוגמה, באמצעות npx tsx index.ts).
קריאה לכלים
כל כלי מחזיר את התוצאה שלו כתוכן מובנה שתואם לסכימת הפלט של הכלי, כך שאתם יכולים לקרוא שדות ישירות במקום לנתח טקסט. הסכימות המלאות של הקלט והפלט מפורטות בחומר העזר בנושא MCP.
חיפוש מסמכים
קוראים לפונקציה search_documents עם מחרוזת query כדי לאחזר את חלקי התיעוד הרלוונטיים ביותר. כל תוצאה מכילה את החלק content ואת שם המשאב parent של המסמך שממנו הוא הגיע:
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`);
}
אחזור מסמכים מלאים
אם קטע לא מכיל מספיק הקשר, מעבירים ערך אחד או יותר של parent אל get_documents כדי לאחזר את תוכן ה-Markdown המלא של כל דף. אפשר לבקש עד 20 מסמכים בקריאה אחת. כמה קטעים יכולים להגיע מאותו מסמך, לכן קודם צריך להסיר ערכים כפולים של parent:
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);
}
מסמכים מלאים יכולים להיות גדולים, לכן צריך להתקשר אל get_documents רק אם חלקי החיפוש לא מספיקים. מידע נוסף זמין במאמר בנושא אופטימיזציה של חלון ההקשר והשימוש בטוקנים.
יצירת תשובה
תתקשר אל answer_query כדי ליצור תשובה שמבוססת על מאגר הידע למפתחים. התוצאה מכילה את answerText ואת references ששימשו ליצירתה:
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'));
השדה references מכיל שמות של משאבי מסמכים שאפשר להעביר אל get_documents. אותו מסמך יכול להופיע יותר מפעם אחת, לכן צריך להסיר כפילויות לפני שמאחזרים את המסמכים. answer_query למכסה של הכלי הזה יש ערך נמוך יותר מאשר לכלים האחרים. מידע נוסף זמין במאמר בנושא מכסות ומגבלות.
אימות באמצעות Application Default Credentials
במקום מפתח API, אפשר לבצע אימות באמצעות Application Default Credentials (ADC). במהלך הפיתוח המקומי, ADC פועל עם פרטי הכניסה של המשתמש, וכשהקוד פועל ב-Google Cloud, הוא פועל עם חשבונות שירות.
כשמשתמשים ב-ADC, צריך לשלוח את הכותרות הבאות בכל בקשה:
-
Authorization: אסימון גישה מסוג OAuth 2.0 שלBearerעם היקף ההרשאותhttps://www.googleapis.com/auth/cloud-platform. -
X-Goog-User-Project: מזהה הפרויקט שבו פועל Developer Knowledge API, ושהחיוב על המכסה מתבצע בו. לחשבון שלכם צריכה להיות ההרשאהserviceusage.services.useבפרויקט הזה.
תוקף טוקני הגישה פג, ולכן לקוחות שפועלים לאורך זמן צריכים לרענן אותם. בדוגמאות הבאות נעשה שימוש בספריות האימות של Google כדי להוסיף אסימון נוכחי לכל בקשה.
כדי להגדיר ADC לפיתוח מקומי, פועלים לפי השלבים שבכרטיסייה ADC בקטע בחירת סוג פרטי הכניסה ל-OAuth.
מגדירים את משתנה הסביבה
GOOGLE_CLOUD_PROJECTלפרויקט שבו פועל Developer Knowledge API. בדוגמאות האלה, מזהה הפרויקט נשלח בכותרתX-Goog-User-Project:export GOOGLE_CLOUD_PROJECT="PROJECT_ID"מתקינים את ספריית האימות של Google בשפה הרצויה:
Python
pip install --upgrade google-auth requestsTypeScript
npm install google-auth-libraryיוצרים את הלקוח באמצעות 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);
טיפול בשגיאות
שגיאות משרת ה-MCP של Developer Knowledge מגיעות לקוד שלכם בשתי דרכים:
- שגיאות בבקשות: שגיאות שקשורות לאימות, להרשאות ולמכסות מוחזרות עם סטטוס שגיאת HTTP, כמו
400,403או429. ערכות ה-SDK מעלות את השגיאות האלה כחריגות:MCPErrorב-Python ו-StreamableHTTPErrorב-TypeScript. כדאי לטפל בחריגים האלה בשיחות עם כלים. - שגיאות בכלי: כשהכלי פועל אבל לא מצליח להשלים את הבקשה, התוצאה כוללת את הערך
trueבשדהis_error(Python) אוisError(TypeScript), והשדהcontentמכיל תיאור טקסטואלי של הבעיה. חשוב לבדוק את השדה הזה לפני שקוראים את התוכן המובנה.
הדוגמה הבאה מטפלת בשני סוגי השגיאות:
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;
}
}
אם answer_query מחזיר שגיאת מכסה (429 RESOURCE_EXHAUSTED), חוזרים ל-search_documents, שיש לו מכסה גבוהה יותר. במאמר טיפול בשגיאות וניהול מכסות מפורטות אסטרטגיות לניסיון חוזר, כולל השהיה מעריכית לפני ניסיון חוזר (exponential backoff).
במאמרים שגיאות במפתח API ושגיאות ב-OAuth וב-ADC מפורטות הסיבות הנפוצות לשגיאות אימות.
המאמרים הבאים
- במסמכי העזר של MCP מפורטות הסכימות המלאות של הכלים.
- במאמר הזה מוסבר אילו מוצרים נוספו לאינדקס.
- שולחים קריאה ישירות ל-Developer Knowledge API באמצעות ספריות הלקוח.