+
    r+UjR                      a  0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RI	t]P                  P                  RR4      P                  R4      t]P                  P                  RR4      t]P                  P                  RR4      tRsR	]R
&   R R ltR R ltR#R R lltR R ltR R ltR$R R lltR R ltR R ltR R ltR R ltRtR  R! ltR" tR# )%u0  Asana project management — in-process MCP so Jarvis runs Ahmed's projects.

Asana (app.asana.com) is where Ahmed's PROJECT work lives: projects, their tasks,
due dates, assignees and comment threads. This module gives Jarvis hands on it by
voice — read what's on a project, what's on his own plate, create/update/complete
tasks, comment, and search. Distinct from mcp__tasks__* (his personal to-do list
on the Railway brain).

Auth: a Personal Access Token in .env as ASANA_PAT, sent as
`Authorization: Bearer <pat>` (Asana's scheme). MCP_ASANA=0 disables the whole
server. Optional ASANA_WORKSPACE (gid or name) pins the workspace when the
account has more than one; otherwise the first workspace is used and cached.
No extra deps — stdlib urllib, same as the other _control.py modules.

Everything a tool returns is SPOKEN ALOUD, so results are short plain prose /
plain "- name — due …" lines. Never markdown, never a JSON dump, never a
traceback: failures come back as one human sentence.

Tools (Claude sees them as mcp__asana__<name>):
  asana_workspaces     list workspaces (and cache the default)
  asana_projects       list projects in the workspace, optional name filter
  asana_tasks          open tasks on a project, or Ahmed's own ("my tasks")
  asana_task_create    new task (project / assignee / due date / notes)
  asana_task_update    rename, re-note, re-date, re-assign, (un)complete
  asana_task_complete  shortcut for "mark it done"
  asana_comment        add a comment to a task
  asana_search         typeahead across tasks + projects in the workspace
)annotationsN	ASANA_URLzhttps://app.asana.com/api/1.0/	ASANA_PAT ASANA_WORKSPACE
str | None_ws_gidc                   V ^8  d   QhRR/# )   returnbool )formats   "A/Users/ahmed/devFolder/Ultron/claude-voice/voice/asana_control.py__annotate__r   -   s           c                 n    \         P                  P                  RR4      R8X  d   R# \        \        4      # )zGOn when a Personal Access Token is present and not explicitly disabled.	MCP_ASANA10F)osenvirongetr   _PATr   r   r   enabledr   -   s&    	zz~~k3'3.:r   c                    V ^8  d   QhRRRR/# )r   msgstrr   dictr   )r   s   "r   r   r   4   s     8 8s 8t 8r   c                    R RRRV /./# )contenttypetextr   )r   s   &r   _textr$   4   s    5677r   c               (    V ^8  d   QhRRRRRRRR/# )r   methodr   pathbodyzdict | Nonetimeoutintr   )r   s   "r   r   r   <   s(          C  {  C  r   c                   \         '       g   \        R4      hVP                  R4      '       g
   RV,           pVe'   \        P                  ! RV/4      P                  4       MRp\        P                  P                  \        V,           W@R7      pVP                  RR\          24       VP                  RR	4       VP                  R
R	4        \        P                  P                  WSR7      ;_uu_ 4       pVP                  4       pRRR4       X'       d   \        P                   ! T4      M/ pTP#                  RT4      #   + '       g   i     LB; i  \        P                  P                   d   pTP                  4       R,          P                  RR4      p	 \        P                   ! T	4      P#                  R4      ;'       g    . p
RP%                  R T
 4       4      ;'       g    T	pM  \&         d    T	p Mi ; iTP(                  R8X  d   Rp\        T R,          4      hRp?i\        P                  P*                   d/   p\        R\-        TP.                  4      R,           R24      hRp?ii ; i)zOne Asana REST call. Returns the unwrapped `data` payload. Raises
