2525 AgentEventHandler ,
2626 ThreadRun ,
2727 RunHandler ,
28+ McpTool ,
29+ ToolApproval ,
30+ RequiredMcpToolCall ,
31+ SubmitToolApprovalAction ,
32+ SubmitToolApprovalDetails ,
2833)
2934
3035from user_functions import user_functions
@@ -217,6 +222,35 @@ def _get_run(
217222 run_dict ["required_action" ] = sb .as_dict ()
218223 run_dict ["tools" ] = definitions
219224 return run_dict
225+
226+
227+ def _get_run_for_mcp (
228+ self , thread_id : str , tool_set : Optional [ToolSet ], mcp_tool : McpTool , is_complete : bool = False
229+ ) -> Dict [str , Any ]:
230+ """Return JSON as if we have created the run."""
231+ with open (
232+ os .path .join (
233+ os .path .dirname (__file__ ),
234+ "test_data" ,
235+ "thread_run.json" ,
236+ ),
237+ "r" ,
238+ ) as fp :
239+ run_dict : Dict [str , Any ] = json .load (fp )
240+ run_dict ["id" ] = thread_id
241+ run_dict ["assistant_id" ] = thread_id [3 :]
242+ assert isinstance (run_dict , dict )
243+ if is_complete :
244+ run_dict ["status" ] = RunStatus .COMPLETED
245+
246+
247+ tool_calls : list [RequiredToolCall ] = [RequiredMcpToolCall (id = '0' , arguments = '' , name = '' , server_label = mcp_tool .server_label )]
248+ definitions = []
249+ sb = SubmitToolApprovalAction (submit_tool_approval = SubmitToolApprovalDetails (tool_calls = tool_calls ))
250+ run_dict ["required_action" ] = sb .as_dict ()
251+ run_dict ["tools" ] = definitions
252+ return run_dict
253+
220254
221255 def _assert_tool_call (self , submit_tool_mock : MagicMock , run_id : str , tool_set : Optional [ToolSet ]) -> None :
222256 """Check that submit_tool_outputs_to_run was called with correct parameters or was not called"""
@@ -544,7 +578,6 @@ def submit_function_call_output(
544578 agents_client = self .get_mock_client ()
545579 with agents_client :
546580 # Check that pipelines are created as expected.
547- self ._set_toolcalls (agents_client , toolset1 , None )
548581 run_handler = MyRunHandler ()
549582 agent1 = agents_client .create_agent (
550583 model = "gpt-4-1106-preview" ,
@@ -560,6 +593,71 @@ def submit_function_call_output(
560593 )
561594 self ._assert_tool_call (agents_client .runs .submit_tool_outputs , "run123" , toolset1 )
562595
596+ @patch ("azure.ai.agents._client.PipelineClient" )
597+ def test_create_and_process_with_mcp (
598+ self ,
599+ mock_pipeline_client_gen : MagicMock ,
600+ ) -> None :
601+ """Test that if user have set tool set in create create_and_process_run method, that tools are used."""
602+ toolset1 = ToolSet ()
603+ mcp_tool = McpTool (server_label = "server1" , server_url = "http://server1.com" , allowed_tools = ["tool1" ])
604+ toolset1 .add (mcp_tool )
605+ mock_response = MagicMock ()
606+ mock_response .status_code = 200
607+ side_effect = [self ._get_agent_json ("first" , "123" , toolset1 )]
608+ side_effect .append (self ._get_run_for_mcp ("run123" , toolset1 , mcp_tool )) # create_run
609+ side_effect .append (self ._get_run_for_mcp ("run123" , toolset1 , mcp_tool )) # get_run
610+ side_effect .append (
611+ self ._get_run_for_mcp ("run123" , toolset1 , mcp_tool , is_complete = True )
612+ ) # get_run after resubmitting with tool results
613+
614+ class MyRunHandler (RunHandler ):
615+ def submit_mcp_tool_approval (
616+ self ,
617+ run : ThreadRun ,
618+ tool_call : RequiredMcpToolCall ,
619+ ** kwargs : Any ,
620+ ) -> Optional [ToolApproval ]:
621+ self .tool_approval = ToolApproval (
622+ tool_call_id = tool_call .id ,
623+ approve = True ,
624+ headers = mcp_tool .headers ,
625+ )
626+ return self .tool_approval
627+
628+
629+ mock_response .json .side_effect = side_effect
630+ mock_pipeline_response = MagicMock ()
631+ mock_pipeline_response .http_response = mock_response
632+ mock_pipeline = MagicMock ()
633+ mock_pipeline ._pipeline .run .return_value = mock_pipeline_response
634+ mock_pipeline_client_gen .return_value = mock_pipeline
635+ agents_client = self .get_mock_client ()
636+ with agents_client :
637+ # Check that pipelines are created as expected.
638+ run_handler = MyRunHandler ()
639+ agent1 = agents_client .create_agent (
640+ model = "gpt-4-1106-preview" ,
641+ name = "first" ,
642+ instructions = "You are a helpful agent" ,
643+ toolset = toolset1 ,
644+ )
645+
646+
647+ # Create run with new tool set, which also can be none.
648+ agents_client .runs .create_and_process (
649+ thread_id = "some_thread_id" , agent_id = agent1 .id , polling_interval = 0 , run_handler = run_handler
650+ )
651+
652+ agents_client .runs .submit_tool_outputs .assert_called_once ()
653+ agents_client .runs .submit_tool_outputs .assert_called_with (
654+ thread_id = "some_thread_id" ,
655+ run_id = "run123" ,
656+ tool_approvals = [run_handler .tool_approval ],
657+ )
658+ agents_client .runs .submit_tool_outputs .reset_mock ()
659+
660+
563661 @patch ("azure.ai.agents._client.PipelineClient" )
564662 @pytest .mark .parametrize (
565663 "file_agent_1,add_azure_fn" ,
0 commit comments