Skip to content

Commit 48f71b1

Browse files
authored
Python: Support AzureAI agent MCP tools for streaming and non-streaming invocations (#12736)
### Motivation and Context MCP tool support was released for the AzureAI Agent and it has yet to be added to the SK Python AzureAIAgent. This PR adds functionality to handle the MCP tools for both streaming and non-streaming invocations. <!-- Thank you for your contribution to the semantic-kernel repo! Please help reviewers and future users, providing the following information: 1. Why is this change required? 2. What problem does it solve? 3. What scenario does it contribute to? 4. If it fixes an open issue, please link to the issue here. --> ### Description Adds MCP support for the Python AzureAI Agent. - Upgrades dependent packages to be able to use the mcp tool from the Azure SDK. <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [X] The code builds clean without any errors or warnings - [X] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [X] All unit tests pass, and I have added new tests where possible - [X] I didn't break anyone 😄
1 parent bbe179f commit 48f71b1

17 files changed

+570
-71
lines changed

python/pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ classifiers = [
2424
]
2525
dependencies = [
2626
# azure agents
27-
"azure-ai-projects >= 1.0.0b11",
28-
"azure-ai-agents >= 1.1.0b1",
27+
"azure-ai-projects >= 1.0.0b12",
28+
"azure-ai-agents >= 1.1.0b4",
2929
"aiohttp ~= 3.8",
3030
"cloudevents ~=1.0",
3131
"pydantic >=2.0,!=2.10.0,!=2.10.1,!=2.10.2,!=2.10.3,<2.12",

python/samples/concepts/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
- [Azure AI Agent Declarative with OpenAPI Interpreter](./agents/azure_ai_agent/azure_ai_agent_declarative_openapi.py)
2222
- [Azure AI Agent Declarative with Existing Agent ID](./agents/azure_ai_agent/azure_ai_agent_declarative_with_existing_agent_id.py)
2323
- [Azure AI Agent File Manipulation](./agents/azure_ai_agent/azure_ai_agent_file_manipulation.py)
24+
- [Azure AI Agent MCP Streaming](./agents/azure_ai_agent/azure_ai_agent_mcp_streaming.py)
2425
- [Azure AI Agent Prompt Templating](./agents/azure_ai_agent/azure_ai_agent_prompt_templating.py)
2526
- [Azure AI Agent Message Callback Streaming](./agents/azure_ai_agent/azure_ai_agent_message_callback_streaming.py)
2627
- [Azure AI Agent Message Callback](./agents/azure_ai_agent/azure_ai_agent_message_callback.py)
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Copyright (c) Microsoft. All rights reserved.
2+
3+
import asyncio
4+
5+
from azure.ai.agents.models import McpTool
6+
from azure.identity.aio import DefaultAzureCredential
7+
8+
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
9+
from semantic_kernel.contents import ChatMessageContent, FunctionCallContent, FunctionResultContent
10+
11+
"""
12+
The following sample demonstrates how to create a simple, Azure AI agent that
13+
uses the mcp tool to connect to an mcp server with streaming responses.
14+
"""
15+
16+
TASK = "Please summarize the Azure REST API specifications Readme"
17+
18+
19+
async def handle_intermediate_messages(message: ChatMessageContent) -> None:
20+
for item in message.items or []:
21+
if isinstance(item, FunctionResultContent):
22+
print(f"Function Result:> {item.result} for function: {item.name}")
23+
elif isinstance(item, FunctionCallContent):
24+
print(f"Function Call:> {item.name} with arguments: {item.arguments}")
25+
else:
26+
print(f"{item}")
27+
28+
29+
async def main() -> None:
30+
async with (
31+
DefaultAzureCredential() as creds,
32+
AzureAIAgent.create_client(credential=creds) as client,
33+
):
34+
# 1. Define the MCP tool with the server URL
35+
mcp_tool = McpTool(
36+
server_label="github",
37+
server_url="https://gitmcp.io/Azure/azure-rest-api-specs",
38+
allowed_tools=[], # Specify allowed tools if needed
39+
)
40+
41+
# Optionally you may configure to require approval
42+
# Allowed values are "never" or "always"
43+
mcp_tool.set_approval_mode("never")
44+
45+
# 2. Create an agent with the MCP tool on the Azure AI agent service
46+
agent_definition = await client.agents.create_agent(
47+
model=AzureAIAgentSettings().model_deployment_name,
48+
tools=mcp_tool.definitions,
49+
instructions="You are a helpful agent that can use MCP tools to assist users.",
50+
)
51+
52+
# 3. Create a Semantic Kernel agent for the Azure AI agent
53+
agent = AzureAIAgent(
54+
client=client,
55+
definition=agent_definition,
56+
)
57+
58+
# 4. Create a thread for the agent
59+
# If no thread is provided, a new thread will be
60+
# created and returned with the initial response
61+
thread: AzureAIAgentThread | None = None
62+
63+
try:
64+
print(f"# User: '{TASK}'")
65+
# 5. Invoke the agent for the specified thread for response
66+
async for response in agent.invoke_stream(
67+
messages=TASK,
68+
thread=thread,
69+
on_intermediate_message=handle_intermediate_messages,
70+
):
71+
print(f"{response}", end="", flush=True)
72+
thread = response.thread
73+
finally:
74+
# 6. Cleanup: Delete the thread, agent, and file
75+
await thread.delete() if thread else None
76+
await client.agents.delete_agent(agent.id)
77+
78+
"""
79+
Sample Output:
80+
81+
# User: 'Please summarize the Azure REST API specifications Readme'
82+
Function Call:> fetch_azure_rest_api_docs with arguments: {}
83+
The Azure REST API specifications Readme provides comprehensive documentation and guidelines for designing,
84+
authoring, validating, and evolving Azure REST APIs. It covers key areas including:
85+
86+
1. Breaking changes and versioning: Guidelines to manage API changes that break backward compatibility, when to
87+
increment API versions, and how to maintain smooth API evolution.
88+
89+
2. OpenAPI/Swagger specifications: How to author REST APIs using OpenAPI specification 2.0 (Swagger), including
90+
structure, conventions, validation tools, and extensions used by AutoRest for generating client SDKs.
91+
92+
3. TypeSpec language: Introduction to TypeSpec, a powerful language for describing and generating REST API
93+
specifications and client SDKs with extensibility to other API styles.
94+
95+
4. Directory structure and uniform versioning: Organizing service specifications by teams, resource provider
96+
namespaces, and following uniform versioning to keep API versions consistent across documentation and SDKs.
97+
98+
5. Validation and tooling: Tools and processes like OAV, AutoRest, RESTler, and CI checks used to validate API
99+
specs, generate SDKs, detect breaking changes, lint specifications, and test service contract accuracy.
100+
101+
6. Authoring best practices: Manual and automated guidelines for quality API spec authoring, including writing
102+
effective descriptions, resource modeling, naming conventions, and examples.
103+
104+
7. Code generation configurations: How to configure readme files to generate SDKs for various languages
105+
including .NET, Java, Python, Go, Typescript, and Azure CLI using AutoRest.
106+
107+
8. API Scenarios and testing: Defining API scenario test files for end-to-end REST API workflows, including
108+
variables, ARM template integration, and usage of test-proxy for recording traffic.
109+
110+
9. SDK automation and release requests: Workflows for SDK generation validation, suppressing breaking change
111+
warnings, and requesting official Azure SDK releases.
112+
113+
Overall, the Readme acts as a central hub providing references, guidelines, examples, and tools for maintaining
114+
high-quality Azure REST API specifications and seamless SDK generation across multiple languages and
115+
platforms. It ensures consistent API design, versioning, validation, and developer experience in the Azure
116+
ecosystem.
117+
"""
118+
119+
120+
if __name__ == "__main__":
121+
asyncio.run(main())

0 commit comments

Comments
 (0)