xj}JUdZddlmZddlZddlZddlmZmZmZddl m Z ddl m Z m Z mZddlmZmZddlmZmZmZmZddlZddlZdd lmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-dd lm.Z/dd l0m1Z1m2Z2m3Z3m4Z4dd l5m6Z6m7Z7dd l8m9Z9ddl:m;Z;ddlZ>ddl?m@Z@mAZAmBZBmCZCddlDmEZEddlFmGZGddlHmIZIddlJmKZKmLZLddlMmNZNmOZOmPZPmQZQmRZRddlSmTZTmUZUddlVmWZWmXZXddlYmZZZm[Z[ddl\m]Z]m^Z^m_Z_ddl`maZaerddlbmcZcgdZdejefZge9deZheidhZjd ekd!<d"Zld#ekd$< d?d%Zmd@d&ZndAd'Zo dBd(Zpe Gd)d*eehZqdejd+ dCd,Zsddd-d. dDd/ZtdEd0ZudFd1ZvdGd2Zwe Gd3d4Zxddd-d. dDd5Zyd6Zzd7ekd8< dHd9Z{e dId:Z| dDd;Z} dJd<Z~ dKd=ZdLd>Zy)May`ServerRunner` - the per-connection handler kernel. `ServerRunner` bridges the dispatch layer (`on_request` / `on_notify`, untyped dicts) and the user's handler layer (typed `Context`, typed params). It is a pure kernel: it holds a pre-populated `Connection` and reads `connection.protocol_version` / `connection.outbound` as facts. Driving a dispatcher loop and tearing down the connection live in the free-function drivers (`serve_connection`, `serve_loop`, `serve_dual_era_loop`, `serve_one`); the entry constructs the `Connection`, the driver tears it down. `ServerRunner` holds a `Server` directly - `Server` is the registry. ) annotationsN) AsyncIterator AwaitableMapping)asynccontextmanager)KW_ONLY dataclassreplace)cached_propertypartial) TYPE_CHECKINGAnyGenericcast)CLIENT_CAPABILITIES_META_KEYCLIENT_INFO_META_KEYCORE_RESULT_TYPESINTERNAL_ERRORINVALID_PARAMSINVALID_REQUESTMETHOD_NOT_FOUNDPROTOCOL_VERSION_META_KEYSERVER_INFO_META_KEYUNSUPPORTED_PROTOCOL_VERSIONCacheableResult ErrorDataImplementationInitializeRequestParamsInitializeResultJSONRPCRequest RequestId RequestParamsRequestParamsMeta#UnsupportedProtocolVersionErrorData)methods)HANDSHAKE_PROTOCOL_VERSIONSLATEST_HANDSHAKE_VERSIONLATEST_MODERN_VERSIONMODERN_PROTOCOL_VERSIONS) BaseModelValidationError)TypeVar)apply_cache_hint) ConnectionNotifyOnlyOutbound)CallNext HandlerResultServerMiddlewareServerRequestContext)InitializationOptions) ServerSession)ContextReceiveStream) ReadStream WriteStream) CallOptionsDispatchContext DispatcherOnNotify OnRequest)MCPErrorNoBackChannelError)InboundLadderRejectionclassify_inbound_request)JSONRPCDispatcherhandler_exception_to_error_data)MessageMetadataServerMessageMetadataSessionMessage)TransportContext)Server) r0r2 ServerRunneraclose_shieldedmodern_on_requestserve_connectionserve_dual_era_loop serve_loop serve_one LifespanT)defaultpingzfrozenset[str] _INIT_EXEMPTfloat_EXIT_STACK_CLOSE_TIMEOUTcr|rd|vry tj|djS#t$rYywxYw)z}Lift `_meta` from raw params; `None` when absent or malformed, so context construction is independent of params validity._metaNFby_name)r"model_validatemetar+)paramss e/mnt/ssd/data/Dropbox/adrian/sandbox/mcp-query/venv/lib/python3.12/site-packages/mcp/server/runner.py _extract_metar_csA WF*++FEBGGG s * 66cL|iSt|trtj|t|tr|j dddSt|t r&t tt ttf|Stdt|jd)NTjson)by_aliasmode exclude_nonezhandler returned z#; expected BaseModel, dict, or None) isinstancerr>from_error_datar* model_dumpdictrstrr TypeErrortype__name__)results r^ _dump_resultrnns ~ &)$&&v..&)$  $V$ OO&$Dc3h011 'V (=(='>>ab cccLKtjtd5} |jj d{dddjrt jdtyy74#t $rt jdYRwxYw#1swYWxYww)aUnwind ``connection.exit_stack`` under a shielded, bounded scope. Called from a driver's ``finally``: the shield lets per-connection cleanup callbacks run even when the driver itself is being cancelled, the `_EXIT_STACK_CLOSE_TIMEOUT` bound stops a hung callback wedging shutdown, and a raising callback is logged-and-swallowed so it never masks the driver's own exception. T)shieldNz$connection exit_stack cleanup raisedzQconnection exit_stack cleanup exceeded %s seconds; abandoning remaining callbacks) anyio move_on_afterrV exit_stackaclose Exceptionlogger exceptioncancelled_caughtwarning) connectionscopes r^rJrJs   6t DE E''..0 0 0E   _ %  1 E   C D EEEsIB$BA4A2A40B$2A44BBBBB!B$c|||S)zAdapt one middleware to the `CallNext` shape: bind `call_next`, take `ctx` at call time so a rewritten context flows down the chain.) middleware call_nextctxs r^_apply_middlewarers c9 %%roceZdZUdZded<ded<ded<ded <d Zd ed < edd ZeddZ ddZ ddZ ddZ ddZ ddZ ddZeddZd dZy )!rIzBPer-connection handler kernel. One instance per client connection.Server[LifespanT]serverr.r{rPlifespan_stater_NInitializationOptions | None init_optionsc|jSN) _on_requestselfs r^ on_requestzServerRunner.on_requestsroc|jSr) _on_notifyrs r^ on_notifyzServerRunner.on_notifys rocR Kt|}jj j|||| }d fd }j |}t ||d{}|dk(r2j |\j_j_|S7Aw)NcK|j|j}}|tjvr tj|||dk(r"j|j|Sjj|}|t td|jjs|tvrt tdd|j j#|in|d}|j%||d{}t'|t(rt j*|j||S#t $rt td|dwxYw7\w)NzMethod not foundcodemessagedata initializezInvalid request parametersFrY)methodr]_methodsSPEC_CLIENT_METHODSvalidate_client_requestKeyErrorr>r _serialize_handle_initializerget_request_handlerr{initialize_acceptedrSr params_typer[handlerrerrf)rrr]entry typed_paramsrmrversions r^_innerz(ServerRunner._on_request.._innersR!ZZFF 555m44VWfM %vw8O8OPV8WXX KK33F;E}$4>PW]^^??666;UN._innersN ZZFFBBB99&'6R44++//1__88 I6RKK88@E} =vF $00??fnZ`jo?p --\2 2 21 LL!@&'R&NN#A6J$# =vF  3se+E;DB E;!E3E;E9 E; E.E;0EE;EE;E63E;5E66E;z"notification handler for %r raised)rrrNone)r_r{rrrrvrwrx) rrrr]r\rrrrs ` @r^rzServerRunner._on_notifys V$//22  vvtWE 3>..v6 Ks)OO K   A6 J Ks<AB  A'A% A'$B %A''B B B  B ct|}t|jjD]}tt||}|S)a+Wrap `inner` in `Server.middleware`, outermost-first. Shared by `_on_request` and `_on_notify` so the same middleware chain observes every inbound message. The composed callable takes the `ctx` at call time, so a middleware can rewrite it for the rest of the chain. )reversedrrr r)rinnerrrs r^rz'ServerRunner._compose_server_middleware#s="4;;#9#9: @J,j$?D @ roc .|j}t|tr%|j}|j}|j } ndx}x}} t ||j|j|nd} t| |j|||j|||||  S)N) request_meta) sessionlifespan_contextrr] request_idr\rrequestclose_sse_streamclose_standalone_sse_stream) message_metadatarerErequest_contextrrr5r{rr3r) rrrr]r\rmdrrrrs r^rzServerRunner._make_context/s " " b/ 0((G!22 *,*H*H 'GK KG K&)D dooDOOLgDmqr#!00--(C  roc|jjj|x}]t|tr t ||}n@t|t r0tj|s|j|jd|}t|}|jd}|tvxst|t xs|tv}|tjvr|r tj |||}|tvr|jdd|d<|j-||S#t"$r)t$j'd|t)t*ddwxYw)aNShape a handler result into its wire form: the outbound counterpart of the inbound classification ladder. One pass owns the whole response envelope, in order: cache hints fill `ttlMs`/`cacheScope` the handler left unset, core-vocabulary spec-method results are validated and sieved by the per-version surface (a claimed extension `resultType` shape is the extension's to own), and 2026-era results get the `serverInfo` `_meta` stamp (spec #3002). Runs inside the middleware chain so the OpenTelemetry span observes a failing return shape (unsupported type, malformed spec result) as an error rather than closing on a request that the client sees fail - and so a middleware that short-circuits without `call_next` owns its result, envelope included. N)ttlMs cacheScope resultTypez)handler for %r returned an invalid resultz"Handler returned an invalid resultrrcomplete)r cache_hintsgetrerr-rris_input_requiredttl_msr|rnr)rirrserialize_server_resultr+rwrxr>r_stamp_server_info)rrrrmhintdumped result_type core_shapes r^rzServerRunner._serializeUsL KK++//7 7D D&/2)&$7FG,X5O5OPV5W#';;djjSFSf%jj. 3 3 0k3// 0//  X11 1j l!99&'6R . .6::l3K3S $.F< &&w77# l  !LfUN<`agkk  ls D""2Ec*|tvr|S|jd}|!t|jji|d<|St |t rDtd|}|jt#i|t|jji|d<|S)aFill the `serverInfo` `_meta` stamp on a 2026-era result (spec #3002). A handler-authored value wins; an explicit `null` reads as absent and is stamped over, mirroring the request-side `clientInfo` posture (a `null` is not a valid `Implementation`, so presence means a value). A non-mapping `_meta` is the handler's to own, and handshake-era results are never stamped. `result` is pipeline-owned (`_dump_result` copies dicts; the spec-method sieve re-dumps), but `_meta` may still be the handler's object, so the stamp replaces it rather than writing into it. `server_info_stamp` is a fresh dict per access, so the response never aliases server state. rXdict[str, Any])r)rrrserver_info_stamprerhr)rrrmraw_metar\s r^rzServerRunner._stamp_server_infos 2 2M::g&  3T[[5R5RSF7O  $ '((3Dxx,-5"_T"_+?A^A^"_w rocxtj|xsid}|j}|tvr|nt}||fS)z;Validate `initialize` params and pick the protocol version.FrY)rr[rr&r')r]init requested negotiateds r^rz"ServerRunner._negotiate_initializes@'55flER)) "+/J"JYPh Zroc j|j|\}}|j |jn|jj}t ||j t |j|j|j|j|j|j|jS)zDBuild the `initialize` result; state commits later in `_on_request`.)nametitle descriptionr website_urlicons)r capabilities server_info instructions)rrrcreate_initialization_optionsrrr server_namerrserver_versionrrr)rr]rroptss r^rzServerRunner._handle_initializes226: :$($5$5$At  t{{GpGpGr'**&%%jj ,,++ ,,jj **  ro)rr=)rr<r!DispatchContext[TransportContext]rrir]Mapping[str, Any] | Nonerrrrrrir]rrr)rr0rr0) rrrrir]rr\RequestParamsMeta | Nonerrirr)rrirrirmr1rr)rrirmrrr)r]rrz#tuple[InitializeRequestParams, str])r]rrr)rl __module__ __qualname____doc____annotations__rr rrrrrrrr staticmethodrrr~ror^rIrIsL J15L.5[  A/AA) A  AF/K//K/K) /K  /Kb $ /$ $ ) $ ' $  $  .$ L58n0   rorI)r task_statuscKt||||} |j|j|j|d{t |d{y77#t |d{7wxYww)a.Drive ``dispatcher`` until the underlying channel closes. The loop-mode driver: builds the kernel, hands `on_request`/`on_notify` to `dispatcher.run()`, and tears down `connection.exit_stack` (shielded) on the way out. The entry constructs the `Connection`; this only consumes it. r)rN)rIrunrrrJ)r dispatcherr{rrrrunners r^rLrLsg &*n< XF*nnV..0@0@knZZZj))) [)oj)))sJA4+AAAA4AA4AA4A1*A-+A11A4F) session_idrraise_exceptionscKt|||tdh}tj||}t |||||d{y7w)aDrive ``server`` in handshake-only loop mode over a stream pair until the channel closes. Builds the loop-mode `JSONRPCDispatcher` + `Connection` and hands them to `serve_connection`. The streamable-HTTP manager (which owns its lifespan and serves the modern era on the single-exchange entry instead) calls this; `Server.run` drives `serve_dual_era_loop`, which extends the same dispatcher recipe (notably the `inline_methods={"initialize"}` rule) with era routing. rraise_handler_exceptionsinline_methodsr)r{rrN)rB frozensetr.for_looprL) r read_stream write_streamrrrrrr{s r^rNrNsZ&7H!1!,07J$$ZJGJ  z._k sAAA Ac^|sy|jd}t|txrt|vS)aWhether `params._meta` carries the reserved protocol-version key. The `io.modelcontextprotocol/protocolVersion` key exists only in 2026-07-28+ envelopes and its prefix is spec-reserved, so legacy traffic never mints it (a bare `_meta` is not evidence - legacy requests carry `progressToken` there). The version key alone is the signal, not the full required pair, so a half-built envelope still routes modern and gets the classifier's INVALID_PARAMS naming the missing key. FrX)rrerr)r]r\s r^_has_modern_enveloper s0  ::g D dG $ J)Bd)JJroc|xsijd}t|tr*tt t |j dSdt t iS)zError data for an `initialize` arriving on a modern-locked connection. The typed -32022 payload when the client's proposed version is parseable; otherwise just the supported list (the point is naming what we serve). protocolVersion) supportedrra)rcr)rrerir$listr)rg)r]rs r^_initialize_after_modern_datarsZ 2""#45I)S!234  *&* ! " 67 88roclt|}||StjdttdS)aMap a modern request's handler exception to its wire `ErrorData`. The exception-to-wire fact shared by the modern entries (the single-exchange HTTP path and the dual-era stream loop), so an identical modern request fails identically on every transport: `MCPError` and `ValidationError` map via the shared `handler_exception_to_error_data` ladder; anything else is logged server-side and surfaced as a generic INTERNAL_ERROR so handler internals never reach the wire. zmodern request handler raisedzInternal server errorr)rCrwrxrr)excerrors r^modern_error_datars6 ,C 0E   45 .2I JJroceZdZUdZded<ed dZeddZeddZeddZ eddZ d dd Z ddd Z ddd Z y ) _NoServerRequestsDispatchContexta>Delegating `DispatchContext` that refuses server-initiated requests. Wraps the loop dispatcher's per-message context for modern-era dispatch: the modern protocol forbids server-initiated JSON-RPC requests, so `send_raw_request` refuses while notifications and progress still ride the duplex pipe. rrcd|jj}|jr t|dS|S)NF)can_send_request)r transportrr )rrs r^rz*_NoServerRequestsDispatchContext.transport3s. KK)) =F=W=Wwy59f]ffrocy)NFr~rs r^rz1_NoServerRequestsDispatchContext.can_send_request;sroc.|jjSr)rrrs r^rz+_NoServerRequestsDispatchContext.request_id?s{{%%%roc.|jjSr)rrrs r^rz1_NoServerRequestsDispatchContext.message_metadataC{{+++roc.|jjSr)rcancel_requestedrs r^rz1_NoServerRequestsDispatchContext.cancel_requestedGrroNc Kt|wr)r?rrr]rs r^send_raw_requestz1_NoServerRequestsDispatchContext.send_raw_requestKs !((s cZK|jj|||d{y7wr)rnotifyr!s r^r$z'_NoServerRequestsDispatchContext.notifySs"kk  666 !+)+cZK|jj|||d{y7wr)rprogress)rr'totalrs r^r'z)_NoServerRequestsDispatchContext.progressVs"kk""8UG<<dt+ #1)!-%5  &!!###'      & $l!!###sC"CB%CAB-B'B-7B)8B-< CB+C C"C C"%C'B-)B-+C-B?3B6 4B?;CC"CCCC"int_PRE_REQUEST_REPLAY_LIMITcLt|dd}||StjS)zTThe per-message sender context a context-aware stream carries, else the current one. last_contextN)getattr contextvars copy_context)streamrs r^_sender_contextr=s( &.$ /C/3A{'?'?'AArocKgd}tjttjt t zf\}t|}dfd } 23d{}t|t r't|jtr |j}n)ttk\rtjd|ijt!|f|tj$4d{}|j'|||f|j(j+dddd{j-d{j/|j/y76#tj"$rtjdYwxYw77r#1d{7swYxYw7q#j-d{7j/|j/wxYww)aTPeek at the client's first request without consuming it. Yields that request together with a stream that replays it - preceded by up to `_PRE_REQUEST_REPLAY_LIMIT` earlier frames - and relays the rest of `read_stream` behind it, sender contexts included. The request is `None` if the channel closes before one arrives. NcK4d{D]}j|d{ 23d{}jt|fd{.7U797-7 6n.#tj$rtj dYnwxYwdddd{7y#1d{7swYyxYww)N0read stream closed by transport; treating as EOF)sendr=rrClosedResourceErrorrwr)envelopeitemleadr replay_sends r^replay_then_relayz7_replay_from_opening_request..replay_then_relays Q Q  1!&&x000 1 Q"-QQ$%**OK,H$+OPPP  Q0QP#.,, Q OP Q  Q Q Q Q QsB?A B?B*A"B*A*A(A$A( A*A&A* B?"B*$A(&A*(A*)B**(BB*BB* B?#B&$B?*B<0B3 1B<8B?z5dropped a frame received before the first request: %rr@)rr)rrcreate_memory_object_streamtupler:ContextrFrvr6rerr lenr6rwrappendr=rBcreate_task_group start_soon cancel_scopecancelruclose) ropening_requestreplay_receiver2rGrDtgrErFs ` @@r^r.r.sJLD-1O"'"C"C k!!>I#==>##K$N3H Q M)  ddN3 4<"F%A?F%F&G >F1?G 3F55 G F3G H G %H >FF(F.+G -F..G 3G 5G;F> <GG H  H G#!&HH cR Kt|||tdh}tj||}t |||| d fd } |j | j d{t|d{y77#t|d{7wxYww)zBServe a 2025 handshake connection; enveloped requests are refused.rrrrcK|dk7rt|rttdj|||d{S7w)Nrzsthis connection serves the handshake protocol era; requests carrying the 2026-07-28 envelope are not accepted on itr)r r>rr)rrr]rs r^rz(_serve_legacy_stream..on_requestsL \ !&:6&B$S  &&tVV<<<rrrArer@rrrr. from_enveloper client_infoclient_capabilitiesrOrr+rvr) rrr]router{rrrrZrrs r^rz(_serve_modern_stream..on_requests \ !1q26:  )Ff)MN e3 4 EMM S S--  " "E$5$5u7P7P[c  ]"06%-  /*   ]%c*E EMM SY\ \  ]s<B"D%&C CC D%C D"";DD""D%c Ktjtdd}t|} |j t |||d{t |d{y77#t |d{7wxYww)NrY)r.r\r(rIrrrJ)rrr]r{ notify_runnerrrZrs r^rz'_serve_modern_stream..on_notify"sz --.CT4Zbc $VZH  .))*J4*PRXZ`a a a!*- - - b -/*- - -sL+BA+A'A+B!A)"B'A+)B+B:A=;BBNrr)rBr/r) rrr rrrrrrZs ` `` @r^r/r/st7H\.handleVs "!!'2.-- HH.0E F HH) * HH1 2   ,T 2  !)     sB B B Brr~)rrres`` r^rKrKIs/ / 9< F^  $ Mro)r]rrr)rmrrr)r{r.rr)rzServerMiddleware[Any]rr0rzServerRequestContext[Any, Any]rzAwaitable[HandlerResult])rrrzDispatcher[Any]r{r.rrPrrrzanyio.abc.TaskStatus[None]rr)rrr&ReadStream[SessionMessage | Exception]r WriteStream[SessionMessage]rrPrr+rrrr)rr)r]rrr))r]rrr)rrvrr)r<zReadStream[Any]rzcontextvars.Context)rrfrzSAsyncIterator[tuple[JSONRPCRequest | None, ReadStream[SessionMessage | Exception]]]) rrrrfr rgrrPrr)rr)rrrrrrir]rr{r.rrPrr)rrrrPrr=)r __future__rr:loggingcollections.abcrrr contextlibr dataclassesrr r functoolsr r typingr rrrrr anyio.abc mcp_typesrrrrrrrrrrrrrrrr r!r"r#r$r%rmcp_types.versionr&r'r(r)pydanticr*r+typing_extensionsr,mcp.server.cachingr-mcp.server.connectionr.r/mcp.server.contextr0r1r2r3mcp.server.modelsr4mcp.server.sessionr5mcp.shared._context_streamsr6mcp.shared._stream_protocolsr7r8mcp.shared.dispatcherr9r:r;r<r=mcp.shared.exceptionsr>r?mcp.shared.inboundr@rAmcp.shared.jsonrpc_dispatcherrBrCmcp.shared.messagerDrErFmcp.shared.transport_contextrGmcp.server.lowlevel.serverrH__all__ getLoggerrlrwrPrrSrrVr_rnrJrrITASK_STATUS_IGNOREDrLrNr rrrrMr6r=r.r0r/rOrKr~ror^rs #==*33.44 ,* 0%/@^^3,<@__>O\UU91    8 $ K -  )&2 n2#$5$d" *&%&2:&A_&& _ 79%_  _ P 26.3.G.G* ** *  * / *,* *:"15" 7.    / D K 9K" /=/= /=p"15",$ ,$7,$.,$  ,$  ,$/,$,$ ,$^"#3"@ B 474X44n#* #*7#*.#*  #*  #*/#*#* #*L90 90790.90  90  90 90x* * +* * % *  ***4ro