+
    lHàjr>  ã                   óš  a€ RC t%0 t R t^ RIt^ RIt^ RIt^ RIt^ RIHtHt ^ RI	H
t
 ^ RIHt ]P                  ! R4      tRD U Uu. uF#  w  r]P                  V ]P                   4      V3NK%  	  upp tR R ltRR	R
/ /tR tREtRR/R ltR R ltR R ltRt^@t^t]! 4       t] ^ k R R ltR R ltRR/ R3RRRRRRR//R.3R R!/ R3R"R#R$RRRR%/R&RR	RR'R
/ R(R)//R$.3R*R+/ R3R,R-R$RRRR./R&RR	RR/R
/ R(R)/R0RRRR1/R2RRRR3/R4RRRR5//R$.3R6R7R$RRRR8/R&RR	RR9R
/ R(R)//R$.33t R: R; lt!R< R= lt"R> R? lt#RR@RR@R RAR"RAR*RBR,RBR6RB/t$R# u upp i )FzÈMCP tool schema conversion and naming: JSON-schema normalisation for provider
compatibility, mcp__server__tool naming, utility-tool schemas, include/exclude filters and
description injection scanning.N)ÚAnyÚList)Ústrip_unicode_tags)Ú	mcp_fieldztools.mcp_toolc          	      ó^   € V ^8„  d   QhR\         R\         R\         R\        \         ,          /# )é   Úserver_nameÚ	tool_nameÚdescriptionÚreturn)ÚstrÚlist)Úformats   "Ú:/home/ubuntu/.hermes/hermes-agent/tools/mcp_tool_schema.pyÚ__annotate__r       s/   € ÷ 	ñ 	¤sð 	´sð 	Ìð 	ÔQUÔVYÕQZñ 	ó    c                óè   € V'       g   . # \          UUu. uF   w  r4VP                  V4      '       g   K  VNK"  	  pppV'       d(   \        P                  RWRP	                  V4      V4       V# u uppi )zzScan a tool description for injection patterns; returns finding strings (empty =
clean) and logs a warning when any match.uU   MCP server '%s' tool '%s': suspicious description content â€” %s. Description: %.200sz; )Ú_MCP_INJECTION_PATTERNSÚsearchÚloggerÚwarningÚjoin)r   r	   r
   ÚpatternÚreasonÚfindingss   &&&   r   Ú_scan_mcp_descriptionr       s`   € ÷ Øˆ	Ý.EÔeÑ.E™?˜7ÈÏÉÐXc×Id—�Ñ.E€HÑeßÜ�‰ÐnØ"¨t¯y©y¸Ó/BÀKô	Qà€Oùó	 fs
   ”A.´A.ÚtypeÚobjectÚ
propertiesc           	     óZ  € \        V \        4      '       d   V  Uu. uF  p\        V4      NK  	  up# \        V \        4      '       g   V # / pV P	                  4        Fj  w  r4VR9   dI   \        V\        4      '       d3   VP	                  4        UUu/ uF  w  rVV\        V4      bK  	  uppW#&   KT  \        V4      Y#R8X  d   RMT&   Kl  	  VP                  R4      p\        V\        4      '       d0   VP                  R4      '       d   RV\        R4      R ,           VR&   V# u upi u uppi )u_  Promote legacy ``definitions`` to ``$defs`` (Moonshot rejects the draft-07 form) â€” ONLY
where it is a JSON Schema meta-keyword, never as a property NAME inside
``properties``/``patternProperties``: a parameter legitimately named ``definitions``
rewritten to ``$defs`` would 400 the whole tool array (Anthropic/OpenAI forbid ``$`` in
property names).Údefinitionsú$defsz$refz#/definitions/z#/$defs/N)r   ÚpatternProperties)	Ú
isinstancer   Ú_rewrite_local_refsÚdictÚitemsÚgetr   Ú
startswithÚlen)ÚnodeÚitemÚ
normalizedÚkeyÚvalueÚnameÚschemaÚrefs   &       r   r$   r$   /   s	  € ô �$œ×ÒÙ6:Ó;±d¨dÔ# DÖ)±dÑ;Ð;Ü�dœD×!Ò!ØˆØ€JØ—j‘j–l‰
ˆØÐ5Ô5¼*ÀUÌD×:QÒ:QØUZ×U`ÑU`ÔUbÔcÑUbÁ\ÀT˜tÔ%8¸Ó%@Ò@ÑUbÒcˆJ‹OäCVÐW\ÓC]ˆJ¨Ô"6‘w¸CÓ@ñ	 #ð
 �.‰.˜Ó
 €CÜ�#”s×Ò §¡Ð/?× @Ò @Ø'¨#¬cÐ2BÓ.CÐ.DÐ*EÕEˆ
�6ÑØÐùò <ùó ds   ›D"ÂD'Ú_object_rootFc          	     ó   € \        V \        4      '       d   V  Uu. uF  p\        V4      NK  	  up# \        V \        4      '       g   V # / pV P	                  4        Fe  w  rEV\
        9   dI   \        V\        4      '       d3   VP	                  4        UUu/ uF  w  rgV\        V4      bK  	  uppW4&   KX  \        V4      W4&   Kg  	  V'       g   RV9   g   RV 9   dä   VP                  R4      '       g   RV9   g   RV9   d   RVR&   VP                  R4      R8X  d¤   \        VP                  R4      \        4      '       g   / VR&   VP                  R4      pVP                  R4      ;'       g    / p	\        V\        4      '       d3   V U
u. uF%  p
\        V
\        4      '       g   K  W©9   g   K#  V
NK'  	  up
M. VR&   V# u upi u uppi u up
i )u   Recursively fill a missing object ``type``, ensure ``properties`` (so ``required``
can't dangle) and prune ``required`` to names present in ``properties`` (Gemini 400s
otherwise).

A dict carrying ``required`` but declaring no ``properties`` and no ``type`` is NOT an
object declaration â€” it is a *constraint fragment*, the JSON Schema idiom for "at least
one of these keys must be present" (``allOf``/``oneOf``/``anyOf``/``if`` branches).
Synthesising ``properties: {}`` for it prunes every name out of ``required``, so sibling
branches collapse into identical always-true schemas; the enclosing ``oneOf`` then has
two matches and can never be satisfied, making the tool permanently un-dispatchable while
the server-side tool itself is fine. Only the parameters-schema ROOT still gets the
dangling-``required`` repair (``_object_root``), because that is the single node handed
to providers as the function's argument object.
r   r   Úrequiredr   )r#   r   Ú_repair_object_shaper%   r&   Ú_SCHEMA_MAP_KEYSr'   r   )r*   r2   r+   Úrepairedr-   r.   r/   r0   r4   ÚpropsÚrs   &$         r   r5   r5   J   s�  € ô �$œ×ÒÙ7;Ó<±t¨tÔ$ TÖ*±tÑ<Ð<Ü�dœD×!Ò!ØˆØ€HØ—j‘j–l‰
ˆØÔ"Ô"¤z°%¼×'>Ò'>ð UZ×T_ÑT_ÔTaÔbÑTaÁLÀD˜TÔ#7¸Ó#?Ò?ÑTaÒbˆH‹Mä0°Ó7ˆH‹Mñ #÷ �| xÔ/°6¸T´>Ø�|‰|˜F×#Ò#¨¸Ô)AÀZÐS[ÔE[Ø'ˆH�VÑØ�<‰<˜Ó 8Ô+Ü˜hŸl™l¨<Ó8¼$×?Ò?Ø)+�˜Ñ&ð  —|‘| JÓ/ˆHØ—L‘L Ó.×4Ð4°"ˆEä'1°(¼D×'AÒ'Añ 19Ó$^±¨1¼JÀqÌ#×<N¤QÐSTÑS]§Q Q±Ò$^ØGIð �ZÑ à€Oùò3 =ùó cùò %_s   ›G ÂGÆGÆ(GÆ0Gc                ó>   € V ^8„  d   QhR\         R,          R\         /# )r   r0   Nr   )r%   )r   s   "r   r   r   w   s   € ÷ ñ ¬¨t­ð ¼ñ r   c                ó,  € V '       g   \        \        4      # ^ RIHpHp \        V 4      pV! VRR7      pV! V4      p\        VRR7      p\        V\         4      '       g   \        \        4      # VP                  R4      R8X  d   RV9  d	   / VCR/ /CpV# )aã  Normalize MCP input schemas so one form is valid on OpenAI, Anthropic, Gemini and
Moonshot. Order matters: ``definitions`` -> ``$defs``; nullable ``anyOf`` unions collapsed
to the non-null branch (Anthropic rejects nullable branches; optionality lives in the
parent's ``required``; the ``nullable: true`` hint is kept so runtime coercion can map a
model-emitted ``"null"`` string to ``None``); same-typed const unions -> enum (AFTER the
nullable strip); then object-shape repair.

* Missing or ``null`` ``type`` on an object-shaped node is coerced to ``"object"`` (some servers omit
it). See PR #4897. * When an ``object`` node lacks ``properties``, an empty ``properties`` dict is added
so ``required`` entries don't dangle. * ``required`` arrays are pruned to only names that exist in
``properties``; otherwise Google AI Studio / Gemini 400s with ``property is not defined``. See PR #4651.
* MCP/Pydantic optional fields commonly arrive as ``anyOf: [{...}, {"type": "null"}], default: null``.
)Úcollapse_const_unionsÚstrip_nullable_unionsT)Úkeep_nullable_hint)r2   r   r   r   )	r%   Ú_EMPTY_OBJECT_SCHEMAÚtools.schema_sanitizerr<   r=   r$   r5   r#   r'   )r0   r<   r=   r,   s   &   r   Ú_normalize_mcp_input_schemarA   w   sŠ   € ÷ ÜÔ(Ó)Ð)ßSÜ$ VÓ,€JÙ& zÀdÔK€JÙ& zÓ2€JÜ% j¸tÔD€JÜ�j¤$×'Ò'ÜÔ(Ó)Ð)Ø‡~�~�fÓ Ô)¨lÀ*Ô.LØ5˜
Ð5 L°"Ñ5ˆ
ØÐr   c                ó0   € V ^8„  d   QhR\         R\         /# )r   r.   r   ©r   )r   s   "r   r   r   “   s   € ÷ ;ñ ;¤sð ;¬sñ ;r   c                óX   € \         P                  ! RR\        T ;'       g    R4      4      # )z�Replace every char outside ``[A-Za-z0-9_]`` with ``_`` (hyphens included, the
historical behavior) so generated names pass provider validation.z[^A-Za-z0-9_]Ú_Ú )ÚreÚsubr   )r.   s   &r   Úsanitize_mcp_name_componentrI   “   s#   € ô �6Š6Ð" C¬¨U¯[¨[°bÓ)9Ó:Ð:r   Úmcp__c                ó<   € V ^8„  d   QhR\         R\         R\         /# )r   r   r	   r   rC   )r   s   "r   r   r   ¬   s&   € ÷ Hñ H¬ð H¼ð HÄñ Hr   c                ó¸  € \          \        V 4       R\        V4       2p\        V4      \        8:  d   V# R\        P
                  ! VP                  R4      4      P                  4       R\         ,           pV\        9  d;   \        P                  V4       \        P                  RV\        V4      \        4       VR\        \        V4      ,
           V,           # )z�Registry/wire name: ``mcp__<sanitizedServer>__<sanitizedTool>``, clamped to 64 chars with a
stable hash suffix when the natural name is longer.Ú__rE   zutf-8NzoMCP tool name %r (%d chars) exceeds the %d-char provider limit; shortened to a deterministic hash-suffixed name)ÚMCP_TOOL_NAME_PREFIXrI   r)   Ú_MCP_TOOL_NAME_MAX_LENGTHÚhashlibÚsha256ÚencodeÚ	hexdigestÚ_MCP_TOOL_NAME_HASH_LENGTHÚ_clamped_names_warnedÚaddr   r   )r   r	   Ú	full_nameÚsuffixs   &&  r   Úmcp_prefixed_tool_namerY   ¬   s¾   € ô (Ð(Ô)DÀ[Ó)QÐ(RÐRTÔUpÐqzÓU{ÐT|Ð}€IÜ
ˆ9ƒ~Ô2Ô2ØÐØ”7—>’> )×"2Ñ"2°7Ó";Ó<×FÑFÓHÐIdÔJdÐeÕe€FØÔ-Ô-Ü×!Ñ! )Ô,Ü�‰ð :Ø;DÄcÈ)ÃnÔVoô	qàÐ=Ô/´#°f³+Õ=Ð>ÀÕGÐGr   c                ó0   € V ^8„  d   QhR\         R\        /# ©r   r   r   )r   r%   )r   s   "r   r   r   º   s   € ÷ ñ ¤Sð ´tñ r   c                óº   € R\        WP                  4      R\        VP                  ;'       g    RVP                   RV  24      R\	        \        VRR4      4      /# )z|Convert an MCP ``Tool`` (``.input_schema``, or ``.inputSchema`` before mcp 2.0) to a
``registry.register(schema=...)`` dict.r/   r
   z	MCP tool z from Ú
parametersÚinput_schemaÚinputSchema)rY   r/   r   r
   rA   r   )r   Úmcp_tools   &&r   Ú_convert_mcp_schemara   º   s_   € ð 	Ô& {·M±MÓBØÔ)¨(×*>Ñ*>×*pÐ*pÀIÈhÏmÉmÈ_Ð\bÐcnÐboÐBpÓqØÔ1´)¸HÀnÐVcÓ2dÓeðð r   Úlist_resourcesz3List available resources from MCP server '{server}'Úread_resourcez1Read a resource by URI from MCP server '{server}'ÚuriÚstringr
   zURI of the resource to readÚlist_promptsz1List available prompts from MCP server '{server}'Ú
get_promptz/Get a prompt by name from MCP server '{server}'r/   zName of the prompt to retrieveÚ	argumentsz(Optional arguments to pass to the promptÚadditionalPropertiesTÚlist_event_typeszbList the event types MCP server '{server}' can notify about, and your active subscriptions to themÚsubscribe_eventzœSubscribe to an event from MCP server '{server}': each occurrence starts a new agent run with your instructions and delivers its result to the chosen targetz%Event type name from list_event_typesz7Subscription arguments matching the event's inputSchemaÚinstructionsz>What to do each time the event arrives (up to 2000 characters)Údeliverz@Where each run's result goes: log, telegram, discord, slack, ...Údeliver_chat_idz(Optional chat id on the deliver platformÚunsubscribe_eventz<Cancel a subscription to an event from MCP server '{server}'zEvent type namez1The same arguments the subscription was made withc                óF   € V ^8„  d   QhR\         R\        \        ,          /# r[   )r   r   r%   )r   s   "r   r   r   ñ   s   € ÷ ñ ¬ð ´´Tµ
ñ r   c                ó&  € . p\          F~  w  r#rERRRVP                  4        UUu/ uF  w  rgV\        V4      bK  	  upp/pVe   \        V4      VR&   VP	                  RR\        W4      RVP                  V R7      R	V/R
V/4       K€  	  V# u uppi )zQSchemas for the resource/prompt utility tools as ``{schema, handler_key}`` dicts.r   r   r   r4   r0   r/   r
   )Úserverr]   Úhandler_key)Ú_UTILITY_TOOL_SPECSr&   r%   r   ÚappendrY   r   )	r   Úoutrs   r
   r   r4   ÚkÚvr]   s	   &        r   Ú_build_utility_schemasry   ñ   s­   € à
€Cß:MÑ6ˆ *Ø˜h¨Èj×N^ÑN^ÔN`Ô6aÑN`ÁdÀa°q¼$¸q»'²zÑN`Ò6aÐbˆ
ØÒÜ%)¨(£^ˆJ�zÑ"Ø�
‰
ØØÔ.¨{ÓHØ˜{×1Ñ1¸Ð1ÓEØ˜jð*ð ˜;ð(ö 	)ñ	 ;Nð €Jùó 7bs   ¥Bc                óR   € V ^8„  d   QhR\         R\        R\        \        ,          /# )r   r.   Úlabelr   )r   r   Úset)r   s   "r   r   r     s%   € ÷ 	ñ 	¤#ð 	¬cð 	´c¼#µhñ 	r   c                ó  € V f   \        4       # \        V \        4      '       d   V 0# \        V \        \        \         34      '       d   V  Uu0 uF  p\        V4      kK  	  up# \
        P                  RW4       \        4       # u upi )zJNormalize include/exclude config to a set of exact names or fnmatch globs.z>MCP config %s must be a string or list of strings; ignoring %r)r|   r#   r   r   Útupler   r   )r.   r{   r+   s   && r   Ú_normalize_name_filterr     sk   € à‚}Ü‹uˆÜ�%œ×ÒØˆwˆÜ�%œ$¤¤sÐ+×,Ò,Ù&+Ó,¡e˜d”�D–	¡eÑ,Ð,Ü
‡N�NÐSÐUZÔbÜ‹5€Lùò -s   ÁBc                óR   € V ^8„  d   QhR\         R\        \         ,          R\        /# )r   r	   Úpatternsr   )r   r|   Úbool)r   s   "r   r   r     s*   € ÷ hñ h¤3ð h´#´cµ(ð h¼tñ hr   c                óž   a € V'       g   R# S V9   d   R# \         ;QJ d    V 3R lV 4       F  '       g   K   R# 	  R# ! V 3R lV 4       4      # )zØTrue if ``tool_name`` matches any entry: exact names literally, entries with
``*``/``?``/``[`` as case-sensitive globs (same semantics as ``approvals.deny``). Exact
membership is checked first so big lists stay O(1).FTc              3   ó€   <"  € T F3  pR V9   g   RV9   g
   RV9   g   K  \         P                  ! SV4      x € K5  	  R# 5i)Ú*Ú?Ú[N)ÚfnmatchÚfnmatchcase)Ú.0Úpr	   s   & €r   Ú	<genexpr>Ú&matches_name_filter.<locals>.<genexpr>  s<   øé € Ðg¹(°QÀcÈQÄhÐRUÐYZÔRZÐ^aÐefÑ^fÔ0Œw×"Ò" 9¨a×0Ð0»(ùs   ƒ>Ÿ>)Úany)r	   r�   s   f&r   Úmatches_name_filterr�     s?   ø€ ÷ ÙØ�HÔÙß‹3Ôg¹(Óg�3Œ3ÐgŠ3Ðgˆ3Ôg¹(ÓgÓgÐgr   Ú	resourcesÚpromptsÚeventsc                óV   € V ^8„  d   Qh/ ^ \         9   d   \        \        ,          ;R&   # )r   rU   )Ú__conditional_annotations__r|   r   )r   s   "r   r   r      s$   € ÷ #ñ #÷P (Ò '”sœ3•xÑ 'òQ#r   )
)z)ignore\s+(all\s+)?previous\s+instructionsz8prompt override attempt ('ignore previous instructions'))zyou\s+are\s+now\s+az.identity override attempt ('you are now a...'))z1your\s+new\s+(task|role|instructions?)\s+(is|are)ztask override attempt)zsystem\s*:\s*zsystem prompt injection attempt)z <\s*(system|human|assistant)\s*>zrole tag injection attempt)z'do\s+not\s+(tell|inform|mention|reveal)zconcealment instruction)z(curl|wget|fetch)\s+https?://znetwork command in description)zbase64\.(b64decode|decodebytes)zbase64 decode reference)zexec\s*\(|eval\s*\(zcode execution reference)z&import\s+(subprocess|os|shutil|socket)zdangerous import reference)r   r"   r!   r    ÚdependentSchemas)&r”   Ú__doc__ÚloggingrP   rˆ   rG   Útypingr   r   Útools.ansi_stripr   Útools.mcp_tool_commonr   Ú	getLoggerr   ÚcompileÚ
IGNORECASEr   r   r?   r$   r6   r5   rA   rI   rN   rO   rT   r|   rU   rY   ra   rt   ry   r   r�   Ú_UTILITY_CAPABILITY_ATTRSr   )r   r   r”   s   00@r   Ú<module>rŸ      s‚  øðö#ó Û Û Û 	ß Ý /Ý +à	×	Ò	Ð+Ó	,€ñ
SôTñ
S‰ˆð ‡Z�Z�˜Ÿ™Ó'¨Ó0ñ
SòTÐ õ	ð  ¨,¸Ð;Ð òð0 cÐ ð)¨uô )õZõ8;ð Ð ð Ð ØÐ Ù"%£%Ð Ó 'õHõð ÐLÈbÐRVÐWØÐIØˆf�h Ð/LÐMÐNÐQVÐPWðYàÐHÈ"ÈdÐSØÐDà	�&˜( MÐ3SÐTØ	Ø�XØÐFØ˜2Ø# Tð	+ðð 
ˆðð ð Ø  $ð(àð Uð 
�&˜( MÐ3ZÐ[Ø	Ø�XØÐUØ˜2Ø# Tð	+ð
 
˜& (Ø'Ð)iðkà	�V˜XØ"Ð$fðhà	˜V X¨}Ð>hÐiðð 
ˆðð ÐXà	�&˜( MÐ3DÐEØ	Ø�XØÐOØ˜2Ø# Tð	+ðð 
ˆðð?'Ð õTõ 	õhð* �k ?°KØ�I˜|¨YØ˜Ð"3°XÐ?RÐT\ð^Ò ùóaTs   Á)E