
    lKj                     ,   U d Z ddlmZ ddlmZ ddlmZ ddlmZ ddl	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mZmZmZmZ ddlmZ ddlmZ dd	lm Z  dd
l!m"Z" ddl#m$Z$ ddl%m&Z&m'Z'm(Z( ddl)m*Z*m+Z+ ddl,m-Z- ddl.Z.ddl/Z/ddl0Z0ddl1m2Z2 ddl3Z3ddl4Z4ddl5Z5ddl6Z6ddl7Z7ddl8m9Z9 ddl:Z: e/jv                  e<      Z=da>e(e   e?d<   da@e(e   e?d<   daAe(e   e?d<   daBe(e   e?d<    e9       ZCdaDd\  ZEZF e-d      ZGddZHddeIddfdZJ G d d      ZK	 	 	 ddeLdz  d eMdz  deMfd!ZNed"e*fd#       ZO e*d$eGeO%      ZPePj                  d&d' e d&dd(dd)      *      	 	 	 	 	 dd+e'd,   d-eLdz  d.eMeI   dz  d/eMeI   dz  d0e+f
d1       ZRePj                  d2d3 e d2dd(dd()      *      	 	 	 dd4eLd+e'd5   d6eId0e+deLf
d7       ZSePj                  d8d9 e d8d(dd(d)      *      dd:eTd0e+fd;       ZUePj                  d<d= e d<dd(dd)      *      	 	 	 dd>eMeI   d?e'd@   dAeId0e+deLf
dB       ZVePj                  dCdD e dCdd(dd)      *      	 	 	 	 dd>eMeI   dEeLdFeTdGe'dH   dIeTd0e+deLfdJ       ZWePj                  dKdL e dKddd(d)      *      	 	 	 	 	 dd>eMeI   dMe'dN   dOe'dP   dQeId0e+deLfdR       ZXePj                  dSdT e dSddd(d)      *      dd>eMeI   dUeTd0e+deLfdV       ZYePj                  dWdX e dWdd(dd)      *      ddYeLd0e+fdZ       ZZePj                  d[d\ e d[d(dd(d)      *      dd]eId0e+deLfd^       Z[d_Z\ePj                  d`da e d`d(dd(d()      *      ddbeLd0e+deLfdc       Z]ePj                  ddde e dddddd)      *      	 	 	 	 ddfeLdgeLdheLdz  die'dj   dz  d0e+deLfdk       Z^d0e:jV                  d-eLdeTfdlZ_d0e:jV                  d-eLfdmZ` e:j                         dn        Zbebj                         e:j                   e:j                  dodp e:j                  g dq      drs       e:j                  dtdudveLd(w       e:j                  dxdydzeId(w       e:j                  d{d|d(dd(}       e:j                  d~dd e:jd                  d      dw       e:j                  ddddeLd       e:j                  ddd(dd(}       e:j                  ddddeLd       e:j                  ddddeLd       e:j                  ddddeLd       e:j                  ddddeLd       e:j                  ddddeLd      d                                                                                                   ZgdeLddfdZhebj                          e:j                  do e:j                  g dq      dd(d       e:j                  dtdd(d       e:j                  dxdzd(eId       e:j                  dd(d       e:j                  dd(d      deLdeLdeIdeTdeTddfd                                          ZidZj e2j                         dz  dz  Zlelej dz  ZmdeMeL   fdZndeMeL   deLfdZodeLde6j                  fdZqebj                          e:j                  do e:j                  ddg      dd(d       e:j                  dtdvd(d       e:j                  dxdzd(eId       e:j                  dd(d      deLdeLdeIdeTddf
d                                   Zrebj                         dd       Zse<dk(  r eb        yy)zy
macOS-MCP: MCP Server for macOS Desktop Interaction.

Provides tools to interact with the macOS desktop for automation.
    )Desktop)Size)WatchDog)validate_permissions)AuthKeyMiddlewareOAuthOnlyMiddlewareIPAllowlistMiddlewarePostHogAnalytics	Analyticsis_loopback_hostparse_ip_allowlistvalidate_url
CONFIG_DIRCONFIG_FILEMacOSMCPConfigdiscover_config_pathload_configwrite_config
OAuthStorebuild_oauth_routesvalidate_oauth_token)asynccontextmanager)Image)ToolAnnotations)
Middleware)CORSMiddleware)AnyLiteralOptional)FastMCPContext)dedentN)Path)Lockdesktopscreen_sizewatchdog	analyticsF)i  i8  z
macOS MCP server provides tools to interact directly with the macOS desktop, 
enabling operation of the desktop on the user's behalf.
returnc                     t         5  t        r
	 ddd       ydaddd       t        r(	 t        j                  rt        j	                          dayy# 1 sw Y   8xY w# t
        $ r t        j                  d       Y dayw xY w# daw xY w)z4Stop the watchdog once, even if shutdown paths race.NTzBFailed to stop watchdog during shutdown (may have already crashed))_shutdown_lock_shutdown_startedr'   
is_runningstop	Exceptionloggerdebug     c/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/macos_mcp/__main__.py_stop_watchdogr5   C   s     
 
 ! 

 	"" H  
  	LLT H	
 Hs3   AA$A AB ;B ?B  B B	exit_codec                     t                t        j                  t        j                  fD ]  }	 |j	                           t        j                  |        y# t
        $ r Y 7w xY w)zGFlush stdio and exit immediately to avoid daemon-thread shutdown hangs.N)r5   sysstdoutstderrflushr/   os_exit)r6   streams     r4   _force_exitr?   X   sO    ::szz*	LLN + HHY  		s   A	A#"A#c                   8    e Zd ZdZdeddfdZdedededdfd	Zy)
OptionsMiddlewarezDASGI middleware that intercepts OPTIONS requests and returns 200 OK.appr)   Nc                     || _         y NrB   )selfrB   s     r4   __init__zOptionsMiddleware.__init__h   s	    r3   scopereceivesendc           	         K   |d   dk(  r<|d   dk(  r4 |ddddgd	d
gdd
gdd
ggd       d {     |ddd       d {    y | j                  |||       d {    y 7 47 #7 	w)NtypehttpmethodOPTIONSzhttp.response.start   s   content-length   0s   access-control-allow-origin   *s   access-control-allow-methodss   access-control-allow-headers)rL   statusheaderszhttp.response.bodyr3   )rL   bodyrE   )rF   rH   rI   rJ   s       r4   __call__zOptionsMiddleware.__call__k   s     =F"uX)'C1!*D17>8$?8$?	 	    4cBCCC((5'4000 D0s3   ,A)A#A)A%A)A'A)%A)'A))__name__
__module____qualname____doc__r   rG   rV   r2   r3   r4   rA   rA   e   s9    NC D 1C 1# 1S 1T 1r3   rA   auth_keyip_allowlistc                 "   t        t              t        t        dgdgdg      g}|r |j                  t        t        |             | r#|j                  t        t
        | |             |S |r |j                  t        t        |             |S )zOReturn ASGI middleware for HTTP transports including CORS and OPTIONS handling.*)allow_originsallow_methodsallow_headers)	allowlist)r[   oauth_validator)rc   )r   rA   r   appendr	   r   r   )r[   r\   rc   
middlewares       r4   _http_middlewarerf   ~   s     	$%>#se\_[`aJ *%:lST*%6[jkl  
*%8/Z[r3   rB   c                  K   t        j                  dd      j                         dk7  r
t               at               at        j                         ada	t               at        j                  t        j                  j                         	 t        j                          	 t'        j(                  d       d{    d t+                t        rt        j-                          d{    yy# t         $ r#}t"        j%                  d| d       Y d}~xd}~ww xY w7 f7 7# t+                t        rt        j-                          d{  7   w w xY ww)	zWRuns initialization code before the server starts and cleanup code after it shuts down.ANONYMIZED_TELEMETRYtruefalseFz&Watchdog failed to start (non-fatal): z&. Continuing without event monitoring.Ng      ?)r<   getenvlowerr
   r(   r   r%   get_screen_sizer&   r,   r   r'   set_focus_callbacktreeon_focus_changedstartr/   r0   warningasynciosleepr5   close)rB   es     r4   lifespanrw      s
    
 
yy'0668GC$&	iG))+KzH = =>
$mmC   //###   
4QC7]^	
 	

 	!
 $ 	//### sr   B	EC1 !D$ 9D :	D$ 'E*D"+E1	D:DEDE D$ "E$(EEEE	macos-mcp)nameinstructionsrw   AppzManages macOS applications with four modes: 'launch' (opens the application), 'resize' (adjusts active window size), 'move' (repositions active window), 'switch' (brings specific app into focus).T)titlereadOnlyHintdestructiveHintidempotentHintopenWorldHint)ry   descriptionannotationsmode)launchresizemoveswitchry   
window_locwindow_sizectxc                 n    t         j                  | ||rt        |      nd |rt        |            S d       S rD   )r%   rB   tuple)r   ry   r   r   r   s        r4   app_toolr      s@    $ ;;'jT)k	  04	 r3   Shella  Execute commands on macOS. Modes: 'shell' (default) for bash/zsh commands, 'osascript' for AppleScript. Use for file system, process management, system operations, and automation scripts. SECURITY WARNING: Commands are executed with the same permissions as the terminal/application running this server. Review and understand all actions before execution, especially those involving file operations, system modifications, or external processes.command)shell	osascripttimeoutc                 ^    t         j                  | ||      \  }}|dk(  rdnd}| d| d| S )N)r   r   r   AppleScriptr   z Response: z
Status Code: )r%   execute_command)r   r   r   r   responsestatus_code
mode_labels          r4   
shell_toolr      sF    " $33G$PW3XHk"&+"57J\XJok]KKr3   Snapshotab  Captures complete desktop state including: focused window, open applications, interactive elements (buttons, text fields, links, menus with coordinates), and scrollable areas. Set use_vision=True to include screenshot with numbered annotations on interactive elements. Always call this first to understand the current desktop state before taking actions.
use_visionc                    d}t         rt         j                  dkD  rt         j                  dkD  rlt         j                  t        kD  rt        t         j                  z  nd}t         j                  t        kD  rt        t         j                  z  nd}t        ||      }t        j                  | d|      }|j                  j                         }|j                  j                         }|j                         }|j                         }	t        d|	 d| d|xs d d	|xs d
 d	      g| r&|j                  rt        |j                  d      gz   S g z   S )Ng      ?r   T)r   as_bytesscalez
    Focused Window:
    z

    Open Applications:
    z(

    List of Interactive Elements:
    zNo interactive elements found.z'

    List of Scrollable Elements:
    zNo scrollable elements found.z
    png)dataformat)r&   widthheightMAX_IMAGE_WIDTHMAX_IMAGE_HEIGHTminr%   	get_state
