# Python SDK से आपका पहला Server — MCP और Agent-to-Agent Protocols

Source: https://www.geekswithgeeks.com/hi/mcp-a2a/b-first

> सादे functions को tools, resources और prompts में बदलें।

## Decorators protocol का काम करते हैं

आधिकारिक SDKs (Python, TypeScript, Java, C#, Kotlin आदि) JSON-RPC के ब्योरे छिपाते हैं। Python SDK में आप server ऑब्जेक्ट बनाते हैं और decorators से functions पंजीकृत करते हैं: `@tool()` function को tool बनाता है, **नाम** function से, **विवरण** **docstring** से और **इनपुट schema** **type hints** से लेकर; `@resource("uri")` डेटा उपलब्ध कराता है; `@prompt()` template। `run("stdio")` उसे standard input और output पर परोसता है। पहले दिखाया server लगभग 20 पंक्तियों का है। ध्यान दें कि SDK सक्रिय विकास में है: 1.x संस्करण में class का नाम `FastMCP` था, जबकि 2.x ने उसे `MCPServer` किया और अन्य APIs बदले, इसलिए SDK संस्करण pin करें और upgrade पर migration guide देखें।

## छोटा, ईमानदार interface

अच्छे servers कुछ अच्छी तरह वर्णित tools देते हैं, इनपुट validate करते हैं और सहायक errors लौटाते हैं।

![चार आदतें: वर्णन, validate, उबरना, version।](assets/figures/mcp-a2a/section-3-map.svg) — चित्र 3.1 — वर्णन, validate, उबरना और version।

## SDK ने type hints से क्या बनाया, चलाकर

मैंने यह पहले दिखाए असली server के विरुद्ध चलाया, virtual environment में आधिकारिक `mcp` Python SDK 2.2.0 के साथ; client पक्ष stdio पर कच्चा JSON-RPC है, SDK के बिना। Server को उसी folder में `server.py` नाम से सहेजें। SDK के नाम और डिफ़ॉल्ट संस्करणों के बीच बदलते हैं, इसलिए मौजूदा दस्तावेज़ देखें। `tools/list` परिणाम में `order_id: str` से बना इनपुट JSON Schema है, जो उसे आवश्यक चिह्नित करता है। वही session lifecycle विषय में पूरा दिखाया गया है; यहाँ ध्यान बने schema की पंक्ति पर है।

```python
import json, subprocess, sys

proc = subprocess.Popen([sys.executable, "server.py"], stdin=subprocess.PIPE,
                        stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True)

def send(msg):
    proc.stdin.write(json.dumps(msg) + "\n"); proc.stdin.flush()

def call(id_, method, params=None):
    send({"jsonrpc": "2.0", "id": id_, "method": method, **({"params": params} if params is not None else {})})
    return json.loads(proc.stdout.readline())

init = call(1, "initialize", {"protocolVersion": "2025-06-18", "capabilities": {},
                              "clientInfo": {"name": "demo-client", "version": "0.1"}})
print("server:", init["result"]["serverInfo"]["name"], "| protocol:", init["result"]["protocolVersion"])
print("capabilities:", sorted(init["result"]["capabilities"]))
send({"jsonrpc": "2.0", "method": "notifications/initialized"})     # a notification: no id, no reply

tools = call(2, "tools/list")["result"]["tools"]
print("tools:", [t["name"] for t in tools])
print("input schema:", json.dumps(tools[0]["inputSchema"]))

ok = call(3, "tools/call", {"name": "get_order_status", "arguments": {"order_id": "481516"}})
print("call ok     :", ok["result"]["content"][0]["text"], "| isError:", ok["result"].get("isError"))
bad = call(4, "tools/call", {"name": "get_order_status", "arguments": {"order_id": "12"}})
print("call bad id :", bad["result"]["content"][0]["text"])
missing = call(5, "tools/call", {"name": "get_order_status", "arguments": {}})
print("missing arg :", "isError" , missing["result"].get("isError"), "|", missing["result"]["content"][0]["text"][:60].replace(chr(10), " "))
unknown = call(6, "no/such/method")
print("unknown     :", unknown["error"]["code"], unknown["error"]["message"])

res = call(7, "resources/list")["result"]["resources"]
print("resources:", [r["uri"] for r in res])
print("read:", call(8, "resources/read", {"uri": "policy://refunds"})["result"]["contents"][0]["text"])
pr = call(9, "prompts/get", {"name": "triage", "arguments": {"ticket": "I was charged twice"}})
print("prompt:", pr["result"]["messages"][0]["content"]["text"])
proc.stdin.close(); proc.wait()

```

Output:

```
server: demo-orders | protocol: 2025-06-18
capabilities: ['experimental', 'prompts', 'resources', 'tools']
tools: ['get_order_status']
input schema: {"properties": {"order_id": {"title": "Order Id", "type": "string"}}, "required": ["order_id"], "type": "object", "title": "get_order_statusArguments"}
call ok     : {
  "order_id": "481516",
  "status": "shipped"
} | isError: False
call bad id : {
  "error": "order_id must be exactly 6 digits"
}
missing arg : isError True | Error executing tool get_order_status: 1 validation error fo
unknown     : -32601 Method not found
resources: ['policy://refunds']
read: Refunds above 5000 rupees need approval.
prompt: Classify this ticket as billing, technical or other: I was charged twice
```

**Quiz:** SDK tool का विवरण कहाँ से लेता है?

- [x] Function के docstring से
- [ ] File आकार से
- [ ] GPU से
- [ ] वह नहीं ले सकता

*Answer:* Function के docstring से. Docstrings, नाम और type hints वह tool परिभाषा बनते हैं जो मॉडल पढ़ता है।
