
    `gjt                    Z   U d Z ddlmZ ddlZddlZddlZddlmZmZ ddl	m
Z
 ddlmZmZmZmZ ddlZddlmZmZ ddlmZmZ dd	lmZmZmZmZ dd
lmZ dZdZ e G d d             Z!e G d d             Z"e G d d             Z#e G d d             Z$e G d d             Z%e G d d             Z& G d de'      Z(d5dZ)d6dZ*d7dZ+d8dZ,g Z-de.d <   d9d!Z/d:d"Z0d;d#Z1d<d$Z2d<d%Z3d5d&Z4d=d'Z5d>d(Z6d?d)Z7d@d*Z8	 	 	 	 	 	 dAd+Z9dBd,Z:dCd-Z;dDd.Z<	 	 	 	 	 	 dEd/Z=d0d1dFd2Z>d0d3dGd4Z?y)Hug  MCP catalog — curated, Nous-approved MCP servers shipped with the repo.

Mirrors the optional-skills/ pattern: each catalog entry lives under
``optional-mcps/<name>/manifest.yaml`` and ships disabled. Users discover
entries via ``hermes mcp catalog`` or the interactive ``hermes mcp picker``,
and install them with ``hermes mcp install <name>`` (or by toggling in the
picker, which flows them through any required env/OAuth setup).

Catalog policy:
- Entries are added only by merging a PR into hermes-agent. Presence in the
  ``optional-mcps/`` directory = Nous approval. No community tier, no trust
  signals beyond "it's in the catalog".
- Manifests pin transport details (commands, args, refs). Pins follow the
  same supply-chain rules as pyproject dependencies: exact versions for
  package launchers (``uvx pkg==X``, ``npx pkg@X``), full commit SHAs for
  git installs, and the pinned release should be at least 2 weeks old at
  pin time. MCPs are never
  auto-updated; users explicitly re-run ``hermes mcp install <name>`` to
  pull a new manifest version after a repo update.
- Secrets prompted at install time go to ``~/.hermes/.env`` (the
  .env-is-for-secrets rule). Non-secret env vars also go to .env to keep
  one credential store.

See website/docs/user-guide/mcp-catalog.md for user docs.
See references/mcp-catalog.md (this repo's skill) for the manifest schema.
    )annotationsN)	dataclassfield)Path)AnyDictListOptional)get_hermes_homeget_optional_mcps_dir)Colorscolor)load_configsave_configget_env_valuesave_env_value)prompt   z${INSTALL_DIR}c                  L    e Zd ZU ded<   ded<   dZded<   dZded<   dZded	<   y
)
EnvVarSpecstrnamer   Tboolrequiredsecret defaultN)__name__
__module____qualname____annotations__r   r   r        I/root/.hermes/venv/lib/python3.12/site-packages/hermes_cli/mcp_catalog.pyr   r   :   s*    
IKHdFDGSr#   r   c                  l    e Zd ZU ded<    ee      Zded<   dZded<    ee      Zd	ed
<   dZ	ded<   y)AuthSpecr   typedefault_factoryList[EnvVarSpec]envNOptional[str]provider	List[str]scopesenv_var)
r   r   r    r!   r   listr+   r-   r/   r0   r"   r#   r$   r&   r&   C   s:    
I!$7C	7"Hm"d3FI3!G]!r#   r&   c                  z    e Zd ZU ded<   dZded<    ee      Zded<   dZded	<   dZ	ded
<    ee
      Zded<   y)TransportSpecr   r'   Nr,   commandr(   r.   argsurlversionDict[str, str]r+   )r   r   r    r!   r4   r   r1   r5   r6   r7   dictr+   r"   r#   r$   r3   r3   M   sE    
I!G]!D1D)1C!G]!  5C5r#   r3   c                  L    e Zd ZU dZded<   ded<   ded<    ee      Zded<   y	)
InstallSpeczmOptional bootstrap step (git clone + dep install).

    Omit for one-shot launchable servers (npx, uvx).
    r   r'   r6   refr(   r.   	bootstrapN)r   r   r    __doc__r!   r   r1   r=   r"   r#   r$   r;   r;   Z   s'     I	H	H 6Iy6r#   r;   c                       e Zd ZU dZdZded<   y)	ToolsSpeczManifest-side tool-selection hints.

    Drives the pre-checked state of the install-time tool checklist, and acts
    as the fallback selection when probe fails. See install_entry() flow.
    NOptional[List[str]]default_enabled)r   r   r    r>   rB   r!   r"   r#   r$   r@   r@   f   s     ,0O(/r#   r@   c                      e Zd ZU ded<   ded<   ded<   ded<   ded<    ee	      Zd
ed<   dZded<   dZded<    ee		      Z
ded<   y)CatalogEntryr   r   descriptionsourcer3   	transportr&   authr(   r@   toolsNzOptional[InstallSpec]installr   post_installr   manifest_path)r   r   r    r!   r   r@   rI   rJ   rK   r   rL   r"   r#   r$   rD   rD   t   sP    
IK
NY7E97%)G")L#5M45r#   rD   c                      e Zd ZdZy)CatalogErrorz3Manifest parse/validation failure or install error.N)r   r   r    r>   r"   r#   r$   rN   rN      s    =r#   rN   c                 `    t        t        t              j                  j                  dz        S )zEReturn the optional-mcps/ directory shipped with this Hermes install.zoptional-mcps)r   r   __file__parentr"   r#   r$   _catalog_rootrR      s$     !h!6!6!=!=!OPPr#   c                   t        | t              s!t        dt        |       j                         | j                  d      xs d}|rt        j                  d|      st        d|      t        || j                  d      xs |t        | j                  dd            t        | j                  d	d            t        | j                  d
      xs d            S )Nz!env entry must be a mapping, got r   r   z^[A-Za-z_][A-Za-z0-9_]*$zinvalid env var name: r   r   Tr   r   )r   r   r   r   r   )
