Tamamlamalar
Makine çevirisi
Bu sayfa İngilizce dokümantasyondan otomatik olarak çevrildi; esas alınması gereken sürüm İngilizce sayfadır. Yanlış görünen bir şey varsa, nasıl bildireceğinizi Çeviriler sayfası açıklar.
Sunucunuzun üzerine bir arayüz kuran bir istemci, kullanıcı yazdıkça argüman değerlerini otomatik tamamlamak ister: dil adları, depo adları, dosya yolları.
Tamamlamalar, sunucunuzun bu önerileri sağlama yoludur.
Tamamlamaya değer bir şey
Tamamlamalar tam olarak iki şeye uygulanır: bir prompt'un argümanlarına ve bir kaynak şablonunun parametrelerine. O halde her birinden birer tane içeren bir sunucuyla başlayın:
from mcp.server import MCPServer
mcp = MCPServer("GitHub Explorer")
@mcp.resource("github://repos/{owner}/{repo}")
def github_repo(owner: str, repo: str) -> str:
"""A GitHub repository."""
return f"Repository: {owner}/{repo}"
@mcp.prompt()
def review_code(language: str, code: str) -> str:
"""Review a snippet of code."""
return f"Review this {language} code:\n{code}"
Burada henüz tamamlamalarla ilgili hiçbir şey yok.
review_codebirlanguagealır. Kullanıcı hangi yazımları kabul ettiğinizi tahmin etmek zorunda kalmamalı.github_repobirownerve birrepoalır. İkisi için de serbest metin kutuları kötü bir form olur.
Tamamlama işleyicisi
@mcp.completion() ile dekore edilmiş tek bir fonksiyon ekleyin:
from mcp.server import MCPServer
from mcp.types import Completion, CompletionArgument, CompletionContext, PromptReference, ResourceTemplateReference
mcp = MCPServer("GitHub Explorer")
LANGUAGES = ["go", "javascript", "python", "rust", "typescript"]
@mcp.resource("github://repos/{owner}/{repo}")
def github_repo(owner: str, repo: str) -> str:
"""A GitHub repository."""
return f"Repository: {owner}/{repo}"
@mcp.prompt()
def review_code(language: str, code: str) -> str:
"""Review a snippet of code."""
return f"Review this {language} code:\n{code}"
@mcp.completion()
async def handle_completion(
ref: PromptReference | ResourceTemplateReference,
argument: CompletionArgument,
context: CompletionContext | None,
) -> Completion | None:
if isinstance(ref, PromptReference) and argument.name == "language":
return Completion(values=[lang for lang in LANGUAGES if lang.startswith(argument.value)])
return None
- Sunucu başına tek bir işleyici vardır. Her tamamlama isteği buraya düşer; neyin tamamlandığına göre siz dallanırsınız.
async defolmak zorundadır: SDK onu await eder.- Üç argüman alır:
ref: hangi prompt veya kaynak şablonu olduğu; birPromptReferenceya daResourceTemplateReferenceolarak gelir. İkisiniisinstanceile ayırt edersiniz.argument:argument.nametamamlanmakta olan argüman,argument.valueise kullanıcının şu ana kadar yazdığıdır.context: hâlihazırda çözümlenmiş argümanlar. Şimdilik görmezden gelin.- Bir
Completion(values=[...])döndürürsünüz; sunacak bir şeyiniz yoksaNone.
Tip
argument.value, kullanıcının yazdığı ön ektir. SDK sizin yerinize filtreleme yapmaz:
values içine ne koyarsanız arayüz onu gösterir. startswith'i yazmak size düşer.
Deneyin
Test etme sayfasındaki bellek içi Client ile çalıştırın.
client.complete()'i ref=PromptReference(name="review_code") ve
argument={"name": "language", "value": "py"} ile çağırın:
result.completion.values # ['python']
ref, işleyicinizin aldığı referans türünün aynısıdır.argument, tam olarak iki anahtarı (namevevalue) olan düz bir dict'tir.
Boş bir value gönderin, listenin tamamı geri döner. lang.startswith("") her dil için doğrudur:
result.completion.values # ['go', 'javascript', 'python', 'rust', 'typescript']
code hakkında sorun (işleyicinizin tanımadığı bir argüman); None döndürür, SDK da bunu boş bir listeye çevirir:
result.completion.values # []
None "öneri yok" demektir, asla bir hata değildir. Arayüz düz bir metin kutusuna geri döner.
Hiç bildirmediğiniz bir yetenek
İşleyiciyi kaydetmek bildirimin ta kendisidir. Bir istemci bağlayın ve bakın:
client.server_capabilities.completions # CompletionsCapability()
completions'ı hiçbir yerde listelemediniz. SDK işleyiciyi gördü ve yeteneği sizin yerinize bildirdi. İsteğe bağlı her yetenek böyle çalışır: işleyici bildirimin kendisidir. (Üç temel yapı isteğe bağlı değildir: MCPServer işleyici olsun olmasın bunları her zaman bildirir.)
Check
İlk server.py dosyasına (işleyicisi olmayana) dönün ve yine de sorun. Çağrı bir JSON-RPC
hatasıyla başarısız olur:
Method not found
Ve client.server_capabilities.completions None olur. Yeteneğin anlamı budur: düzgün
davranan bir istemci bunu kontrol eder ve yanıtlayamayacağınız isteği hiç göndermez.
Bağımlı argümanlar
github://repos/{owner}/{repo} kaynağının iki parametresi var ve repo için işe yarar değerler önce hangi owner'ın seçildiğine bağlı.
context tam da bunun için var. Kullanıcının hâlihazırda çözümlediği argümanları taşır:
from mcp.server import MCPServer
from mcp.types import Completion, CompletionArgument, CompletionContext, PromptReference, ResourceTemplateReference
mcp = MCPServer("GitHub Explorer")
LANGUAGES = ["go", "javascript", "python", "rust", "typescript"]
REPOS_BY_OWNER = {
"modelcontextprotocol": ["python-sdk", "typescript-sdk", "inspector"],
"pydantic": ["pydantic", "pydantic-ai", "logfire"],
}
@mcp.resource("github://repos/{owner}/{repo}")
def github_repo(owner: str, repo: str) -> str:
"""A GitHub repository."""
return f"Repository: {owner}/{repo}"
@mcp.prompt()
def review_code(language: str, code: str) -> str:
"""Review a snippet of code."""
return f"Review this {language} code:\n{code}"
@mcp.completion()
async def handle_completion(
ref: PromptReference | ResourceTemplateReference,
argument: CompletionArgument,
context: CompletionContext | None,
) -> Completion | None:
if isinstance(ref, PromptReference) and argument.name == "language":
return Completion(values=[lang for lang in LANGUAGES if lang.startswith(argument.value)])
if isinstance(ref, ResourceTemplateReference) and argument.name == "repo":
if context is None or context.arguments is None:
return None
repos = REPOS_BY_OWNER.get(context.arguments.get("owner", ""), [])
return Completion(values=[repo for repo in repos if repo.startswith(argument.value)])
return None
- Yeni dal, şablonun
repoparametresi için devreye girer. context.arguments, şu ana kadar seçilen değerlerin (buradaowner) birdict[str, str] | None'ıdır.- Henüz
owneryoksa mantıklı öneri de yoktur; bu yüzden işleyiciNonedöndürür.
İstemci bu çözümlenmiş değerleri context_arguments= ile gönderir. Bu kez ref bir
ResourceTemplateReference(uri="github://repos/{owner}/{repo}") olur. Boş bir value ile
repo'yu isteyin ve context_arguments={"owner": "modelcontextprotocol"} geçirin:
result.completion.values # ['python-sdk', 'typescript-sdk', 'inspector']
context_arguments='ı kaldırın, aynı çağrı [] döndürür. İşleyici, sahibi bilmeden hangi depoları önereceğini bilemez.
Info
Completion ayrıca total= ve has_more= de alır. values daha uzun bir listenin bir dilimi
olduğunda bunları ayarlayın; böylece arayüz "ve 200 tane daha" gösterebilir. Çoğu işleyicinin
bunlara hiç ihtiyacı olmaz.
Özet
- Tamamlamalar, prompt argümanları ve kaynak şablonu parametreleri için önerilerdir. Başka bir şey değil.
@mcp.completion()tek işleyiciyi kaydeder. İmzasıasync def (ref, argument, context) -> Completion | None'dır.isinstance(ref, ...)veargument.nameüzerinden dallanın.argument.value'ya göre filtrelemeyi kendiniz yapın.Noneboş bir listeye dönüşür. Asla bir hata değildir.context.argumentshâlihazırda çözümlenmiş değerleri tutar; istemci bunlarıcontext_arguments=olarak sağlar.completionsyeteneği, işleyiciyi kaydettiğiniz anda ortaya çıkar. O olmadan istekMethod not foundolur.
Öneriler, kullanıcı bir prompt'u veya şablonu hâlâ doldururken işe yarar; bir araç çağrısının ortasında kullanıcıya soru sormak için Elicitation gerekir. Bir aracın metin dışında döndürebileceği her şey ise Görseller, ses ve simgeler sayfasında.