Python: Introducing Local MCP Servers (#389)

* mcp parts

* mcp parts 2

* removed structured output in favor of handling in chatresponse, mcp as AITool and running samples

* updated naming

* fixed test
This commit is contained in:
Eduard van Valkenburg
2025-08-13 11:48:22 +02:00
committed by GitHub
Unverified
parent 80b0920e58
commit ad3d8171bf
20 changed files with 1970 additions and 298 deletions
@@ -0,0 +1,76 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from agent_framework import ChatClientAgent, McpStreamableHttpTool
from agent_framework.openai import OpenAIChatClient
async def mcp_tools_on_run_level() -> None:
"""Example showing MCP tools defined when running the agent."""
print("=== Tools Defined on Run Level ===")
# Tools are provided when running the agent
# This means we have to ensure we connect to the MCP server before running the agent
# and pass the tools to the run method.
async with (
McpStreamableHttpTool(
name="Microsoft Learn MCP",
url="https://learn.microsoft.com/api/mcp",
) as mcp_server,
ChatClientAgent(
chat_client=OpenAIChatClient(),
name="DocsAgent",
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
) as agent,
):
# First query
query1 = "How to create an Azure storage account using az cli?"
print(f"User: {query1}")
result1 = await agent.run(query1, tools=mcp_server)
print(f"{agent.name}: {result1}\n")
print("\n=======================================\n")
# Second query
query2 = "What is Microsoft Semantic Kernel?"
print(f"User: {query2}")
result2 = await agent.run(query2, tools=mcp_server)
print(f"{agent.name}: {result2}\n")
async def mcp_tools_on_agent_level() -> None:
"""Example showing tools defined when creating the agent."""
print("=== Tools Defined on Agent Level ===")
# Tools are provided when creating the agent
# The agent can use these tools for any query during its lifetime
# The agent will connect to the MCP server through its context manager.
async with OpenAIChatClient().create_agent(
name="DocsAgent",
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
tools=McpStreamableHttpTool( # Tools defined at agent creation
name="Microsoft Learn MCP",
url="https://learn.microsoft.com/api/mcp",
),
) as agent:
# First query
query1 = "How to create an Azure storage account using az cli?"
print(f"User: {query1}")
result1 = await agent.run(query1)
print(f"{agent.name}: {result1}\n")
print("\n=======================================\n")
# Second query
query2 = "What is Microsoft Semantic Kernel?"
print(f"User: {query2}")
result2 = await agent.run(query2)
print(f"{agent.name}: {result2}\n")
async def main() -> None:
print("=== OpenAI Chat Client Agent with MCP Tools Examples ===\n")
await mcp_tools_on_agent_level()
await mcp_tools_on_run_level()
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,87 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from agent_framework import ChatClientAgent, McpStreamableHttpTool
from agent_framework.openai import OpenAIResponsesClient
async def streaming_with_mcp(show_raw_stream: bool = False) -> None:
"""Example showing tools defined when creating the agent.
If you want to access the full stream of events that has come from the model, you can access it,
through the raw_representation. You can view this, by setting the show_raw_stream parameter to True.
"""
print("=== Tools Defined on Agent Level ===")
# Tools are provided when creating the agent
# The agent can use these tools for any query during its lifetime
async with ChatClientAgent(
chat_client=OpenAIResponsesClient(),
name="DocsAgent",
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
tools=McpStreamableHttpTool( # Tools defined at agent creation
name="Microsoft Learn MCP",
url="https://learn.microsoft.com/api/mcp",
),
) as agent:
# First query
query1 = "How to create an Azure storage account using az cli?"
print(f"User: {query1}")
print(f"{agent.name}: ", end="")
async for chunk in agent.run_streaming(query1):
if show_raw_stream:
print("Streamed event: ", chunk.raw_representation.raw_representation) # type:ignore
elif chunk.text:
print(chunk.text, end="")
print("")
print("\n=======================================\n")
# Second query
query2 = "What is Microsoft Semantic Kernel?"
print(f"User: {query2}")
print(f"{agent.name}: ", end="")
async for chunk in agent.run_streaming(query2):
if show_raw_stream:
print("Streamed event: ", chunk.raw_representation.raw_representation) # type:ignore
elif chunk.text:
print(chunk.text, end="")
print("\n\n")
async def run_with_mcp() -> None:
"""Example showing tools defined when creating the agent."""
print("=== Tools Defined on Agent Level ===")
# Tools are provided when creating the agent
# The agent can use these tools for any query during its lifetime
async with ChatClientAgent(
chat_client=OpenAIResponsesClient(),
name="DocsAgent",
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
tools=McpStreamableHttpTool( # Tools defined at agent creation
name="Microsoft Learn MCP",
url="https://learn.microsoft.com/api/mcp",
),
) as agent:
# First query
query1 = "How to create an Azure storage account using az cli?"
print(f"User: {query1}")
result1 = await agent.run(query1)
print(f"{agent.name}: {result1}\n")
print("\n=======================================\n")
# Second query
query2 = "What is Microsoft Semantic Kernel?"
print(f"User: {query2}")
result2 = await agent.run(query2)
print(f"{agent.name}: {result2}\n")
async def main() -> None:
print("=== OpenAI Responses Client Agent with Function Tools Examples ===\n")
await run_with_mcp()
await streaming_with_mcp()
if __name__ == "__main__":
asyncio.run(main())
@@ -4,9 +4,10 @@ import asyncio
from random import randint
from typing import Annotated
from agent_framework import ChatResponse
from agent_framework.azure import AzureResponsesClient
from azure.identity import DefaultAzureCredential
from pydantic import Field
from pydantic import BaseModel, Field
def get_weather(
@@ -17,20 +18,28 @@ def get_weather(
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
class OutputStruct(BaseModel):
"""Structured output for weather information."""
location: str
weather: str
async def main() -> None:
client = AzureResponsesClient(ad_credential=DefaultAzureCredential())
message = "What's the weather in Amsterdam and in Paris?"
stream = False
stream = True
print(f"User: {message}")
if stream:
print("Assistant: ", end="")
async for chunk in client.get_streaming_response(message, tools=get_weather):
if str(chunk):
print(str(chunk), end="")
print("")
response = await ChatResponse.from_chat_response_generator(
client.get_streaming_response(message, tools=get_weather, response_format=OutputStruct),
output_format_type=OutputStruct,
)
print(f"Assistant: {response.value}")
else:
response = await client.get_response(message, tools=get_weather)
print(f"Assistant: {response}")
response = await client.get_response(message, tools=get_weather, response_format=OutputStruct)
print(f"Assistant: {response.value}")
if __name__ == "__main__":