isinstancer9   rN   r'   r   getrematchr   r   r   )rawr   s     r$   _parse_env_specrY      s    c4 >tCy?Q?Q>RSTT776? bDrxx ;TB3D8<==wwx (Dcggj$/0CGGHd+,CGGI&,"- r#   c                
   	 t        | dd      5 }t        j                  |      xs i }ddd       t        t              st	        |  d      |j                  d      }|t        k7  rt	        |  d	|d
t         d      |j                  d      xs d}|rt        j                  d|      st	        |  d      t        |j                  d      xs d      j                         }|st	        |  d      t        |j                  d      xs d      j                         }|j                  d      xs i }t        |t              st	        |  d      |j                  d      }	|	dvrt	        |  d      |j                  d      xs g }
t        |
t              st	        |  d      |j                  d      xs i }t        |t              r t        d |j                         D              st	        |  d      t!        |	|j                  d      |
D cg c]  }t        |       c}|j                  d      |j                  d      t        |             }|	d!k(  r|j"                  st	        |  d"      |	d#k(  r|j$                  st	        |  d$      |j                  d%      xs dd&i}t        |t              st	        |  d'      |j                  d      xs d&}|d(vrt	        |  d)      |j                  d      xs g }t        |t              st	        |  d*      |D cg c]  }t'        |       }}t)        |||j                  d+      t        |j                  d,      xs g       |j                  d-      .      }|j                  d/      xs i }t        |t              st	        |  d0      |j                  d1      }|0t        |t              rt        d2 |D              st	        |  d3      t+        |4      }d}|j                  d5      }|t        |t              st	        |  d6      |j                  d      }|d7k7  rt	        |  d8|d      |j                  d      xs d}|j                  d9      xs d}|r|st	        |  d:      |j                  d;      xs g }t        |t              st	        |  d<      t-        ||||D cg c]  }t        |       c}=      }t/        |||||||t        |j                  d>      xs d      | ?	      S # 1 sw Y   xY w# t        $ r}t	        d|  d|       |d}~ww xY wc c}w c c}w c c}w )@zERead and validate a manifest.yaml. Raise CatalogError on any problem.rzutf-8)encodingNzfailed to read z: z: manifest must be a mappingmanifest_versionz: manifest_version z. unsupported (this Hermes understands version )r   r   z^[A-Za-z0-9_-]+$z: invalid or missing 'name'rE   z: 'description' requiredrF   rG   z: 'transport' must be a mappingr'   )stdiohttpz*: transport.type must be 'stdio' or 'http'r5   z: transport.args must be a listr+   c              3  f   K   | ])  \  }}t        |t              xr t        |t               + y wNrT   r   ).0kvs      r$   	<genexpr>z"_parse_manifest.<locals>.<genexpr>   s/      06:a
1c1z!S110s   /1z5: transport.env must be a mapping of string to stringr4   r6   r7   )r'   r4   r5   r6   r7   r+   r_   z$: stdio transport requires 'command'r`   z: http transport requires 'url'rH   nonez: 'auth' must be a mapping)api_keyoauthrh   z,: auth.type must be 'api_key'|'oauth'|'none'z: auth.env must be a listr-   r/   r0   )r'   r+   r-   r/   r0   rI   z: 'tools' must be a mappingrB   c              3  <   K   | ]  }t        |t                y wrb   rc   rd   ts     r$   rg   z"_parse_manifest.<locals>.<genexpr>   s      <
#$Jq#<
   z1: tools.default_enabled must be a list of strings)rB   rJ   z: 'install' must be a mappinggitz": install.type must be 'git' (got r<   z*: install.url and install.ref are requiredr=   z": install.bootstrap must be a list)r'   r6   r<   r=   rK   )	r   rE   rF   rG   rH   rI   rJ   rK   rL   )openyaml	safe_load	ExceptionrN   rT   r9   rU   _MANIFEST_VERSIONrV   rW   r   stripr1   allitemsr3   r4   r6   rY   r&   r@   r;   rD   )pathfdataexcmvr   rE   rF   transport_rawt_typer5   env_rawarG   auth_rawa_typeenv_list_raweenv_listrH   	tools_rawrB   
