Completions
मशीनी अनुवाद
यह page अंग्रेज़ी documentation से अपने-आप अनुवादित किया गया है, और अंग्रेज़ी page ही प्रामाणिक version है। अगर कुछ गलत लगे, तो अनुवाद page बताता है कि इसकी सूचना कैसे दें।
आपके server के ऊपर UI बना रहा कोई client चाहता है कि user के टाइप करते ही argument values अपने आप पूरे हों: भाषाओं के नाम, repositories के नाम, file paths।
Completions वह तरीका है जिससे server ये सुझाव देता है।
कुछ ऐसा जो complete करने लायक हो
Completions ठीक दो चीज़ों पर लागू होते हैं: किसी prompt के arguments और किसी resource template के parameters। तो ऐसे server से शुरू करें जिसमें दोनों में से एक-एक हो:
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}"
यहाँ अभी तक completions के बारे में कुछ नहीं है।
review_codeएकlanguageलेता है। user को यह अनुमान नहीं लगाना चाहिए कि आप कौन-सी वर्तनियाँ स्वीकार करते हैं।github_repoएकownerऔर एकrepoलेता है। दोनों के लिए free-text boxes रखना खराब form बनाता है।
Completion handler
@mcp.completion() से सजाया हुआ एक function जोड़ें:
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
- हर server में एक ही handler होता है। हर completion request यहीं आती है, और जो complete हो रहा है उसके हिसाब से आप branch करते हैं।
- इसे
async defहोना ज़रूरी है: SDK इसे await करता है। - इसे तीन arguments मिलते हैं:
ref: कौन-सा prompt या resource template,PromptReferenceयाResourceTemplateReferenceके रूप में। दोनों में फ़र्कisinstanceसे पता चलता है।argument:argument.nameवह argument है जो complete हो रहा है,argument.valueवह है जो user ने अब तक टाइप किया है।context: पहले से तय हो चुके arguments। अभी इसे नज़रअंदाज़ करें।- आप
Completion(values=[...])लौटाते हैं, या जब देने को कुछ न हो तोNone।
Tip
argument.value वह prefix है जो user ने टाइप किया है। SDK आपके लिए filter नहीं करता: जो कुछ
आप values में रखते हैं, UI वही दिखाता है। startswith आपको खुद लिखना है।
इसे आज़माएँ
इसे Testing वाले in-memory Client से चलाएँ।
client.complete() को ref=PromptReference(name="review_code") और
argument={"name": "language", "value": "py"} के साथ call करें:
result.completion.values # ['python']
refवही reference type है जो आपके handler को मिलता है।argumentएक सादी dict है जिसमें ठीक दो keys हैं,nameऔरvalue।
खाली value भेजें और आपको पूरी सूची वापस मिलती है। lang.startswith("") हर भाषा के लिए true है:
result.completion.values # ['go', 'javascript', 'python', 'rust', 'typescript']
code के बारे में पूछें (ऐसा argument जिसे handler नहीं पहचानता) और वह None लौटाता है, जिसे SDK खाली list में बदल देता है:
result.completion.values # []
None का मतलब है "कोई सुझाव नहीं", error कभी नहीं। UI सादे text box पर लौट आता है।
एक capability जो आपने कभी declare नहीं की
handler register करना ही declaration है। कोई client जोड़ें और देखें:
client.server_capabilities.completions # CompletionsCapability()
आपने completions कहीं नहीं लिखी। SDK ने handler देखा और आपके लिए capability declare कर दी। हर optional capability ऐसे ही काम करती है: handler ही declaration है। (तीनों primitives optional नहीं हैं: MCPServer उन्हें हमेशा declare करता है, handlers हों या न हों।)
Check
पहली server.py पर वापस जाएँ (जिसमें कोई handler नहीं है) और फिर भी उससे पूछें। call
JSON-RPC error के साथ fail होती है:
Method not found
और client.server_capabilities.completions None है। capability का यही मतलब है:
सही ढंग से बना client इसे जाँचता है और वह request कभी नहीं भेजता जिसका जवाब आप नहीं दे सकते।
एक-दूसरे पर निर्भर arguments
github://repos/{owner}/{repo} में दो parameters हैं, और repo के काम के values इस पर निर्भर करते हैं कि पहले कौन-सा owner चुना गया।
context इसी के लिए है। इसमें वे arguments होते हैं जो user पहले ही तय कर चुका है:
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
- नई branch template के
repoparameter के लिए चलती है। context.argumentsअब तक चुने गए values (यहाँ,owner) कीdict[str, str] | Noneहै।- अभी
ownerनहीं है तो कोई समझदार सुझाव भी नहीं, इसलिए handlerNoneलौटाता है।
client ये तय हो चुके values context_arguments= से भेजता है। इस बार ref है
ResourceTemplateReference(uri="github://repos/{owner}/{repo}")। खाली value के साथ
repo माँगें और context_arguments={"owner": "modelcontextprotocol"} pass करें:
result.completion.values # ['python-sdk', 'typescript-sdk', 'inspector']
context_arguments= हटा दें और वही call [] लौटाती है। जब तक handler को owner पता न हो, वह नहीं जान सकता कि कौन-से repos सुझाए।
Info
Completion total= और has_more= भी लेता है। इन्हें तब set करें जब values किसी लंबी सूची का
एक हिस्सा हो, ताकि UI "और 200 बाकी" दिखा सके। ज़्यादातर handlers को इनकी कभी ज़रूरत नहीं पड़ती।
सारांश
- Completions prompt arguments और resource template parameters के लिए सुझाव हैं। और कुछ नहीं।
@mcp.completion()वह एक handler register करता है। यहasync def (ref, argument, context) -> Completion | Noneहै।isinstance(ref, ...)औरargument.nameपर branch करें।argument.valueसे filter खुद करें।Noneखाली list बन जाता है। यह कभी error नहीं है।context.argumentsमें पहले से तय values होती हैं; client उन्हेंcontext_arguments=के रूप में देता है।completionscapability उसी पल आ जाती है जब आप handler register करते हैं। उसके बिना, request का जवाबMethod not foundहै।
सुझाव तब काम आते हैं जब user अभी prompt या template भर ही रहा हो; किसी tool call के बीच में उससे सवाल पूछना हो तो आपको Elicitation चाहिए। text के अलावा tool जो कुछ लौटा सकता है वह सब Images, audio और icons में है।