tree_stateinteractive_elements_to_stringscrollable_elements_to_stringwindows_to_stringactive_window_to_stringr"   
screenshotr   )
r   r   r   scale_widthscale_heightdesktop_stateinteractive_elementsscrollable_elementswindowsactive_windows
             r4   
state_toolr      ss    E{((1,1C1Ca1G   ?2 k/// 	 !!$44 {111 	
 K.%%dRW%XM(33RRT'22PPR--/G!99;M 	 O  I  ==> ? ;;< = 		  -22 
M,,U	;< " # r3   ClickzPerforms mouse clicks at specified coordinates [x, y]. Supports button types: 'left' for selection/activation, 'right' for context menus, 'middle'. Supports clicks: 0=hover only, 1=single click, 2=double click.locbutton)leftrightmiddleclicksc                     t        |       dk7  rt        d      | d   | d   }}t        j                  ||f||       dddd	}|j	                  |       d
| d| d| dS )N   4Location must be a list of exactly 2 integers [x, y]r      )r   r   r   HoverSingleDouble)r   r   r    z clicked at (,).)len
ValueErrorr%   clickget)r   r   r   r   xy
num_clickss          r4   
click_toolr     sw    " 3x1}OPPq63q6qAMMq!fVFM;h7JnnV$%QvhmA3as"EEr3   TypezTypes text at specified coordinates [x, y]. Set clear=True to clear existing text first. Set press_enter=True to submit after typing. Set caret_position to 'start', 'end', or 'idle' (default).textclearcaret_position)rq   idleendpress_enterc                     t        |       dk7  rt        d      | d   | d   }}t        j                  ||f||||       d| d| d| d	S )
Nr   r   r   r   )r   r   r   r   r   zTyped  at (r   r   )r   r   r%   rL   )r   r   r   r   r   r   r   r   s           r4   	type_toolr   1  sm    & 3x1}OPPq63q6qALLF%   D6qc1#R((r3   ScrollzScrolls at coordinates [x, y] or current mouse position if loc=None. Type: vertical (default) or horizontal. Direction: up/down for vertical, left/right for horizontal. wheel_times controls scroll amount.rL   )
horizontalvertical	direction)updownr   r   wheel_timesc                     | rt        |       dk7  rt        d      t        j                  | rt	        |       nd |||      }|r|S d| d| d| d| rd| d    d	| d
    dz   S dz   S )Nr   r   z	Scrolled r   z by z wheel timesr   r   r   r   r   .)r   r   r%   scrollr   )r   rL   r   r   r   r   s         r4   scroll_toolr   Q  s    $ s3x1}OPP~~CeCjT4KXHtfAi[[MF'*%AxqQ# 03 r3   MovezMoves mouse cursor to coordinates [x, y]. Set drag=True to perform a drag-and-drop operation from current position to target coordinates.dragc                     t        |       dk7  rt        d      | d   | d   }}|r t        j                  ||f       d| d| dS t        j	                  ||f       d| d| dS )	Nr   z/loc must be a list of exactly 2 integers [x, y]r   r   zDragged to (r   r   zMoved the mouse pointer to ()r   r   r%   r   r   )r   r   r   r   r   s        r4   	move_toolr   m  sy     3x1}JKKq63q6qAaVaS!B''aV-aS!B77r3   ShortcutzExecutes keyboard shortcuts using key combinations separated by +. Examples: "command+c" (copy), "command+v" (paste), "command+tab" (switch apps), "command+space" (Spotlight). Note: Use "command" instead of "ctrl" on macOS.shortcutc                 8    t         j                  |        d|  dS )NzPressed r   )r%   r   )r   r   s     r4   shortcut_toolr     s!     XhZq!!r3   WaitzPauses execution for specified duration in seconds. Use when waiting for: applications to launch, UI animations to complete, content to load. Helps ensure UI is ready before next interaction.durationc                 8    t         j                  |        d|  dS )NzWaited for z	 seconds.)r%   wait)r   r   s     r4   	wait_toolr     s     LL
),,r3   i N  ScrapezcFetch content from a URL. Performs a lightweight HTTP request and returns the page content as text.urlc                     t        |        t        j                  |       }t        |      t        kD  r |d t         dt        |      t        z
   dz   }d|  d| S )Nu   

