@@ -10,6 +10,10 @@ export interface CodexDynamicToolSpec {
1010 inputSchema : Record < string , any >
1111}
1212
13+ export interface CodexRuntimeConfig {
14+ mcp_servers ?: Record < string , Record < string , any > >
15+ }
16+
1317interface CodexModelListResult {
1418 success ?: boolean
1519 models ?: Array < {
@@ -128,9 +132,79 @@ export function convertToolsToCodexDynamicTools(
128132 } ) )
129133}
130134
131- async function buildCodexDynamicTools ( ) : Promise < CodexDynamicToolSpec [ ] > {
135+ function normalizeCodexMcpApprovalMode ( value : unknown ) : string | undefined {
136+ if ( value === 'never' || value === false ) {
137+ return 'approve'
138+ }
139+ if ( value === 'always' || value === true ) {
140+ return 'prompt'
141+ }
142+ return undefined
143+ }
144+
145+ function normalizeStringRecord ( value : unknown ) : Record < string , string > | null {
146+ if ( ! value || typeof value !== 'object' || Array . isArray ( value ) ) {
147+ return null
148+ }
149+
150+ const entries = Object . entries ( value as Record < string , unknown > ) . filter (
151+ ( entry ) : entry is [ string , string ] =>
152+ typeof entry [ 0 ] === 'string' && typeof entry [ 1 ] === 'string'
153+ )
154+
155+ return entries . length > 0 ? Object . fromEntries ( entries ) : null
156+ }
157+
158+ export function convertToolsToCodexRuntimeConfig (
159+ tools : any [ ]
160+ ) : CodexRuntimeConfig | undefined {
161+ const mcpServers : Record < string , Record < string , any > > = { }
162+
163+ for ( const tool of tools ) {
164+ if (
165+ tool ?. type !== 'mcp' ||
166+ typeof tool . server_label !== 'string' ||
167+ typeof tool . server_url !== 'string'
168+ ) {
169+ continue
170+ }
171+
172+ const serverName = tool . server_label . trim ( )
173+ const serverUrl = tool . server_url . trim ( )
174+ if ( ! serverName || ! serverUrl ) {
175+ continue
176+ }
177+
178+ const serverConfig : Record < string , any > = { url : serverUrl }
179+ const approvalMode = normalizeCodexMcpApprovalMode ( tool . require_approval )
180+ if ( approvalMode ) {
181+ serverConfig . default_tools_approval_mode = approvalMode
182+ }
183+
184+ const headers = normalizeStringRecord ( tool . headers )
185+ if ( headers ) {
186+ serverConfig . http_headers = headers
187+ }
188+
189+ mcpServers [ serverName ] = serverConfig
190+ }
191+
192+ if ( Object . keys ( mcpServers ) . length === 0 ) {
193+ return undefined
194+ }
195+
196+ return { mcp_servers : mcpServers }
197+ }
198+
199+ async function buildCodexTooling ( ) : Promise < {
200+ dynamicTools : CodexDynamicToolSpec [ ]
201+ config ?: CodexRuntimeConfig
202+ } > {
132203 const tools = await buildToolsForProvider ( )
133- return convertToolsToCodexDynamicTools ( tools )
204+ return {
205+ dynamicTools : convertToolsToCodexDynamicTools ( tools ) ,
206+ config : convertToolsToCodexRuntimeConfig ( tools ) ,
207+ }
134208}
135209
136210function isLikelyCodexModelCompatibilityError ( error : unknown ) : boolean {
@@ -150,6 +224,7 @@ async function* streamViaCodexAppServerWithFallback(
150224 instructions : string
151225 effort ?: string
152226 dynamicTools ?: CodexDynamicToolSpec [ ]
227+ config ?: CodexRuntimeConfig
153228 } ,
154229 signal ?: AbortSignal
155230) : AsyncGenerator < any > {
@@ -275,13 +350,15 @@ export const createCodexResponse = async (
275350 const instructions =
276351 customInstructions ||
277352 buildAssistantSystemPrompt ( settings . assistantSystemPrompt )
353+ const tooling = await buildCodexTooling ( )
278354
279355 const request = {
280356 input : convertResponsesInputToCodexInput ( input ) ,
281357 model,
282358 instructions,
283359 effort : normalizeCodexEffort ( settings . assistantReasoningEffort ) ,
284- dynamicTools : await buildCodexDynamicTools ( ) ,
360+ dynamicTools : tooling . dynamicTools ,
361+ config : tooling . config ,
285362 }
286363
287364 return streamViaCodexAppServerWithFallback ( request , signal )
@@ -320,6 +397,7 @@ async function* streamViaCodexAppServer(
320397 instructions : string
321398 effort ?: string
322399 dynamicTools ?: CodexDynamicToolSpec [ ]
400+ config ?: CodexRuntimeConfig
323401 } ,
324402 signal ?: AbortSignal
325403) : AsyncGenerator < any > {
@@ -380,6 +458,7 @@ async function* streamViaCodexAppServer(
380458 instructions : request . instructions ,
381459 effort : request . effort ,
382460 dynamicTools : request . dynamicTools ,
461+ config : request . config ,
383462 }
384463 )
385464 if ( ! startResult ?. success ) {
0 commit comments