@@ -10,9 +10,17 @@ import {CodexApprovalHandler} from "./CodexApprovalHandler";
1010import { CodexAuthMethods , type CodexAuthRequest } from "./CodexAuthMethod" ;
1111import { CodexAcpClient , type SessionMetadata , type SessionMetadataWithThread } from "./CodexAcpClient" ;
1212import { ACPSessionConnection , type UpdateSessionEvent } from "./ACPSessionConnection" ;
13- import type { Account , CollabAgentToolCallStatus , Model , Thread , ThreadItem , UserInput , ReasoningEffortOption } from "./app-server/v2" ;
13+ import type { McpStartupCompleteEvent , InputModality , ReasoningEffort } from "./app-server" ;
14+ import type {
15+ Account ,
16+ CollabAgentToolCallStatus ,
17+ Model ,
18+ Thread ,
19+ ThreadItem ,
20+ UserInput ,
21+ ReasoningEffortOption
22+ } from "./app-server/v2" ;
1423import type { RateLimitsMap } from "./RateLimitsMap" ;
15- import type { InputModality , ReasoningEffort } from "./app-server" ;
1624import { ModelId } from "./ModelId" ;
1725import { AgentMode } from "./AgentMode" ;
1826import type { TokenCount } from "./TokenCount" ;
@@ -43,6 +51,10 @@ export interface SessionState {
4351 sessionMcpServers ?: Array < string > ;
4452}
4553
54+ interface PendingMcpStartupSession {
55+ requestedServers : Set < string > ;
56+ }
57+
4658export class CodexAcpServer implements acp . Agent {
4759 private readonly codexAcpClient : CodexAcpClient ;
4860 private readonly connection : acp . AgentSideConnection ;
@@ -51,6 +63,7 @@ export class CodexAcpServer implements acp.Agent {
5163 private readonly availableCommands : CodexCommands ;
5264
5365 private readonly sessions : Map < string , SessionState > ;
66+ private readonly pendingMcpStartupSessions : Map < string , PendingMcpStartupSession > ;
5467
5568 constructor (
5669 connection : acp . AgentSideConnection ,
@@ -59,6 +72,7 @@ export class CodexAcpServer implements acp.Agent {
5972 getExitCode ?: ( ) => number | null ,
6073 ) {
6174 this . sessions = new Map ( ) ;
75+ this . pendingMcpStartupSessions = new Map ( ) ;
6276 this . connection = connection ;
6377 this . codexAcpClient = codexAcpClient ;
6478 this . defaultAuthRequest = defaultAuthRequest ?? null ;
@@ -159,6 +173,14 @@ export class CodexAcpServer implements acp.Agent {
159173 }
160174 this . sessions . set ( sessionId , sessionState ) ;
161175
176+ const requestedMcpServers = request . mcpServers ?? [ ] ;
177+ if ( requestedMcpServers . length > 0 ) {
178+ this . pendingMcpStartupSessions . set ( sessionId , {
179+ requestedServers : new Set ( requestedMcpServers . map ( server => server . name ) ) ,
180+ } ) ;
181+ this . publishMcpStartupStatusAsync ( sessionId , mcpStartupVersion ) ;
182+ }
183+
162184 this . publishAvailableCommandsAsync ( sessionId ) ;
163185 const sessionModelState : SessionModelState = this . createModelState ( models , currentModelId ) ;
164186 const sessionModeState : SessionModeState = sessionState . agentMode . toSessionModeState ( ) ;
@@ -359,6 +381,14 @@ export class CodexAcpServer implements acp.Agent {
359381 } ;
360382 this . sessions . set ( sessionId , sessionState ) ;
361383
384+ const requestedMcpServers = request . mcpServers ?? [ ] ;
385+ if ( requestedMcpServers . length > 0 ) {
386+ this . pendingMcpStartupSessions . set ( sessionId , {
387+ requestedServers : new Set ( requestedMcpServers . map ( server => server . name ) ) ,
388+ } ) ;
389+ this . publishMcpStartupStatusAsync ( sessionId , mcpStartupVersion ) ;
390+ }
391+
362392 await this . availableCommands . publish ( sessionId ) ;
363393 const sessionModelState : SessionModelState = this . createModelState ( models , currentModelId ) ;
364394 const sessionModeState : SessionModeState = sessionState . agentMode . toSessionModeState ( ) ;
@@ -621,6 +651,49 @@ export class CodexAcpServer implements acp.Agent {
621651 return await this . runWithProcessCheck ( ( ) => this . codexAcpClient . awaitMcpStartup ( mcpStartupVersion ) ) ;
622652 }
623653
654+ private publishMcpStartupStatusAsync ( sessionId : string , mcpStartupVersion : number ) : void {
655+ void this . doPublishMcpStartupStatus ( sessionId , mcpStartupVersion ) ;
656+ }
657+
658+ private async doPublishMcpStartupStatus ( sessionId : string , mcpStartupVersion : number ) : Promise < void > {
659+ try {
660+ const mcpStartup = await this . runWithProcessCheck ( ( ) => this . codexAcpClient . awaitMcpStartupResult ( mcpStartupVersion ) ) ;
661+ const sessionState = this . sessions . get ( sessionId ) ;
662+ const pendingStartup = this . pendingMcpStartupSessions . get ( sessionId ) ;
663+ if ( sessionState && pendingStartup ) {
664+ sessionState . sessionMcpServers = mcpStartup . ready . filter ( serverName =>
665+ pendingStartup . requestedServers . has ( serverName )
666+ ) ;
667+ }
668+ await this . publishMcpStartupStatus ( sessionId , mcpStartup , pendingStartup ?. requestedServers ) ;
669+ } catch ( err ) {
670+ logger . error ( `Failed to publish MCP startup status for session ${ sessionId } ` , err ) ;
671+ } finally {
672+ this . pendingMcpStartupSessions . delete ( sessionId ) ;
673+ }
674+ }
675+
676+ private async publishMcpStartupStatus (
677+ sessionId : string ,
678+ mcpStartup : McpStartupCompleteEvent ,
679+ requestedServers ?: Set < string >
680+ ) : Promise < void > {
681+ const filteredStartup = requestedServers
682+ ? {
683+ ready : mcpStartup . ready . filter ( server => requestedServers . has ( server ) ) ,
684+ failed : mcpStartup . failed . filter ( server => requestedServers . has ( server . server ) ) ,
685+ cancelled : mcpStartup . cancelled . filter ( server => requestedServers . has ( server ) ) ,
686+ }
687+ : mcpStartup ;
688+
689+ for ( const update of CodexEventHandler . createMcpStartupUpdates ( filteredStartup ) ) {
690+ await this . connection . sessionUpdate ( {
691+ sessionId,
692+ update,
693+ } ) ;
694+ }
695+ }
696+
624697 async prompt ( params : acp . PromptRequest ) : Promise < acp . PromptResponse > {
625698 logger . log ( "Prompt received" , {
626699 sessionId : params . sessionId ,
0 commit comments