...[truncated — z? chars omitted. Scroll the page and scrape again to read more.]zURL:z

Content:
)r   r%   scraper   _SCRAPE_MAX_CHARS)r   r   contents      r4   scrape_toolr     sm     nnS!G
7|'',,-2HWXiIiHj  kj  1k  k#l7),,r3   Notificationz_Sends a macOS notification banner with a message, title, optional subtitle, and optional sound.messager|   subtitlesound)GlassPingBassoTinkFunkBottleFrogHeroMorsePopPurrSosumi	Submarinec                 2    t         j                  | |||      S rD   )r%   notify)r   r|   r   r   r   s        r4   notification_toolr    s    B >>'5(E::r3   c                 B    | j                  |      }t        |dd       dv S )Nry   >   COMMANDLINEENVIRONMENT)get_parameter_sourcegetattr)r   ry   srcs      r4   _param_explicitr    s'    

"
"4
(C3%)GGGr3   c                 *    t        | |      r|S ||S |S rD   )r  )r   ry   	cli_valueconfig_valuedefault_values        r4   _choose_valuer    s$    sD!r3   c                       y)z3macOS-MCP: MCP server for macOS desktop automation.Nr2   r2   r3   r4   mainr    s    r3   --transportz+The transport layer used by the MCP server.)stdiossestreamable-httpr  )helprL   default--hostz,Host to bind the SSE/Streamable HTTP server.	127.0.0.1)r  r  rL   show_default--portz,Port to bind the SSE/Streamable HTTP server.@  z--debugzAEnable debug mode to provide verbose logging for troubleshooting.)r  is_flagr  r"  z--configz#Path to macos-mcp.toml config file.)dir_okayz
--auth-keyzSBearer token required on all HTTP requests. Can also be set via MACOS_MCP_AUTH_KEY.MACOS_MCP_AUTH_KEY)r  r  envvarrL   r"  z--allow-insecure-remotezQAllow binding to non-loopback addresses without authentication (not recommended).z--ip-allowlistzsComma-separated list of allowed client IPs or CIDR ranges (e.g. '10.0.0.0/8,192.168.1.5'). IPv4 and IPv6 supported.MACOS_MCP_IP_ALLOWLISTz--ssl-certfilezFPath to TLS certificate file (.pem) for HTTPS. Requires --ssl-keyfile.MACOS_MCP_SSL_CERTFILEz--ssl-keyfilezGPath to TLS private key file (.pem) for HTTPS. Requires --ssl-certfile.MACOS_MCP_SSL_KEYFILEz--oauth-client-idzVOAuth client ID (pre-provisioned confidential client). Requires --oauth-client-secret.MACOS_MCP_OAUTH_CLIENT_IDz--oauth-client-secretz0OAuth client secret. Requires --oauth-client-id.MACOS_MCP_OAUTH_CLIENT_SECRETc                   ! t                |rjt        j                         j                  t        j                         dD ]4  }t        j                  |      j                  t        j                         6 t        |      }	 t        |      }t        | d||j                  j                  d      }t        | d||j                  j                  d      }t!        t        | d||j                  j"                  d            }t        | d||j                  j$                  d       }t'        t        | d	||j                  j(                  d
            }t        | d|	|j                  j*                  d       }	t        | d|
