docs: refresh translations for recent English changes (#3379)

This commit is contained in:
Max 2026-08-24 19:29:54 +01:00 • committed by GitHub
commit c5d7d0b6d0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 3149 additions and 1047 deletions

View file

@ -1,6 +1,6 @@
---
translation:
sections: [2c79b6338e09b7ac, 7edc43b3fae11314, 1086e77ce561cd7f, a3f71823df5efc31, 9fc7109f72201cae, 7bf25983df655b66, 6330e1f4c6029683, 2f1749c8c133fa1c, b3530fcf4d11fd56, ebc33704fbd74262, cd0e9c933350390e]
sections: [2c79b6338e09b7ac, 7edc43b3fae11314, 1086e77ce561cd7f, a3f71823df5efc31, 9fc7109f72201cae, d50fe7faead8cf68, 7bf25983df655b66, 6330e1f4c6029683, 2f1749c8c133fa1c, 8db7116fc8ddd0ee, ebc33704fbd74262, cd0e9c933350390e]
tool: 1
---
# Low-level Server {#the-low-level-server}
@ -116,6 +116,17 @@ asyncio.run(main())
Server इन दोनों fields की कभी तुलना नहीं करता। इस SDK का `Client` करता है: ऐसा `structured_content` लौटाएँ जो आपके declare किए `output_schema` पर खरा न उतरे, और `call_tool` एक `RuntimeError` raise करता है जो `Invalid structured content returned by tool search_books` से शुरू होता है और आगे `jsonschema` की failure उद्धृत करता है। Schema का वादा करना सस्ता है; उसे निभाना आपकी ज़िम्मेदारी है। Return types और schemas की पूरी सीढ़ी **[Structured Output](../servers/structured-output.md)** में है।
## Dialect JSON Schema 2020-12 है {#the-dialect-is-json-schema-2020-12}
`input_schema` और `output_schema` JSON Schema हैं, और dialect [MCP specification](https://modelcontextprotocol.io/specification/latest/basic#json-schema-usage) तय करती है: जिस schema में `$schema` key नहीं है वह **JSON Schema 2020-12** है। `MCPServer` जो schemas generate करता है वे इसी default पर टिके हैं (Pydantic 2020-12 लिखता है और key छोड़ देता है), और हाथ से लिखे dict पर भी यही लागू होता है, इसलिए 2020-12 की पूरी vocabulary उपलब्ध है:
```python title="server.py" hl_lines="8 14-15"
--8<-- "docs_src/lowlevel/tutorial007.py"
```
* `input_schema` का root `"type": "object"` होना ज़रूरी है। उसके साथ `oneOf`, `additionalProperties`, `anyOf`, `if`/`then`/`else`, `prefixItems`, local `$ref`s वाले `$defs` और बाकी 2020-12 keywords client तक ठीक वैसे ही पहुँचते हैं जैसे लिखे गए।
* `$schema` key की ज़रूरत नहीं है। इसे सिर्फ़ किसी पुराने draft को चुनने के लिए जोड़ें: इस SDK का `Client`, जो `structured_content` को tool के `output_schema` से validate करता है, अपना validator `$schema` से चुनता है और कोई न होने पर 2020-12 इस्तेमाल करता है।
## `_meta`: application के लिए, model के लिए नहीं {#\_meta-for-the-application-not-the-model}
`content` जवाब का वह हिस्सा है जिसे model पढ़ता है। `structured_content` वही जवाब typed data के रूप में है। `_meta` तीसरा channel है: ऐसा data जो result के साथ **client application** के लिए चलता है, जवाब का हिस्सा बने बिना।
@ -167,7 +178,7 @@ Constructor उन methods को cover करता है जिन्हे
--8<-- "docs_src/lowlevel/tutorial006.py"
```
* पहला argument method string है। Notifications के लिए इसका जुड़वाँ है, `add_notification_handler`।
* पहला argument method string है। Notifications के लिए इसका जुड़वाँ है, `add_notification_handler`। इसके handlers stdio पर और handshake पीढ़ी के HTTP connections पर चलते हैं; `2026-07-28` के streamable-HTTP रास्ते पर client की notification POST को `202` से acknowledge किया जाता है और dispatch नहीं किया जाता, क्योंकि वह revision HTTP पर client-से-server कोई notification define नहीं करता।
* `params_type` वह model है जिससे आने वाले `params` आपका handler चलने से **पहले** validate होते हैं, इसलिए custom methods को वह validation **मिलती** है जो tools को नहीं मिलती। `RequestParams` को subclass करें ताकि `_meta` field हर दूसरे method की तरह parse हो।
* Handler `BaseModel`, `dict`, या `None` लौटाता है। SDK इसे JSON-RPC result में serialise कर देता है।

View file

@ -1,6 +1,6 @@
---
translation:
sections: [6048b4f308edbb8c, 068bda0f21ee9c1b, c3e565b61acd75c5, c62422b159c6ed09, 47204fab253cc45c]
sections: [6048b4f308edbb8c, 46056f318ef205e4, c3e565b61acd75c5, c62422b159c6ed09, 420968f514138f43]
tool: 1
---
# Middleware {#middleware}
@ -52,8 +52,11 @@ client ने connection तैयार करने के लिए भेज
यही असली बात है। middleware **हर** inbound message को wrap करता है:
* connection setup: `server/discover`, या legacy session पर `initialize` और `notifications/initialized`।
* हर request और हर notification। notification के लिए `ctx.request_id is None` होता है,
* हर request और हर notification जो server तक पहुँचे। notification के लिए `ctx.request_id is None` होता है,
`call_next(ctx)` `None` लौटाता है, और आप जो भी लौटाएँ वह फेंक दिया जाता है।
(`2026-07-28` वाले streamable-HTTP path पर client का notification POST transport पर ही `202` से
acknowledge हो जाता है और कभी dispatch नहीं होता, इसलिए वह middleware तक भी नहीं पहुँचता; वह revision
HTTP पर कोई client-to-server notifications define ही नहीं करता।)
* वह method भी जिसके लिए server के पास कोई handler नहीं है: `call_next`
`MCPError(-32601, "Method not found")` को client की ओर जाते हुए आपके middleware के **बीच से** raise करता है।
@ -109,8 +112,8 @@ SDK ठीक एक middleware साथ देता है, और वह प
* middleware `async (ctx, call_next) -> result` है, जिसे `MCPServer(middleware=[...])` के रूप में पास किया जाता है (या
`mcp.middleware` में append किया जाता है), और low-level `Server` पर `server.middleware` में append किया जाता है।
* यह **हर** inbound message को wrap करता है (`server/discover`, `initialize`, requests, notifications,
अनजान methods) और outermost-first चलता है।
* यह server तक पहुँचने वाले **हर** inbound message को wrap करता है (`server/discover`, `initialize`, requests,
notifications, अनजान methods) और outermost-first चलता है।
* `ctx.request_id is None` से आप notification और request में फ़र्क करते हैं।
* एक message को अस्वीकार करने के लिए `call_next` call करने के बजाय raise करें; connection बचा रहता है।
* SDK का अपना OpenTelemetry tracing भी एक middleware है, जो पहले से list में है। देखें

View file

@ -1,6 +1,6 @@
---
translation:
sections: [ebef1e7a0df854f4, a4c687d3d627d516, 8e79141fc2985342, b345dd05b9c3c7ab, 80ce41579825a6fa, 5f0fa90494de8f65, 83d10514eaa62fa5, 9190555aa39a5d28, 84a4c9d8bf14dddb, 927d71cf40b58c30]
sections: [ebef1e7a0df854f4, 8355cfaf1f76c9d5, 8e79141fc2985342, 46bdb07c7537e8a5, 80ce41579825a6fa, 5f0fa90494de8f65, 83d10514eaa62fa5, 9190555aa39a5d28, 84a4c9d8bf14dddb, 927d71cf40b58c30]
tool: 1
---
# Client {#the-client}
@ -27,9 +27,10 @@ translation:
* `MCPServer` (या low-level `Server`) instance: **in-process** connect होता है।
* URL string (`Client("http://localhost:8000/mcp")`): Streamable HTTP, production वाला रास्ता।
* **transport**: कोई भी चीज़ जिसे आप `async with ... as (read, write)` कर सकें, जैसे subprocess को wrap करने वाला `stdio_client(...)`।
* `StdioServerParameters`: वह command जो **subprocess** के रूप में launch होता है, और जिससे उसके stdin और stdout के ज़रिए बात होती है।
* **transport**: कोई भी चीज़ जिसे आप `async with ... as (read, write)` कर सकें, जैसे आपके अपने HTTP client के ऊपर `streamable_http_client(url, http_client=...)`।
इस page की बाकी हर चीज़ तीनों में एक जैसी है। Headers, subprocesses, timeouts और `Transport` protocol का अपना अलग page है: **[Client transports](transports.md)**।
इस page की बाकी हर चीज़ चारों में एक जैसी है। Headers, subprocesses, timeouts और `Transport` protocol का अपना अलग page है: **[Client transports](transports.md)**।
### connected client पर क्या है {#whats-on-a-connected-client}
@ -85,7 +86,7 @@ UI को argument form दिखाने के लिए, और model को
`call_tool(name, arguments)` tool चलाता है और आपको `CallToolResult` वापस देता है।
```python title="client.py" hl_lines="26-33"
```python title="client.py" hl_lines="27-34"
--8<-- "docs_src/client/tutorial003.py"
```
@ -117,7 +118,7 @@ result.is_error # False
!!! check
`lookup_book` से `"Solaris"` माँगें (ऐसा title जो catalog में नहीं है) और function
`ValueError` raise करता है। call फिर भी सामान्य रूप से लौटता है:
`ToolError` raise करता है। call फिर भी सामान्य रूप से लौटता है:
```python
result.is_error # True
@ -125,9 +126,10 @@ result.is_error # False
result.structured_content # None
```
exception का message `content` में पहुँचा, जहाँ **model** उसे पढ़कर दोबारा कोशिश कर सकता है। यह
जानबूझकर है: tool error बातचीत का हिस्सा है, crash नहीं। `structured_content` पर भरोसा करने से
पहले हमेशा `is_error` देखें।
`ToolError` का message `content` में पहुँचा, जहाँ **model** उसे पढ़कर दोबारा कोशिश कर सकता है। यह
जानबूझकर है: tool error बातचीत का हिस्सा है, crash नहीं। (अगर tool किसी और exception से crash
हुआ होता, तो `content` में सिर्फ़ `Error executing tool lookup_book` लिखा होता।) `structured_content`
पर भरोसा करने से पहले हमेशा `is_error` देखें।
!!! warning
`is_error=True` सिर्फ़ आपके अपने `raise` तक सीमित नहीं है। ऐसा tool माँगें जो server के पास है ही नहीं

View file

@ -1,6 +1,6 @@
---
translation:
sections: [9cac816674181eb0, 0700f337babcd4dd, 2bde0dd58cdf00f5, ff7401df479af877, 3d0832f39b0d7059, d4bf7e4479637768, 05e20c0a798860e7]
sections: [9cac816674181eb0, 0700f337babcd4dd, 2bde0dd58cdf00f5, 40b4916d82eaf1d4, 3d0832f39b0d7059, dfa4446556badef0, 5bd93be2ab2ecb9c]
tool: 1
---
# Client transports {#client-transports}
@ -87,15 +87,15 @@ environment variables set करें या अपने `httpx2.AsyncClient`
**stdio** server एक subprocess है। client उसे launch करता है, उसके stdin पर JSON-RPC लिखता है और उसके stdout से JSON-RPC पढ़ता है। desktop host आपकी machine पर server इसी तरह चलाता है: host यही code **है**, बस ऊपर एक UI के साथ, और **[असली host से जुड़ें](../get-started/real-host.md)** यही रिश्ता host की तरफ़ से, एक config file के रूप में दिखाता है।
process को `StdioServerParameters` से बताएँ, `stdio_client` से उसे transport में बदलें, और **वही** `Client` को दें:
process को `StdioServerParameters` से बताएँ और उसे `Client` को दें:
```python title="client.py" hl_lines="4-8 12"
```python title="client.py" hl_lines="3-7 11"
--8<-- "docs_src/client_transports/tutorial004.py"
```
`Client` अकेले parameters object को स्वीकार नहीं करता। `StdioServerParameters` configuration है; `stdio_client(server)` वह transport है जो उससे process spawn करना जानता है। हमेशा wrap करें।
block में enter करते ही process spawn हो जाता है। बाहर निकलने पर subprocess बंद हो जाता है: stdin बंद, इंतज़ार, और अटका रहे तो kill। आपको उसे खुद कभी साफ़ नहीं करना पड़ता।
`async with` block से बाहर निकलने पर subprocess भी बंद हो जाता है: stdin बंद, इंतज़ार, और अटका रहे तो kill। आपको उसे खुद कभी साफ़ नहीं करना पड़ता।
child का stderr आपके stderr पर जाता है। उसे कहीं और भेजना हो तो transport खुद `stdio_client` (`mcp` से) के साथ बनाएँ और वही पास करें: `Client(stdio_client(server, errlog=log_file))`।
!!! warning
child आपका environment inherit **नहीं** करता। उसे एक minimal allow-list मिलती है (POSIX पर `HOME`, `LOGNAME`,
@ -113,16 +113,16 @@ process को `StdioServerParameters` से बताएँ, `stdio_client`
`Client` के लिए ऊपर की सभी चीज़ें एक ही हैं।
**transport** कोई भी async context manager है जो message streams का `(read, write)` जोड़ा yield करता है: औपचारिक रूप से, `mcp.client` का `Transport` protocol। `Client` अपने argument को type से resolve करता है: server object in-process जुड़ता है, `str` `streamable_http_client(url)` बन जाता है, और बाकी सब कुछ सीधे transport के रूप में enter किया जाता है। यही आख़िरी नियम वजह है कि `stdio_client(...)`, `streamable_http_client(...)` और `sse_client(...)` सब उसी एक slot में बैठते हैं, और यही वजह है कि आप अपना खुद का भी लिख सकते हैं।
**transport** कोई भी async context manager है जो message streams का `(read, write)` जोड़ा yield करता है: औपचारिक रूप से, `mcp.client` का `Transport` protocol। `Client` अपने argument को type से resolve करता है: server object in-process जुड़ता है, `str` `streamable_http_client(url)` बन जाता है, `StdioServerParameters` `stdio_client(params)` बन जाता है, और बाकी सब कुछ सीधे transport के रूप में enter किया जाता है। यही आख़िरी नियम वजह है कि `stdio_client(...)`, `streamable_http_client(...)` और `sse_client(...)` सब उसी एक slot में बैठते हैं, और यही वजह है कि आप अपना खुद का भी लिख सकते हैं।
## सारांश {#recap}
* `Client(mcp)` (server object) memory में जुड़ता है। इसे tests और embedding के लिए इस्तेमाल करें।
* `Client("http://.../mcp")` (URL) Streamable HTTP पर जुड़ता है, जो production transport है।
* Headers, auth, proxies और timeouts उस `httpx2.AsyncClient` पर होने चाहिए जो आप `streamable_http_client(url, http_client=...)` को पास करते हैं। कोई `headers=` keyword नहीं है।
* stdio है `Client(stdio_client(StdioServerParameters(...)))`, अकेला parameters object कभी नहीं।
* stdio है `Client(StdioServerParameters(...))`। इसे खुद `stdio_client(...)` में सिर्फ़ तब wrap करें जब child का stderr कहीं और भेजना हो।
* subprocess को allow-list वाला environment मिलता है, आपका नहीं; `env=` उसमें जोड़ता है।
* transport वह हर चीज़ है जिस पर आप `async with x as (read, write)` कर सकें। जो कुछ server object या URL नहीं है, `Client` उसे सीधे उसी protocol को सौंप देता है।
* transport वह हर चीज़ है जिस पर आप `async with x as (read, write)` कर सकें। जो कुछ server object, URL या `StdioServerParameters` नहीं है, `Client` उसे सीधे उसी protocol को सौंप देता है।
* `Client` बनाने से transport चुना जाता है। `async with` उसे खोलता है।
transport खुल जाने के बाद दोनों पक्षों को protocol version पर सहमत होना होता है। आम तौर पर आपको इस बारे में सोचना ही नहीं पड़ता; जब पड़े, तो **[Protocol versions](../protocol-versions.md)** वह page है।

View file

@ -1,13 +1,13 @@
---
translation:
sections: [20541a40dbdd5980, 01262a123ad9501d, 429db5b574a2ac08, 56b2d49da412cb28, 6a1717123fe4513c]
sections: [490237e61c3a7a44, 01262a123ad9501d, 429db5b574a2ac08, e2d0d273fbd2d74b, 64ab0331e868f3d4, 6c8878ce2d1f6d56, 4068f23e371bf0b3, eaef75b8725bc931]
tool: 1
---
# Deprecated features {#deprecated-features}
2026-07-28 spec पाँच चीज़ों को retire करता है। SDK अब भी इनमें से हर एक को implement करता है, और अब हर एक पर **deprecation warning** लगी है।
2026-07-28 spec पाँच चीज़ों को retire करता है। SDK अब भी इनमें से हर एक को implement करता है, और अब हर एक पर **deprecation warning** लगी है। एक SDK helper अपनी अलग वजह से deprecated है और [आख़िर में](#deprecated-sdk-helpers) दिया गया है।
नीचे दी गई table हर deprecated feature का नाम, उसके हटने की वजह, और उसकी जगह किस पर build करना है, यह बताती है।
नीचे दी गई table हर deprecated feature का नाम, उसके हटने की वजह, और उसकी जगह किस replacement पर build करना है, यह बताती है।
## क्या deprecated है {#what-is-deprecated}
@ -55,6 +55,55 @@ MCPDeprecationWarning: The logging capability is deprecated as of 2026-07-28 (SE
कोशिश करता है। ये दोनों end-to-end सिर्फ़ ऐसे `mode="legacy"` connection पर काम करते हैं
जिसके client ने matching callback register किया हो।
## legacy session पर `ping` {#ping-on-a-legacy-session}
**ping** एक खाली request है जिसे कोई भी पक्ष यह जाँचने के लिए भेज सकता है कि दूसरा अब भी जवाब दे रहा है। 2026-07-28 spec इसे हटा देता है ([SEP-2575](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575)): modern client की भेजी हर request पहले ही साबित कर देती है कि server मौजूद है, और modern server के पास इसे भेजने का कोई channel नहीं है। दोनों SDK methods handshake वाली पीढ़ी के session पर अब भी काम करते हैं। client से:
```python
async def main() -> None:
async with Client("http://localhost:8000/mcp", mode="legacy") as client:
await client.send_ping() # warns; returns an EmptyResult
```
और server से, किसी भी handler के अंदर:
```python
@mcp.tool()
async def check_client(ctx: Context) -> str:
"""A tool that still pings the client mid-call."""
await ctx.session.send_ping() # no warning; an EmptyResult while the client is connected
return "client answered"
```
* `client.send_ping()` हर call पर `MCPDeprecationWarning` के साथ warn करता है। default (`2026-07-28`) connection पर server इसके बजाय `MCPError: Method not found` जवाब देता है।
* `ctx.session.send_ping()` पर कोई warning नहीं है। modern connection पर यह वही no-back-channel error raise करता है जो कोई भी दूसरी server-initiated request करती है।
* ping का जवाब देने के लिए कोई भी पक्ष कुछ register नहीं करता।
## roots में बदलाव के notifications {#roots-change-notifications}
roots capability declare करने वाला 2025 पीढ़ी का client `notifications/roots/list_changed` भेजकर server को बता सकता है कि उसके workspace folders बदल गए हैं; जवाब में server दोबारा `roots/list` की request करता है। 2026-07-28 spec बाकी push-style roots flow के साथ इस notification को भी हटा देता है। client पर `list_roots_callback=` देना (**[Client callbacks](client/callbacks.md)**) ही `"roots": {"listChanged": true}` declare करता है, और एक call वह वादा निभाता है:
```python
async def open_folder(client: Client, uri: str, name: str) -> None:
"""The user opened another folder: expose it through the roots callback, then tell the server."""
workspace.append(Root(uri=FileUrl(uri), name=name))
await client.send_roots_list_changed()
```
server पर, इसे पाने वाला handler low-level `Server` लेता है:
```python
async def roots_changed(ctx: ServerRequestContext, params: NotificationParams | None) -> None:
"""The client's roots changed: ask for the new list."""
roots = (await ctx.session.list_roots()).roots
server = Server("Bookshop", on_roots_list_changed=roots_changed)
```
* `workspace` वह list है जो आपका `list_roots_callback` लौटाता है। `client.send_roots_list_changed()` warn करता है, और इसे `mode="legacy"` client चाहिए: modern connection पर notification चुपचाप drop हो जाता है। इसके बाद session खुला रखें, क्योंकि server की follow-up `roots/list` उसी पर आती है।
* `MCPServer` के पास इस notification के लिए कोई hook नहीं है। low-level `Server` पर `on_roots_list_changed=` handler register करता है (यह भी deprecated है, और construction के समय warn करता है)। notification में कोई payload नहीं होता, इसलिए handler नई list के लिए `ctx.session.list_roots()` call करता है।
## warning को चुप कराना {#silencing-the-warning}
नए code में ऐसा न करें।
@ -75,15 +124,25 @@ warnings.filterwarnings("ignore", category=MCPDeprecationWarning)
filter को उल्टा चलाएँ और आपको मुफ़्त में regression test मिलता है। अपनी pytest
configuration की `filterwarnings` setting में `"error::mcp.MCPDeprecationWarning"`
जोड़ें और deprecated call warn करने के बजाय **raise** करता है। `old_log` नाम का tool
जो अब भी `ctx.info()` call करता है, pass होना बंद कर देता है और यह report करने लगता है:
जो अब भी `ctx.info()` call करता है, pass होना बंद कर देता है: call `is_error=True` और
`Error executing tool old_log` के साथ वापस आता है, और capture किया गया server log
असली दोषी का नाम बताता है:
```text
Error executing tool old_log: The logging capability is deprecated as of 2026-07-28 (SEP-2577).
mcp.shared.exceptions.MCPDeprecationWarning: The logging capability is deprecated as of 2026-07-28 (SEP-2577).
```
pytest configuration की एक line, और कोई deprecated call बिना test fail किए आपके
codebase में चुपके से वापस नहीं आ सकता।
## Deprecated SDK helpers {#deprecated-sdk-helpers}
ये spec के बदलाव नहीं हैं, सिर्फ़ SDK के अंदरूनी हिस्से हैं जिनका बेहतर replacement मौजूद है। ये उसी `MCPDeprecationWarning` के साथ warn करते हैं और 3.0 में हटा दिए जाएँगे।
| Deprecated | इसके बजाय क्या करें |
|---|---|
| `FuncMetadata.call_fn_with_arg_validation()` | `FuncMetadata.validate_arguments()` और फिर `FuncMetadata.call_fn()`। इसे सिर्फ़ वही code call करता था जो `FuncMetadata` को सीधे चलाता है (जैसे कोई custom `Tool` subclass)। |
## सारांश {#recap}
* 2026-07-28 spec **roots**, server-initiated **sampling**, और protocol **logging** को deprecate करता है (तीनों [SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577)), **progress** को server-से-client तक सीमित करता है, और **`ping`** को हटा देता है।
@ -91,6 +150,7 @@ warnings.filterwarnings("ignore", category=MCPDeprecationWarning)
* Deprecated होना बस सलाह भर है: wire में कोई बदलाव नहीं, 2026 से पहले के sessions पर सब कुछ काम करता रहता है, और आपको साफ़ दिखने वाली `MCPDeprecationWarning` मिलती है (यह `UserWarning` है, इसलिए default रूप से चालू है)।
* sampling और roots को इसके अलावा back-channel चाहिए जो 2026-07-28 session के पास नहीं है। modern connection पर ये warn करते हैं और फिर raise करते हैं।
* `warnings.filterwarnings("ignore", category=MCPDeprecationWarning)` पूरी category को चुप कराता है; pytest में `"error::mcp.MCPDeprecationWarning"` इसे test failure में बदल देता है।
* एक SDK helper, `FuncMetadata.call_fn_with_arg_validation()`, अलग से deprecated है और 3.0 में हटाया जाएगा।
* नया code इनमें से किसी पर भी नहीं बनना चाहिए।
इन docs का बाकी हर page मौजूदा API सिखाता है।

View file

@ -1,6 +1,6 @@
---
translation:
sections: [3c4f2f06b4e978b6, 22520eecae3d1961, f4e1709db18d635a, 2eb57992049671d9, 1ba83e9af37cc1b4, 4822586344b08d9e, 1c93afef72478992, b6b448f9eddd51dc, fe55370fd931815b]
sections: [3c4f2f06b4e978b6, 51ea5fbcb0e93563, 32d8808606ffdae0, 2eb57992049671d9, 1ba83e9af37cc1b4, 4822586344b08d9e, 1c93afef72478992, b6b448f9eddd51dc, fe55370fd931815b]
tool: 1
---
# असली host से connect करना {#connect-to-a-real-host}
@ -11,13 +11,13 @@ translation:
## एक server, हर host {#one-server-every-host}
```python title="server.py" hl_lines="3 33-34"
```python title="server.py" hl_lines="4 34-35"
--8<-- "docs_src/real_host/tutorial001.py"
```
दो tools और एक resource, एक ही file में। इस file की तीन बातें नीचे के हर host के लिए मायने रखती हैं:
* बिना arguments के `mcp.run()` एक **stdio** server शुरू करता है: यह block होता है, stdin पर protocol messages पढ़ता है और stdout पर लिखता है। इस page का हर host यही transport बोलता है। host आपकी file को child process के रूप में शुरू करता है और उन दोनों pipes का मालिक होता है, इसीलिए connect करना हमेशा बस "यह रहा command" ही होता है। आप कभी port नहीं चुनते, और किसी port पर कुछ listen नहीं करता।
* बिना arguments के `mcp.run()` **stdio** server शुरू करता है: यह block होता है, stdin पर protocol messages पढ़ता है और stdout पर लिखता है। इस page का हर host यही transport बोलता है। host आपकी file को child process के रूप में शुरू करता है और उन दोनों pipes का मालिक होता है, इसीलिए connect करना हमेशा बस "यह रहा command" ही होता है। आप कभी port नहीं चुनते, और किसी port पर कुछ listen नहीं करता।
* `run()` `if __name__ == "__main__":` के नीचे है। नीचे की हर चीज़ इस file को execute करने के बजाय **import** करती है, इसलिए बिना guard वाला `run()` module के load होते ही server शुरू कर देता।
* server object module-level global है जिसका नाम `mcp` है। `mcp run` इसी नाम को ढूँढता है (`server` और `app` भी चलते हैं)। कोई और नाम रखें तो उसे साफ़-साफ़ बताना होगा: `mcp run server.py:bookshop`।
@ -31,7 +31,7 @@ translation:
uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py
```
सबके लिए एक ही command, क्योंकि `uv run --with` उसी वक़्त SDK को एक नए environment में resolve कर देता है: यह किसी भी directory से चलता है और इसे न कोई project चाहिए, न activate करने के लिए कोई virtual environment। यहाँ यह बात कहीं और से ज़्यादा मायने रखती है, क्योंकि host आपके server को आपके shell से नहीं, बल्कि **अपनी** working directory से, लगभग खाली environment के साथ launch करता है।
सबके लिए एक ही command, क्योंकि `uv run --with` उसी वक़्त SDK को नए environment में resolve कर देता है: यह किसी भी directory से चलता है और इसे न कोई project चाहिए, न activate करने के लिए कोई virtual environment। यहाँ यह बात कहीं और से ज़्यादा मायने रखती है, क्योंकि host आपके server को आपके shell से नहीं, बल्कि **अपनी** working directory से, लगभग खाली environment के साथ launch करता है।
यही वह command है जो `mcp install` आपके लिए Claude Desktop के config में लिखता है (नीचे देखें), इसलिए जो आप हाथ से लिखते हैं और जो tool बनाता है, दोनों मेल खाते हैं, सिवाय उस exact version pin के जो tool जोड़ता है।
@ -50,7 +50,7 @@ uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py
और host किसी application से ज़्यादा कुछ नहीं जिसके अंदर MCP client हो, इसलिए आपका अपना
Python भी host की भूमिका निभा सकता है: **[Client transports](../client/transports.md)** इसी
file को `stdio_client(...)` से subprocess के रूप में launch करता है, और **[Testing](testing.md)**
file को `Client(StdioServerParameters(...))` से subprocess के रूप में launch करता है, और **[Testing](testing.md)**
बिना किसी process के, memory में ही उससे connect करता है।
## Claude Desktop {#claude-desktop}

View file

@ -1,6 +1,6 @@
---
translation:
sections: ['4926721070127497', c52a1de2b6b32f40, 2e410b412c25f314, 627195f7159e24ef]
sections: ['4926721070127497', c52a1de2b6b32f40, 8e792bf8c7489ec6, 627195f7159e24ef]
tool: 1
---
# Testing {#testing}
@ -84,12 +84,12 @@ async def test_call_add_tool(client: Client):
दो अलग-अलग चीज़ें गड़बड़ हो सकती हैं, और यह flag उनमें से सिर्फ़ एक को छूता है।
**आपके tools** में से किसी के अंदर हुआ exception protocol failure नहीं है। वह `is_error=True` वाला सामान्य result बन जाता है, और model उसका message पढ़ता है। `raise_exceptions` इसमें कुछ नहीं बदलता: इसके साथ या इसके बिना, `call_tool` वही `is_error=True` वाला result लौटाता है। इस पर एक पूरा page है:
**[Errors संभालना](../servers/handling-errors.md)**।
**आपके tools** में से किसी के अंदर हुआ exception protocol failure नहीं है। वह `is_error=True` वाला सामान्य result बन जाता है (और अगर वह `ToolError` था, तो model आपका message पढ़ता है)। `raise_exceptions` इसमें कुछ नहीं बदलता: इसके साथ या इसके बिना, `call_tool` वही `is_error=True` वाला result लौटाता है। इस पर पूरा एक page है:
**[errors संभालना](../servers/handling-errors.md)**।
Tool body के **बाहर** की failure अलग है। `Client(mcp)` जो connection देता है, उस पर server इसे client तक पहुँचने से पहले एक सामान्य `"Internal server error"` में sanitise कर देता है। किसी अनपेक्षित crash की बारीकियाँ remote caller तक कभी leak नहीं होनी चाहिए। Test में आप ठीक यही **नहीं** चाहते, और `raise_exceptions=True` यही बदलता है: आपके test को sanitise किया हुआ message नहीं, बल्कि असली message दिखता है।
tool body के **बाहर** का failure अलग है। `Client(mcp)` जो connection देता है, उस पर server इसे client तक पहुँचने से पहले एक सामान्य `"Internal server error"` में sanitise कर देता है। किसी अनपेक्षित crash की बारीकियाँ remote caller तक कभी leak नहीं होनी चाहिए। test में आप ठीक यही **नहीं** चाहते, और `raise_exceptions=True` यही बदलता है: आपके test को sanitise किया हुआ message नहीं, बल्कि असली message दिखता है।
Tests में इसे चालू रहने दें। Production code में इसका कोई मतलब नहीं है।
tests में इसे चालू रहने दें। production code में इसका कोई मतलब नहीं है।
## Default रूप से in-process {#in-process-by-default}

View file

@ -1,6 +1,6 @@
---
translation:
sections: [335ca2a0b266f003, d1ad562d3fe87bc0, 0bb1396c86daeba4, d1cb1235bb9ee267, 833179c09d239c83, e5d6dec2d2e655e8]
sections: [335ca2a0b266f003, d1ad562d3fe87bc0, 25b49f89c9e6f9d0, d1cb1235bb9ee267, 833179c09d239c83, e5d6dec2d2e655e8]
tool: 1
---
# Elicitation {#elicitation}
@ -89,7 +89,8 @@ client को आपका message मिलता है और उसके
!!! warning
elicitation schema tool के input schema जितना expressive नहीं होता। सिर्फ़ flat, primitive
fields: `str`, `int`, `float`, `bool`, या strings का `Literal` (यह `enum` बन जाता है)।
model के अंदर model रखें और `ctx.elicit` client को कुछ भी भेजे जाने से पहले ही raise कर देता है:
model के अंदर model रखें और `ctx.elicit` client को कुछ भी भेजे जाने से पहले ही raise कर देता है।
tool call `Error executing tool <name>` के साथ fail हो जाता है, और वजह आपके server log में मिलती है:
```text
TypeError: Elicitation schema field 'address' rendered as {'$ref': '#/$defs/Address'}, which is not a valid PrimitiveSchemaDefinition
@ -112,8 +113,8 @@ client को आपका message मिलता है और उसके
!!! tip
जवाब आपके code तक पहुँचने से पहले आपके model के विरुद्ध validate होता है। जो client
`bool` के लिए `"maybe"` भेजता है, वह आपकी booking को खराब नहीं करता: call
schema-mismatch error के साथ fail हो जाता है, आपका `if` कभी नहीं चलता।
`bool` के लिए `"maybe"` भेजता है, वह आपकी booking को खराब नहीं करता: `ctx.elicit`
`ValueError` raise करता है, call fail हो जाता है, और आपका `if` कभी नहीं चलता।
## user को URL पर भेजना {#send-the-user-to-a-url}

View file

@ -1,6 +1,6 @@
---
translation:
sections: [c93a3e1aefd77955, 7851abd5ec54393b, f49d1ca2f330f9cd, c03764bd9dfeef7b, 4a0391691a674ae4, 2df5cd279eabf9f5]
sections: [c93a3e1aefd77955, 7851abd5ec54393b, f49d1ca2f330f9cd, 4cc0a00347c3f534, 4a0391691a674ae4, 2df5cd279eabf9f5]
tool: 1
---
# Logging {#logging}
@ -54,6 +54,8 @@ default `"INFO"` है।
`logging.basicConfig()` पहले से मौजूद handlers को कभी नहीं बदलता। अगर आप server बनाने से पहले खुद logging configure करते हैं, तो आपका configuration ही चलता है।
सिर्फ़ failures दर्ज करने के लिए हर handler में `try`/`except` लगाने की भी ज़रूरत नहीं है। जब कोई tool या resource function raise करता है, तो SDK उसे आपके लिए log कर देता है। क्या log होता है और किस level पर, यह **[errors संभालना](../servers/handling-errors.md#any-other-exception)** में बताया गया है।
## इसे आज़माएँ {#try-it}
server को MCP Inspector के साथ चलाएँ:

View file

@ -1,6 +1,6 @@
---
translation:
sections: [fea8d769ff9edeba, ce8e2ad42f29ef71, 0d705efb19cf99c2, 7a53ead3e704a7f0, 9adc400e8c88e854, 318893ad8e2e9924, 6b63ab96b34476c0]
sections: [fea8d769ff9edeba, ce8e2ad42f29ef71, 0d705efb19cf99c2, 2fd7cf825e6d2b2c, 9adc400e8c88e854, 318893ad8e2e9924, 6b63ab96b34476c0]
tool: 1
---
# अपना server चलाना {#running-your-server}
@ -72,14 +72,14 @@ Inspector ठीक वही करता है जो असली host क
* `streamable_http_path`: MCP endpoint कहाँ रहता है। Default `/mcp`।
* `json_response=True`: हर POST का जवाब SSE stream के बजाय एक अकेली JSON body से देना। उस body में सिर्फ़ response की जगह है, और कुछ नहीं, इसलिए जो tool request के बीच में client को वापस call करता है (`ctx.elicit()`, sampling), वह इस leg पर `NoBackChannelError` raise करता है, और चल रही call से जुड़े notifications (`ctx.report_progress()` का progress, per-call log messages) छोड़ दिए जाते हैं; standalone `GET` stream असंबंधित notifications अब भी ले जाती है।
* `stateless_http=True`: हर request के लिए नया transport, कोई session tracking नहीं।
* `max_request_body_size`: स्वीकार की जाने वाली सबसे बड़ी POST body, bytes में। Default 4 MiB है; इससे बड़ी requests
* `max_request_body_size`: स्वीकार की जाने वाली सबसे बड़ी request body, bytes में। Default 4 MiB है; इससे बड़ी requests
को parsing या session बनने से पहले ही HTTP 413 मिलता है। इसे तभी बढ़ाएँ जब जायज़ MCP messages
उस आकार से बड़े हों।
* `event_store`, `retry_interval`, `transport_security`: resumability और DNS-rebinding से सुरक्षा। ये इंतज़ार कर सकते हैं, जब तक आप localhost के अलावा कहीं deploy न करें; `transport_security` की जानकारी **[Deploy & scale](deploy.md)** में है।
!!! warning
Transport options `run()` को जाते हैं, `MCPServer(...)` को **नहीं**। Constructor बताता है कि
आपका server **क्या है**: name, version, instructions. `run()` बताता है कि वह कैसे serve होता है। इसे
आपका server **क्या है**: name, version, instructions। `run()` बताता है कि वह कैसे serve होता है। इसे
उल्टा करेंगे तो MCP के शामिल होने से पहले ही Python जवाब दे देता है:
```text

View file

@ -1,25 +1,25 @@
---
translation:
sections: [e33d441f12d50535, 7099694c603e0f5f, c1df4cf9673433e6, c9cd294541422e6e, 6cec073617bfd037, efa92b8f99e908c8, 6a22a29e27fb4601]
sections: [7be05607887e6853, e7375894888d9750, c36f73fc7e3af13b, 2fec2d7e129e62fe, 809b0e0a7c27295a, b4395a04d2a5d906, 1a436007f5f54779, c6b2078ed1e63ba5]
tool: 1
---
# errors संभालना {#handling-errors}
tool दो तरीकों से fail हो सकता है, और SDK दोनों के साथ बहुत अलग बर्ताव करता है।
tool तीन तरीकों से fail हो सकता है, और SDK हर एक के साथ अलग बर्ताव करता है।
साधारण exception raise करें तो उसे **model** देखता है। `MCPError` raise करें तो उसे **protocol** देखता है।
`ToolError` raise करें तो आपका message **model** देखता है। `MCPError` raise करें तो उसे **protocol** देखता है। कुछ और raise करें तो वह crash है: model को सिर्फ़ इतना पता चलता है कि call fail हुआ, और traceback आपके log में जाता है।
यह page इन दोनों में से चुनने के बारे में है।
यह page इनमें से चुनने के बारे में है।
## ऐसा error जिसे model ठीक कर सकता है {#an-error-the-model-can-fix}
ऐसा tool लें जो कुछ खोजता है, और खोज को नाकाम होने दें:
```python title="server.py" hl_lines="11-12"
```python title="server.py" hl_lines="2 12-13"
--8<-- "docs_src/handling_errors/tutorial001.py"
```
उन दो lines में MCP जैसा कुछ नहीं है। `get_author` सादा `ValueError` raise करता है, जैसे कोई भी Python function करता।
`mcp.server.mcpserver.exceptions` से आने वाला `ToolError` वह तरीका है जिससे tool model को बताता है कि कुछ गड़बड़ हुई।
इसे ऐसे title से call करें जो catalog में नहीं है और result देखें:
@ -30,13 +30,15 @@ result.structured_content # None
```
* request **सफल रही**। result मौजूद है; caller की तरफ़ कुछ raise नहीं हुआ।
* `is_error` `True` है, और आपके exception का message (आगे tool का नाम लगा हुआ) `content` में है, ठीक वहीं जहाँ model पढ़ता है।
* `is_error` `True` है, और आपका message (आगे tool का नाम लगा हुआ) `content` में है, ठीक वहीं जहाँ model पढ़ता है।
* `structured_content` `None` है। fail हुए call के पास structure करने को कोई return value नहीं होती।
यह **tool error** है, और आपका tool **कोई भी** exception raise करे, default यही है। और लगभग हमेशा आप यही चाहते भी हैं।
यह **tool error** है, और लगभग हमेशा आप यही चाहते हैं।
आपके tool को call करने वाला model ही है। arguments उसी ने चुने। इसलिए tool error बातचीत का एक turn है: model *"No book titled 'Nothing' in the catalog."* पढ़ता है, समझ जाता है कि उसने title का गलत अंदाज़ा लगाया, और बेहतर title के साथ फिर call करता है। आपने एक `raise` लिखा और बदले में खुद को सुधारने वाला agent मिल गया।
server पर `ToolError` log में बस एक `INFO` line है, बिना traceback के। इसका आपको पहले से अंदाज़ा था, इसलिए जाँचने को कुछ नहीं है।
!!! tip
tool से कभी error message `return` न करें। लौटाई गई string का `is_error=False` होता है, इसलिए
model को (और हर client UI को) लगता है कि tool ठीक चला और वही string जवाब थी।
@ -44,7 +46,7 @@ result.structured_content # None
## ऐसा error जिसे model ठीक नहीं कर सकता {#an-error-the-model-cannot-fix}
अब `ValueError` की जगह `MCPError` रखें।
अब `ToolError` की जगह `MCPError` रखें।
```python title="server.py" hl_lines="1 3 14"
--8<-- "docs_src/handling_errors/tutorial002.py"
@ -77,10 +79,10 @@ result.structured_content # None
दोनों रास्ते दो अलग-अलग सवालों का जवाब देते हैं।
* **कोई भी exception raise करें** जब नाकामी **execution** की हो: आपके tool ने जो करने की कोशिश की, वह नहीं हुआ। call model ने चुना था, इसलिए नतीजा भी model को दिखना चाहिए और उसे संभलने का मौका मिलना चाहिए। गलत वर्तनी वाला title, timeout हो गया upstream API, ऐसी row जो मौजूद नहीं: सब tool errors।
* **`ToolError` raise करें** जब नाकामी **execution** की हो: आपके tool ने जो करने की कोशिश की, वह नहीं हुआ। call model ने चुना था, इसलिए नतीजा भी model को दिखना चाहिए और उसे संभलने का मौका मिलना चाहिए। गलत वर्तनी वाला title, timeout हो गया upstream API, ऐसी row जो मौजूद नहीं: सब tool errors।
* **`MCPError` raise करें** जब **request खुद** ठुकराई जानी चाहिए: client के पास वह capability नहीं जिस पर आपका tool निर्भर है, server किसी को भी serve करने की हालत में नहीं है, caller ने कोई ज़रूरी चरण छोड़ दिया। model का कोई retry इनमें से किसी को ठीक नहीं करता, इसलिए उसे message थमाने से कुछ हासिल नहीं।
एक सवाल से फ़ैसला हो जाता है: **क्या ज़्यादा समझदार model इससे बच सकता था?** हाँ -> साधारण exception। नहीं -> `MCPError`।
एक सवाल से फ़ैसला हो जाता है: **क्या ज़्यादा समझदार model इससे बच सकता था?** हाँ -> `ToolError`। नहीं -> `MCPError`।
इस कसौटी पर `get_author` के दूसरे version ने गलत चुनाव किया: बेहतर title से बात बन जाती है, इसलिए model message देखने का हक़दार था। वह version आपको mechanism दिखाने के लिए है, उसकी सिफ़ारिश करने के लिए नहीं।
@ -89,6 +91,25 @@ result.structured_content # None
`data` payload लेता है। इनमें आप जो भी रखें, client को वही मिलता है: SDK raise किए गए
`MCPError` को sanitise करने के बजाय जस का तस आगे भेज देता है।
## कोई और exception {#any-other-exception}
अब check हटा दें और dictionary lookup को अपने आप fail होने दें:
```python title="server.py" hl_lines="11"
--8<-- "docs_src/handling_errors/tutorial004.py"
```
`CATALOG[title]` `KeyError` raise करता है। आपने इसकी कोई योजना नहीं बनाई थी, इसलिए SDK इसे crash मानता है:
```python
result.is_error # True
result.content # [TextContent(text="Error executing tool get_author")]
```
call अब भी `is_error=True` लौटाता है, इसलिए model जानता है कि वह fail हुआ और आगे बढ़ सकता है। जो उसे नहीं मिलता वह है exception का text: आपके code का `KeyError`, या तीन libraries नीचे के किसी driver से आया SQL का ढेर, आपके server की अंदरूनी बातें बयान कर सकता है, इसलिए वह server से बाहर कभी नहीं जाता।
वह आपको मिलता है। server crash को पूरे traceback के साथ `ERROR` पर log करता है, `Tool 'get_author' raised an unexpected exception` के रूप में। इसलिए `WARNING` पर चलने वाला production log हर `ToolError` के दौरान चुप रहता है और जैसे ही कुछ सच में टूटता है, बोल उठता है।
## ऐसा resource जो मौजूद नहीं है {#a-resource-that-doesnt-exist}
resources भी यही रेखा खींचते हैं, और आम मामले के लिए एक नाम वाला exception साथ देते हैं।
@ -109,7 +130,7 @@ resources भी यही रेखा खींचते हैं, और आ
}
```
ध्यान दें, यहाँ कोई `is_error=True` वाला आधा-अधूरा result नहीं है। resource read या तो contents लौटाता है या fail होता है: resources के पास सिर्फ़ protocol वाला रास्ता है। templates और resources के बारे में बाकी सब कुछ **[Resources](resources.md)** में है।
ध्यान दें, यहाँ कोई `is_error=True` वाला आधा-अधूरा result नहीं है। resource read या तो contents लौटाता है या fail होता है: resources के पास सिर्फ़ protocol वाला रास्ता है। `ResourceError` वही चीज़ है ऐसी नाकामी के लिए जो "not found" नहीं है (`-32603`, आपका message), और दोनों आपके log में एक `INFO` line हैं। `MCPError` को छोड़कर कोई भी और exception crash है: client को `-32603` मिलता है जिसमें सिर्फ़ URI का नाम होता है, और traceback `ERROR` पर आपके log में जाता है। templates और resources के बारे में बाकी सब कुछ **[Resources](resources.md)** में है।
## ऐसे errors जो आप कभी raise नहीं करते {#errors-you-never-raise}
@ -120,19 +141,21 @@ resources भी यही रेखा खींचते हैं, और आ
इसका मतलब है `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](../get-started/testing.md)** में यह pattern बताया गया है।
इस page पर जो कुछ **client** को दिखता है, वह उस in-memory `Client` को भी दिखता है जिससे आप
tests लिखेंगे। `raise_exceptions=True` भी fail होते tool का exception caller को वापस नहीं
थमाता: जब तक वह flag कुछ कर पाता, आपका exception पहले ही `is_error=True` result बन चुका
होता है। result पर assert करें। crash का traceback चाहिए तो वह server के log में है, और
pytest का `caplog` उसे capture कर लेता है। **[Testing](../get-started/testing.md)** में यह pattern बताया गया है।
## सारांश {#recap}
* tool में **कोई भी exception** raise करें -> call `is_error=True` लौटाता है, `content` में आपके message के साथ। model उसे पढ़ता है और retry कर सकता है। यही default है।
* tool में **`ToolError`** raise करें -> call `is_error=True` लौटाता है, `content` में आपके message के साथ। model उसे पढ़ता है और retry कर सकता है।
* **`MCPError`** raise करें -> call खुद JSON-RPC error के साथ fail हो जाता है। model को कुछ नहीं दिखता; host इससे निपटता है। `code`, `message`, और `data` जस के तस बचे रहते हैं।
* फ़ैसला करने वाला सवाल: **क्या ज़्यादा समझदार model इससे बच सकता था?** हाँ -> exception। नहीं -> `MCPError`।
* फ़ैसला करने वाला सवाल: **क्या ज़्यादा समझदार model इससे बच सकता था?** हाँ -> `ToolError`। नहीं -> `MCPError`।
* कोई भी **और exception** crash है -> model के लिए `is_error=True` जिसमें सिर्फ़ `Error executing tool <name>`, और आपके लिए traceback वाला `ERROR` record।
* resource handler से `ResourceNotFoundError` -> protocol का `-32602`, `data` में URI के साथ।
* गलत arguments आपका function चलने से पहले ही schema के आधार पर ठुकरा दिए जाते हैं; उनके लिए आप `raise` नहीं करते।
* `from mcp import MCPError`; error-code constants `mcp.types` से आते हैं।
* Imports: `from mcp import MCPError`, `from mcp.server.mcpserver.exceptions import ToolError, ResourceError, ResourceNotFoundError`, और error-code constants `mcp.types` से।
errors संभल गए। server जो कुछ **expose** करता है, वह सब यही है। हर handler क्या पढ़ सकता है, और चलते-चलते client के साथ वापस क्या कर सकता है, यह अगला section है: **[आपके handler के अंदर](../handlers/index.md)**।

View file

@ -1,6 +1,6 @@
---
translation:
sections: [496394d24d221bf1, 4ceb4591180dc6c3, 0fd63e4682d02e0c, 969ede0bd3686a16, 043f526230dd243d, 6ee3e9bcfd24047a]
sections: [496394d24d221bf1, 4ceb4591180dc6c3, 0fd63e4682d02e0c, 969ede0bd3686a16, 864137b5e9c61e91, 043f526230dd243d, db1ef91db7d6b3f3]
tool: 1
---
# Media {#media}
@ -86,6 +86,24 @@ result.structured_content # None
MP3 bytes से `Audio` बनाएँ तो client को `mime_type="audio/wav"` बताया जाता है, और फिर
वह ईमानदारी से उसे decode करने में नाकाम रहता है। जब `data=` दें, तो `format=` भी दें।
## resource embed करना {#embedding-a-resource}
tool एक document भी लौटा सकता है: कुछ text या bytes, साथ में वह URI जहाँ वह रहता है और एक MIME type। यह **`EmbeddedResource`** है, content block की एक और किस्म। सादे `str` के उलट यह client को बताता है कि content क्या है, ताकि client उसे attachment की तरह दिखा सके या ऐसे resource को पहचान सके जिसे वह पहले से जानता है।
```python title="server.py" hl_lines="7 14 16-18"
--8<-- "docs_src/media/tutorial005.py"
```
* `brand://guidelines` एक साधारण resource है (इनके बारे में **[Resources](resources.md)** बताता है)। माँगे जाने पर tool वही document model को सौंपता है, और `guidelines()` को सीधे call करने से सच का एक ही स्रोत बना रहता है।
* `EmbeddedResource` और `TextResourceContents` `mcp.types` से आते हैं। images जैसा कोई helper यहाँ नहीं है: जो block आप बनाते हैं वह बिना छुए result में जाता है, और कोई `structured_content` नहीं होता।
* वही URI इस्तेमाल करें जिसके तहत resource register है, ताकि client बता सके कि attachment और `brand://guidelines` एक ही document हैं। कोई भी URI मान्य है, register हो या न हो।
```python
result.content # [EmbeddedResource(type="resource", resource=TextResourceContents(uri="brand://guidelines", mime_type="text/markdown", text="# Brand guidelines\n\n..."))]
```
binary content के लिए `TextResourceContents` की जगह `BlobResourceContents(uri=..., mime_type=..., blob=...)` इस्तेमाल करें, जिसमें bytes base64-encoded होकर `blob` में जाते हैं। सिर्फ़ एक pointer भेजना हो, जिसे client बाद में `resources/read` कर सके, तो उसकी जगह `ResourceLink(name=..., uri=...)` लौटाएँ; यह भी content block ही है।
## Icons {#icons}
`Icon` metadata है, content नहीं। इसमें image नहीं होती; यह URI से किसी image की ओर इशारा करता है, और client उसे fetch करके आपके server के नाम, किसी tool, resource या prompt के बगल में दिखा सकता है।
@ -115,6 +133,7 @@ tool के icons `tools/list` से मिले `Tool` object पर हो
* tool से `Image` या `Audio` लौटाएँ तो client को `ImageContent` / `AudioContent` block मिलता है: आपके bytes base64-encoded, MIME type के साथ।
* इसे `path=` से बनाएँ और suffix को MIME type तय करने दें, या in-memory `data=` और स्पष्ट `format=` से बनाएँ।
* result में कोई document (text या base64 blob, उसके URI और MIME type के साथ) डालने के लिए `EmbeddedResource` लौटाएँ, या सिर्फ़ pointer भेजने के लिए `ResourceLink`।
* media results में न `structured_content` होता है, न output schema।
* `Icon` एक pointer है: `src` URI और साथ में optional `mime_type`, `sizes` और `theme`।
* `icons=[...]` server पर, tools पर, resources पर और prompts पर काम करता है, और clients इन्हें संबंधित objects पर पाते हैं।

View file

@ -1,6 +1,6 @@
---
translation:
sections: [d65c098f37f5b6c3, dd0c2724d6f2877e, 6835bb3570c6714c, ffe823cb0fedd488, f33651add1b59094]
sections: [d65c098f37f5b6c3, dd0c2724d6f2877e, 6835bb3570c6714c, d30d3c20168b88b2, f5ef38dad59d6f76, 6e38a699ba57fbdf, 2b984a3bf37a0ddd]
tool: 1
---
# Prompts {#prompts}
@ -112,9 +112,9 @@ Code review एक message है। Debugging session एक बातचीत
आख़िरी message पर ध्यान दें। `assistant` turn पहले से भरना ही वह तरीका है जिससे आप model के **अगले** जवाब की दिशा तय करते हैं, बिना user से वह निर्देश खुद type करवाए।
## Titles और argument descriptions {#titles-and-argument-descriptions}
## titles और argument descriptions {#titles-and-argument-descriptions}
`review_code` function का नाम है, label नहीं। Client को button पर लगाने के लिए कुछ बेहतर दें, और हर argument का description लिखें ताकि form खुद ही समझ में आ जाए:
`review_code` function का नाम है, label नहीं। client को button पर लगाने के लिए कुछ बेहतर दें, और हर argument का description लिखें ताकि form खुद ही समझ में आ जाए:
```python title="server.py" hl_lines="10-13"
--8<-- "docs_src/prompts/tutorial003.py"
@ -139,17 +139,64 @@ Code review एक message है। Debugging session एक बातचीत
```
!!! info
अगर आपने **[Tools](tools.md)** पढ़ लिया है, तो इस page की हर बात आप पहले से जानते हैं। वही decorator, वही
अगर आपने **[Tools](tools.md)** पढ़ लिया है, तो यहाँ तक की हर बात आप पहले से जानते हैं। वही decorator, वही
docstring-as-description, वही `Annotated`/`Field`। बदलता सिर्फ़ इतना है कि इसे
trigger कौन करता है (user) और result कहाँ जाता है (बातचीत में)।
## सिर्फ़ text ही नहीं {#more-than-text}
`UserMessage` और `AssistantMessage` जहाँ भी `str` लेते हैं, वहाँ content block या `Image` / `Audio` helper भी ले लेते हैं। prompts में दो मामले सामने आते हैं: document जोड़ना और तस्वीर जोड़ना।
### file embed करना {#embedding-a-file}
```python title="server.py" hl_lines="5 12 21 23"
--8<-- "docs_src/prompts/tutorial004.py"
```
* style guide `style://python` पर एक resource है (**[Resources](resources.md)** में इनकी बात है), जो `server.py` के बगल में रखी `style-guide.md` से पढ़ा जाता है। वहाँ कोई भी Markdown file रख दें।
* `EmbeddedResource(resource=TextResourceContents(...))`, दोनों `mcp.types` से, file को उसके URI और MIME type के साथ पहले message के रूप में ले जाता है; उसका ज़िक्र करने वाली request उसके बाद plain text के रूप में आती है।
* guide को f-string में चिपकाने के बजाय embed करने से client उसे attachment की तरह दिखा सकता है और बाद में `style://python` फिर से खोल सकता है, और model को file ज्यों की त्यों मिलती है। binary file के लिए base64 `blob` के साथ `BlobResourceContents` इस्तेमाल करें।
render होने पर पहले message का `content` एक `resource` block है:
```json
{"type": "resource", "resource": {"uri": "style://python", "mimeType": "text/markdown", "text": "* Prefer early returns.\n..."}}
```
### image जोड़ना {#attaching-an-image}
```python title="server.py" hl_lines="4 15"
--8<-- "docs_src/prompts/tutorial005.py"
```
* `Image` **[Images, audio और icons](media.md)** वाला helper है। prompt render होते समय `UserMessage` इसे `ImageContent` block में बदल देता है (file base64-encoded, MIME type `.png` से अंदाज़ा लगाया गया); `Audio` इसी तरह `AudioContent` बन जाता है।
* `server.py` के बगल में `architecture.png` नाम की कोई भी PNG रख दें। prompt arguments strings होते हैं, इसलिए तस्वीर हमेशा server से आती है; `component` सिर्फ़ शब्द देता है।
```json
{"type": "image", "data": "iVBORw0KGgoAAAANSUhEUg...", "mimeType": "image/png"}
```
## runtime पर list बदलना {#changing-the-list-at-runtime}
clients जुड़े रहते हुए भी prompts जोड़े जा सकते हैं, उदाहरण के लिए ताकि user किसी निर्देश को अपनी खुद की menu entry के रूप में save कर सके। prompt register करें, फिर notify करें:
```python title="server.py" hl_lines="5 23-27"
--8<-- "docs_src/prompts/tutorial006.py"
```
* `mcp.add_prompt(Prompt.from_function(fn, name=..., description=...))` किसी function को ठीक वैसे ही register करता है जैसे `@mcp.prompt()` करता, और `mcp.remove_prompt(name)` इसका उल्टा है। `add_prompt` उसी नाम की मौजूदा entry को overwrite करने के बजाय बनाए रखता है, इसलिए tool पहले कोई भी पुरानी entry हटा देता है ताकि save करना replace बन जाए। `prompts/list` बदलाव तुरंत दिखाती है।
* `await ctx.notify_prompts_changed()` हर उस `2026-07-28` client को `notifications/prompts/list_changed` भेजता है जो `subscriptions/listen` stream पर सुन रहा हो (**[Subscriptions](../handlers/subscriptions.md)**)। `await ctx.session.send_prompt_list_changed()` इसे call करने वाले client को भेजता है, जब वह client 2026 से पहले का हो (**[legacy clients को serve करना](../run/legacy-clients.md)**)। दोनों call करें; जब बताने के लिए कोई न हो तो दोनों में से कोई कुछ नहीं करता।
* जिस client को notification मिलता है, वह `prompts/list` फिर से call करता है। Python `Client` में यह `async with client.listen(prompts_list_changed=True) as sub:` है, जो `PromptsListChanged` event देता है।
## सारांश {#recap}
* Function पर `@mcp.prompt()` लगाने से वह prompt बन जाता है। नाम function से, description docstring से।
* Prompts **user-controlled** हैं: client इन्हें list करता है, user कोई एक चुनता है और arguments भरता है।
* Arguments named strings की flat list हैं (कोई schema नहीं)। Default वाला parameter optional है।
* `str` लौटाएँ और वह एक user message बन जाता है। Multi-turn बातचीत की शुरुआत करने के लिए `UserMessage` / `AssistantMessage` की list लौटाएँ।
* function पर `@mcp.prompt()` लगाने से वह prompt बन जाता है। नाम function से, description docstring से।
* prompts **user-controlled** हैं: client इन्हें list करता है, user कोई एक चुनता है और arguments भरता है।
* arguments named strings की flat list हैं (कोई schema नहीं)। default वाला parameter optional है।
* `str` लौटाएँ और वह एक user message बन जाता है। multi-turn बातचीत की शुरुआत करने के लिए `UserMessage` / `AssistantMessage` की list लौटाएँ।
* `title=` और `Field(description=...)` वही हैं जो client अपने UI में दिखाता है।
* कोई required argument छूट जाए तो पूरी request fail होती है। हर prompt का अलग error result नहीं होता।
* document या तस्वीर जोड़ने के लिए `EmbeddedResource` या `Image` को `UserMessage` में wrap करें।
* runtime पर `mcp.add_prompt(...)` / `mcp.remove_prompt(...)` से prompts जोड़ें या हटाएँ, फिर `await ctx.notify_prompts_changed()` और `await ctx.session.send_prompt_list_changed()` call करें।
Prompt के (या resource template के) arguments के लिए server-side autocomplete **[Completions](completions.md)** में है।
prompt के (या resource template के) arguments के लिए server-side autocomplete **[Completions](completions.md)** में है।

View file

@ -1,6 +1,6 @@
---
translation:
sections: [a838d57f003aed44, 857d03886a0137ed, 42d9efcb9f542867, 2290ff08435b5573, e866c192e11d1c14, 6cdbad079f7b47f0, d4b607372fb28b51, 18dbf726ac45e0b7, c6f7d2a148aa49f4, c851964bb3301907, d715db6f8dccc9cc, ef86634aa70498a7]
sections: [a838d57f003aed44, 857d03886a0137ed, 42d9efcb9f542867, 2290ff08435b5573, 91be9b73602abcf1, 6cdbad079f7b47f0, d4b607372fb28b51, 18dbf726ac45e0b7, c7eff2a5698225fa, c851964bb3301907, 8f296f1f09e4c400, d715db6f8dccc9cc, a0c344a48450dbe4]
tool: 1
---
# Structured output {#structured-output}
@ -105,7 +105,7 @@ result.structured_content # {"temperature": 16.2, "humidity": 0.83, "conditions
--8<-- "docs_src/structured_output/tutorial003.py"
```
runtime पर `TypedDict` सादा `dict` होता है, इसलिए आप वही बनाते और लौटाते हैं। schema, validation और `structured_content` ठीक `BaseModel` वाले version जैसे हैं (descriptions को छोड़कर, जिनके लिए `TypedDict` में कोई जगह नहीं)।
runtime पर `TypedDict` सादा `dict` होता है, इसलिए आप वही बनाते और लौटाते हैं। schema, validation और `structured_content` उन्हीं नियमों पर चलते हैं जिन पर `BaseModel` वाला version चलता है: class docstring या `Annotated[..., Field(description=...)]` जोड़ें और वही descriptions बन जाते हैं, और जो `NotRequired` key आप dict में नहीं डालते, वह `structured_content` से भी बाहर रहती है।
## Dataclass {#a-dataclass}
@ -187,18 +187,19 @@ keys का `str` होना ज़रूरी है। `dict[int, float]` J
annotation `WeatherData` का वादा करता है। upstream response ने `humidity` भेजना बंद कर दिया।
!!! check
`get_weather` को call करें और यह चुपचाप client को आधा-खाली object नहीं थमाता। call fail होता है,
और error की पहली lines field का नाम बताती हैं:
`get_weather` को call करें और यह चुपचाप client को आधा-खाली object नहीं थमाता। call fail होता है:
client को `Error executing tool get_weather` के साथ `is_error=True` मिलता है, ताकि model को पता रहे कि
call fail हुआ है, बजाय इसके कि वह पूरे भरोसे से ऐसा मौसम पढ़े जो है ही नहीं। field का नाम आपके लिए है,
server log में `ERROR` पर:
```text
Error executing tool get_weather: 1 validation error for WeatherData
Tool 'get_weather' raised an unexpected exception
...
pydantic_core._pydantic_core.ValidationError: 1 validation error for WeatherData
humidity
Field required [type=missing, input_value={'temperature': 16.2, 'conditions': 'Overcast'}, input_type=dict]
```
यह text `is_error=True` के साथ tool result बनकर लौटता है, ताकि model को पता रहे कि call fail हुआ है,
बजाय इसके कि वह पूरे भरोसे से ऐसा मौसम पढ़े जो है ही नहीं।
वैसे, `-> WeatherData` वाले tool से सादा `dict` लौटाना ठीक है। `json.loads` ने ठीक वही तो बनाया था। validation value पर होता है, Python type पर नहीं।
## इससे बाहर रहना {#opting-out}
@ -213,6 +214,10 @@ annotation `WeatherData` का वादा करता है। upstream res
इसका उल्टा, `structured_output=True`, automatic detection को शर्त बना देता है: जिस tool का return type schema नहीं बना सकता, वह text पर वापस आने के बजाय import के समय ही raise करता है।
## Content blocks और media {#content-blocks-and-media}
content blocks और media (`TextContent`, `EmbeddedResource`, `Image`, `Audio` वगैरह, चाहे अकेले हों, किसी `list`, `tuple` या `Sequence` के items हों, या किसी union के हिस्से हों) आपके लिए अपने आप इससे बाहर रखे जाते हैं: ये model के पढ़ने के लिए हैं, इसलिए auto-detection इनसे कोई schema नहीं बनाता (`Image` और `Audio` की जानकारी **[Images, audio और icons](media.md)** में है)। content-block classes के लिए `structured_output=True` फिर भी schema बनवा देता है।
## बिना type hints वाली class {#a-class-without-type-hints}
बिना माँगे unstructured रह जाने का एक तरीका है: ऐसी class लौटाना जिसकी **body पर कोई annotations न हों**।
@ -245,6 +250,6 @@ annotation `WeatherData` का वादा करता है। upstream res
* scalars, lists, tuples और unions `{"result": ...}` में wrap होते हैं। models, `TypedDict`, dataclasses, annotated classes और `dict[str, ...]` पहले से object हैं और जैसे हैं वैसे ही रहते हैं।
* हर result में `content` (text, model के लिए) **और** `structured_content` (data, application के लिए) होता है।
* आप जो लौटाते हैं वह schema के मुक़ाबले validate होता है। मेल न खाना tool error है, ख़राब result नहीं।
* `structured_output=False` tool को इससे बाहर रखता है। बिना type hints वाली class चुपचाप बाहर हो जाती है; इस पर नज़र रखें।
* `structured_output=False` tool को इससे बाहर रखता है। content blocks, `Image` और `Audio` default रूप से बाहर रहते हैं; बिना type hints वाली class चुपचाप बाहर हो जाती है, इसलिए इस पर नज़र रखें।
अब tool जो कुछ भी जवाब में कह सकता है, वह सब आपके हाथ में है। आगे, दूसरा primitive: **[Resources](resources.md)**।

View file

@ -1,6 +1,6 @@
---
translation:
sections: [e4cc390d56573409, 8566e2b68594e9ad, 2c97b9f888398951, 048e5471dfa71aea, 3076b1e16ad95950, edbedf2a16e71311, 3d8ef8da89fa87c1, f6c0e02e6ea5a363]
sections: [e4cc390d56573409, f30cf8103a6e918c, 2c97b9f888398951, 048e5471dfa71aea, 3076b1e16ad95950, edbedf2a16e71311, 3d8ef8da89fa87c1, f6c0e02e6ea5a363]
tool: 1
---
# Tools {#tools}
@ -39,6 +39,8 @@ translation:
दोनों arguments `required` में हैं क्योंकि किसी का भी default नहीं है। इसे आप थोड़ी ही देर में ठीक करेंगे। (`title` keys Pydantic की देन हैं; properties, उनके types और `required` ही असली contract हैं।)
`$schema` key भी नहीं है: जिस schema में यह न हो उसे MCP **JSON Schema 2020-12** मानता है, और Pydantic यही बनाता है, इसलिए चुनने को कुछ नहीं है जब तक आप **[low-level Server](../advanced/low-level-server.md#the-dialect-is-json-schema-2020-12)** पर हाथ से schemas न लिखें।
!!! tip
यहाँ type hints documentation नहीं हैं। वे ही **contract** हैं। अगर कोई client `"limit": "ten"` भेजता है,
तो SDK उसे आपके function के चलने से पहले ही reject कर देता है।

View file

@ -1,6 +1,6 @@
---
translation:
sections: [4a7033e1ed8ad602, 55dcbfff0c6271bf, 101ef9d14bf4ec46, 4b6c4a845438abc7, f98b46bafbee4acd]
sections: [4a7033e1ed8ad602, 55dcbfff0c6271bf, 317f4256a650cab6, 4b6c4a845438abc7, f98b46bafbee4acd]
tool: 1
---
# URI templates और path safety {#uri-templates-and-path-safety}
@ -115,7 +115,7 @@ template parameters client से आते हैं। अगर वे बि
built-in जाँचें आम मामलों को रोकती हैं लेकिन आपकी sandbox सीमा नहीं जान सकतीं। filesystem access के लिए, path resolve करने और यह पक्का करने के लिए कि वह आपकी base directory के अंदर ही रहे, `safe_join` इस्तेमाल करें:
```python title="server.py" hl_lines="4 14"
```python title="server.py" hl_lines="5 15"
--8<-- "docs_src/uri_templates/tutorial002.py"
```
@ -146,7 +146,7 @@ configure की जा सकने वाली जाँचें:
`safe_join` ही containment boundary बना रहता है।
!!! tip
अगर आपका handler request पूरी नहीं कर सकता (file मौजूद नहीं है, id अनजान है), तो exception raise करें। SDK उसे error response में बदल देता है। protocol error और tool error के बीच के फ़र्क़ के लिए **[errors संभालना](handling-errors.md)** देखें।
अगर आपका handler request पूरी नहीं कर सकता (file मौजूद नहीं है, id अनजान है), तो `ResourceNotFoundError` raise करें, जैसा ऊपर `read_manual` करता है। client को आपके message और URI के साथ `-32602` मिलता है। कोई अनपेक्षित exception इसकी जगह generic `-32603` बन जाता है। **[errors संभालना](handling-errors.md#a-resource-that-doesnt-exist)** देखें।
## Low-level Server पर resources {#resources-on-the-low-level-server}

View file

@ -1,6 +1,6 @@
---
translation:
sections: [2efaecdef109a5c5, fcacd3e66b8635a4, 25323d737dcf0261, 4835ed1772f1d113, 137454d469c867f5, 6392596bd6df54f0, 41126fa9c4fe432f, 480b6d7897e30ab4, d83bb682e708dde0, ebbed3449c499db4, 323ef84f6b4bebde, 30fd31be74169d9a, 656943c6cb567218, c2dc3b1007d2e987, 7cf5386b997d04e9, 0b59feed8384456e, 0cba47bae78d04eb, 954dc21efdb532a3]
sections: [2efaecdef109a5c5, fcacd3e66b8635a4, 25323d737dcf0261, 8a6e351ec756904d, 137454d469c867f5, 6392596bd6df54f0, 41126fa9c4fe432f, 480b6d7897e30ab4, d83bb682e708dde0, ebbed3449c499db4, 323ef84f6b4bebde, 30fd31be74169d9a, 656943c6cb567218, c2dc3b1007d2e987, 7cf5386b997d04e9, 0b59feed8384456e, 0cba47bae78d04eb, e4355f4c7cf4fb2e]
tool: 1
---
# समस्याएँ सुलझाना {#troubleshooting}
@ -81,11 +81,11 @@ async def main() -> None:
`__aexit__` ही disconnection है, इसीलिए भूल जाने लायक कोई `client.close()` है ही नहीं। **[Testing](get-started/testing.md)** ठीक इसी pattern पर बना है।
## `Error executing tool <name>: <message>` और `Unknown tool: <name>` {#error-executing-tool-name-message-and-unknown-tool-name}
## `Error executing tool <name>: <message>`, `Error executing tool <name>`, और `Unknown tool: <name>` {#error-executing-tool-name-message-error-executing-tool-name-and-unknown-tool-name}
आप एक **result** पढ़ रहे हैं, exception नहीं। `call_tool` ने raise नहीं किया, और fail होने वाले tool के लिए वह कभी करेगा भी नहीं।
`forecast` को ऐसे city के लिए call करें जिसे server नहीं जानता, तो उसका raise किया हुआ exception वापस आता है और request **सफल** mark होती है:
`forecast` को ऐसे city के लिए call करें जिसे server नहीं जानता, तो उसका raise किया हुआ `ToolError` वापस आता है और request **सफल** mark होती है:
```python
result.is_error # True
@ -97,6 +97,8 @@ result.structured_content # None
सुधार आपके client में है: **`result.is_error` जाँचें**। `call_tool` के चारों ओर लगा `try/except` इनमें से कुछ नहीं पकड़ता, क्योंकि पकड़ने को कुछ है ही नहीं। यह जान-बूझकर है, और इस page की सबसे काम की बात यही है जिसे मन में बिठा लें: call **model** ने चुना था, इसलिए message भी model को मिलता है और दोबारा कोशिश करने का मौका भी। पूरी जानकारी **[errors संभालना](servers/handling-errors.md)** में है, उस `MCPError` वाले रास्ते समेत जो सच में raise **करता** है।
बिना message वाला सादा रूप, `Error executing tool <name>`, बताता है कि tool **crash हुआ**: कोई exception जिसकी उसने उम्मीद नहीं की थी उससे बाहर निकल गया (या उसकी return value output schema पर खरी नहीं उतरी), और उस exception का text wire से दूर रखा जाता है। traceback **server के log** में `ERROR` पर है, `Tool '<name>' raised an unexpected exception` के रूप में।
## `TypeError: The @tool decorator was used incorrectly. Did you forget to call it? Use @tool() instead of @tool` {#typeerror-the-tool-decorator-was-used-incorrectly-did-you-forget-to-call-it-use-tool-instead-of-tool}
आपने `@mcp.tool()` की जगह `@mcp.tool` लिख दिया। `tool()` एक decorator **factory** है: parentheses के बिना Python आपका function उसके `name=` parameter को थमा देता है।
@ -409,7 +411,7 @@ mcp = MCPServer("Weather", request_state_security=RequestStateSecurity(keys=[key
## सारांश {#recap}
* `ExceptionGroup: unhandled errors in a TaskGroup` कभी असली error नहीं है। **आखिरी line** पढ़ें; `async with Client(...)` block के **अंदर** `MCPError` catch करने से wrapping पूरी तरह टल जाती है।
* `call_tool` fail होने वाले tool के लिए raise नहीं करता। `Error executing tool ...` और `Unknown tool: ...` results हैं: `result.is_error` जाँचें।
* `call_tool` fail होने वाले tool के लिए raise नहीं करता। `Error executing tool ...` और `Unknown tool: ...` results हैं: `result.is_error` जाँचें। tool के नाम के बाद कोई message न हो तो मतलब वह crash हुआ, और traceback server log में है।
* `Client must be used within an async context manager` -> `async with` इस्तेमाल करें। `Use @tool() instead of @tool` -> parentheses जोड़ें।
* server log में `Tool already exists:` ही इकलौता संकेत है कि एक ही नाम के दो tools सिमटकर एक रह गए।
* एक 421, तीन रूप: `Server returned an error response` (python `Client`), `421 Misdirected Request` / `Invalid Host header` (बाकी सब), `Invalid Host header: <host>` (server log)। सुधार: `transport_security=TransportSecuritySettings(allowed_hosts=[...])`।

View file

@ -1,6 +1,6 @@
---
translation:
sections: [cfe01c0c5863dfa2, 11d93f1fa09eadf5, a7392996acf1ad8f, 875eb2889263424e]
sections: [cfe01c0c5863dfa2, 1c58c5cfcc37d455, a7392996acf1ad8f, 875eb2889263424e]
tool: 1
---
# v2 में नया क्या है {#whats-new-in-v2}
@ -18,7 +18,7 @@ v2 में दो चीज़ें एक साथ हुईं। **SDK
### `FastMCP` अब `MCPServer` है {#fastmcp-is-now-mcpserver}
High-level server class का नाम बदला, और उसके module का भी। हर v1 server सबसे पहले इसी से टकराता है, क्योंकि पुराना import path deprecated नहीं, बल्कि हटा दिया गया है:
high-level server class का नाम बदला, और साथ में उसके module का भी। हर v1 server सबसे पहले इसी से टकराता है, क्योंकि पुराना import path deprecated नहीं, बल्कि हटा दिया गया है:
```python
from mcp.server import MCPServer # v1: from mcp.server.fastmcp import FastMCP
@ -26,11 +26,11 @@ from mcp.server import MCPServer # v1: from mcp.server.fastmcp import FastMCP
mcp = MCPServer("Demo") # v1: FastMCP("Demo")
```
Decorator से बने server के लिए port का ज़्यादातर हिस्सा भी बस यही है। `@mcp.tool()`, `@mcp.resource()` और `@mcp.prompt()` वही स्वीकार करते हैं जो v1 में करते थे (`@mcp.resource()` में एक optional `security=` keyword जुड़ा है), और input schema अब भी आपके type hints से आता है। किनारों पर: `mcp.server.fastmcp.*` के नीचे की हर चीज़ अब `mcp.server.mcpserver.*` के नीचे रहती है, `ctx.fastmcp` अब `ctx.mcp_server` है, `get_context()` हटा दिया गया है (उसकी जगह `ctx: Context` parameter declare करें), और exception base `FastMCPError` अब `MCPServerError` है। Import table **[Migration Guide](migration.md#fastmcp-renamed-to-mcpserver)** में है।
decorator से बने server के लिए port का ज़्यादातर हिस्सा भी बस यही है। `@mcp.tool()`, `@mcp.resource()` और `@mcp.prompt()` वही स्वीकार करते हैं जो v1 में करते थे (`@mcp.resource()` में एक optional `security=` keyword जुड़ा है), और input schema अब भी आपके type hints से आता है। किनारों पर: `mcp.server.fastmcp.*` के नीचे की हर चीज़ अब `mcp.server.mcpserver.*` के नीचे रहती है, `ctx.fastmcp` अब `ctx.mcp_server` है, `get_context()` हटा दिया गया है (उसकी जगह `ctx: Context` parameter declare करें), और exception base `FastMCPError` अब `MCPServerError` है। import table **[Migration Guide](migration.md#fastmcp-renamed-to-mcpserver)** में है।
### `Resolve`: user से input माँगने का नया तरीका {#resolve-the-new-way-to-ask-the-user-for-input}
Tool को जो कुछ चाहिए, वह सब model से नहीं आना चाहिए। v2 में नया: `Resolve(fn)` से annotate किया गया tool parameter model के बजाय आपके लिखे function से भरा जाता है, model को इसकी भनक तक नहीं लगती, और वह function user के सामने सवाल रखने के लिए `Elicit(...)` लौटा सकता है। Call के बीच client से कुछ भी पाने का यही पसंदीदा तरीका है: SDK सवाल को उसी mechanism पर ले जाता है जिसे connection support करता है (legacy client के लिए live elicitation request, 2026-07-28 पर multi-round-trip), इसलिए एक ही tool body दोनों पीढ़ियों को serve करती है। इसका page **[Dependencies](handlers/dependencies.md)** है।
tool को जो कुछ चाहिए, वह सब model से नहीं आना चाहिए। v2 में नया: `Resolve(fn)` से annotate किया गया tool parameter model के बजाय आपके लिखे function से भरा जाता है, model को इसकी भनक तक नहीं लगती, और वह function user के सामने सवाल रखने के लिए `Elicit(...)` लौटा सकता है। call के बीच client से कुछ भी पाने का यही पसंदीदा तरीका है: SDK सवाल को उसी mechanism पर ले जाता है जिसे connection support करता है (legacy client के लिए live elicitation request, 2026-07-28 पर multi-round-trip), इसलिए एक ही tool body दोनों पीढ़ियों को serve करती है। इसका page **[Dependencies](handlers/dependencies.md)** है।
!!! note
बाकी दो रूप ज़रूरत पड़ने पर अब भी मौजूद हैं: legacy connections पर clients के लिए `ctx.elicit()` अब भी काम करता है
@ -38,7 +38,7 @@ Tool को जो कुछ चाहिए, वह सब model से नह
rounds को हाथ से चला सकता है, और 2026-07-28 पर sampling और roots requests भी इसी रास्ते से जाती हैं
(**[Multi-round-trip requests](handlers/multi-round-trip.md)**)।
### एक first-class `Client` {#a-first-class-client}
### first-class `Client` {#a-first-class-client}
v1 आपको तीन nested परतें थमाता था: raw streams देने वाला transport context manager, उनके चारों ओर लिपटा `ClientSession`, और हाथ से call किया जाने वाला `await session.initialize()`। v2 में एक ही object है:
@ -46,11 +46,11 @@ v1 आपको तीन nested परतें थमाता था: raw str
--8<-- "docs_src/client/tutorial001.py"
```
`Client` एक server object लेता है (in memory, कोई transport नहीं: testing की कहानी), एक URL (Streamable HTTP), या कोई भी transport context manager जैसे `stdio_client(...)`। `async with` में प्रवेश करते ही connect होता है और protocol version negotiate होता है, server चाहे जिस पीढ़ी का हो; उसके बाद `client.server_capabilities` और `client.protocol_version` बस उपलब्ध रहते हैं, और जब server अपनी पहचान बताता है तो `client.server_info` भी (यह अब `Implementation | None` है, क्योंकि 2026 पीढ़ी में identity optional है)। v1 में register किए गए sampling और elicitation callbacks अब भी काम करते हैं (उनकी bodies में वही snake_case attribute rename दिखता है जो इस page की हर चीज़ में), वे अब 2026-style requests-inside-results (नीचे) का जवाब भी देते हैं, और वे एक-एक करके नहीं, बल्कि concurrently चलते हैं। जिसे low-level surface चाहिए, उसके लिए `ClientSession` अब भी नीचे मौजूद है, और `client.session` उसे आपको देता है; वह भी बदला है (वह नए dispatcher engine पर चलता है, और उसके कुछ अपने signatures बदले हैं), इसलिए नीचे उतरने से पहले **[Migration Guide](migration.md#clientsession-now-runs-on-jsonrpcdispatcher-basesession-removed)** पढ़ें।
`Client` server object लेता है (in memory, कोई transport नहीं: testing वाली कहानी), URL (Streamable HTTP), `StdioServerParameters` (stdio subprocess), या `sse_client(...)` जैसा कोई भी दूसरा transport context manager। `async with` में प्रवेश करते ही connect होता है और protocol version negotiate होता है, server चाहे जिस पीढ़ी का हो; उसके बाद `client.server_capabilities` और `client.protocol_version` बस उपलब्ध रहते हैं, और जब server अपनी पहचान बताता है तो `client.server_info` भी (यह अब `Implementation | None` है, क्योंकि 2026 पीढ़ी में identity optional है)। v1 में register किए गए sampling और elicitation callbacks अब भी काम करते हैं (उनकी bodies में वही snake_case attribute rename दिखता है जो इस page की हर चीज़ में), वे अब 2026-style requests-inside-results (नीचे) का जवाब भी देते हैं, और वे एक-एक करके नहीं, बल्कि concurrently चलते हैं। जिसे low-level surface चाहिए, उसके लिए `ClientSession` अब भी नीचे मौजूद है, और `client.session` उसे आपको देता है; वह भी बदला है (वह नए dispatcher engine पर चलता है, और उसके कुछ अपने signatures बदले हैं), इसलिए नीचे उतरने से पहले **[Migration Guide](migration.md#clientsession-now-runs-on-jsonrpcdispatcher-basesession-removed)** पढ़ें।
**[The Client](client/index.md)** इसका परिचय देता है, **[Client transports](client/transports.md)** connection के तीनों रूप समझाता है, **[Client callbacks](client/callbacks.md)** खुद callbacks को, और **[Testing](get-started/testing.md)** वह in-memory pattern दिखाता है जो v1 के `create_connected_server_and_client_session()` helper की जगह लेता है।
**[The Client](client/index.md)** इसका परिचय देता है, **[Client transports](client/transports.md)** connection के चारों रूप समझाता है, **[Client callbacks](client/callbacks.md)** खुद callbacks को, और **[Testing](get-started/testing.md)** वह in-memory pattern दिखाता है जो v1 के `create_connected_server_and_client_session()` helper की जगह लेता है।
### Low-level `Server` का नाम नहीं बदला, उसे दोबारा बनाया गया {#the-low-level-server-was-rebuilt-not-renamed}
### low-level `Server` का नाम नहीं बदला, उसे दोबारा बनाया गया {#the-low-level-server-was-rebuilt-not-renamed}
अगर आप JSON-RPC layer पर काम करते हैं, तो v2 का "सब कुछ अलग है" वाला हिस्सा यही है। यहाँ वही one-tool server दोनों तरह से है; क्या बदला, यह देखने के लिए markers पर click करें।
@ -90,66 +90,66 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[types.ContentB
return [types.TextContent(type="text", text=f"Found 3 books matching {arguments['query']!r}.")] # (7)!
```
1. Handlers decorators से register होते हैं (call किए गए, parentheses के साथ), server बनने के बाद कभी भी।
1. handlers decorators से register होते हैं (call किए गए, parentheses के साथ), server बनने के बाद कभी भी।
2. आप bare `list[Tool]` लौटाते हैं और SDK उसे `ListToolsResult` में लपेट देता है।
3. Python में fields camelCase हैं, और schema **enforce होता है**: SDK आपके function के चलने से पहले `call_tool` arguments को इसके सामने jsonschema-validate करता है, इसीलिए नीचे `arguments["query"]` सुरक्षित है।
4. एक ही `call_tool` handler हर tool को serve करता है, और उसे tool का नाम और पहले से validate किए हुए arguments मिलते हैं, unpack किए हुए और कभी `None` नहीं।
5. v1 tool failure का संकेत raise करके देता है: कोई भी exception पकड़ा जाता है और `CallToolResult(isError=True)` के रूप में लौटाया जाता है, text में `str(e)` के साथ, इसलिए call करने वाला model यह message पढ़ता है और retry कर सकता है।
6. Context एक ambient ContextVar से आता है, जिस तक request के बीच server object के ज़रिए पहुँचा जाता है।
7. Bare content blocks आपके लिए `CallToolResult` में लपेट दिए जाते हैं।
6. context एक ambient ContextVar से आता है, जिस तक request के बीच server object के ज़रिए पहुँचा जाता है।
7. bare content blocks आपके लिए `CallToolResult` में लपेट दिए जाते हैं।
```python title="v2"
--8<-- "docs_src/whats_new/tutorial001.py"
```
1. Fields अब snake_case हैं, और schema **advertise होता है, पर कभी apply नहीं होता**: आपके handler के चलने से पहले arguments को कोई नहीं जाँचता।
2. हर handler का आकार एक जैसा है: `async (ctx, params) -> result`। Context पहला argument है (`ctx.session`, `ctx.request_id`, `ctx.protocol_version` इसी पर रहते हैं); `server.request_context` यहीं गया।
3. पूरा `ListToolsResult` आप खुद बनाते हैं। Bare list लौटाना अब server-side `TypeError` है, SDK उसे लपेटता नहीं।
4. Typed params अंदर (`params.name`, `params.arguments`), पूरा result बाहर। आपके लिए कुछ भी unpack, wrap या convert नहीं किया जाता।
1. fields अब snake_case हैं, और schema **advertise होता है, पर कभी apply नहीं होता**: आपके handler के चलने से पहले arguments को कोई नहीं जाँचता।
2. हर handler का आकार एक जैसा है: `async (ctx, params) -> result`। context पहला argument है (`ctx.session`, `ctx.request_id`, `ctx.protocol_version` इसी पर रहते हैं); `server.request_context` यहीं गया।
3. पूरा `ListToolsResult` आप खुद बनाते हैं। bare list लौटाना अब server-side `TypeError` है, SDK उसे लपेटता नहीं।
4. typed params अंदर (`params.name`, `params.arguments`), पूरा result बाहर। आपके लिए कुछ भी unpack, wrap या convert नहीं किया जाता।
5. वही जाँच, अलग verb। यहाँ `ValueError` model तक एक opaque `-32603` बनकर पहुँचता (नीचे देखें), इसलिए जानबूझकर भेजा जाने वाला wire error `MCPError` के रूप में raise किया जाता है: वह अपने code और message के साथ जस का तस निकल जाता है, और unknown tool के लिए इस text के साथ `-32602` spec का अपना जवाब है।
6. `params.arguments` `None` हो सकता है; v1 इसे आपके code तक पहुँचने से पहले ही `{}` कर देता था। Handler के सामने कोई validation न होने से यह line ज़रूरी है।
6. `params.arguments` `None` हो सकता है; v1 इसे आपके code तक पहुँचने से पहले ही `{}` कर देता था। handler के सामने कोई validation न होने से इस line पर बहुत कुछ टिका है।
7. यहाँ raise हुआ कोई अनपेक्षित exception एक **sanitized** protocol error बनता है, `-32603` `"Internal server error"`: model को message कभी नहीं दिखता। ऐसे failure के लिए जिसे model पढ़े और उस पर प्रतिक्रिया दे, `CallToolResult(is_error=True, ...)` लौटाएँ।
8. Handlers constructor arguments हैं, इसलिए server बनते ही उसकी surface पूरी हो जाती है; `add_request_handler()` construction के बाद का escape hatch है, और custom methods का दरवाज़ा भी।
8. handlers constructor arguments हैं, इसलिए server बनते ही उसकी surface पूरी हो जाती है; `add_request_handler()` construction के बाद का escape hatch है, और custom methods का दरवाज़ा भी।
यह उदाहरण ही pattern है। और आम तौर पर: हर handler का आकार एक जैसा है, typed params अंदर और पूरा result type बाहर; tool arguments की पुरानी jsonschema जाँच हट गई है; exception एक protocol error है, कभी `is_error=True` tool result नहीं; और ambient `server.request_context` ContextVar हट गया है। Custom, vendor-namespaced methods `add_request_handler(method, params_type, handler)` के ज़रिए first class हैं, जो आपके handler के चलने से पहले inbound params को आपके model के सामने validate करता है। और एक `middleware` list (जानबूझकर provisional चिह्नित) हर inbound message को लपेटती है, उन private `_handle_*` methods की जगह जिन्हें लोग override किया करते थे।
यह उदाहरण ही pattern है। और आम तौर पर: हर handler का आकार एक जैसा है, typed params अंदर और पूरा result type बाहर; tool arguments की पुरानी jsonschema जाँच हट गई है; exception एक protocol error है, कभी `is_error=True` tool result नहीं; और ambient `server.request_context` ContextVar हट गया है। custom, vendor-namespaced methods `add_request_handler(method, params_type, handler)` के ज़रिए first class हैं, जो आपके handler के चलने से पहले inbound params को आपके model के सामने validate करता है। और एक `middleware` list (जानबूझकर provisional चिह्नित) हर inbound message को लपेटती है, उन private `_handle_*` methods की जगह जिन्हें लोग override किया करते थे।
अंदर ही अंदर, v1 के `BaseSession` receive loop की जगह एक dispatcher engine ने ली है जिसे अब client और server दोनों साझा करते हैं, और इसी की वजह से इस page की कई बातें एक साथ सच हैं: एक ही `Server` object दोनों protocol पीढ़ियों को serve करता है, `Client(server)` बिना JSON-RPC framing के in process dispatch करता है, और timed-out client request अब वाकई server-side handler को cancel करती है।
इसका page **[The low-level Server](advanced/low-level-server.md)** है; **[Migration Guide](migration.md#lowlevel-server-decorator-based-handlers-replaced-with-constructor-on_-params)** हर हटाए गए hook से गुज़रता है। अगर आप कभी `MCPServer` से नीचे नहीं उतरे, तो इनमें से कुछ भी आपको नहीं छूता।
### Wire types `mcp-types` में चले गए, और हर field snake_case है {#the-wire-types-moved-to-mcp-types-and-every-field-is-snake_case}
### wire types `mcp-types` में चले गए, और हर field snake_case है {#the-wire-types-moved-to-mcp-types-and-every-field-is-snake_case}
Protocol types अब अपने अलग distribution, `mcp-types`, में रहते हैं। यह pydantic और typing-extensions के सिवा किसी पर निर्भर नहीं है, इसलिए कोई gateway, proxy या code generator बिना HTTP stack install किए MCP के wire shapes इस्तेमाल कर सकता है: ऐसा project `mcp-types` install करता है और `mcp_types` import करता है। खुद `mcp` उस package पर exact version के साथ निर्भर है और उसे दोबारा expose करता है, इसलिए SDK पर निर्भर code पहले की तरह `import mcp.types as types` और `from mcp.types import Tool` लिखता रहता है (एक स्थायी alias, हर नाम वही object) और सिर्फ़ अपनी एक असली dependency, `mcp`, declare करता है। मोटा नियम: जिस package पर आप वाकई निर्भर हैं, उसी से import करें।
protocol types अब अपने अलग distribution, `mcp-types`, में रहते हैं। यह pydantic और typing-extensions के सिवा किसी पर निर्भर नहीं है, इसलिए कोई gateway, proxy या code generator बिना HTTP stack install किए MCP के wire shapes इस्तेमाल कर सकता है: ऐसा project `mcp-types` install करता है और `mcp_types` import करता है। खुद `mcp` उस package पर exact version के साथ निर्भर है और उसे दोबारा expose करता है, इसलिए SDK पर निर्भर code पहले की तरह `import mcp.types as types` और `from mcp.types import Tool` लिखता रहता है (एक स्थायी alias, हर नाम वही object) और सिर्फ़ अपनी एक असली dependency, `mcp`, declare करता है। मोटा नियम: जिस package पर आप वाकई निर्भर हैं, उसी से import करें।
उन types पर हर Python attribute अब snake_case है: `result.is_error`, `tool.input_schema`, `listing.next_cursor`। Wire पर जाने वाला JSON camelCase है, बिल्कुल पहले जैसा; सिर्फ़ attribute की spelling बदली है। दो और सख्त defaults साथ आते हैं: unknown fields round-trip होने के बजाय ignore किए जाते हैं (extras `_meta` में रखें), और दोनों पक्ष traffic को उस protocol version के सामने validate करते हैं जो उन्होंने negotiate किया। Rename table के लिए **[Migration Guide](migration.md#field-names-changed-from-camelcase-to-snake_case)** देखें।
उन types पर हर Python attribute अब snake_case है: `result.is_error`, `tool.input_schema`, `listing.next_cursor`। wire पर जाने वाला JSON camelCase है, बिल्कुल पहले जैसा; सिर्फ़ attribute की spelling बदली है। दो और सख्त defaults साथ आते हैं: unknown fields round-trip होने के बजाय ignore किए जाते हैं (extras `_meta` में रखें), और दोनों पक्ष traffic को उस protocol version के सामने validate करते हैं जो उन्होंने negotiate किया। rename table के लिए **[Migration Guide](migration.md#field-names-changed-from-camelcase-to-snake_case)** देखें।
### Transport configuration `run()` में चली गई {#transport-configuration-moved-to-run}
### transport configuration `run()` में चली गई {#transport-configuration-moved-to-run}
`MCPServer(...)` इस बारे में है कि आपका server **क्या है**: उसका नाम, उसके instructions, उसका lifespan, उसका auth। उसे **serve कैसे** किया जाता है, यह अब `run()` और app builders का काम है, और `host`, `port`, `stateless_http`, `json_response`, endpoint paths और `transport_security` वहीं गए (`MCPServer("x", port=9000)` अब `TypeError` है)। Overloads हर transport के लिए typed हैं, इसलिए आपका editor बताता है कि `stdio` कौन से options लेता है और `streamable-http` कौन से। एक हटाव जानने लायक है: `mount_path` हट गया है; prefix के नीचे serve करने का supported तरीका ASGI app को mount करना है।
`MCPServer(...)` इस बारे में है कि आपका server **क्या है**: उसका नाम, उसके instructions, उसका lifespan, उसका auth। उसे **serve कैसे** किया जाता है, यह अब `run()` और app builders का काम है, और `host`, `port`, `stateless_http`, `json_response`, endpoint paths और `transport_security` वहीं गए (`MCPServer("x", port=9000)` अब `TypeError` है)। overloads हर transport के लिए typed हैं, इसलिए आपका editor बताता है कि `stdio` कौन से options लेता है और `streamable-http` कौन से। एक हटाव जानने लायक है: `mount_path` हट गया है; prefix के नीचे serve करने का supported तरीका ASGI app को mount करना है।
Options के लिए **[अपना server चलाना](run/index.md)** देखें; mounting के लिए **[मौजूदा app में जोड़ना](run/asgi.md)**।
options के लिए **[अपना server चलाना](run/index.md)** देखें; mounting के लिए **[मौजूदा app में जोड़ना](run/asgi.md)**।
### बिना import error के बदलने वाला व्यवहार {#behavior-that-changes-without-an-import-error}
Renames खुद अपनी घोषणा करते हैं। ये नहीं करते:
renames खुद अपनी घोषणा करते हैं। ये नहीं करते:
* **Sync functions worker thread पर चलते हैं।** `def` tool (या resource, prompt, या resolver) अब event loop को block नहीं करता; बदले में उसकी body अब event-loop thread **पर** नहीं चलती, जो thread-affine code के लिए मायने रखता है। `async def` handlers अछूते हैं। **[Migration Guide](migration.md#sync-handler-functions-now-run-on-a-worker-thread)**।
* **Tool के अंदर raise हुआ `MCPError` (v1 का `McpError`) अब protocol error है।** Model उसे कभी नहीं देखता। बाकी हर exception अब भी `is_error=True` result बनता है जिसे model पढ़ सकता है और उस पर प्रतिक्रिया दे सकता है। यह विभाजन **[Errors संभालना](servers/handling-errors.md)** में है।
* **Results निकलने से पहले validate होते हैं।** हाथ से बना `Tool` जिसका `input_schema` `{}` है, अब `tools/list` में fail होता है (spec को `"type": "object"` चाहिए)। `@mcp.tool()` पर बने servers को यह कभी नहीं दिखता; उनके schemas SDK लिखता है।
* **sync functions worker thread पर चलते हैं।** `def` tool (या resource, prompt, या resolver) अब event loop को block नहीं करता; बदले में उसकी body अब event-loop thread **पर** नहीं चलती, जो thread-affine code के लिए मायने रखता है। `async def` handlers अछूते हैं। **[Migration Guide](migration.md#sync-handler-functions-now-run-on-a-worker-thread)**।
* **tool के अंदर raise हुआ `MCPError` (v1 का `McpError`) अब protocol error है।** model उसे कभी नहीं देखता। बाकी हर exception अब भी `is_error=True` result बनता है, लेकिन model तक सिर्फ़ `ToolError` का message पहुँचता है: कोई भी दूसरा exception अब `Error executing tool <name>` पढ़ा जाता है, और traceback आपके server log में जाता है। यह विभाजन **[errors संभालना](servers/handling-errors.md)** में है।
* **results निकलने से पहले validate होते हैं।** हाथ से बना `Tool` जिसका `input_schema` `{}` है, अब `tools/list` में fail होता है (spec को `"type": "object"` चाहिए)। `@mcp.tool()` पर बने servers को यह कभी नहीं दिखता; उनके schemas SDK लिखता है।
* **आपका client जो पाता है उसे validate करता है।** `list_tools()` और `call_tool()` server के जवाब को negotiated protocol version के सामने जाँचते हैं, इसलिए पूरी तरह valid न रहने वाला server, जिसे v1 का ढीला parse सह लेता था, अब `pydantic.ValidationError` raise करता है। अगर आप ऐसे servers से connect करते हैं जो आपके नियंत्रण में नहीं हैं, तो मानकर चलें कि उन्हें खोजने वाले आप ही होंगे; ब्योरा **[Migration Guide](migration.md#client-validates-inbound-traffic-against-the-protocol-schema)** में है।
* **URI templates अब असली RFC 6570 हैं।** `{+path}`, `{?query}` वगैरह काम करते हैं, matching regex-loose के बजाय exact है, और निकाली गई values में path traversal default रूप से reject होता है। ज़्यादा सख्त templates decoration के समय fail होते हैं, पहली request पर नहीं। **[URI templates](servers/uri-templates.md)**।
* **Streamable HTTP lifespan एक बार चलता है**, startup पर, और उसका state हर session और request के बीच साझा होता है। v1 में यह हर session पर एक बार चलता था, और `stateless_http=True` के तहत हर request पर एक बार। Lifespan में बने pools और caches बहुत सस्ते हो जाते हैं; जो कुछ वहाँ per-connection resource लेता था, वह अब handler body में होना चाहिए। **[Lifespan](handlers/lifespan.md)**।
* **Streamable HTTP lifespan एक बार चलता है**, startup पर, और उसका state हर session और request के बीच साझा होता है। v1 में यह हर session पर एक बार चलता था, और `stateless_http=True` के तहत हर request पर एक बार। lifespan में बने pools और caches बहुत सस्ते हो जाते हैं; जो कुछ वहाँ per-connection resource लेता था, वह अब handler body में होना चाहिए। **[Lifespan](handlers/lifespan.md)**।
* **`mcp dev` और `mcp install` जो environment spawn करते हैं उसे** आपके installed SDK version पर pin करते हैं। दोनों commands आपके server को नए `uv run --with ...` environment में चलाते हैं, जो पहले `mcp` को उस version के बजाय newest stable release पर resolve करता था जिसके सामने आप develop कर रहे हैं। **[Migration Guide](migration.md#mcp-dev-and-mcp-install-pin-the-spawned-environment-to-your-sdk-version)**।
* **HTTP client अब `httpx` नहीं, `httpx2` है।** Dependency बदलने से यह बदलता है कि आपका code क्या catch करता और pass करता है (`httpx2.AsyncClient`, `httpx2.ConnectError`), और यह भी कि TLS certificates कैसे verify होते हैं: `httpx2` certifi की bundled CA list के बजाय `truststore` के ज़रिए operating system trust store के सामने validate करता है। ज़्यादातर environments को पता भी नहीं चलता; बिना system CA store वाला minimal container, या ऐसा private CA जिसे सिर्फ़ certifi का bundle जानता था, TLS handshake fail करने लगता है। `SSL_CERT_FILE`/`SSL_CERT_DIR` set करें या अपने client को `verify=ssl_context` pass करें। **[Migration Guide](migration.md#httpx-and-httpx-sse-replaced-by-httpx2)**।
* **HTTP client अब `httpx` नहीं, `httpx2` है।** dependency बदलने से यह बदलता है कि आपका code क्या catch करता और pass करता है (`httpx2.AsyncClient`, `httpx2.ConnectError`), और यह भी कि TLS certificates कैसे verify होते हैं: `httpx2` certifi की bundled CA list के बजाय `truststore` के ज़रिए operating system trust store के सामने validate करता है। ज़्यादातर environments को पता भी नहीं चलता; बिना system CA store वाला minimal container, या ऐसा private CA जिसे सिर्फ़ certifi का bundle जानता था, TLS handshake fail करने लगता है। `SSL_CERT_FILE`/`SSL_CERT_DIR` set करें या अपने client को `verify=ssl_context` pass करें। **[Migration Guide](migration.md#httpx-and-httpx-sse-replaced-by-httpx2)**।
### पूरी तरह हटाए गए {#removed-outright}
इनमें से हर एक **[Migration Guide](migration.md)** में एक section है:
* **WebSocket transport**, दोनों तरफ़, और `mcp[ws]` extra। यह कभी MCP specification का हिस्सा नहीं था।
* **Experimental Tasks** API (`mcp.*.experimental`)। 2026-07-28 tasks को core protocol से निकालकर एक official extension में ले जाता है ([SEP-2663](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2663)), जिसे यह SDK अभी implement नहीं करता।
* Import paths के रूप में `mcp.shared.version`, `mcp.shared.progress` और `mcp.shared.session` (उस `RequestResponder` stub के साथ जिसे v1 के `message_handler` annotations import करते थे)। (`mcp.types` हटाया **नहीं** गया है: यह standalone `mcp_types` package के स्थायी alias के रूप में बना रहता है।)
* Deprecated `streamablehttp_client` spelling, और `streamable_http_client` से `get_session_id` callback (जो अब ठीक दो streams देता है)।
* **experimental Tasks** API (`mcp.*.experimental`)। 2026-07-28 tasks को core protocol से निकालकर एक official extension में ले जाता है ([SEP-2663](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2663)), जिसे यह SDK अभी implement नहीं करता।
* import paths के रूप में `mcp.shared.version`, `mcp.shared.progress` और `mcp.shared.session` (उस `RequestResponder` stub के साथ जिसे v1 के `message_handler` annotations import करते थे)। (`mcp.types` हटाया **नहीं** गया है: यह standalone `mcp_types` package के स्थायी alias के रूप में बना रहता है।)
* deprecated `streamablehttp_client` spelling, और `streamable_http_client` से `get_session_id` callback (जो अब ठीक दो streams देता है)।
* `McpError`, जिसका नाम बदलकर **`MCPError`** हुआ, सीधे `(code, message, data)` constructor के साथ।
* `MCPServer.get_context()`, `mount_path=`, और lowlevel `Server` के decorator methods, ContextVar और handler dicts।