Azure / Azure/azure-sdk-for-python

MCP tool approval in multi-step workflow with Anthropic model

Abierto
#47,996 1 comentario 2 reacciones 1 asignado Ver en GitHub

@dargilco ya está trabajando en esto.

Desde el 13/7/2026.

AI Projects Client customer-reported needs-team-attention question
Lenguaje dominante
Python
Estrellas
5.6k
Forks
3.4k
Merge medio
2 d 2 h
PR fusionados (30 d)
213

Descripción

  • Package Name: azure-ai-projects, azure-identity, openai
  • Package Version:
    • azure-ai-projects version: 2.3.0
    • azure-identity version: 1.25.3
    • openai version: 2.44.0
  • Operating System: Windows 11
  • Python Version: Python 3.14.5

Describe the bug
When using Azure AI Foundry Agents with an MCP tool configured with require_approval="always" and the claude-sonnet-4-6 model, the first MCP approval succeeds, but a subsequent MCP approval request in the same response chain fails with HTTP 400.

The same workflow succeeds when require_approval="never" is used.

The issue appears when Claude performs a multi-step MCP interaction:

  1. Request MCP approval.
  2. Execute MCP tool call.
  3. Request approval for a second MCP tool call.
  4. Approval response for the second request returns HTTP 400.

The identical approval payload format works for the first approval request.

To Reproduce
I was following https://github.com/MicrosoftLearning/mslearn-ai-agents/tree/main/Labfiles/03-mcp-integration/Python and adjusted the code for agent.py slightly to handle multi-step approvals.

Steps to reproduce the behavior:

agent.py
import os
from dotenv import load_dotenv
import json

# Add references
import azure.identity as azure_identity
import azure.ai.projects as azure_ai_projects
import openai as openai

from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import PromptAgentDefinition, MCPTool
from openai.types.responses.response_input_param import (
    McpApprovalResponse,
    ResponseInputParam,
)
from openai import BadRequestError

# Load environment variables from .env file
load_dotenv()
project_endpoint = os.getenv("PROJECT_ENDPOINT")
model_deployment = os.getenv("MODEL_DEPLOYMENT_NAME")

print("=" * 80)
print(f"azure-ai-projects version: {azure_ai_projects.__version__}")
print(f"azure-identity version: {azure_identity.__version__}")
print(f"openai version: {openai.__version__}")
print("=" * 80)

# Connect to the agents client
with (
    DefaultAzureCredential() as credential,
    AIProjectClient(endpoint=project_endpoint, credential=credential) as project_client,
    project_client.get_openai_client() as openai_client,
):

    # Initialize agent MCP tool
    mcp_tool = MCPTool(
        server_label="api-specs",
        server_url="https://learn.microsoft.com/api/mcp",
        require_approval="always",
    )

    # Create a new agent with the MCP tool
    agent = project_client.agents.create_version(
        agent_name="MyAgent",
        definition=PromptAgentDefinition(
            model=model_deployment,
            instructions="You are a helpful agent that can use MCP tools to assist users. Use the available MCP tools to answer questions and perform tasks.",
            tools=[mcp_tool],
        ),
    )
    print(
        f"Agent created (id: {agent.id}, name: {agent.name}, version: {agent.version})"
    )

    # Create conversation thread
    conversation = openai_client.conversations.create()
    print(f"Created conversation (id: {conversation.id})")

    # Send initial request that will trigger the MCP tool
    response = openai_client.responses.create(
        conversation=conversation.id,
        input="Give me the Azure CLI commands to create an Azure Container App with a managed identity.",
        extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}},
    )

    response_nr = 1

    # Process any MCP approval requests that were generated
    # The agent may issue several tool calls, each needing its own approval,
    # so we loop until there are none left.
    # # I had to change this from the instructions,
    # # because my model iterated over tools instead of providing a list of tool calls.
    while not response.output_text:

        print("=" * 80)
        print(
            f"Response {response_nr}: {json.dumps(response.model_dump(), indent=2, sort_keys=True)}"
        )
        print("=" * 80)

        # Collect any MCP approval requests from the latest response
        input_list: ResponseInputParam = []
        item_nr = 1
        for item in response.output:
            print(
                f"Input Item {response_nr}.{item_nr}: {json.dumps(item.model_dump(), indent=2, sort_keys=True)}"
            )
            if item.type == "mcp_approval_request":
                if item.server_label == "api-specs" and item.id:
                    # Automatically approve the MCP request to allow the agent to proceed
                    result = McpApprovalResponse(
                        type="mcp_approval_response",
                        approve=True,
                        approval_request_id=item.id,
                    )
                    print(
                        f"Output Item {response_nr}.{item_nr}: {json.dumps(result, indent=2, sort_keys=True)}"
                    )
                    input_list.append(result)
            item_nr += 1

        response_nr += 1
        if not input_list:
            break

        try:
            response = openai_client.responses.create(
                input=input_list,
                previous_response_id=response.id,
                extra_body={
                    "agent_reference": {"name": agent.name, "type": "agent_reference"}
                },
            )

        except BadRequestError as e:
            print("Status:", e.status_code)

            if hasattr(e, "response") and e.response:
                print("Headers:", e.response.headers)

                try:
                    print("JSON:", e.response.json())
                except Exception:
                    print("TEXT:", e.response.text)

            raise

    print(f"\nAgent response: {response.output_text}")

    # Clean up resources by deleting the agent version
    project_client.agents.delete_version(
        agent_name=agent.name, agent_version=agent.version
    )
    print("Agent deleted")
output structure
Response 1: {...}
Input Item 1.1: {type: mcp_list_tools}
Input Item 1.2: {type: mcp_approval_request}
Output Item 1.2: {type: mcp_approval_response}
Response 2: {...}
Input Item 2.1: {type: mcp_call}
Input Item 2.2: {type: mcp_approval_request}
Output Item 2.2: {type: mcp_approval_response}
...
openai.BadRequestError: Error code: 400 - {'error': {'message': 'There was an issue with your request. Please check your inputs and try again', 'type': 'invalid_request_error', 'param': None, 'code': None}}

Expected behavior
The second MCP approval should be accepted and the agent should continue execution, eventually producing a final response.

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.