|j                  j,                  d       }
t        | d||j.                  j0                  d       }t        | d||j.                  j2                  d       }|r-|j5                  d      D cg c]  }|j7                          c}nd }t9        | d      r|n|j.                  j:                  }t'        |	      t'        |
      k7  rt        j                  d      t'        |      t'        |      k7  rt        j                  d      d }|r	 t=        |      }t'        |xr |      }|dk7  r*t?        |      s|s|s|st        j                  d| d      |s|r|dk(  rt@        jC                  d       d }|rl|dk7  rgtE               !|	r|
rdnd}| d| d| }tG        !|||      }|jI                         D ]$  \  }\  }}tK        jM                  ||      |       & !fd}|jN                  jP                  D ]0  }	 tJ        jS                  |       t@        jU                  d|        2 d }|dk(  rJtY        jZ                  tX        j\                        }d! }tY        jX                  tX        j\                  |       |xdk(  rA 	 tJ        j_                  |d
"       |%tY        jX                  tX        j\                  |       y y xd$k(  rnxd%k(  rn n= i } |	r|
r
|	| d<   |
| d<   tJ        j_                  |||d
tg        |||&      | xs d '       y 	 t        d(|       # t        t        f$ r#}t        j                  t        |            d }~ww xY wc c}w # t        $ r}t        j                  d|       d }~ww xY w# tV        $ r t@        jC                  d| d        Y w xY w# t`        t        jb                  f$ r te        d#       Y 5w xY w# |%tY        jX                  tX        j\                  |       w w xY w))N)uvicornzuvicorn.errorzuvicorn.accessfastmcp	transportr  hostr!  portr$  r[   allow_insecure_remoteFssl_certfilessl_keyfileoauth_client_idoauth_client_secretr   r\   z;--ssl-certfile and --ssl-keyfile must be provided together.z@OAuth requires both --oauth-client-id and --oauth-client-secret.zInvalid ip_allowlist: z$Refusing to bind HTTP transport to 'z' without authentication.
  Use --auth-key <token> or --oauth-client-id/--oauth-client-secret.
  Or pass --allow-insecure-remote to explicitly allow unauthenticated access (not recommended).z9auth_key / ip_allowlist have no effect on stdio transporthttpsrM   ://:)storeissuerconfigured_client_idconfigured_client_secret)methodsc                     t        |       S rD   )r   )tokoauth_stores    r4   <lambda>zserve.<locals>.<lambda>  s    &:;&Lr3   zExcluded tool: zCould not exclude tool 'u   ' — not foundc                     t        d       y )N   )r?   )signumframes     r4   _handle_sigintzserve.<locals>._handle_sigint  s
    r3   )r1  show_bannerrF  r  r  )r[   r\   rc   )r1  r2  r3  rJ  re   uvicorn_configzInvalid transport: )4r   logging	getLoggersetLevelDEBUGr   r   FileNotFoundErrorr   r   ClickExceptionstrr  serverr1  r2  intr3  r[   boolr4  r5  r6  securityr7  r8  splitstripr  r\   r   r   r0   rr   r   r   itemsmcpcustom_routetoolsexcluderemove_toolr1   r/   signal	getsignalSIGINTrunKeyboardInterruptAbortr?   rf   )"r   r1  r2  r3  r1   configr[   r4  r\   r5  r6  r7  r8  ry   config_pathcfgexcrv   cli_allowlistallowlist_entriesparsed_allowlistconfigured_oauthrc   schemer=  routespathhandlerr@  	tool_nameprevious_sigint_handlerrI  rK  rC  s"                                    @r4   servers    s   z $$W]]3MDd#,,W]]; N 'v.K-+& c;	3::;O;OQXYIfdCJJOO[ID}S&$

