@@ -14,7 +14,13 @@ import {
1414} from './items' ;
1515import logger , { Logger } from './logger' ;
1616import { ModelResponse , ModelSettings } from './model' ;
17- import { ComputerTool , FunctionTool , Tool , FunctionToolResult } from './tool' ;
17+ import {
18+ ComputerTool ,
19+ FunctionTool ,
20+ Tool ,
21+ FunctionToolResult ,
22+ HostedMCPTool ,
23+ } from './tool' ;
1824import { AgentInputItem , UnknownContext } from './types' ;
1925import { Runner } from './run' ;
2026import { RunContext } from './runContext' ;
@@ -31,6 +37,7 @@ import * as protocol from './types/protocol';
3137import { Computer } from './computer' ;
3238import { RunState } from './runState' ;
3339import { isZodObject } from './utils' ;
40+ import * as ProviderData from './types/providerData' ;
3441
3542type ToolRunHandoff = {
3643 toolCall : protocol . FunctionCallItem ;
@@ -47,11 +54,17 @@ type ToolRunComputer = {
4754 computer : ComputerTool ;
4855} ;
4956
57+ type ToolRunMCPApprovalRequest = {
58+ requestItem : RunToolApprovalItem ;
59+ mcpTool : HostedMCPTool ;
60+ } ;
61+
5062export type ProcessedResponse < TContext = UnknownContext > = {
5163 newItems : RunItem [ ] ;
5264 handoffs : ToolRunHandoff [ ] ;
5365 functions : ToolRunFunction < TContext > [ ] ;
5466 computerActions : ToolRunComputer [ ] ;
67+ mcpApprovalRequests : ToolRunMCPApprovalRequest [ ] ;
5568 toolsUsed : string [ ] ;
5669} ;
5770
@@ -68,21 +81,78 @@ export function processModelResponse<TContext>(
6881 const runHandoffs : ToolRunHandoff [ ] = [ ] ;
6982 const runFunctions : ToolRunFunction < TContext > [ ] = [ ] ;
7083 const runComputerActions : ToolRunComputer [ ] = [ ] ;
84+ const runMCPApprovalRequests : ToolRunMCPApprovalRequest [ ] = [ ] ;
7185 const toolsUsed : string [ ] = [ ] ;
7286 const handoffMap = new Map ( handoffs . map ( ( h ) => [ h . toolName , h ] ) ) ;
7387 const functionMap = new Map (
7488 tools . filter ( ( t ) => t . type === 'function' ) . map ( ( t ) => [ t . name , t ] ) ,
7589 ) ;
7690 const computerTool = tools . find ( ( t ) => t . type === 'computer' ) ;
91+ const mcpToolMap = new Map (
92+ tools
93+ . filter ( ( t ) => t . type === 'hosted_tool' && t . providerData ?. type === 'mcp' )
94+ . map ( ( t ) => t as HostedMCPTool )
95+ . map ( ( t ) => [ t . providerData . serverLabel , t ] ) ,
96+ ) ;
7797
7898 for ( const output of modelResponse . output ) {
7999 if ( output . type === 'message' ) {
80100 if ( output . role === 'assistant' ) {
81101 items . push ( new RunMessageOutputItem ( output , agent ) ) ;
82102 }
83103 } else if ( output . type === 'hosted_tool_call' ) {
84- items . push ( new RunToolCallItem ( output , agent ) ) ;
85- toolsUsed . push ( output . name ) ;
104+ if (
105+ output . providerData ?. type === 'mcp_approval_request' ||
106+ output . name === 'mcp_approval_request'
107+ ) {
108+ // Hosted remote MCP server support
109+ const providerData =
110+ output . providerData as ProviderData . HostedMCPApprovalRequest ;
111+ const mcpServerLabel = providerData . serverLabel ;
112+ const mcpServerTool = mcpToolMap . get ( mcpServerLabel ) ;
113+ if ( mcpServerTool !== undefined ) {
114+ const toolName = JSON . stringify ( {
115+ server : providerData . serverLabel ,
116+ name : providerData . name ,
117+ } ) ;
118+ // Do this approval later
119+ runMCPApprovalRequests . push ( {
120+ requestItem : new RunToolApprovalItem (
121+ {
122+ type : 'function_call' ,
123+ name : toolName ,
124+ callId : providerData . id ,
125+ arguments : providerData . arguments || '' ,
126+ status : 'in_progress' ,
127+ providerData,
128+ } ,
129+ agent ,
130+ ) ,
131+ mcpTool : mcpServerTool ,
132+ } ) ;
133+ items . push ( new RunToolCallItem ( output , agent ) ) ;
134+ toolsUsed . push ( toolName ) ;
135+ } else {
136+ const message = `MCP server (${ mcpServerLabel } ) not found in Agent (${ agent . name } )` ;
137+ addErrorToCurrentSpan ( {
138+ message,
139+ data : { mcp_server_label : mcpServerLabel } ,
140+ } ) ;
141+ throw new ModelBehaviorError ( message ) ;
142+ }
143+ } else {
144+ // the rest of the hosted
145+ items . push ( new RunToolCallItem ( output , agent ) ) ;
146+ const toolName = output . providerData ?. serverLabel
147+ ? // hosted MCP tool
148+ JSON . stringify ( {
149+ server : output . providerData . serverLabel ,
150+ name : output . name ,
151+ } )
152+ : // other hosted tools
153+ output . name ;
154+ toolsUsed . push ( toolName ) ;
155+ }
86156 } else if ( output . type === 'reasoning' ) {
87157 items . push ( new RunReasoningItem ( output , agent ) ) ;
88158 } else if ( output . type === 'computer_call' ) {
@@ -146,6 +216,7 @@ export function processModelResponse<TContext>(
146216 handoffs : runHandoffs ,
147217 functions : runFunctions ,
148218 computerActions : runComputerActions ,
219+ mcpApprovalRequests : runMCPApprovalRequests ,
149220 toolsUsed : toolsUsed ,
150221 } ;
151222}
@@ -336,6 +407,40 @@ export async function executeToolsAndSideEffects<TContext>(
336407 newItems = newItems . concat ( functionResults . map ( ( r ) => r . runItem ) ) ;
337408 newItems = newItems . concat ( computerResults ) ;
338409
410+ // run hosted MCP approval requests
411+ if ( processedResponse . mcpApprovalRequests . length > 0 ) {
412+ for ( const approvalRequest of processedResponse . mcpApprovalRequests ) {
413+ const toolData = approvalRequest . mcpTool
414+ . providerData as ProviderData . HostedMCPTool < TContext > ;
415+ if ( ! toolData . onApproval ) {
416+ throw new UserError (
417+ `Hosted remote MCP server tool (${ toolData . serverLabel } ) does not have an onApproval function` ,
418+ ) ;
419+ }
420+ const approvalResult = await toolData . onApproval (
421+ state . _context ,
422+ approvalRequest . requestItem ,
423+ ) ;
424+ const requestData = approvalRequest . requestItem . rawItem
425+ . providerData as ProviderData . HostedMCPApprovalRequest ;
426+ const approvalResponseData : ProviderData . HostedMCPApprovalResponse = {
427+ approve : approvalResult . approve ,
428+ approvalRequestId : requestData . id ,
429+ reason : approvalResult . reason ,
430+ } ;
431+ newItems . push (
432+ new RunToolCallItem (
433+ {
434+ type : 'hosted_tool_call' ,
435+ name : 'mcp_approval_response' ,
436+ providerData : approvalResponseData ,
437+ } ,
438+ agent as Agent < unknown , 'text' > ,
439+ ) ,
440+ ) ;
441+ }
442+ }
443+
339444 // process handoffs
340445 if ( processedResponse . handoffs . length > 0 ) {
341446 return await executeHandoffCalls (
0 commit comments