errors संभालना
मशीनी अनुवाद
यह page अंग्रेज़ी documentation से अपने-आप अनुवादित किया गया है, और अंग्रेज़ी page ही प्रामाणिक version है। अगर कुछ गलत लगे, तो अनुवाद page बताता है कि इसकी सूचना कैसे दें।
tool दो तरीकों से fail हो सकता है, और SDK दोनों के साथ बहुत अलग बर्ताव करता है।
साधारण exception raise करें तो उसे model देखता है। MCPError raise करें तो उसे protocol देखता है।
यह page इन दोनों में से चुनने के बारे में है।
ऐसा error जिसे model ठीक कर सकता है
ऐसा tool लें जो कुछ खोजता है, और खोज को नाकाम होने दें:
from mcp.server import MCPServer
mcp = MCPServer("Bookshop")
CATALOG = {"Dune": "Frank Herbert", "Neuromancer": "William Gibson"}
@mcp.tool()
def get_author(title: str) -> str:
"""Look up the author of a book in the catalog."""
if title not in CATALOG:
raise ValueError(f"No book titled {title!r} in the catalog.")
return CATALOG[title]
उन दो lines में MCP जैसा कुछ नहीं है। get_author सादा ValueError raise करता है, जैसे कोई भी Python function करता।
इसे ऐसे title से call करें जो catalog में नहीं है और result देखें:
result.is_error # True
result.content # [TextContent(text="Error executing tool get_author: No book titled 'Nothing' in the catalog.")]
result.structured_content # None
- request सफल रही। result मौजूद है; caller की तरफ़ कुछ raise नहीं हुआ।
is_errorTrueहै, और आपके exception का message (आगे tool का नाम लगा हुआ)contentमें है, ठीक वहीं जहाँ model पढ़ता है।structured_contentNoneहै। fail हुए call के पास structure करने को कोई return value नहीं होती।
यह tool error है, और आपका tool कोई भी exception raise करे, default यही है। और लगभग हमेशा आप यही चाहते भी हैं।
आपके tool को call करने वाला model ही है। arguments उसी ने चुने। इसलिए tool error बातचीत का एक turn है: model "No book titled 'Nothing' in the catalog." पढ़ता है, समझ जाता है कि उसने title का गलत अंदाज़ा लगाया, और बेहतर title के साथ फिर call करता है। आपने एक raise लिखा और बदले में खुद को सुधारने वाला agent मिल गया।
Tip
tool से कभी error message return न करें। लौटाई गई string का is_error=False होता है, इसलिए
model को (और हर client UI को) लगता है कि tool ठीक चला और वही string जवाब थी।
raise करें। flag ही संकेत है।
ऐसा error जिसे model ठीक नहीं कर सकता
अब ValueError की जगह MCPError रखें।
from mcp import MCPError
from mcp.server import MCPServer
from mcp.types import INVALID_PARAMS
mcp = MCPServer("Bookshop")
CATALOG = {"Dune": "Frank Herbert", "Neuromancer": "William Gibson"}
@mcp.tool()
def get_author(title: str) -> str:
"""Look up the author of a book in the catalog."""
if title not in CATALOG:
raise MCPError(code=INVALID_PARAMS, message=f"No book titled {title!r} in the catalog.")
return CATALOG[title]
MCPError SDK का protocol error है। यही वह एक exception है जिसे tool wrapper catch नहीं करता: यह ऊपर propagate होता है, और पूरी tools/call request result के बजाय JSON-RPC error के साथ fail हो जाती है।
{
"code": -32602,
"message": "No book titled 'Nothing' in the catalog."
}
- कोई result नहीं है। न
content, नis_error: model के पढ़ने के लिए कुछ भी नहीं। - इसके बजाय error host application को मिलता है, ठीक वैसे ही जैसे tool के बिल्कुल मौजूद न होने पर मिलता।
code,message, औरdataजस के तस पहुँचते हैं।INVALID_PARAMS-32602है;mcp.typesइसे और बाकी JSON-RPC error codes (INVALID_REQUEST,INTERNAL_ERROR, ...) को constants के रूप में export करता है, ताकि आपको कभी magic number न लिखना पड़े।
Check
वही lookup, वही चूक, लेकिन अब call client की तरफ़ लौटने के बजाय raise होता है:
mcp.shared.exceptions.MCPError: No book titled 'Nothing' in the catalog.
पहले version ने model को एक वाक्य थमाया जिस पर वह कुछ कर सकता था। यह version उसे कुछ नहीं देता।
get_author के लिए यह साफ़ तौर पर बदतर है, और यही अगले section का मुद्दा है।
कौन सा raise करें
दोनों रास्ते दो अलग-अलग सवालों का जवाब देते हैं।
- कोई भी exception raise करें जब नाकामी execution की हो: आपके tool ने जो करने की कोशिश की, वह नहीं हुआ। call model ने चुना था, इसलिए नतीजा भी model को दिखना चाहिए और उसे संभलने का मौका मिलना चाहिए। गलत वर्तनी वाला title, timeout हो गया upstream API, ऐसी row जो मौजूद नहीं: सब tool errors।
MCPErrorraise करें जब request खुद ठुकराई जानी चाहिए: client के पास वह capability नहीं जिस पर आपका tool निर्भर है, server किसी को भी serve करने की हालत में नहीं है, caller ने कोई ज़रूरी चरण छोड़ दिया। model का कोई retry इनमें से किसी को ठीक नहीं करता, इसलिए उसे message थमाने से कुछ हासिल नहीं।
एक सवाल से फ़ैसला हो जाता है: क्या ज़्यादा समझदार model इससे बच सकता था? हाँ -> साधारण exception। नहीं -> MCPError।
इस कसौटी पर get_author के दूसरे version ने गलत चुनाव किया: बेहतर title से बात बन जाती है, इसलिए model message देखने का हक़दार था। वह version आपको mechanism दिखाने के लिए है, उसकी सिफ़ारिश करने के लिए नहीं।
Info
MCPError from mcp import MCPError पर मिलता है और code, message, और एक optional
data payload लेता है। इनमें आप जो भी रखें, client को वही मिलता है: SDK raise किए गए
MCPError को sanitise करने के बजाय जस का तस आगे भेज देता है।
ऐसा resource जो मौजूद नहीं है
resources भी यही रेखा खींचते हैं, और आम मामले के लिए एक नाम वाला exception साथ देते हैं।
from mcp.server import MCPServer
from mcp.server.mcpserver.exceptions import ResourceNotFoundError
mcp = MCPServer("Bookshop")
CATALOG = {"Dune": "Frank Herbert", "Neuromancer": "William Gibson"}
@mcp.resource("books://{title}")
def book(title: str) -> str:
"""The catalog entry for one book."""
if title not in CATALOG:
raise ResourceNotFoundError(f"No book titled {title!r} in the catalog.")
return f"{title} by {CATALOG[title]}"
books://{title} एक template है। यह किसी भी title से match करता है, इसलिए "URI सही बना है" और "किताब मौजूद है" दो अलग सवाल हैं, और दूसरे का जवाब सिर्फ़ आपका function दे सकता है।
जब वह न दे सके, ResourceNotFoundError raise करें। SDK इसे उस protocol error में बदल देता है जो spec ने गायब resource के लिए तय किया है: -32602, और data में माँगा गया URI, ताकि client को पता रहे कि कौन सा read fail हुआ।
{
"code": -32602,
"message": "No book titled 'Nothing' in the catalog.",
"data": {"uri": "books://Nothing"}
}
ध्यान दें, यहाँ कोई is_error=True वाला आधा-अधूरा result नहीं है। resource read या तो contents लौटाता है या fail होता है: resources के पास सिर्फ़ protocol वाला रास्ता है। templates और resources के बारे में बाकी सब कुछ Resources में है।
ऐसे errors जो आप कभी raise नहीं करते
गलत argument आपके function तक कभी पहुँचता ही नहीं।
get_author को ऐसा title भेजें जो string नहीं है, और SDK आपको call करने से पहले ही उसे input schema के आधार पर ठुकरा देता है, उसी तरह के is_error=True tool error के रूप में जिसे model पढ़ और सुधार सकता है। Tools यही अस्वीकृति Field(le=50) constraint के साथ दिखाता है।
इसका मतलब है raise statements की एक पूरी श्रेणी जो आपको लिखनी नहीं पड़ती: अपने ही type hints को दोबारा validate न करें।
Info
इस page पर सब कुछ वही है जो client को दिखता है, और जिस in-memory Client से आप
tests लिखेंगे, उसे भी ठीक यही दिखता है। raise_exceptions=True भी tool error को वापस
traceback में नहीं बदलता: जब तक वह flag कुछ कर पाता, आपका exception पहले ही
is_error=True result बन चुका होता है। result पर assert करें। Testing में यह pattern बताया गया है।
सारांश
- tool में कोई भी exception raise करें -> call
is_error=Trueलौटाता है,contentमें आपके message के साथ। model उसे पढ़ता है और retry कर सकता है। यही default है। MCPErrorraise करें -> call खुद JSON-RPC error के साथ fail हो जाता है। model को कुछ नहीं दिखता; host इससे निपटता है।code,message, औरdataजस के तस बचे रहते हैं।- फ़ैसला करने वाला सवाल: क्या ज़्यादा समझदार model इससे बच सकता था? हाँ -> exception। नहीं ->
MCPError। - resource handler से
ResourceNotFoundError-> protocol का-32602,dataमें URI के साथ। - गलत arguments आपका function चलने से पहले ही schema के आधार पर ठुकरा दिए जाते हैं; उनके लिए आप
raiseनहीं करते। from mcp import MCPError; error-code constantsmcp.typesसे आते हैं।
errors संभल गए। server जो कुछ expose करता है, वह सब यही है। हर handler क्या पढ़ सकता है, और चलते-चलते client के साथ वापस क्या कर सकता है, यह अगला section है: आपके handler के अंदर।
जिन SDK errors से आपका सामना होने की सबसे ज़्यादा संभावना है, उनका हूबहू text, हर एक का मतलब, और हर एक का एक-कदम वाला हल Troubleshooting में है।