FGDS*h

8K8KTRH c24I3::KkKkmrs !nlCJJD[D[]abL]KAWAWY]^K#C):OS\\MiMikopO'"$79Y9Y[_ EQ(:(:3(?@(?1QWWY(?@VZM)8n)MSVS_S_SlSlLT+..""#`aaO%8 99""#eff	G12CD OC0CD 	W & %""24& 9n n
 	
 	%9+?RS OI0 l)k83tfAdV,#!0%8	
 )/$D$7GT73G< )7LYY&&		ROOI&LL?9+67 ' #G"("2"26=="A	 	fmm^4
J)? +6MM&--1HI 7&&#%N1=~.0;}-GG#!+XL\n}~-5   29+>??W z* -""3s8,,-" A  	G&&)?u'EFF	GR  	RNN5i[PQ	R" &u{{3 !C ! +6MM&--1HI 7sl   R  1SS ?-TT,  S/SS	T #S;;T "T)(T),$UU UU )V r2  c                    t        |      }t        |      }t        j                  ddgd      j                  dk(  }|rt	        j
                  d       t        j                  ddgdd      }|j                  dk7  r0t	        j                  d	|j                  j                                | d
vr| gng d}t        j                  ddt        |      dt        |      g|dd      }|j                  dk7  r0t	        j                  d|j                  j                                t	        j
                  d       nt	        j
                  d       t	        j
                  d       t        j                  ddddddt        |      dt        |      ddddd| xs d gdd      }|j                  dk7  r0t	        j                  d|j                  j                                t	        j
                  d        t	        j
                  d!       t	        j
                  d"|        t	        j
                  d#|        t	        j
                  d$|        y%)&z=Generate a TLS cert/key pair, preferring mkcert over openssl.whichmkcertT)capture_outputr   u?   mkcert detected — generating a locally-trusted certificate...z-installrw  r   zmkcert -install failed:
)0.0.0.0 )	localhostr!  z::1z
-cert-filez	-key-filezmkcert failed:
z0  Certificate is automatically trusted by macOS.u=   mkcert not found — falling back to openssl (self-signed)...z=  Tip: brew install mkcert  for auto-trusted certs next time.opensslreqz-x509z-newkeyzrsa:4096z-keyoutz-outz-days365z-nodesz-subjz/CN=rx   zopenssl failed:
z%  To make macOS trust this cert, run:z4    sudo security add-trusted-cert -d -r trustRoot \z,      -k /Library/Keychains/System.keychain u     cert → u     key  → N)
r#   
subprocessrb  
returncoder   echorQ  r:   rX  rR  )r2  	cert_pathkey_pathrv  installsansresults          r4   _gen_tlsr    s   YIH~H^^Wh/EPPTUUF