tools_specrJ   install_rawi_typer6   r<   r=   cs                                 r$   _parse_manifestr      s   E$g. 	+!>>!$*D	+
 dD!dV#?@AA	$	%B	f'v .00A/B!E
 	

 88F!rDrxx 3T:dV#>?@@dhh}-34::<KdV#;<==(#)r*002FHH[)/RMmT*dV#BCDDv&F&&dV#MNOOV$*DdD!dV#BCDD&,"Ggt$C 0>Emmo0 - fIJ
 	
 !!),"#c!f#e$!!),MI !2!2dV#GHII	dV#BCDDxx3FF#3Hh%dV#=>??\\&!+VF11dV#OPQQ<<&,"LlD)dV#<=>>,89q"9H9j)HLL*0b1Y'D !'RIi&dV#>?@@mm$56O"/40 <
(7<
 9
 &IJ  ?;J%)G((9%K+t,$'DEFF(U?$'I&STUVVooe$*ooe$*#$'QRSSOOK06B	)T*$'IJKK'01!s1v1	
 .17R8
 
W	+ 	+ E_TF"SE:;DET $& :R 2s?   T< T/T< U0U$%U)/T94T< <	UUUc                    t               } | j                         sg S g }t        j                          t	        | j                               D ]3  }|dz  }|j                         s	 |j                  t        |             5 |S # t        $ rb}t        |      }d|v r'd|v r#t        j                  |j                  d|f       n"t        j                  |j                  d|f       Y d}~d}~ww xY w)aS  Return all valid catalog entries, sorted by name.

    Invalid manifests are skipped silently (CI tests catch them at PR time).
    Manifests with a future ``manifest_version`` are also skipped, but the
    skip is surfaced via :func:`catalog_diagnostics` so the picker / catalog
    UIs can tell the user their Hermes is out of date.
    zmanifest.yamlr]   unsupportedfuture_manifestinvalidN)rR   exists_CATALOG_DIAGNOSTICSclearsortediterdiris_fileappendr   rN   r   r   )rootentrieschildmanifestr{   msgs         r$   list_catalogr     s     ?D;;=	"$G ' ?*!
	NN?845 N  	c(C "S(]c-A$++UZZ9JC,PQ$++UZZC,HI	s   &B	C/AC**C/List[tuple]r   c                      t        t              S )u  Diagnostics from the most recent :func:`list_catalog` call.

    Returns a list of ``(entry_name, kind, message)`` tuples where ``kind``
    is one of:
      - ``future_manifest`` — manifest_version is newer than this Hermes
        understands. Update Hermes to install this entry.
      - ``invalid`` — manifest is malformed in some other way (caught by
        CI for shipped manifests; user-modified manifests can hit this).
    )r1   r   r"   r#   r$   catalog_diagnosticsr   =  s     $%%r#   c                    | j                  d      r| t        d      d } t               D ]  }|j                  | k(  s|c S  y)zDLook up a single entry by name. ``official/<name>`` prefix accepted.z	official/N)
startswithlenr   r   )r   entrys     r$   	get_entryr   J  sG    {#C$%& ::L r#   c                 h    t               } | j                  d      xs i }t        |t              r|S i S )z6Return current ``mcp_servers`` block from config.yaml.mcp_servers)r   rU   rT   r9   )cfgserverss     r$   installed_serversr   W  s0    
-Cggm$*G $/77R7r#   c                    | t               v S rb   )r   )r   s    r$   is_installedr   ^  s    $&&&r#   c                    t               }|j                  |       }|sy|j                  dd      }t        |t              r|j	                         dv S t        |      S )NFenabledT>   1yestrue)r   rU   rT   r   lowerr   )r   r   r   r   s       r$   
is_enabledr   b  sT    !G
++d
Cggi&G'3}}"666=r#   c                 F    t               dz  } | j                  dd       | S )z@Where git-bootstrapped MCPs are cloned. Per-user, profile-aware.zmcp-installsT)parentsexist_ok)r   mkdir)r   s    r$   _install_rootr   p  s$    ~-DJJtdJ+Kr#   c                    |D ]s  }t        t        d| t        j                               t	        j
                  |t        |       d      }|j                  dk7  sZt        d|j                   d|        y)zExecute bootstrap commands in *cwd*. Raise CatalogError on first failure.

    Each command runs through the shell (so `&&` etc. work). The output is
    streamed to the user's terminal for visibility.
    z  $ T)cwdshellr   zbootstrap step failed (exit z): N)	printr   r   DIM
