@@ -535,10 +535,6 @@ impl ExtensionManager {
535535 return Ok ( ( ) ) ;
536536 }
537537
538- // Resolve working_dir: explicit > current_dir
539- let effective_working_dir =
540- working_dir. unwrap_or_else ( || std:: env:: current_dir ( ) . unwrap_or_default ( ) ) ;
541-
542538 let mut temp_dir = None ;
543539
544540 let client: Box < dyn McpClientTrait > = match & config {
@@ -577,63 +573,6 @@ impl ExtensionManager {
577573 )
578574 . await ?
579575 }
580- ExtensionConfig :: Stdio {
581- cmd,
582- args,
583- envs,
584- env_keys,
585- timeout,
586- ..
587- } => {
588- let config = Config :: global ( ) ;
589- let mut all_envs =
590- merge_environments ( envs, env_keys, & sanitized_name, config) . await ?;
591-
592- if let Some ( sid) = session_id {
593- all_envs. insert ( "AGENT_SESSION_ID" . to_string ( ) , sid. to_string ( ) ) ;
594- }
595-
596- // Check for malicious packages before launching the process
597- extension_malware_check:: deny_if_malicious_cmd_args ( cmd, args) . await ?;
598-
599- let command = if let Some ( container) = container {
600- let container_id = container. id ( ) ;
601- tracing:: info!(
602- container = %container_id,
603- cmd = %cmd,
604- "Starting stdio extension inside Docker container"
605- ) ;
606- Command :: new ( "docker" ) . configure ( |command| {
607- command. arg ( "exec" ) . arg ( "-i" ) ;
608- for ( key, value) in & all_envs {
609- command. arg ( "-e" ) . arg ( format ! ( "{}={}" , key, value) ) ;
610- }
611- command. arg ( container_id) ;
612- command. arg ( cmd) ;
613- command. args ( args) ;
614- } )
615- } else {
616- let cmd = resolve_command ( cmd) ;
617- Command :: new ( cmd) . configure ( |command| {
618- command. args ( args) . envs ( all_envs) ;
619- } )
620- } ;
621-
622- let capabilities = GooseMcpClientCapabilities {
623- mcpui : self . capabilities . mcpui ,
624- } ;
625- let client = child_process_client (
626- command,
627- timeout,
628- self . provider . clone ( ) ,
629- Some ( & effective_working_dir) ,
630- container. map ( |c| c. id ( ) . to_string ( ) ) ,
631- self . client_name . clone ( ) ,
632- capabilities,
633- )
634- . await ?;
635- Box :: new ( client)
636- }
637576 ExtensionConfig :: Builtin { name, timeout, .. } => {
638577 let timeout_duration = Duration :: from_secs ( timeout. unwrap_or ( 300 ) ) ;
639578 let normalized_name = name_to_key ( name) ;
@@ -660,9 +599,14 @@ impl ExtensionManager {
660599 . arg ( & normalized_name) ;
661600 } ) ;
662601
602+ let effective_working_dir = working_dir
603+ . clone ( )
604+ . unwrap_or_else ( || std:: env:: current_dir ( ) . unwrap_or_default ( ) ) ;
605+
663606 let capabilities = GooseMcpClientCapabilities {
664607 mcpui : self . capabilities . mcpui ,
665608 } ;
609+
666610 let client = child_process_client (
667611 command,
668612 timeout,
@@ -675,12 +619,16 @@ impl ExtensionManager {
675619 . await ?;
676620 Box :: new ( client)
677621 } else {
622+ // Non-containerized builtin runs in-process via duplex channels.
623+ // Working directory is passed per-request via call_tool metadata, not here.
678624 let ( server_read, client_write) = tokio:: io:: duplex ( 65536 ) ;
679625 let ( client_read, server_write) = tokio:: io:: duplex ( 65536 ) ;
680626 extension_fn ( server_read, server_write) ;
627+
681628 let capabilities = GooseMcpClientCapabilities {
682629 mcpui : self . capabilities . mcpui ,
683630 } ;
631+
684632 Box :: new (
685633 McpClient :: connect (
686634 ( client_read, client_write) ,
@@ -693,6 +641,66 @@ impl ExtensionManager {
693641 )
694642 }
695643 }
644+ ExtensionConfig :: Stdio {
645+ cmd,
646+ args,
647+ envs,
648+ env_keys,
649+ timeout,
650+ ..
651+ } => {
652+ let config = Config :: global ( ) ;
653+ let mut all_envs =
654+ merge_environments ( envs, env_keys, & sanitized_name, config) . await ?;
655+
656+ if let Some ( sid) = session_id {
657+ all_envs. insert ( "AGENT_SESSION_ID" . to_string ( ) , sid. to_string ( ) ) ;
658+ }
659+
660+ // Check for malicious packages before launching the process
661+ extension_malware_check:: deny_if_malicious_cmd_args ( cmd, args) . await ?;
662+
663+ let command = if let Some ( container) = container {
664+ let container_id = container. id ( ) ;
665+ tracing:: info!(
666+ container = %container_id,
667+ cmd = %cmd,
668+ "Starting stdio extension inside Docker container"
669+ ) ;
670+ Command :: new ( "docker" ) . configure ( |command| {
671+ command. arg ( "exec" ) . arg ( "-i" ) ;
672+ for ( key, value) in & all_envs {
673+ command. arg ( "-e" ) . arg ( format ! ( "{}={}" , key, value) ) ;
674+ }
675+ command. arg ( container_id) ;
676+ command. arg ( cmd) ;
677+ command. args ( args) ;
678+ } )
679+ } else {
680+ let cmd = resolve_command ( cmd) ;
681+ Command :: new ( cmd) . configure ( |command| {
682+ command. args ( args) . envs ( all_envs) ;
683+ } )
684+ } ;
685+
686+ let effective_working_dir = working_dir
687+ . clone ( )
688+ . unwrap_or_else ( || std:: env:: current_dir ( ) . unwrap_or_default ( ) ) ;
689+ let capabilities = GooseMcpClientCapabilities {
690+ mcpui : self . capabilities . mcpui ,
691+ } ;
692+ let client = child_process_client (
693+ command,
694+ timeout,
695+ self . provider . clone ( ) ,
696+ Some ( & effective_working_dir) ,
697+ container. map ( |c| c. id ( ) . to_string ( ) ) ,
698+ self . client_name . clone ( ) ,
699+ capabilities,
700+ )
701+ . await ?;
702+ Box :: new ( client)
703+ }
696704 ExtensionConfig :: Platform { name, .. } => {
697705 let normalized_key = name_to_key ( name) ;
698706 let def = PLATFORM_EXTENSIONS
@@ -724,6 +732,11 @@ impl ExtensionManager {
724732 command. arg ( "python" ) . arg ( file_path. to_str ( ) . unwrap ( ) ) ;
725733 } ) ;
726734
735+ // Compute working_dir for InlinePython (runs as child process via uvx)
736+ let effective_working_dir = working_dir
737+ . clone ( )
738+ . unwrap_or_else ( || std:: env:: current_dir ( ) . unwrap_or_default ( ) ) ;
739+
727740 let capabilities = GooseMcpClientCapabilities {
728741 mcpui : self . capabilities . mcpui ,
729742 } ;
0 commit comments