TU..(J!7SWX"&&)B7>>CWCWCYBZ'[\\ _4v:[c)nS] 	  d
 !&&)9&--:M:M:O9P'QRR

EF

RS

RS5'9j3x=I4 345  d	
 !&&):6==;N;N;P:Q'RSS

:;

JL

A)MN	JJYK()	JJXJ'(r3   r  z=Transport mode to configure. Saves the choice to config.toml.)rL   r  r"  r  ry  zHost to bind the server to.)r  r"  r  zPort to bind the server to.)r  r"  rL   r  z
--with-tlsz/Generate a self-signed TLS certificate and key.)r%  r  z--forcez1Overwrite existing credentials without prompting.r1  r3  with_tlsforcec                    t         }|j                         rt        |      n	t               }|j                  j
                  r|st        j                  d| d       yt        j                  dd       t        j                  d      }||j                  _        | |j                  _        ||j                  _        ||j                  _        t        j                  d|        |rm| dk(  rt        j                  d	      t        d
z  }t        dz  }	t!        |||	       t#        |      |j                  _        t#        |	      |j                  _        t)        ||       t        j                  d|        | dk(  r+t        j                  d       t        j                  d       y|rdnd}
|
 d| d| d}|
 d| d| d}t        j                  d       t        j                  d       | dk(  r2t        j                  d       t        j                  d| d| d       yt        j                  d       t        j                  d| d| d       y)zUGenerate an auth key (and optionally TLS certs) and save to ~/.macos-mcp/config.toml.zAuth key already set in z. Use --force to regenerate.NTparentsexist_ok    zGenerated auth key: r  z%TLS has no effect on stdio transport.zcert.pemzkey.pemz