subprocessrunr   
returncoderN   )r   commandscmdprocs       r$   _run_bootstrapr   w  sp      ed3%L&**-.~~cs3xt<??a.t.?s3%H 	r#   c                   | j                   | j                   j                  dk(  sJ | j                   }t               | j                  z  }t	        j
                  d      }|st        d      |j                         r;t        t        d| t        j                               t	        j                  |       t        t        d|j                   d|j                   d| t        j                               t!        t#        j$                  d|j                              }|sqt'        j(                  |dd	d
d|j                  |j                  t+        |      g      }|j,                  dk(  rn'|j                         rt	        j                  |       d}|rt'        j(                  |d|j                  t+        |      g      }|j,                  dk7  rt        d|j                         t'        j(                  |dt+        |      d|j                  g      }|j,                  dk7  rt        d|j                   d      |j.                  rt1        ||j.                         |S )z|Clone the entry's repo into ``~/.hermes/mcp-installs/<name>`` and run
    bootstrap commands. Returns the install directory.ro   z=git is required to install this MCP but was not found on PATHz  Removing existing install at z
  Cloning z (u   ) → z[0-9a-f]{7,40}clonez--depthr   z--branchr   Tzgit clone failed for z-Ccheckoutzgit checkout z failed)rJ   r'   r   r   shutilwhichrN   r   r   r   r   r   rmtreer6   r<   CYANr   rV   	fullmatchr   r   r   r   r=   r   )r   rJ   destro   
