docs: publish translated docs in twelve languages and the tool that maintains them (#3280)

This commit is contained in:
Max 2026-08-14 17:07:34 +01:00 • committed by GitHub
commit 52ad0a8876
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 89737 additions and 54 deletions

View file

@ -0,0 +1,144 @@
---
translation:
sections: [0d6c05bcbf836bf3, 59a7b14eeefc68c1, 7114d8d6daba203f, e8bbb56a98ba7bc9, 5138010f6159901c, f78da7c7c363d4c6, 220a939cab348686]
tool: 1
---
# पहले कदम {#first-steps}
**[landing page](../index.md)** तेज़ी से चलता है: server लिखें, उसे चलाएँ, tool call करें।
यह page आराम से चलता है: वे तीनों चीज़ें जो server expose कर सकता है, और रास्ते में हर चीज़ का नाम भी।
## host, client और server {#host-client-and-server}
तीन शब्द जो यहाँ से आगे हर page पर दिखेंगे:
* **host** LLM application है: Claude, कोई IDE, कोई agent runtime। यह वह चीज़ है जिससे user बात करता है।
* **client** host के अंदर रहता है और MCP बोलता है। host जितने servers से जुड़ा है, हर एक के लिए एक client चलाता है।
* **server** वह है जो आप इस SDK से बनाते हैं। यह clients को चीज़ें expose करता है। यह model से सीधे कभी बात नहीं करता।
server आप लिखते हैं। hosts किसी और का product हैं। SDK आपको एक `Client` भी देता है। इससे आप अपने servers test करेंगे, और यह इसी page पर आगे दिखता है।
## तीन primitives {#the-three-primitives}
server ठीक तीन तरह की चीज़ें expose करता है। इन्हें अलग करने वाली बात यह है कि **इन्हें इस्तेमाल करने का फ़ैसला कौन करता है**:
| Primitive | नियंत्रण किसका | यह क्या है | उदाहरण |
|---------------|-----------------|-----------------------------------------------------|------------------------------------|
| **Tools** | model | ऐसा function जिसे model कोई काम करने के लिए call करता है | API call, database write |
| **Resources** | application | data जिसे host model के context में load करता है | किसी file की सामग्री, API response |
| **Prompts** | user | दोबारा इस्तेमाल होने वाला message template जिसे user नाम से चलाता है | slash command, menu entry |
"नियंत्रण किसका" ही इस बँटवारे का पूरा मतलब है। tool इसलिए चलता है क्योंकि **model** ने उसे call करने का फ़ैसला किया। resource इसलिए जुड़ता है क्योंकि **application** ने तय किया कि model को उसकी ज़रूरत है। prompt इसलिए चलता है क्योंकि **user** ने उसे चुना।
!!! info
अगर आपने web API बनाया है तो ज़्यादातर समझ आपके पास पहले से है: **resource** एक `GET` है
(data load करता है और कुछ बदलता नहीं) और **tool** एक `POST` है (काम करता है और उसके
side effects हो सकते हैं)। **prompt** का HTTP में कोई जोड़ीदार नहीं; यह उस saved query के
ज़्यादा करीब है जिसे user नाम से चलाता है।
## एक server, तीनों चीज़ें {#one-server-all-three}
```python title="server.py" hl_lines="6 12 18"
--8<-- "docs_src/first_steps/tutorial001.py"
```
तीन सादे functions, तीन decorators। हर decorator ही पूरा registration है:
* `@mcp.tool()` `add` को **tool** बनाता है।
* `@mcp.resource("greeting://{name}")` `greeting` को **resource template** बनाता है: URI में `{name}` function का parameter है।
* `@mcp.prompt()` `summarize` को **prompt** बनाता है। यह जो string लौटाता है, वही user message बन जाती है।
बाकी सब कुछ (नाम, description, argument schema) SDK function से ही पढ़ लेता है: उसका नाम, उसका docstring, उसके type hints। आपने इनमें से कुछ भी अलग से declare नहीं किया।
!!! tip
SDK के दो हिस्सों के दो import paths हैं: `from mcp import Client` और
`from mcp.server import MCPServer`। `from mcp import MCPServer` जैसा कुछ नहीं है।
### इसे आज़माएँ {#try-it}
इसे MCP Inspector से चलाएँ:
```console
uv run mcp dev server.py
```
जो URL यह print करता है उसे खोलें। Inspector में हर primitive के लिए एक tab है; उन्हें क्रम से देखें।
**Tools.** एक entry: `add`, जिसका description है *Add two numbers.* form में `a` के लिए एक ज़रूरी integer field है और `b` के लिए एक और। उन्हें भरें, call करें, और result `3` है। Inspector ने वह form `a: int, b: int` से बनाया। बाकी हर client भी यही करता है।
**Resources.** *Resources* सूची खाली है। `greeting` **Resource Templates** के नीचे है, क्योंकि `greeting://{name}` में parameter है: जब तक कोई `name` न दे, सूची में दिखाने के लिए कोई एक resource है ही नहीं। इसे `World` दें और पढ़ें:
```text
Hello, World!
```
**Prompts.** एक entry: `summarize`, एक ही ज़रूरी `text` argument के साथ। कुछ text देकर इसे get करें और आपको एक message मिलता है जिसमें `role: user` है और content के रूप में आपकी render की हुई string। prompt बस इतना ही है: messages बनाने वाला function।
Inspector ने आपका server **stdio** पर चलाया, जो उन transports में से एक है जो MCP server बोल सकता है। अभी आपको कोई चुनना नहीं है; उसके लिए **[अपना server चलाना](../run/index.md)** page है।
## Capabilities {#capabilities}
Inspector में आपने तीन tabs देखे। उसे कैसे पता चला कि तीन हैं?
जब client जुड़ता है, server अपनी **capabilities** declare करता है: requests के कौन-से परिवारों का वह जवाब देगा। client उसी declaration से तय करता है कि माँगे भी तो क्या। आपने यह कभी नहीं लिखा; `MCPServer` आपके लिए इसे declare करता है।
खुद देखें। SDK का `Client` सीधे server object लेता है और उससे **in memory** जुड़ता है (न subprocess, न port):
```python
import asyncio
from mcp import Client
from server import mcp
async def main() -> None:
async with Client(mcp) as client:
print(client.server_capabilities.model_dump(exclude_none=True))
asyncio.run(main())
```
```text
{'prompts': {'list_changed': True}, 'resources': {'subscribe': True, 'list_changed': True}, 'tools': {'list_changed': True}}
```
वह dictionary आपके server की declared **capabilities** है। हर जुड़ने वाला client सबसे पहले यही जानता है:
| Capability | client अब ये call कर सकता है |
|-------------|------------------------------------------------------------|
| `tools` | `tools/list`, `tools/call` |
| `resources` | `resources/list`, `resources/templates/list`, `resources/read` |
| `prompts` | `prompts/list`, `prompts/get` |
`MCPServer` तीनों primitives serve करता है, इसलिए तीनों हमेशा declare होती हैं।
ध्यान दें कि क्या नहीं है। `completions` (resource templates और prompts के लिए argument autocomplete) को आपका लिखा handler चाहिए, इस server में वह नहीं है, इसलिए capability मौजूद नहीं है और सलीके वाला client पूछेगा ही नहीं। हर optional चीज़ का यही नियम है: चीज़ register करें और capability आ जाती है; **[Completions](../servers/completions.md)** इसे साबित करता है।
!!! info
`Client(mcp)` वही in-memory client है जिससे इन docs का हर उदाहरण test होता है, और
इसी से आप अपने servers test करेंगे। इसे पूरा एक page मिलता है: **[Testing](testing.md)**।
## जो आपने नहीं लिखा {#what-you-did-not-write}
इस page पर पीछे मुड़कर देखें। आपने तीन छोटे Python functions लिखे। आपने ये **नहीं** लिखे:
* JSON Schema। `a: int, b: int` **ही** `add` का schema है।
* request handler। `tools/list`, `resources/read`, `prompts/get`: सब आपके लिए serve होते हैं।
* capability declaration। `MCPServer` ने आपके लिए बना दिया।
* protocol की एक भी line। version negotiation, JSON-RPC framing, capability exchange: यह सब `mcp dev` और `Client(mcp)` के अंदर हुआ, और आपने कभी देखा ही नहीं।
यही अनुपात SDK का पूरा मतलब है।
## सारांश {#recap}
* **host** LLM app है, **client** उसका MCP बोलने वाला हिस्सा है, **server** वह है जो आप बनाते हैं।
* tools पर **model** का नियंत्रण है, resources पर **application** का, prompts पर **user** का।
* हर primitive के लिए एक decorator: `@mcp.tool()`, `@mcp.resource(uri)`, `@mcp.prompt()`। नाम, description और schema function से आते हैं।
* `{param}` वाला URI resource **template** बनाता है, जो concrete resources से अलग सूची में दिखता है।
* server की **capabilities** आपके लिए declare हो जाती हैं, और client वही माँगता है जो server declare करता है।
* `Client(mcp)` server object से in memory जुड़ता है: पहले दिन से आपका test harness।
आगे है **[असली host से जुड़ें](real-host.md)**: यही server Claude Desktop या किसी IDE के अंदर, सच में। फिर **[Testing](testing.md)**: एक page, एक in-memory client, और आपको कभी अंदाज़ा नहीं लगाना पड़ेगा कि यह काम करता है या नहीं। उसके बाद हर primitive को अपना page मिलता है, शुरुआत उससे जिसे model चलाता है: **[Tools](../servers/tools.md)**।

View file

@ -0,0 +1,57 @@
---
translation:
sections: [ed4a756b4c53c585, 97e2fb315b7fe398, 4d04f1c6f4bf6c1d, 577d73078fc62baf]
tool: 1
---
# शुरू करें {#get-started}
MCP में नए हैं, या इस SDK में? यहीं से शुरू करें। ये pages आपको शून्य से एक चालू,
test किए हुए server तक ले जाते हैं: [SDK install करें](installation.md), अपना
[पहला server](first-steps.md) बनाएँ, [उसे असली host से जोड़ें](real-host.md), और
in-memory client से [उसे test करें](testing.md)।
## code चलाएँ {#run-the-code}
सभी code blocks सीधे copy करके इस्तेमाल किए जा सकते हैं: ये पूरी, काम करने वाली files हैं।
साथ-साथ चलने के लिए, किसी block को `server.py` में paste करें और उसे MCP Inspector में खोलें:
```console
uv run mcp dev server.py
```
**पुरज़ोर सलाह** है कि code खुद लिखें (या copy करें), उसमें बदलाव करें और उसे locally चलाएँ। अपने editor में इस्तेमाल करने पर ही असली बात समझ आती है: कितना कम लिखना पड़ता है, autocompletion, और कुछ भी चलाने से पहले गलतियाँ पकड़ लेने वाले type checks।
## आपको अंदाज़ा नहीं लगाना पड़ेगा {#you-will-not-be-guessing}
इन docs का हर उदाहरण SDK की अपनी repository में [`docs_src/`](https://github.com/modelcontextprotocol/python-sdk/tree/main/docs_src) के नीचे एक पूरी file है, और SDK का test suite हर एक को **in-memory client** के ज़रिए चलाकर परखता है:
```python
import pytest
from mcp import Client
from server import mcp
@pytest.mark.anyio
async def test_add() -> None:
async with Client(mcp) as client:
result = await client.call_tool("add", {"a": 1, "b": 2})
assert result.structured_content == {"result": 3}
```
न subprocess, न port, न transport। `Client(mcp)` सीधे server object से जुड़ता है।
अगर SDK में कोई बदलाव इन pages के किसी उदाहरण को तोड़ता है, तो page से पहले CI लाल हो जाता है। जो code आप यहाँ पढ़ते हैं, वही code चलता है।
[Testing](testing.md) में आप इसे खुद इस्तेमाल करेंगे; अपने servers भी इसी तरह test किए जाते हैं।
## आगे कहाँ जाएँ {#where-to-go-next}
एक बार server चल जाए, तो बाकी docs course नहीं, reference हैं।
हर page अपने आप में पूरा है, इसलिए सीधे वहीं जाएँ जिसकी ज़रूरत है:
* server क्या expose करता है (tools, resources, prompts), यह **[Servers](../servers/index.md)** में है।
* आपके register किए functions के अंदर क्या-क्या उपलब्ध है, यह **[आपके handler के अंदर](../handlers/index.md)** में है।
* इसे clients के सामने लाना (stdio, HTTP, आपका मौजूदा FastAPI app) **[अपना server चलाना](../run/index.md)** में है।
* दूसरा पक्ष बनाना, यानी ऐसा application जो MCP servers **इस्तेमाल करता है**, **[Clients](../client/index.md)** में है।

View file

@ -0,0 +1,47 @@
---
translation:
sections: [6e2f9bab94d5ed36, 8cf653388f69e28b, 6fd9ea2f65de0df6]
tool: 1
---
# Installation {#installation}
Python SDK PyPI पर [`mcp`](https://pypi.org/project/mcp/) नाम से उपलब्ध है। इसके लिए **Python 3.10+** ज़रूरी है।
ये docs **v2** का वर्णन करते हैं, जो मौजूदा stable release line है:
=== "uv"
```bash
uv add "mcp[cli]"
```
=== "pip"
```bash
pip install "mcp[cli]"
```
!!! note "v1 से आ रहे हैं?"
v2 एक major version है जिसमें breaking changes हैं; **[Migration Guide](../migration.md)**
में हर एक बदलाव की जानकारी है। अगर आपका **package** `mcp` पर निर्भर है और अभी migrate करने के लिए
तैयार नहीं है, तो `<2` की upper bound रखें (उदाहरण के लिए `mcp>=1.28,<2`), ताकि बिना pin किया गया resolve 1.x line पर ही रहे।
## क्या-क्या install होता है {#what-gets-installed}
SDK इस्तेमाल करने के लिए यह सब जानना ज़रूरी नहीं है, लेकिन अगर आप सोच रहे हैं कि हर dependency किस काम की है:
* `mcp-types`: हर protocol type (requests, results, content blocks) अपने अलग package के रूप में, जिसका version SDK के साथ कदम मिलाकर चलता है। जो code `mcp` पर निर्भर है, वह इसे `mcp.types` alias के ज़रिए import करता है (इन docs में हर `from mcp.types import ...`); `mcp_types` को सीधे सिर्फ़ उसी project में import करें जो SDK के बिना `mcp-types` install करता है।
* [`anyio`](https://anyio.readthedocs.io/): async runtime। पूरा SDK anyio के आधार पर लिखा गया है, इसलिए यह `asyncio` या `trio` दोनों में से किसी पर भी चलता है।
* [`pydantic`](https://docs.pydantic.dev/): हर `mcp.types` model इसी पर बना है, साथ ही पूरा schema generation और validation भी।
* [`httpx2`](https://pypi.org/project/httpx2/): Streamable HTTP और SSE **client** transports के पीछे का HTTP client, जिसमें server-sent events का support पहले से मौजूद है।
* [`starlette`](https://www.starlette.io/), [`uvicorn`](https://www.uvicorn.org/), [`sse-starlette`](https://pypi.org/project/sse-starlette/), और [`python-multipart`](https://pypi.org/project/python-multipart/): HTTP **server** transports।
* [`jsonschema`](https://pypi.org/project/jsonschema/): tool के structured output को उसके घोषित output schema के अनुसार validate करता है।
* [`pyjwt[crypto]`](https://pyjwt.readthedocs.io/): authorization के लिए OAuth token संभालना।
* [`opentelemetry-api`](https://opentelemetry-python.readthedocs.io/): सिर्फ़ हल्का-सा API, ताकि SDK के tracing middleware की कोई लागत न हो, जब तक आप खुद OpenTelemetry SDK और exporter install न करें।
* [`typing-extensions`](https://typing-extensions.readthedocs.io/) और [`typing-inspection`](https://pypi.org/project/typing-inspection/): Python 3.10 पर आधुनिक typing features।
* [`pywin32`](https://pypi.org/project/pywin32/): सिर्फ़ Windows पर, `stdio` subprocess management के लिए इस्तेमाल होता है।
## Optional extras {#optional-extras}
* `mcp[cli]`, `mcp` command-line tool (`mcp dev`, `mcp run`, `mcp install`) के लिए [`typer`](https://typer.tiangolo.com/) और [`python-dotenv`](https://pypi.org/project/python-dotenv/) जोड़ता है। development के दौरान आपको यह चाहिए होगा; deploy किए गए server में शायद इसकी ज़रूरत न पड़े।
* `mcp[rich]` बेहतर server logs के लिए [`rich`](https://rich.readthedocs.io/) जोड़ता है।

View file

@ -0,0 +1,182 @@
---
translation:
sections: [3c4f2f06b4e978b6, 22520eecae3d1961, f4e1709db18d635a, 2eb57992049671d9, 1ba83e9af37cc1b4, 4822586344b08d9e, 1c93afef72478992, b6b448f9eddd51dc, fe55370fd931815b]
tool: 1
---
# असली host से connect करना {#connect-to-a-real-host}
**host** वह application है जिसके अंदर आपका server आखिरकार चलता है: Claude Desktop, Claude Code, कोई IDE। user इसी host से बात करता है। इसके अंदर एक MCP **client** आपके server को child process के रूप में launch करता है और उसी process के stdin और stdout पर उससे बात करता है।
यानी host से connect करना बस एक काम है: आप उसे **वह command बताते हैं जो आपका server शुरू करता है**। इस page पर जो कुछ है (दो CLI commands, तीन JSON files), वह उसी एक command को रखने की अलग-अलग जगहें हैं।
## एक server, हर host {#one-server-every-host}
```python title="server.py" hl_lines="3 33-34"
--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 नहीं करता।
* `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`।
इस page पर Python की यह आख़िरी line है। यहाँ से नीचे सब host configuration है।
## Launch command {#the-launch-command}
नीचे के हर host को यही एक command मिलता है:
```bash
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 है जो `mcp install` आपके लिए Claude Desktop के config में लिखता है (नीचे देखें), इसलिए जो आप हाथ से लिखते हैं और जो tool बनाता है, दोनों मेल खाते हैं, सिवाय उस exact version pin के जो tool जोड़ता है।
!!! tip "अगर host को `uv` न मिले"
host आपके server को बहुत छोटे `PATH` के साथ spawn करता है, और हो सकता है `uv` उसमें न हो। सिर्फ़
`uv` की जगह `which uv` (macOS/Linux) या `where uv` (Windows) से मिला absolute path लिखें। `mcp install`
ठीक यही लिखता है।
!!! note "यह page local setup की बात है"
यहाँ की हर चीज़ आपके server को उसी machine पर चलाती है जिस पर host है: host आपकी
file को stdio पर launch करता है। निजी या एक ही machine वाले tool के लिए यह बिल्कुल सही है। जिन
लोगों के पास आपकी file **नहीं** है, उन्हें server देने के लिए आप command नहीं, **URL** देते हैं: वही
`mcp` object, Streamable HTTP पर serve किया हुआ। **[अपना server चलाना](../run/index.md)**
वह फ़ैसला एक table में रखता है, और **[Deploy और scale](../run/deploy.md)** वहाँ से
असली hostname तक का रास्ता है।
और host किसी application से ज़्यादा कुछ नहीं जिसके अंदर MCP client हो, इसलिए आपका अपना
Python भी host की भूमिका निभा सकता है: **[Client transports](../client/transports.md)** इसी
file को `stdio_client(...)` से subprocess के रूप में launch करता है, और **[Testing](testing.md)**
बिना किसी process के, memory में ही उससे connect करता है।
## Claude Desktop {#claude-desktop}
वह इकलौता host जिसे SDK आपके लिए configure कर सकता है:
```bash
uv run mcp install server.py
```
बस इतना ही। `mcp install` server का नाम पढ़ने के लिए file को import करता है, Claude Desktop की config file ढूँढता है और उसमें launch command लिख देता है। साथ ही यह आपके path को absolute बना देता है, ताकि आपको न करना पड़े।
इसमें कोई रहस्य नहीं है। यह रही वह entry जो यह लिखता है:
```json
{
"mcpServers": {
"Bookshop": {
"command": "/absolute/path/to/uv",
"args": [
"run",
"--frozen",
"--with",
"mcp[cli]==2.0.0",
"mcp",
"run",
"/absolute/path/to/server.py"
]
}
}
}
```
यह ऊपर वाले section का launch command ही है, तीन चीज़ें जोड़कर: `uv` का absolute path, `--frozen` ताकि `uv` आस-पास पड़ी किसी lockfile को कभी दोबारा न लिखे, और आपके install किए हुए `mcp` version का exact pin। यह `claude_desktop_config.json` में जाता है, जो यहाँ रहती है:
* **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
* **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
यह file आप हाथ से भी लिख सकते हैं। `mcp install` इसलिए है ताकि ऐसा करते समय आप वह जानी-पहचानी गलती (relative path) न करें।
Claude Desktop को पूरी तरह quit करें (सिर्फ़ उसकी window नहीं) और दोबारा खोलें।
!!! warning
अगर Claude Desktop की config **directory** अभी मौजूद नहीं है तो `mcp install` `Claude app not found` के साथ
fail होता है। Claude Desktop install करें और एक बार चलाएँ: directory उसी से बनती है।
!!! tip
Claude Desktop आपके server को अपने process में शुरू करता है, इसलिए आपके shell के environment variables
वहाँ नहीं होते। `uv run mcp install server.py -v API_KEY=abc123` (या `-f .env`) उन्हें entry के
`env` field में दर्ज कर देता है। `--name` entry का नाम override करता है; default server का `name` है।
## Claude Code {#claude-code}
edit करने के लिए कोई file नहीं है। server को `claude` CLI से register करें; `--` के बाद जो कुछ है वही launch command है।
```bash
claude mcp add bookshop -- uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py
```
यह पक्का करने के लिए कि `bookshop` connected है और उसके tools सूची में दिख रहे हैं, Claude Code session के अंदर `/mcp` चलाएँ।
## Cursor {#cursor}
अपने project root में `.cursor/mcp.json` बनाएँ।
```json
{
"mcpServers": {
"bookshop": {
"command": "uv",
"args": ["run", "--with", "mcp[cli]", "mcp", "run", "/absolute/path/to/server.py"]
}
}
}
```
वही `command` और `args`, उसी `mcpServers` key के नीचे जो Claude Desktop इस्तेमाल करता है। server दोनों tools के साथ Cursor की MCP settings में दिखता है।
## VS Code {#vs-code}
अपने project root में `.vscode/mcp.json` बनाएँ।
```json
{
"servers": {
"bookshop": {
"type": "stdio",
"command": "uv",
"args": ["run", "--with", "mcp[cli]", "mcp", "run", "/absolute/path/to/server.py"]
}
}
}
```
Cursor की file से दो फ़र्क़ हैं, और बस यही दो: wrapper key `mcpServers` नहीं, `servers` है, और हर entry अपना `type` बताती है। trust prompt को confirm करें, फिर Command Palette में **MCP: List Servers** `bookshop` को चलता हुआ दिखाता है।
!!! note
आपको VS Code 1.99 या उससे नया चाहिए, जिसमें **GitHub Copilot** extension signed in हो (Copilot Free
काफ़ी है), और Copilot Chat **Agent** mode में होना चाहिए, क्योंकि कोई और mode tools को call नहीं करता।
## यह दिख नहीं रहा {#it-doesnt-show-up}
किसी भी host config को छूने से पहले, launch command खुद चलाएँ:
```bash
uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py
```
कुछ print नहीं होता, और यह लौटता नहीं। यह चुप्पी सही है: stdio server इंतज़ार कर रहा है कि host पहले stdin पर बोले (रोकने के लिए `Ctrl-C`)। traceback या तुरंत exit ही असली bug है, और अब आप उसे host के ज़रिए अंदाज़ा लगाने के बजाय सीधे पढ़ सकते हैं।
जब वह command बैठकर इंतज़ार करने लगे, तो बाकी समस्या लगभग हमेशा इन तीन में से एक होती है:
* **Relative path।** host आपके server को **अपनी** working directory से launch करता है, उस directory से नहीं जहाँ से आपने register किया था। जहाँ `/absolute/path/to/server.py` चाहिए वहाँ `server.py` लिखना सबसे आम गड़बड़ी है। अगर host को `uv` भी न मिले, तो वह path भी absolute होना चाहिए।
* **host अब भी पुराने config पर चल रहा है।** hosts अपना config launch के समय पढ़ते हैं। ख़ासकर Claude Desktop को **पूरी तरह quit** करना (सिर्फ़ window बंद करना नहीं) और दोबारा खोलना पड़ता है, तभी `claude_desktop_config.json` में किया गया बदलाव लागू होता है।
* **divert की गई window के बाहर कुछ stdout तक पहुँच गया।** stdio पर stdout **ही** protocol है। serve करते समय SDK flush हुए भटके हुए output को stderr की ओर मोड़ देता है, लेकिन उससे पहले stdout पर flush हुआ output (कोई wrapper script जो echo करती है, unbuffered process में import के समय चला `print()`), या interpreter exit पर खाली होने वाला buffered `print()`, host को corrupt message थमा देता है और host connection छोड़ देता है। default `logging` configuration से log करें, जिसका stderr handler हर record को flush करता है; custom handlers को भी stdout से बचना ही है। पूरी जानकारी **[Logging](../handlers/logging.md)** में है।
Claude Desktop हर server का अलग log रखता है: `mcp-server-<NAME>.log` आपके server का stderr है, connections के लिए `mcp.log` के बगल में, macOS पर `~/Library/Logs/Claude` में और Windows पर `%APPDATA%\Claude\logs` में।
इन तीनों के आगे कुछ भी हो, तो **[Troubleshooting](../troubleshooting.md)** वाला page देखें।
## सारांश {#recap}
* **host** (Claude Desktop, कोई IDE) एक MCP client चलाता है जो आपके server को stdio पर child process के रूप में launch करता है। connect करने का मतलब है उसे एक launch command देना।
* वह command है `uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py`: कोई venv activate नहीं करना, किसी भी directory से चलता है।
* **Claude Desktop** वह इकलौता host है जिसे `mcp install` आपके लिए configure करता है। यह वही command (साथ में `uv` का absolute path, `--frozen`, और आपके install किए हुए version का exact pin) `claude_desktop_config.json` में लिख देता है, ताकि आपको कभी न लिखना पड़े।
* **Claude Code** के लिए `claude mcp add bookshop -- <launch command>`। **Cursor** के लिए `mcpServers` के नीचे `.cursor/mcp.json`। **VS Code** के लिए `servers` के नीचे `.vscode/mcp.json`, हर entry में एक `type`।
* हर जगह absolute paths, config edit करने के बाद host को restart करें, और SDK के अलावा किसी को stdout पर न लिखने दें।
इस page का हर host उसी एक file से, उसी एक command से connect हुआ। वह file क्या **expose** कर सकती है, यही बाकी docs हैं: **[Tools](../servers/tools.md)**, **[Resources](../servers/resources.md)**, और stdio के अलावा हर transport **[अपना server चलाना](../run/index.md)** में।

View file

@ -0,0 +1,105 @@
---
translation:
sections: ['4926721070127497', c52a1de2b6b32f40, 2e410b412c25f314, 627195f7159e24ef]
tool: 1
---
# Testing {#testing}
Python SDK में `Client` class आती है जिसके साथ **in-memory transport** मिलता है: इसे अपना server object दें और यह उससे सीधे जुड़ जाता है।
कोई subprocess नहीं। कोई port नहीं। कोई transport ही नहीं। यह वही विचार है जो FastAPI के `TestClient` का है।
## Basic usage {#basic-usage}
मान लेते हैं कि आपके पास एक ही tool वाला सीधा-सादा server है:
```python title="server.py"
--8<-- "docs_src/testing/tutorial001.py"
```
नीचे दिया गया test चलाने के लिए दो अतिरिक्त (development) dependencies चाहिए:
=== "uv"
```bash
uv add --dev pytest inline-snapshot
```
=== "pip"
```bash
pip install pytest inline-snapshot
```
!!! info
ये docs मानकर चलते हैं कि आप [`pytest`](https://docs.pytest.org/en/stable/) पहले से जानते हैं।
नीचे दिया गया test पूरे result object पर एक ही line में assert करने के लिए
[`inline-snapshot`](https://15r10nk.github.io/inline-snapshot/latest/) का इस्तेमाल करता है। यह test के
output को उसी `snapshot(...)` literal के रूप में record करता है जो आपको दिख रहा है। अगर आप इसे इस्तेमाल
नहीं करना चाहते, तो import हटा दें और किसी भी दूसरे test की तरह उन्हीं fields पर assert करें जो आपके
लिए मायने रखती हैं (`result.content[0].text == "3"`)।
अब test:
```python title="test_server.py"
import pytest
from inline_snapshot import snapshot
from mcp import Client
from mcp.types import CallToolResult, TextContent
from server import mcp
@pytest.fixture
def anyio_backend(): # (1)!
return "asyncio"
@pytest.fixture
async def client(): # (2)!
async with Client(mcp, raise_exceptions=True) as c:
yield c
@pytest.mark.anyio
async def test_call_add_tool(client: Client):
result = await client.call_tool("add", {"a": 1, "b": 2})
# Drop the server identity stamp in `_meta`; it is not what this test is about.
result.meta = None
assert result == snapshot(
CallToolResult(
content=[TextContent(type="text", text="3")],
structured_content={"result": 3},
)
)
```
1. अगर आप `trio` इस्तेमाल कर रहे हैं, तो इसकी जगह `"trio"` लौटाएँ। विस्तार से जानने के लिए [anyio documentation](https://anyio.readthedocs.io/en/stable/testing.html#specifying-the-backends-to-run-on) देखें।
2. यह fixture एक जुड़ा हुआ client yield करता है। हर test जो `client` लेता है, उसे उसी server से नया in-memory connection मिलता है।
हो गया! अब आप और scenarios को cover करने के लिए अपने tests बढ़ा सकते हैं।
## `raise_exceptions=True` क्यों? {#why-raise_exceptionstrue}
दो अलग-अलग चीज़ें गड़बड़ हो सकती हैं, और यह 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)**।
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 में इसका कोई मतलब नहीं है।
## Default रूप से in-process {#in-process-by-default}
!!! note
`Client(mcp)` in-process जुड़ता है और default रूप से **पीढ़ी-निरपेक्ष** है: यह server को probe करता है और
सही protocol path चुनता है। अगर आपका test legacy-विशेष semantics (sampling या elicitation push,
`message_handler`) को परखता है, तो `mode="legacy"` pin करें, और वहाँ `raise_exceptions=True` हटा दें:
legacy connection पहले से ही कभी sanitise नहीं करता, और यह flag failure को आपके test में नहीं, बल्कि
server task के अंदर दोबारा raise करता है।
यही एक line वह वजह भी है कि ये docs आपसे वादा कर सकते हैं कि इनके उदाहरण काम करते हैं: हर example file को SDK का अपना test suite चलाकर परखता है, और उनमें से लगभग सभी को ठीक इसी client के ज़रिए। आप वही tool इस्तेमाल कर रहे हैं जो SDK खुद पर इस्तेमाल करता है।
आपके पास एक चलता हुआ, tested server है। इसे किसी असली application (Claude Desktop, कोई IDE) के अंदर रखना **[असली host से जुड़ें](real-host.md)** में है; इसे serve करने का हर दूसरा तरीका **[अपना server चलाना](../run/index.md)** में है।