Saved to u2   
─── Claude Desktop config (stdio) ───zo{
  "mcpServers": {
    "macos-mcp": {
      "command": "uvx",
      "args": ["macos-mcp", "serve"]
    }
  }
}r9  rM   r:  r;  z/mcp/z/sseu%   
─── Start the server ───z  macos-mcp server  u0   
─── Claude Desktop config (SSE) ───zJ{
  "mcpServers": {
    "macos-mcp": {
      "type": "sse",
      "url": "z/",
      "headers": { "Authorization": "Bearer z" }
    }
  }
}u<   
─── Claude Desktop config (Streamable HTTP) ───zK{
  "mcpServers": {
    "macos-mcp": {
      "type": "http",
      "url": ")r   existsr   r   rS  r[   r   r  r   mkdirsecretstoken_urlsafer1  r2  r3  rQ  r  rR  r5  r6  r   )r1  r2  r3  r  r  rf  rg  new_keyr  r  rm  mcp_urlsse_urls                r4   authr    s"   2 K&1&8&8&:+k
"@PC
zz5

-k]:VWXTD1##B'G!CJJ$CJJCJJOCJJO	JJ%gY/0&&'NOO+		)y(+"%i.

!$X

k"	JJ[M*+G

HI


	
 	 WfFD64&.GD64&-G	JJ78	JJ"$E

FG


 i ..5Y 7		
 	

RS


 i ..5Y 7		
r3   zcom.macos-mcp.serverLibraryLaunchAgentsz.plistc                      t        j                  d      rt        fddD              sgS t        j                  d      } | r| dgS t        j                  d      )z@Return the argv prefix to invoke `macos-mcp serve` from launchd.rx   c              3   &   K   | ]  }|v  
 y wrD   r2   ).0m	macos_mcps     r4   	<genexpr>z#_resolve_program.<locals>.<genexpr>l  s     R+Qa1	>+Qs   )z	.cache/uvzuv/toolszuv\toolsuvxz]Cannot find macos-mcp or uvx in PATH.
