xj+-dZddlmZddlmZmZmZmZddlm Z ddl m Z ddl m Z mZddlZddlZddlmZdd lmZdd lmZdd lmZmZmZmZmZmZe rdd lm Z gd Z!e dZ" dZ# edZ$Gdde%Z&Gdde%Z'GddZ(eegedfZ) GddZ*e dddddd ddZ+y)aClient-side `subscriptions/listen` driver (2026-07-28, SEP-2575). `listen()` opens the stream as an async context manager: entering waits for the server's acknowledgment, iteration yields typed change events, a graceful server close ends the loop, and an abrupt drop raises `SubscriptionLost`. There is no replay and no automatic re-listen: a client that re-opens a subscription refetches what it depends on. ) annotations) AsyncIterator AwaitableCallableSequence)asynccontextmanager)count) TYPE_CHECKINGLiteralN)MODERN_PROTOCOL_VERSIONS) CallOptions)MCPError)PromptsListChangedResourcesListChangedResourceUpdated ServerEventToolsListChanged event_matches) ClientSession) ListenNotSupportedErrorOnEventrrrr SubscriptionSubscriptionLostrlisteni)gracefullostlocalc$eZdZdZdfd ZxZS)rz8`subscriptions/listen` requires a 2026-07-28 connection.c:||_t| d|dy)Nz:subscriptions/listen is not available at protocol version z; it requires 2026-07-28. On earlier versions use subscribe_resource() and the change notifications delivered through message_handler.)negotiated_versionsuper__init__)selfr! __class__s l/mnt/ssd/data/Dropbox/adrian/sandbox/mcp-query/venv/lib/python3.12/site-packages/mcp/client/subscriptions.pyr#z ListenNotSupportedError.__init__>s,"4 HI[H^_' ' )r!z str | NonereturnNone)__name__ __module__ __qualname____doc__r# __classcell__)r%s@r&rr;sB  r'rceZdZdZy)rzLThe stream ended without the server's graceful close; re-listen and refetch.N)r*r+r,r-r'r&rrGsVr'rcBeZdZdZd dZd dZd dZd d dZddZd dZ y) ListenRoutezfPackage-internal demux state for one listen stream, fed synchronously in receive order by the session.cd|_tj|_d|_d|_t |_i|_tj|_ yN) honoredanyioEventackederrorend frozenset _honored_uris_pending_waker$s r&r#zListenRoute.__init__NsB8< [[] &* ,0-6[13 [[] r'c|jjs@||_t|jxsd|_|jj yy)z3Record the acknowledged filter; the first ack wins.r0N)r8is_setr5r;resource_subscriptionsr<set)r$r5s r& set_ackedzListenRoute.set_ackedWsDzz  ""DL!*7+I+I+OR!PD  JJNN #r'c |j |jyt|trt |j }n!t |j|j |}|r||jvryt|jtk\r4|jdttjdtdyd|j|<|jjy)zQueue an event within the honored filter, deduplicated against the backlog. Any `ResourceUpdated` is admitted once URI subscriptions were honored at all: the spec allows the stamped URI to be a sub-resource of a subscribed one. Nrzsubscription backlog exceeded z) unconsumed events; re-listen and refetchr9)r:r5 isinstancerboolr<rr=len_MAX_PENDING_EVENTSsettlertypesINTERNAL_ERRORr>rC)r$eventadmitteds r&deliverzListenRoute.deliver^s 88 4<<#7  e_ -D../H$T\\43E3EuMH5DMM1  t}} !4 4 KK((45H4IIrs   # e r'Nc|jC||_||_|jj|jjyy)zFRecord the stream's end; the first reason wins and wakes both waiters.N)r:r9r8rCr>)r$r:r9s r&rKzListenRoute.settlexs; 88 DHDJ JJNN  JJNN  r'cFK |j}|jdk(r |jS|jrtt |jS|j |jS|j d{t j|_7w)zPeek the next pending event, or the stream's end once the backlog drains. A "local" end short-circuits the backlog; the other endings drain it first, so a graceful close never swallows events that preceded it. rN)r>r:r=nextiterwaitr6r7)r$wakes r& next_eventzListenRoute.next_events} ::Dxx7"xx}}D/00xx#xx))+  DJ sA>B!BB!c<|jj|dy)z'Remove a peeked event from the backlog.N)r=pop)r$rNs r&consumezListenRoute.consumes %&r'r(r))r5types.SubscriptionFilterr(r))rNrr(r)r4)r:_SubscriptionEndr9zMCPError | Noner(r))r(zServerEvent | _SubscriptionEnd) r*r+r,r-r#rDrPrKrWrZr0r'r&r2r2Ks#p#4'$'r'r2c:eZdZdZ d ddZddZd dZy) rzOne open `subscriptions/listen` stream: an async iterator of typed events. Produced by `listen()` / `Client.listen()`, not constructed directly. Nc>||_||_||_ ||_yr4)_route _on_eventsubscription_idr5)r$routerbr5on_events r&r#zSubscription.__init__s' !.S Nr'c|Sr4r0r?s r& __aiter__zSubscription.__aiter__s r'clK|jjd{}t|tr9|dk(r.t d|j d|jj t|j|j|d{|jj||S77#w)zYield the next change event; the loop ends when the stream does. Raises: SubscriptionLost: the stream dropped without the server's graceful close. Nr subscription zA ended without the server's graceful close; re-listen and refetch) r`rWrGstrrrbr9StopAsyncIterationrarZ)r$outcomes r& __anext__zSubscription.__anext__s  ..00 gs #& &#D$8$8#;<--{{(()% $ >> %..) ) ) G$1 *s"B4B0A-B4B2"B42B4r4)rcr2rbztypes.RequestIdr5r\rdOnEvent | None)r(r)r(r)r*r+r,r-r#rfrlr0r'r&rrsF$( O O) O* O ! Or'rFr0)tools_list_changedprompts_list_changedresources_list_changedrBrdc  Kjtvrtjt|tr t dt jt jt j|xsd|xsd|xsdt|xsd}j}| tddtt |jdd d  d i j! t#j$ d fd }j'  |j)|t#j*j,5 j.j1d{ddd j2' j4 j4t7d dt9 j2| j;d j=j? y7#1swYxYw# j;d j=j? wxYww)aOpen one `subscriptions/listen` stream on `session` (2026-07-28 only). Entering sends the request and returns once the server's acknowledgment arrives; exiting ends the subscription. `on_event` is awaited before each event is returned - the seam `Client.listen` uses to finish cache eviction before the consumer can refetch. Raises: ListenNotSupportedError: negotiated version predates 2026-07-28. MCPError: the server rejected the request, or the connection failed pre-ack. SubscriptionLost: the stream ended before it was acknowledged. TimeoutError: the session's read timeout elapsed before the acknowledgment. zBresource_subscriptions takes a sequence of URIs, not a bare stringN)rnrorprB) notifications)paramsz$listen() requires an entered sessionzlisten-Tjson)by_aliasmode exclude_none request_idc 6K5 jjdjdd{jtjj ddddy7A#t$r%}j d|Yd}~dddyd}~wt $rW}j j dttjt|Yd}~dddyd}~wwxYw#1swYyxYww)NmethodrsrrFr) _dispatchersend_raw_requestgetrrK ValueError_unregister_listen_routerLrMrirDSubscriptionFilter)r9data driver_scopeoptsrxrcsessions r&drivezlisten..drives  % ))::NDHHX$6 OOE446 7 LL $# % %  V5 1 % % 00< V8E4H4H#e*+U V % %  % %ssDD 2A>A<A>4D 3 D<A>> D B'D  D' D 3AD8D < DD  D  DDrhz! ended before it was acknowledgedrr[) protocol_versionr rrGri TypeErrorrLSubscriptionsListenRequest SubscriptionsListenRequestParamsrlist _task_group RuntimeErrorrS _listen_ids model_dump_stampr6 CancelScope_register_listen_route start_soon fail_after_session_read_timeout_secondsr8rUr5r9rrrKcancelr)rrnrorprBrdrequest task_grouprrrrrxrcs` @@@@@r&rrs .'??%g&>&>??(#.\]]..5522#5#=%9%AT'='E'+,B'C'Kt   G$$JABB$+D,=+>"?J   t&t  LD%z2D NN4$$&L%%,  * *: 6E 5e$   gCC D %++""$ $ $ % == {{&kk!"]:.@a#bc c5*emmXFF W((4 % % %  W((4sID"I +0HH 9H:H >AH3I H  HH4I  I )rrrnrHrorHrprHrBz Sequence[str]rdrmr(zAsyncIterator[Subscription]),r- __future__rcollections.abcrrrr contextlibr itertoolsr typingr r r6 mcp_typesrLmcp_types.versionr mcp.shared.dispatcherr mcp.shared.exceptionsrmcp.shared.subscriptionsrrrrrrmcp.client.sessionr__all__rrJr]rrrr2rrrr0r'r&rs+#HH*) 6-*0 Ah e867  l  W|WI'I'X K=)D/1 2[**Z %!&#(,.#Q5 Q5Q5 Q5 ! Q5 * Q5Q5!Q5Q5r'