RuntimeError with Asana's own message on a non-2xx so the tool can speak it.z,Asana isn't connected (no ASANA_PAT in .env)r   Ndata)r,   r&   AuthorizationzBearer zContent-Typezapplication/jsonAccept)r)   :Ni  Nzutf-8ignoreerrorsz; c              3  X   "   T F   p\        VP                  R R4      4      x  K"  	  R# 5i)messager   N)r   r   ).0xs   & r   	<genexpr>_api.<locals>.<genexpr>O   s#     Dt!Ci 455ts   (*i  z*Asana rejected the token (check ASANA_PAT):Ni,  Nzcouldn't reach Asana (:NP   N))r   RuntimeError
startswithjsondumpsencodeurllibrequestRequest_BASE
add_headerurlopenreaderror	HTTPErrordecodeloadsr   join	ExceptioncodeURLErrorr   reason)r&   r'   r(   r)   r,   reqrrawedetailerrsr   outs   &&&&         r   _apirU   <   s    4IJJ??3Tz262B4::vtn%,,.D
..
 
 D
 
HCNN?gdV$45NN>#56NN8/0K^^##C#99Q&&(C : !$**S/bC7763 :9<<!! 	+$&&w9	::f%))(399rD))DtDDNNC 	C	66S=>CcUD>**<<   K3CM#4F3GqIJJKss   (E 6EE E	E E I63'H&AG-)G-,H&-G=:H&<G==)H&& I6I6)I11I6c               $    V ^8  d   QhRRRRRR/# )r   r'   r   paramsr   r   r   )r   s   "r   r   r   [   s&     H HS H$ H3 Hr   c                    VP                  4        UUu/ uF  w  r#VR9  g   K  W#bK  	  pppV'       d%   V  R\        P                  P                  V4       2# T # u uppi )z-Append a query string, dropping empty values.?)r   N)itemsr>   parse	urlencode)r'   rW   kvcleans   &&   r   _qr`   [   sW    $llnDnda0CTQTnED8=dV1V\\++E234G4G Es
   AAc                   V ^8  d   QhRR/# )r   r   r   r   )r   s   "r   r   r   e   s      C r   c                    \         '       d   \         # \        P                  4       '       d   \        s \         # \        RR4      ;'       g    . p V '       g   \	        R4      h\        '       dd   V  F]  p\        VP                  RR4      4      P                  4       \        P                  4       8X  g   KE  \        VR,          4      s \         u # 	  \        V ^ ,          R,          4      s \         # )z}The workspace gid, resolved once and cached. Honours ASANA_WORKSPACE
