@@ -35,7 +35,9 @@ use async_channel::Sender;
3535use codex_async_utils:: CancelErr ;
3636use codex_async_utils:: OrCancelExt ;
3737use codex_config:: Constrained ;
38+ use codex_config:: McpServerEnvironment ;
3839use codex_config:: types:: OAuthCredentialsStoreMode ;
40+ use codex_exec_server:: Environment ;
3941use codex_protocol:: ToolName ;
4042use codex_protocol:: approvals:: ElicitationRequest ;
4143use codex_protocol:: approvals:: ElicitationRequestEvent ;
@@ -50,6 +52,7 @@ use codex_protocol::protocol::McpStartupStatus;
5052use codex_protocol:: protocol:: McpStartupUpdateEvent ;
5153use codex_protocol:: protocol:: SandboxPolicy ;
5254use codex_rmcp_client:: ElicitationResponse ;
55+ use codex_rmcp_client:: ExecutorStdioServerLauncher ;
5356use codex_rmcp_client:: LocalStdioServerLauncher ;
5457use codex_rmcp_client:: RmcpClient ;
5558use codex_rmcp_client:: SendElicitation ;
@@ -493,6 +496,8 @@ impl AsyncManagedClient {
493496 elicitation_requests : ElicitationRequestManager ,
494497 codex_apps_tools_cache_context : Option < CodexAppsToolsCacheContext > ,
495498 tool_plugin_provenance : Arc < ToolPluginProvenance > ,
499+ environment : Option < Arc < Environment > > ,
500+ remote_stdio_cwd : PathBuf ,
496501 ) -> Self {
497502 let tool_filter = ToolFilter :: from_config ( & config) ;
498503 let startup_snapshot = load_startup_cached_codex_apps_tools_snapshot (
@@ -509,8 +514,16 @@ impl AsyncManagedClient {
509514 return Err ( error. into ( ) ) ;
510515 }
511516
512- let client =
513- Arc :: new ( make_rmcp_client ( & server_name, config. transport , store_mode) . await ?) ;
517+ let client = Arc :: new (
518+ make_rmcp_client (
519+ & server_name,
520+ config. clone ( ) ,
521+ store_mode,
522+ environment,
523+ remote_stdio_cwd,
524+ )
525+ . await ?,
526+ ) ;
514527 match start_server_task (
515528 server_name,
516529 client,
@@ -710,6 +723,8 @@ impl McpConnectionManager {
710723 submit_id : String ,
711724 tx_event : Sender < Event > ,
712725 initial_sandbox_policy : SandboxPolicy ,
726+ environment : Option < Arc < Environment > > ,
727+ remote_stdio_cwd : PathBuf ,
713728 codex_home : PathBuf ,
714729 codex_apps_tools_cache_key : CodexAppsToolsCacheKey ,
715730 tool_plugin_provenance : ToolPluginProvenance ,
@@ -754,6 +769,8 @@ impl McpConnectionManager {
754769 elicitation_requests. clone ( ) ,
755770 codex_apps_tools_cache_context,
756771 Arc :: clone ( & tool_plugin_provenance) ,
772+ environment. clone ( ) ,
773+ remote_stdio_cwd. clone ( ) ,
757774 ) ;
758775 clients. insert ( server_name. clone ( ) , async_managed_client. clone ( ) ) ;
759776 let tx_event = tx_event. clone ( ) ;
@@ -1483,9 +1500,17 @@ struct StartServerTaskParams {
14831500
14841501async fn make_rmcp_client (
14851502 server_name : & str ,
1486- transport : McpServerTransportConfig ,
1503+ config : McpServerConfig ,
14871504 store_mode : OAuthCredentialsStoreMode ,
1505+ exec_environment : Option < Arc < Environment > > ,
1506+ remote_stdio_cwd : PathBuf ,
14881507) -> Result < RmcpClient , StartupOutcomeError > {
1508+ let McpServerConfig {
1509+ transport,
1510+ environment,
1511+ ..
1512+ } = config;
1513+
14891514 match transport {
14901515 McpServerTransportConfig :: Stdio {
14911516 command,
@@ -1501,7 +1526,26 @@ async fn make_rmcp_client(
15011526 . map ( |( key, value) | ( key. into ( ) , value. into ( ) ) )
15021527 . collect :: < HashMap < _ , _ > > ( )
15031528 } ) ;
1504- let launcher = Arc :: new ( LocalStdioServerLauncher ) as Arc < dyn StdioServerLauncher > ;
1529+ let launcher = match environment {
1530+ McpServerEnvironment :: Local => {
1531+ Arc :: new ( LocalStdioServerLauncher ) as Arc < dyn StdioServerLauncher >
1532+ }
1533+ McpServerEnvironment :: Remote => {
1534+ let exec_environment = exec_environment. ok_or_else ( || {
1535+ StartupOutcomeError :: from ( anyhow ! (
1536+ "remote MCP server `{server_name}` requires an executor environment"
1537+ ) )
1538+ } ) ?;
1539+ Arc :: new ( ExecutorStdioServerLauncher :: new (
1540+ exec_environment. get_exec_backend ( ) ,
1541+ remote_stdio_cwd,
1542+ ) )
1543+ }
1544+ } ;
1545+
1546+ // `RmcpClient` always sees a launched MCP stdio server. The
1547+ // launcher hides whether that means a local child process or an
1548+ // executor process whose stdin/stdout bytes cross the process API.
15051549 RmcpClient :: new_stdio_client ( command_os, args_os, env_os, & env_vars, cwd, launcher)
15061550 . await
15071551 . map_err ( |err| StartupOutcomeError :: from ( anyhow ! ( err) ) )
@@ -1511,23 +1555,34 @@ async fn make_rmcp_client(
15111555 http_headers,
15121556 env_http_headers,
15131557 bearer_token_env_var,
1514- } => {
1515- let resolved_bearer_token =
1516- match resolve_bearer_token ( server_name, bearer_token_env_var. as_deref ( ) ) {
1517- Ok ( token) => token,
1518- Err ( error) => return Err ( error. into ( ) ) ,
1519- } ;
1520- RmcpClient :: new_streamable_http_client (
1521- server_name,
1522- & url,
1523- resolved_bearer_token,
1524- http_headers,
1525- env_http_headers,
1526- store_mode,
1527- )
1528- . await
1529- . map_err ( StartupOutcomeError :: from)
1530- }
1558+ } => match environment {
1559+ McpServerEnvironment :: Local => {
1560+ // Local streamable HTTP remains the existing reqwest path from
1561+ // the orchestrator process.
1562+ let resolved_bearer_token =
1563+ match resolve_bearer_token ( server_name, bearer_token_env_var. as_deref ( ) ) {
1564+ Ok ( token) => token,
1565+ Err ( error) => return Err ( error. into ( ) ) ,
1566+ } ;
1567+ RmcpClient :: new_streamable_http_client (
1568+ server_name,
1569+ & url,
1570+ resolved_bearer_token,
1571+ http_headers,
1572+ env_http_headers,
1573+ store_mode,
1574+ )
1575+ . await
1576+ . map_err ( StartupOutcomeError :: from)
1577+ }
1578+ McpServerEnvironment :: Remote => Err ( StartupOutcomeError :: from ( anyhow ! (
1579+ // Remote HTTP needs the future low-level executor
1580+ // `network/request` API so reqwest runs on the executor side.
1581+ // Do not fall back to local HTTP here; the config explicitly
1582+ // asked for remote placement.
1583+ "remote streamable HTTP MCP server `{server_name}` is not implemented yet"
1584+ ) ) ) ,
1585+ } ,
15311586 }
15321587}
15331588
0 commit comments