is_sha_refr   s         r$   _do_git_installr     s    ==$););u)DDDmmG?UZZ'D
,,u
CZ[[{{} 	e5dV<fjjIJd	%*W[[MGKK=tfEv{{
ST bll#4gkkBCJ~~'9c:w{{GKKQTUYQZ[
 ??a {{}d#J~~sGW[[#d)DE??a!6w{{mDEE~~sD#d)ZMN??aw{{m7CDDtW../Kr#   c                ~    t         | vr| S |t        dt          d      | j                  t         t        |            S )Nzmanifest references z but no install block exists)_INSTALL_DIR_VARrN   replacer   )valueinstall_dirs     r$   _expand_install_dirr     sJ    u$"#3"44PQ
 	
 ==)3{+;<<r#   c                   i }| D ]  }t        |j                        }|rAt        t        d|j                   dt        j
                               |||j                  <   [t        |j                  |j                  xs d|j                        }|s%|j                  rt        |j                   d      t        |j                  |       |||j                  <    |S )zWalk the env spec list, prompting the user for each. Writes secrets and
    non-secrets alike to ~/.hermes/.env via save_env_value().     ✓ z already set in .envN)r   passwordz& is required but no value was provided)r   r   r   r   r   GREEN_prompt_inputr   r   r   r   rN   r   )specs	collectedspecexistingr   s        r$   _prompt_env_varsr     s     !#I % +%&+?@&,,OP#+Idii KKLL(D[[

 }}"dii[0V#WXXtyy%($	$))!%" r#   c                   i }| j                   }|j                  dk(  rvt        |j                  xs d|      |d<   |j                  r'|j                  D cg c]  }t        ||       c}|d<   |j
                  rt        |j
                        |d<   |S |j                  dk(  r-|j                  |d<   | j                  j                  dk(  rd|d	<   |S c c}w )
zgTranslate a manifest into the ``mcp_servers.<name>`` block format used
    by hermes_cli/mcp_config.py.r_   r   r4   r5   r+   r`   r6   rj   rH   )	rG   r'   r   r4   r5   r+   r9   r6   rH   )r   r   r   rm   r   s        r$   _build_server_configr     s    
 CAvv,QYY_"kJI66HIO1.q+>OCK55aeeCJ
 J	 
6	UUE
::??g%!CKJ Ps   Cc                
   t               }|j                  |       xs i }|j                  d      xs i }t        |t              sy|j                  d      }t        |t              rt        d |D              rt	        |      S y)a  Return the user's prior `tools.include` for *name*, if any.

    Used during reinstalls so the install-time checklist starts pre-checked
    with whatever the user already had. Tools no longer on the server are
    silently dropped at checklist-display time.
    rI   Nincludec              3  <   K   | ]  }t        |t                y wrb   rc   rl   s     r$   rg   z-_read_prior_tool_selection.<locals>.<genexpr>  s     (MAs);(Mrn   )r   rU   rT   r9   r1   rv   )r   r   r   	tools_cfgr   s        r$   _read_prior_tool_selectionr     sq      !G
++d

!rC &BIi&mmI&G'4 S(MW(M%MG}r#   c                    t               }|j                  |       }|sy	 ddlm}  || |      }|t	        |      S g S # t
        $ r0}t        t        d| t        j                               Y d}~yd}~ww xY w)ug  Connect to a freshly-configured MCP and list its tools.

    Returns a list of ``(tool_name, description)`` tuples on success, or
    ``None`` on any failure (server unreachable, OAuth not yet completed,
    backing service offline, etc.). Failures are intentionally swallowed
    here — the fallback path in :func:`_apply_tool_selection` handles them.
    Nr   )_probe_single_serverz  Probe failed: )
r   rU   hermes_cli.mcp_configr   r1   rs   r   r   r   YELLOW)r   r   
server_cfgr   rI   r{   s         r$   _probe_toolsr     sv      !GT"J	>$T:6#/tE{7R7 e&se,fmm<=s   > > 	A7&A22A7c                R   t               }|j                  di       }|j                  |       xs i }||j                  dd       nL|j                  d      xs i }t	        |t
              si }t        |      |d<   |j                  dd       ||d<   ||| <   ||d<   t        |       y)z6Persist or clear ``mcp_servers.<name>.tools.include``.r   NrI   r   exclude)r   
setdefaultrU   poprT   r9   r1   r   )r   r   r   r   server_entrytools_blocks         r$   _write_tools_includer     s    
-Cnn]B/G;;t$*L$'"&&w/52+t,K!%gI	4( +W GDM Cr#   c          
        t                t        t        d| j                   dt        j                               t        | j                        }|| j                  j                  }|rTt        | j                  |       t        t        dt        |       d| j                   dt        j                               yt        | j                  d       t        t        d| j                   dt        j                               y|s:t        | j                  d       t        t        d	t        j                               y|D cg c]  }|d
   	 }}|r|D ch c]	  }||v s| }}nJ| j                  j                  r)| j                  j                  D ch c]	  }||v s| }}nt        |      }t        |      D ch c]  \  }}||v s| }	}}d
dl}
|
j                  j                         s|+|D cg c]	  }||v s| }}t        | j                  |       y| j                  j                  r?| j                  j                  D cg c]	  }||v s| }}t        | j                  |       yt        | j                  d       yt        t        dt        |       dt        |	       dt        j                                d
dlm} |D cg c]"  \  }}| dt        |      dkD  r|dd dz   n| $ }}} |d| j                   d||	      }|sHt        | j                  g        t        t        d| j                   dt        j                               yt        |      t        |      k(  rGt        | j                  d       t        t        dt        |       dt        j                                yt'        |      D cg c]  }||   	 }}t        | j                  |       t        t        dt        |       dt        |       dt        j                                yc c}w c c}w c c}w c c}}w c c}w c c}w c c}}w c c}w )u  Probe the server and let the user pick which tools to enable.

    Probe-success path:
      - Curses checklist of all probed tools.
      - Pre-check uses (in priority order):
          1. *prior_selection* (reinstall: preserve what the user had)
          2. manifest's ``tools.default_enabled``
          3. all tools (default)
      - All-on selection clears any filter (no ``tools.include`` written).
      - Sub-selection writes ``tools.include``.

    Probe-fail path:
      - If manifest declares ``tools.default_enabled`` → apply directly.
      - Otherwise → leave config with no filter (all on when reachable).
      - Either way, point the user at ``hermes mcp configure <name>``.
    z  Probing 'z' for available tools...Nz3  Couldn't probe server. Applied manifest default (z# tools). Run `hermes mcp configure z*` after the server is reachable to refine.zu  Couldn't probe server; installed with no tool filter (all tools enabled when reachable). Run `hermes mcp configure z` after first connect to prune.z  Server reported no tools.r   z  Found z tool(s). Pre-checked: .)curses_checklistu     —  <   z...zSelect tools for 'z' (SPACE toggle, ENTER confirm)z/  No tools selected. Run `hermes mcp configure z` to change.u
     ✓ All uT    tools enabled (no filter — new tools the server adds later will be auto-enabled).r   /z tools enabled.)r   r   r   r   r   r   rI   rB   r   r   r   set	enumeratesysstdinisattyr   hermes_cli.curses_uir   r   )r   prior_selectionprobedmanifest_defaultrm   
tool_namesnpre_setipre_indices_sysr   r   dlabelschosen_indiceschosen_namess                    r$   _apply_tool_selectionr  .  s   & 
G	%+ejj\)ABFKK
PQ%**%F ~ ;;66 -=>%()* +--2ZZL 9**    	 !T2%--2ZZL 9$$   	UZZ.e16==AB &'1!A$'J' -Aj1AA		$	$#kk99MQ*_1MMj/!*:!6GA!w,1GKG ::&"1EQQ*_qEGE W5 	 [[(("'++"="=QQjqQGQ W5 	 !T2	%
3v;-  K()	,  6 Aq #WQ"afun!<=F  &
UZZL(GHN  	UZZ,e=ejj\ J MM
 	
 	
>c&k) 	UZZ.eV &; ;LL
 	
 	+1.+ABaJqMBLB\2	%
\"#1S[MA O ( BM H F RF CsN   P.	P3%P3	P8$P8P=P=<	QQ	QQ'QQT)enablec          	        t                t        t        d| j                   dt        j                  t        j
                  z                | j                  r0t        t        d| j                   t        j                               | j                  r0t        t        d| j                   t        j                               t                d}| j                  t        |       }| j                  j                  dk(  rMt                t        t        dt        j                               t        | j                  j                         n| j                  j                  dk(  r| j                  j                  rSt        t        d	| j                  j                   d
| j                  j                   dt        j                                n#t        t        dt        j                               t#        | j                        }t%        | |      }||d<   ddlm}  || j                  |      st+        d| j                   d      t-        | |       t                t        t        d| j                   d|rdnd dt        j.                               | j0                  r]t                | j0                  j3                         j5                         D ](  }t        t        d| t        j                               * t                y)a  Install a catalog entry end-to-end.

    Steps:
        1. If ``install.type == git``, clone + run bootstrap commands.
        2. If ``auth.type == api_key``, prompt for env vars, save to .env.
        3. If ``auth.type == oauth`` (remote MCP / case 1), write the
           ``auth: oauth`` marker (MCP client handles browser on first connect
           in the non-pre-authenticated case).
        4. Translate the manifest into an ``mcp_servers.<name>`` block and
           save into config.yaml.
        5. Probe the server, present a curses checklist for tool selection,
           write ``tools.include`` (or no filter, depending on choice).
           If probe fails, fall back to the manifest's
           ``tools.default_enabled`` or all-on.
        6. Print post_install notes.
    z  Installing MCP ''z  z
  Source: Nri   z  Configure credentials:rj   z  This MCP uses z OAuth. Run `hermes auth z(` if you have not already authenticated.z]  This MCP uses native OAuth 2.1; tokens will be acquired on first connection (browser flow).r   r   )_save_mcp_serverzcatalog entry 'z1' rejected: suspicious command/args configuration)r   u     ✓ Installed 'z' (disabledz0). Start a new Hermes session to load its tools.)r   r   r   r   r   BOLDrE   r   rF   rJ   r   rH   r'   r   r+   r-   r   r   r   r   r  rN   r  r   rK   ru   
splitlines)r   r  r   r   r   r  lines          r$   install_entryr    sY   " 
G	%$UZZL2FKK&++4M
NOeb**+,fjj9:||ej/<=	G"&K}} %e, zz)#e.<=(	G	#::
 %"5::#6#6"7 8  %

 3 34 5)) 	  %6

  1<O &e[9J"Jy6EJJ
3ejj\)Z[
 	

 %A	G	%
EJJ< (IZ0 18	9 		  &&,,.99; 	2D%"TFVZZ01	2	Gr#   )purge_install_dirc                  t               }|j                  d      xs i }d}| |v r*|| = |s|j                  dd       n||d<   t        |       d}|r4t	               | z  }|j                         rt        j                  |       d}|S )zRemove a catalog-installed MCP from config and (optionally) wipe its
    clone directory. Returns True if anything was removed.r   FNT)r   rU   r   r   r   r   r   r   )r   r  r   r   removedr   s         r$   uninstall_entryr    s     -Cggm$*GGwDMGGM4(!(CC$&<<>MM% GNr#   )returnr   )rX   r   r  r   )rx   r   r  rD   )r  zList[CatalogEntry])r  r   )r   r   r  zOptional[CatalogEntry])r  zDict[str, dict])r   r   r  r   )r   r   r   r.   r  None)r   rD   r  r   )r   r   r   Optional[Path]r  r   )r   r*   r  r8   )r   rD   r   r  r  r9   )r   r   r  rA   )r   r   r  zOptional[List[tuple]])r   r   r   rA   r  r  )r   rD   r   rA   r  r  )r   rD   r  r   r  r  )r   r   r  r   r  r   )@r>   
__future__r   rV   r   r   dataclassesr   r   pathlibr   typingr   r   r	   r
   rq   hermes_constantsr   r   hermes_cli.colorsr   r   hermes_cli.configr   r   r   r   hermes_cli.cli_outputr   r   rt   r   r   r&   r3   r;   r@   rD   rs   rN   rR   rY   r   r   r   r!   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r"   r#   r$   <module>r$     s  6 # 	   (  , ,  C +  :  $     " " " 	6 	6 	6 7 7 7 
0 
0 
0 	6 	6 	6>9 >QxvB %' k &
&8'1h=0&4	($0(~~-@~	~B :> Up =A r#   