(gid or name), else takes the account's first workspace.GET/workspacesz$this Asana account has no workspacesnamer   gid)r	   _WS_PREFisdigitrU   r9   r   r   lower)spacesws     r   
_workspacerl   e   s     w%'--2FABBxA155$%++-1AAah-  &)E"#GNr   c               (    V ^8  d   QhRRRRRRRR/# )r   resource_typer   querycountr*   r   
list[dict]r   )r   s   "r   r   r   z   s(     3 3c 3# 3c 3: 3r   c                j    \        4       p\        R\        RV R2RV RVRV/4      4      ;'       g    . # )zEAsana's fuzzy search inside the workspace (tasks / projects / users).rc   z/workspaces/z
/typeaheadrn   ro   rp   )rl   rU   r`   )rn   ro   rp   wss   &&& r   
_typeaheadrt   z   sJ    	BrLJ7*M7E"E+, - 3 3023r   c               $    V ^8  d   QhRRRRRR/# )r   rZ   rq   refr   r   r   r   )r   s   "r   r   r      s!     	 	 	# 	* 	r   c                R   VP                  4       pV  FE  p\        VP                  RR4      4      P                  4       V8X  g   K3  \        VR,          4      u # 	  V  FE  pV\        VP                  RR4      4      P                  4       9   g   K3  \        VR,          4      u # 	  R# )zAExact (case-insensitive) name match first, then a contains-match.re   r   rf   N)ri   r   r   )rZ   rv   lowis   &&  r   _pickrz      s    
))+CquuVR !'')S0qx=   #aeeFB'(..00qx=   r   c                    V ^8  d   QhRRRR/# r   rv   r   r   r   r   )r   s   "r   r   r      s      c j r   c                P   \        V 4      P                  4       p V '       g   R# V P                  4       '       d   V #  \        \	        RV 4      V 4      pV'       d   V# \        R\        RR\        4       RRR^d/4      4      ;'       g    . p\        W 4      #   \         d     R# i ; i)	zGResolve a project from a gid or a spoken name ('the website redesign').Nprojectrc   	/projects	workspacearchivedfalselimit)	r   striprh   rz   rt   rU   r`   rl   rJ   )rv   hitprojectss   &  r   _project_gidr      s    
c(..
C
{{}}
Jy#.4J r+Z\0:G070>  ? @ F FCE 	 X## s   B 8B B%$B%c                    V ^8  d   QhRRRR/# r|   r   )r   s   "r   r   r      s     
 
3 
: 
r   c                    \        V 4      P                  4       p V '       g   R# V P                  4       '       d   V #  \        \	        RV 4      V 4      #   \
         d     R# i ; i)z+Resolve a task from a gid or a spoken name.Ntask)r   r   rh   rz   rt   rJ   rv   s   &r   	_task_gidr      sS    
c(..
C
{{}}
Z,c22 s   A A"!A"c                    V ^8  d   QhRRRR/# r|   r   )r   s   "r   r   r      s      3 : r   c                   \        V 4      P                  4       p V '       d   V P                  4       R9   d   R# V P                  4       '       g   RV 9   d   V #  \	        \        RV 4      V 4      #   \         d     R# i ; i)zuResolve an assignee: 'me' / 'myself' / '' stay as 'me'; anything else is
looked up by name or email in the workspace.me@userN)r   myselfahmedry   )r   r   ri   rh   rz   rt   rJ   r   s   &r   	_assigneer      si     c(..
C#))+!??
{{}}s

Z,c22 s   A/ /A>=A>z1name,due_on,completed,assignee.name,projects.namec                    V ^8  d   QhRRRR/# )r   tr   r   r   r   )r   s   "r   r   r      s     	A 	A$ 	A3 	Ar   c                   \        V P                  R R4      4      .pV P                  R4      '       d   VP                  RV R,           24       V P                  R4      ;'       g    / P                  R 4      pV'       d   VP                  V4       V P                  R4      '       d   VP                  R4       RRP                  V4      ,           R	V P                  R
4       R2,           # )re   z
(untitled)due_ondue assignee	completeddone- u    —   [gid rf   ])r   r   appendrI   )r   bitswhos   &  r   
_task_liner      s    fl+,-DuuXd1X;-()55""
'
'
/C
Cuu[F',,t$$ua'@@@r   c                 t  a
 ^ RI o
^ RIHp Hp V ! RR/ 4      R V
3R ll4       pV ! RRR	\        /4      R
 V
3R ll4       pV ! RRR\        R\        /4      R V
3R ll4       pV ! RRR\        R\        R\        R\        R\        /4      R V
3R ll4       pV ! RRR\        R\        R\        R\        R\        R\        /4      R V
3R ll4       pV ! RR R\        /4      R! V
3R" ll4       pV ! R#R$R\        R%\        /4      R& V
3R' ll4       pV ! R(R)R*\        /4      R+ V
3R, ll4       p	V! R-R.W#WEWgVV	.R/7      # )0    N)toolcreate_sdk_mcp_serverasana_workspacesu   List the Asana workspaces this account can see (and remember the default one for every other asana tool). Rarely needed — only for 'which Asana am I on' or when a project can't be found.c                    V ^8  d   QhRRRR/# r   argsr   r   r   )r   s   "r   r   "build_server.<locals>.__annotate__   s     P PT Pd Pr   c           	       <"    SP                  \        R R4      G Rj  xL
 pV'       g   \        R4      # SP                  \        4      G Rj  xL
 pV Uu. uF?  pRVP	                  R4       2\        VP	                  R4      4      V8X  d   RMR,           NKA  	  pp\        \        V4       R	2R
P                  V4      ,           4      #  L L~u upi   \         d)   p\        R\        T4      R,           24      u Rp?# Rp?ii ; i5i)rc   rd   Nz$No Asana workspaces on this account.r   re   rf   z
 (default)r   z workspace(s):

z$Couldn't read the Asana workspaces: N   N)		to_threadrU   r$   rl   r   r   lenrI   rJ   )r   rj   defaultrk   linesrQ   asyncios   &     r   r   &build_server.<locals>.asana_workspaces   s     

	P",,T5-HHFCDD#--j99G %&$ !%%-)(+AEE%L(9W(D"N N$  & CK=(89DIIe<LLMM I :&  	P?At~NOO	Psx   DC CC 
C DC CC AC.C DC C C D D=D>DDDasana_projectsu   List Ahmed's active Asana projects. `filter` is optional — a word or two to narrow it ('redesign', 'client'). Use for 'what projects do I have', 'what's in Asana', 'find the website project'.filterc                    V ^8  d   QhRRRR/# r   r   )r   s   "r   r   r      s     N N4 ND Nr   c                  <"   \        V P                  R R4      4      P                  4       P                  4       p SP	                  \
        R\        RR\        4       RRR^d/4      4      G Rj  xL
 pV'       dB   V Uu. uF5  pV\        VP                  R	R4      4      P                  4       9   g   K3  VNK7  	  ppV'       g   \        V'       d   R
4      # R4      # V Uu. uF*  pRVP                  R	4       RVP                  R4       R2NK,  	  pp\        \        V4       R2RP                  V4      ,           4      #  Lu upi u upi   \         d)   p\        R\        T4      R,           24      u Rp?# Rp?ii ; i5i)r   r   rc   r   r   r   r   r   Nre   zNo matching Asana projects.zNo active Asana projects.r   r   rf   r   z project(s):
r   z"Couldn't list the Asana projects: r   )r   r   r   ri   r   rU   r`   rl   r$   r   rI   rJ   )r   fltr   pr   rQ   r   s   &     r   r   $build_server.<locals>.asana_projects   so     $((8R()//1779	N$..eRk:<.8'.5s.< => >H '/ Fx!"c!%%*;&<&B&B&DD Ax F # ; F F)DF FIQRAr!%%-e~Q?ERCM?.9DIIe<LLMM>
F
 S 	N=c!fTl^LMM	Ns   8F2E .E /E ;E ?0E4E:	E E FE FE !0E.E ?F E 
E E?E:4E?5F:E??Fasana_tasksa!  List OPEN Asana tasks (completed ones are hidden). Give `project` = a project name or gid for that project's tasks, or leave it empty to get Ahmed's OWN assigned tasks ('what's on my plate', 'my Asana tasks'). `assignee` optionally filters a project's tasks to one person ('me' or a name).r~   r   c                    V ^8  d   QhRRRR/# r   r   )r   s   "r   r   r     s     (K (K (K (Kr   c                n  <"   \        V P                  R R4      4      P                  4       p\        V P                  RR4      4      P                  4       p V'       Ed=   SP                  \        V4      G Rj  xL
 pV'       g   \        RV: R24      # R VRRR^dR	\        /pV'       d2   SP                  \        V4      G Rj  xL
 pV'       d   VR
8w  d   WTR&   SP                  \        R\        RV4      4      G Rj  xL
 pV'       d   VP                  4       R9   d   R
MVP                  4       pV Uu. uFU  pVR
8X  gJ   T\        VP                  R4      ;'       g    / P                  RR4      4      P                  4       9   g   KS  VNKW  	  ppRV 2p	MSP                  \        T;'       g    R
4      G Rj  xL
 pSP                  \        R\        RRT;'       g    R
R\        4       RRR^dR	\        /4      4      G Rj  xL
 pV'       d   VR
8X  d   RMRV 2p	V Uu. uF  qP                  R4      '       d   K  VNK  	  ppV'       g   \        V	 R24      # VR,           Uu. uF  p\        V4      NK  	  p
p\        V4      ^(8  d   R\        V4      ^(,
           R2MRp\        V	 R\        V4       R2RP                  V
4      ,           V,           4      #  ELi EL  ELu upi  EL1 Lu upi u upi   \         d)   p\        R\        T4      R,           24      u Rp?# Rp?ii ; i5i)r~   r   r   N!I couldn't find a project called u+    — try asana_projects for the exact name.completed_sincenowr   
opt_fieldsr   rc   /tasksre   zOpen tasks on r   zYour open Asana taskszOpen tasks for r   z: nothing open.:N(   Nz
(+z more)z (z):
r   zCouldn't read the Asana tasks: r   )r   r   )r   r   r   r   r   r$   _TASK_FIELDSr   rU   r`   ri   rl   r   r   rI   rJ   )r   projr   pidrW   rf   tasksrx   r   labelr   morerQ   r   s   &            r   r   !build_server.<locals>.asana_tasks  s     488Ir*+113$((:r*+113%	Kt#--lDAA #DTH MJ "J K K#S*;U!3lD ' 1 1)S AACsd{-0z*%//eR&=QRR"%))+1A"A$syy{C(- 71 #t #sAEE*,=,C,C+H+H!',- (..3eg!6 QE 7 )/#--iEE%//%Hz3;;$/:JL/@%/6/;\	/K "LM M 8;cTk/*3%0  %@1UU;-?QQE@wo677,1#J7JqZ]JE758Z"_T#e*r/*&1"DE7"SZL5		%8HH4OPPC B B S7 FM A 8  	K:3q6$<.IJJ	Ks  AL5"K? 9K":K? K? L5K? ,K? K%K? /K? K(K? +K? 9)K+#&K+K+ K? 5
K? ?K0 $K? %#K? K3	K? K? 'K5K5
K? !L5"K? -K:A K? !L5"K? %K? (K? +K? 3K? 5
K? ?L2
L-'L2(L5-L22L5asana_task_createuz  Create an Asana task. `name` (short, imperative) is required. `project` = the project name or gid to file it under (optional — without one it lands in Ahmed's My Tasks). `notes` = optional detail. `assignee` = a person's name, or 'me' (the default). `due_on` = a date as YYYY-MM-DD — resolve 'tomorrow' / 'next Thursday' to a real date yourself (Asia/Riyadh) before calling.re   notesr   c                    V ^8  d   QhRRRR/# r   r   )r   s   "r   r   r   ;  s     L Ld Lt Lr   c           
       <"   \        V P                  R R4      4      P                  4       pV'       g   \        R4      # R VRR/p S
P	                  \
        4      G Rj  xL
 VR&   \        V P                  RR4      4      P                  4       pV'       d=   S
P	                  \        V4      G Rj  xL
 pV'       g   \        RV: R24      # V.VR&   V P                  R	4      '       d   \        V R	,          4      VR	&   V P                  R
4      '       d+   \        V R
,          4      P                  4       R,          VR
&   S
P	                  \        \        V P                  RR4      4      ;'       g    R4      G Rj  xL
 pV'       d   WRR&   S
P	                  \        RRV4      G Rj  xL
 pV'       d   RV 2MRpVP                  R
4      '       d   RVR
,           2MRp\        RV: V V RVP                  R4       R24      #  EL ELZ L Lf  \         d)   p	\        R\        T	4      R,           24      u Rp	?	# Rp	?	ii ; i5i)re   r   z I need a task name to create it.r   Nr~   r   u    — nothing was created.r   r   r   N
   Nr   r   POSTr   z on z, due zCreated z. [gid rf   r   z Couldn't create the Asana task: r   )
r   r   r   r$   r   rl   r   r   rU   rJ   )r   re   r(   r   r   r   r   wherewhenrQ   r   s   &         r   r   'build_server.<locals>.asana_task_create2  s     488FB'(..0;<<dK6	L&-&7&7
&C CDtxx	2./557D#--lDAA #DTH M8 "8 9 9$'5Z xx   #DM 2Wxx!!!$T(^!4!:!:!<S!AX)))*-dhhz2.F*G*O*O4Q QC#&Z ''fhEEA%)d4&MrE040B0BVDN+,D8D8E74&e~QOPP' !D BQ F  	L;CF4L>JKK	Ls   AIH H AH 1H2H >H IH ++H AH 3
H =H>H 
H )H*H 6H 3H IH H H H II :I;I IIasana_task_updateaK  Change an existing Asana task. `task` = its gid or its name (a name is matched fuzzily). Then set only what changes: `name` (rename), `notes`, `due_on` (YYYY-MM-DD), `assignee` (a person's name or 'me'), `complete` ('true' to close it, 'false' to reopen). Use for 'push that to Friday', 'give it to Sara', 'reopen the launch task'.r   completec                    V ^8  d   QhRRRR/# r   r   )r   s   "r   r   r   `  s     'L 'Ld 'Lt 'Lr   c                "  <"   \        V P                  R R4      4      P                  4       pV'       g   \        R4      # / p. p S	P	                  \
        V4      G Rj  xL
 pV'       g   \        RV: R24      # V P                  R4      '       d@   \        V R,          4      P                  4       VR&   VP                  RVR,          : 24       V P                  R4      '       d'   \        V R,          4      VR&   VP                  R	4       V P                  R
4      '       dF   \        V R
,          4      P                  4       R,          VR
&   VP                  RVR
,           24       V P                  R4      '       dm   S	P	                  \        \        V R,          4      4      G Rj  xL
 pV'       g   \        RV R,          : R24      # WRR&   VP                  RV R,           24       \        V P                  RR4      4      P                  4       P                  4       pVR9   d   RVR&   VP                  R4       MVR 9   d   RVR&   VP                  R4       V'       g   \        R4      # S	P	                  \        RRV 2V4      G Rj  xL
 p\        RVP                  RV4       R2RP                  V4      ,           R,           4      #  ELs EL* LF  \         d)   p\        R\        T4      R,           24      u Rp?# Rp?ii ; i5i)!r   r   zI need which task to update.N I couldn't find a task matching .re   zrenamed to r   znotes updatedr   r   r   r   zI couldn't find anyone called z in the workspace.zassigned to r   Tr   zmarked doneFreopenedu-   Nothing to change — tell me what to update.PUT/tasks/zUpdated z: z, z Couldn't update the Asana task: r   )trueyesr   r   )r   nor   reopen)r   r   r   r$   r   r   r   r   ri   rU   rI   rJ   )
r   rv   r(   changestidr   compr   rQ   r   s
   &        r   r   'build_server.<locals>.asana_task_updateX  s     $((62&'--/788!	L)))S99C?waHIIxx"4<0668VT&\,<=>xx   #DM 2W/xx!!!$T(^!4!:!:!<S!AXd8n%567xx
###--iT*=M9NOO #A$($4#77I"K L L#&Z d:.>-?@Atxx
B/0668>>@D33$([!}-77$)[!z*LMM''ewse_dKKA8AEE&#$6#7r:99W-.034 5 5; : P L  	L;CF4L>JKK	Ls   ALK KK +K :L;K AK (<K %AK )K *K+K 7K LBK '
K 1L2K K?K LK K K L$LLLLLasana_task_completezMark an Asana task done. `task` = its gid or its name. Use for 'tick off the landing page task', 'that Asana task is finished'.c                    V ^8  d   QhRRRR/# r   r   )r   s   "r   r   r     s     N N N Nr   c                  <"   \        V P                  R R4      4      P                  4       pV'       g   \        R4      #  SP	                  \
        V4      G Rj  xL
 pV'       g   \        RV: R24      # SP	                  \        RRV 2RR	/4      G Rj  xL
 p\        R
VP                  RV4       R24      #  L` L%  \         d)   p\        R\        T4      R,           24      u Rp?# Rp?ii ; i5i)r   r   zI need which task to complete.Nr   r   r   r   r   TzMarked re   z done in Asana.z"Couldn't complete the Asana task: r   r   r   r   r$   r   r   rU   rJ   )r   rv   r   r   rQ   r   s   &    r   r   )build_server.<locals>.asana_task_complete  s     
 $((62&'--/9::	N)))S99C?waHII''ewse_)4d(;= =A7155#5"6oFGG :=  	N=c!fTl^LMM	Nsk   =C5B? B;B? 'B? 6C57 B? B="B? :C5;B? =B? ?C2
C-'C2(C5-C22C5asana_commentzAdd a comment to an Asana task so the team sees it. `task` = its gid or name, `text` = the comment. Use for 'comment on the design task that the client approved'.r#   c                    V ^8  d   QhRRRR/# r   r   )r   s   "r   r   r     s     M M$ M4 Mr   c                *  <"   \        V P                  R R4      4      P                  4       p\        V P                  RR4      4      P                  4       pV'       d	   V'       g   \        R4      #  SP	                  \
        V4      G Rj  xL
 pV'       g   \        RV: R24      # SP	                  \        RRV R	2RV/4      G Rj  xL
  \        R
4      #  LM L  \         d)   p\        R\        T4      R,           24      u Rp?# Rp?ii ; i5i)r   r   r#   z%I need both the task and what to say.Nr   r   r   r   z/storieszComment posted.z!Couldn't post the Asana comment: r   r   )r   rv   r#   r   rQ   r   s   &    r   r   #build_server.<locals>.asana_comment  s     
 $((62&'--/488FB'(..0$@AA	M)))S99C?waHII##D&GC52I%+TN4 4 4*++ :4  	M<SVD\NKLL	Msr   A"D&D2C CC C 'D(!C 	C
C DC C D(DDDDDasana_searchzSearch Asana for tasks and projects by keyword when you don't know where something lives ('find the invoice task', 'is there anything about the Riyadh launch'). `query` = a word or two.ro   c                    V ^8  d   QhRRRR/# r   r   )r   s   "r   r   r     s     A A A$ Ar   c           
     b  <"   \        V P                  R R4      4      P                  4       pV'       g   \        R4      #  SP	                  \
        RV^
4      G Rj  xL
 pSP	                  \
        RV^
4      G Rj  xL
 pV'       g   V'       g   \        RV: R24      # . pV'       dP   VP                  R4       TV Uu. uF*  pR	VP                  R
4       RVP                  R4       R2NK,  	  up,          pV'       dO   VP                  R4       YB Uu. uF*  pR	VP                  R
4       RVP                  R4       R2NK,  	  up,          p\        RP                  V4      4      #  EL Lu upi u upi   \         d)   p\        R\        T4      R,           24      u Rp?# Rp?ii ; i5i)ro   r   zI need something to search for.r   Nr~   zNothing in Asana matches r   z	Projects:r   re   r   rf   r   zTasks:r   zAsana search failed: r   )	r   r   r   r$   r   rt   r   rI   rJ   )	r   qr   r   rT   r   r   rQ   r   s	   &       r   r   "build_server.<locals>.asana_search  sy    
 "%&,,.:;;	A!++J2FFE$..z9aLLH8Q?@@C

;'!)+!)A QUU6]O7155<.B!)+ +

8$EREq"QUU6]O7155<.BERR3(( GL+ S 	A0Q?@@	As   =F/E9 E*E9 <E-=E9 	E9 E9  F/!	E9 +E9 0E/1E9 E9 0E4"E9 )F/*E9 -E9 /
E9 9F,F'!F,"F/'F,,F/asanaz1.0.0)re   versiontools)r   claude_agent_sdkr   r   r   )r   r   r   r   r   r   r   r   r   r   r   s             @r   build_serverr      s   <	
DEGIP	IP 

B S/	
N
N$ 
-
 c:s
+-(K-(KT 

3 3	3j#SLL: 

E
 3Wc8SsJ-.'L.'LR 

G3-N	N 
/')/fc(BDM	DM 
.@BI3QA	QA* !g } r   )N   )   )__conditional_annotations____doc__
__future__r   r;   r   urllib.errorr>   urllib.parseurllib.requestr   r   rstriprA   r   rg   r	   __annotations__r   r$   rU   r`   rl   rt   rz   r   r   r   r   r   r   )r   s   @r   <module>r     s   8 #  	   


{$CDKKCP	zz~~k2&::>>+R0  8 >H*3	*
$ C	A wr   