@@ -29,6 +29,10 @@ const decodeInitializeParams = Schema.decodeUnknownOption(
2929 Schema . Struct ( { clientInfo : Schema . Struct ( { name : Schema . String } ) } ) ,
3030) ;
3131
32+ const decodeThreadStartParams = Schema . decodeUnknownOption (
33+ Schema . Struct ( { approvalPolicy : Schema . optional ( Schema . String ) } ) ,
34+ ) ;
35+
3236const decodeThreadParams = Schema . decodeUnknownOption (
3337 Schema . Struct ( {
3438 threadId : Schema . optional ( Schema . String ) ,
@@ -77,6 +81,7 @@ const replyError = (id: number | string, code: number, message: string): void =>
7781} ;
7882
7983let initializedSeen = false ;
84+ let elicitationsAllowed = false ;
8085let nextServerRequestId = 1000 ;
8186/** Elicitation request id → the pending tool call's request id. */
8287const pendingApprovals = new Map < number | string , number | string > ( ) ;
@@ -134,6 +139,15 @@ const handleToolCall = (id: number | string, params: unknown): void => {
134139 return ;
135140 }
136141 if ( call . tool === "needs_approval" ) {
142+ if ( ! elicitationsAllowed ) {
143+ // Exactly what Codex returns when it declines the elicitation for the
144+ // client: an error result, no prompt, no explanation.
145+ reply ( id , {
146+ content : [ { type : "text" , text : "access was not approved" } ] ,
147+ isError : true ,
148+ } ) ;
149+ return ;
150+ }
137151 const elicitationId = nextServerRequestId ++ ;
138152 pendingApprovals . set ( elicitationId , id ) ;
139153 write ( {
@@ -200,6 +214,12 @@ readline.createInterface({ input: process.stdin }).on("line", (line) => {
200214 replyError ( message . id , - 32600 , "thread/start before the initialized notification" ) ;
201215 return ;
202216 }
217+ // Codex DECLINES every MCP elicitation itself on a thread whose approval
218+ // policy does not allow them, so a thread started without one can never
219+ // receive an approval prompt. The fixture models that: it only elicits
220+ // when the bridge asked for a policy that permits elicitations.
221+ const params = Option . getOrUndefined ( decodeThreadStartParams ( message . params ) ) ;
222+ elicitationsAllowed = params ?. approvalPolicy === "on-request" ;
203223 reply ( message . id , { thread : { id : THREAD_ID } } ) ;
204224 return ;
205225 }
0 commit comments