Install via: pip install macos-mcp  or  brew install uv)shutilru  anyr   rQ  )r  r  s    @r4   _resolve_programr  g  s`    [)IR+QRR;
,,u
C
[!!


	B r3   program_argsc           	      |    t         dz  }t         dz  }dj                  d | D              }dt         d| d| d| d		S )
N
server.logzserver.error.log
c              3   (   K   | ]
  }d | d  yw)z        <string>z	</string>Nr2   )r  as     r4   r  z_build_plist.<locals>.<genexpr>z  s     O,Q+A3i8,s   z<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>z6</string>
    <key>ProgramArguments</key>
    <array>
z
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>StandardOutPath</key>
    <string>z7</string>
    <key>StandardErrorPath</key>
    <string>z</string>
</dict>
</plist>)r   join_AGENT_LABEL)r  log_outlog_errargs_xmls       r4   _build_plistr  w  sh    <'G--GyyO,OOH N  

  I I 	% r3   argsc                  8    t        j                  dg| dd      S )N	launchctlTrx  )r  rb  )r  s    r4   
_launchctlr    s    >>;..t$OOr3   r  zGTransport for the background server (stdio not supported as a service).zHost to bind.zPort to bind.z$Reinstall even if already installed.c           
         t         j                         r5|s3t        j                  dt          d       t        j                  d       yt	        j
                  dd       t        j                  dd       t               }|dd| d	|d
t        |      gz   }t         j                  t        |             t        j                  dt                 t        j                         }d| }t        d| dt                t        d|t        t                     }|j                  dk7  r0t        j                   d|j"                  j%                                t        j                  d       t        j                  d|         t        j                  d| d|        t        j                  dt        dz          t        j                  d       t        j                  d       y)zAInstall macos-mcp as a launchd Launch Agent that starts at login.z"Launch agent already installed at r   zUse --force to reinstall.NTr  rs  r  r   r#  zWrote gui/bootout/	bootstrapr   zlaunchctl bootstrap failed:
u/   Launch agent loaded — server is starting now.z  Transport : z  Address   : r;  z  Logs      : r  z6
The server will restart automatically at every login.z'Run `macos-mcp uninstall` to remove it.)_PLIST_PATHr  r   r  r   r  _LAUNCH_AGENTS_DIRr  rR  
write_textr  r<   getuidr  r  r  rQ  r:   rX  )	r1  r2  r3  r  exer  uiddomainr  s	            r4   r  r    s    E

7}AFG

./TD1TD9

C'=)XtXsSWyYYD<-.	JJ}%&
))+CC5\F yVHAl^45VS-=>FA""%B6==CVCVCXBY#Z[[	JJ@B	JJ	{+,	JJvQtf-.	JJ
\ 9:;<	JJHJ	JJ8:r3   c                     t        j                         } t        dd|  dt               }|j                  dk(  rt        j                  d       n*t        j                         rnt        j                  d       t        j                         r1t        j                          t        j                  dt                nt        j                  d       t        j                  d	       y
)zARemove the macos-mcp Launch Agent and stop the background server.r  r  r  r   zStopped the running server.zNo active launch agent found.zRemoved zPlist already removed.z(macos-mcp will no longer start at login.N)
r<   r  r  r  r  r   r  r  r  unlink)r  r  s     r4   	uninstallr    s     ))+C	T#a~#>?FA

01				

23

Xk]+,

+,	JJ9:r3   __main__)r)   N)rF  )NNN)r   NNNN)r   
   N)FN)r   r   N)Fr   FN)Nr   r   r   NrD   )r   NNN)trZ   macos_mcp.desktop.servicer   macos_mcp.desktop.viewsr   macos_mcp.watchdogr   macos_mcp.permissionsr   macos_mcp.infrastructurer   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   
contextlibr   fastmcp.utilities.typesr   	mcp.typesr   starlette.middlewarer   starlette.middleware.corsr   typingr   r   r   r0  r    r!   textwrapr"   rs   rL  r<   pathlibr#   r  r  r_  r  r8   	threadingr$   r   rM  rW   r0   r%   __annotations__r&   r'   r(   r+   r,   r   r   rz   r5   rT  r?   rA   rR  listrf   rw   rZ  toolr   r   rU  r   r   r   r   r   r   r   r   r   r  r  r  groupr  r   pass_contextoptionChoicers  r  r  r  homer  r  r  r  CompletedProcessr  r  r  r2   r3   r4   <module>r     sb   . ( ' 6    & + ) % + 4 ) ) $    	      
  			8	$!'	 !"Xd^ "#(8
 #!%	8I % $. !!  *
3 
 
1 14   $Dj+ 
	& $ $ $: ;\HM 	 V 
 
 ;C#'$(
6
7
* S	D  cT!	
 

 	 N 
 
 +2	LL
&
'L L 
	L
 	L
L 	 u 
 
(4 (g (
(V 	 e 
 
 28	F	cF-.F F 
	F
 	F
F 	 S 
 
 6<)	c)
) ) 23	)
 ) 
) 	)
)* 	 _ 
 
 .88>	c
*
+ 45 	
 
 	
" 	 \ 
 
	849 	8D 	8w 	8# 	8
	8 	 r 
 
"C "g "
"
 	 R 
 
- -' -S -
-
   	u 
 
-S -w -# -
- 	q 
 
    );;; Dj; 	 	;( 
);* 	+;
;2H Hc Hd H
u}} C  > > 	6	9	:	 	7	 	7	 	L 	.	U	# 	^	 	\ 	~#	 	Q#	 	R"	 	a&	 	;*	x@  vx@v/)3 /) /)d 	9	:	H 	&	 		& lD/`ai,_`P
C P
s P
# P
 P
d P
t P
 a b .P
f &TYY[9,~=  l^6#::$s)  tCy S 6Pc Pj99 P 	u/0	1	R h$_Uh4cXi,RS;s ;# ;S ; ;$ ; T Y V ;B ; ;* zF r3   