विषय पर बढ़ें

Cancellation

मशीनी अनुवाद

यह page अंग्रेज़ी documentation से अपने-आप अनुवादित किया गया है, और अंग्रेज़ी page ही प्रामाणिक version है। अगर कुछ गलत लगे, तो अनुवाद page बताता है कि इसकी सूचना कैसे दें।

client किसी call को बीच में छोड़ सकता है: user ने stop दबा दिया, या timeout पूरा हो गया।

ऐसा होने पर SDK आपके handler को cancel कर देता है। handler जिस await पर रुका है वह raise करता है, function unwind हो जाता है, और वह जो कुछ भी लौटाता है उसमें से कुछ नहीं भेजा जाता। ज़्यादातर handlers को इस बारे में कुछ करने की ज़रूरत नहीं होती।

दो तरह के handlers को ज़रूरत होती है: वह handler जिसे कुछ cleanup करना हो, और वह handler जो सादा def हो।

async def tool में cleanup करना

cleanup को finally में रखें:

server.py
import anyio

from mcp.server import MCPServer

mcp = MCPServer("Bookshop")

holds: set[str] = set()


async def take_payment(title: str) -> None:
    await anyio.sleep(30)  # the customer is typing a card number


async def release_hold(title: str) -> None:
    await anyio.sleep(0.1)  # a round trip to the stock system
    holds.discard(title)


@mcp.tool()
async def order_book(title: str) -> str:
    """Hold a copy of a book while the customer pays for it."""
    holds.add(title)
    try:
        await take_payment(title)
        return f"Ordered {title!r}."
    finally:
        with anyio.move_on_after(5, shield=True):
            await release_hold(title)
  • tool चाहे जैसे खत्म हो, finally चलता है: tool ने कुछ लौटाया हो, raise किया हो, या cancel हुआ हो।
  • जिस cleanup को await करना पड़े, उसे shield=True चाहिए। cancel हो चुके handler में आगे का हर await भी raise करता है, इसलिए shield के बिना release_hold अपनी पहली line पर ही रुक जाता।
  • shielded block को कोई cancel नहीं कर सकता, इसलिए उसे समय सीमा दें। यहाँ वह 5 सेकंड है।

Tip

except नहीं, finally इस्तेमाल करें। cleanup पूरा होने के बाद cancellation को ऊपर की ओर बढ़ते रहना होता है, और finally उसे बढ़ने देता है।

सादे def tool में जल्दी रुकना

सादा def tool thread में चलता है, और thread को बाहर से कोई interrupt नहीं कर सकता। tool को खुद पूछना पड़ता है:

server.py
import time

import anyio.from_thread

from mcp.server import MCPServer

mcp = MCPServer("Bookshop")

offline: set[str] = set()


def index_book(title: str) -> None:
    time.sleep(1)  # slow work with nothing to await


@mcp.tool()
def rebuild_index(titles: list[str]) -> str:
    """Take search offline and rebuild its index, one book at a time."""
    offline.add("search")
    try:
        for title in titles:
            anyio.from_thread.check_cancelled()
            index_book(title)
        return f"Indexed {len(titles)} books."
    finally:
        offline.discard("search")
  • जब तक call चालू है, anyio.from_thread.check_cancelled() कुछ नहीं करता, और call cancel हो जाने के बाद raise करता है। इसे काम की इकाइयों के बीच call करें।
  • यहाँ भी cleanup finally में जाता है। thread में कुछ भी await नहीं करता, इसलिए इसे shield की ज़रूरत नहीं होती।
  • जो def tool कभी नहीं पूछता, वह अंत तक चलता है, और उसका नतीजा फेंक दिया जाता है।

यह कहाँ लागू होता है

prompt और resource functions ठीक tools की तरह cancel होते हैं।

stdio और Streamable HTTP दोनों पर यह एक जैसा काम करता है। इस SDK के Client में call छोड़ने का मतलब है उस task को cancel करना जो call_tool को await कर रहा है, या उसका read_timeout_seconds पूरा हो जाने देना।

Warning

Streamable HTTP के दो options यह खबर handler तक नहीं पहुँचने देते: 2026-07-28 connection पर json_response=True, और legacy connection पर stateless_http=True। वहाँ client ने चाहे जो किया हो, handler अंत तक चलता है।

सारांश

  • जब client किसी call को छोड़ देता है, तो SDK handler को cancel कर देता है: tool, prompt या resource।
  • async def: cleanup finally में करें, और जो cleanup await करता है उसे anyio.move_on_after(seconds, shield=True) के अंदर रखें।
  • सादा def: काम की इकाइयों के बीच anyio.from_thread.check_cancelled() call करें, नहीं तो tool अंत तक चलता है। सादा finally cleanup कर देता है।
  • json_response=True (modern connections) और stateless_http=True (legacy connections) cancellation को बंद कर देते हैं।

progress और cancellation चलते हुए tool और उसके caller के बीच की बात हैं। tool जो lines आपके लिए, यानी server चलाने वाले व्यक्ति के लिए, log करता है, वे एक अलग channel हैं: Logging।