chore: import upstream snapshot with attribution
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run

This commit is contained in:
wehub-resource-sync
2026-07-13 13:21:23 +08:00
commit b957a53def
5423 changed files with 863745 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
# Model Context Protocol
The model context protocol is a standard created by Anthropic to allow models to share context with each other. See the [official documentation](https://modelcontextprotocol.io/introduction) for more information.
It consists of clients and servers, and servers can be hosted locally, or they can be exposed as a online API.
Our goal is that Semantic Kernel can act as both a client and a server.
In this folder the client side of things is demonstrated. It takes the definition of a server and uses that to create a Semantic Kernel plugin, this plugin exposes the tools and prompts of the server as functions in the kernel.
Those can then be used with function calling in a chat or agent.
## Server types
There are two types of servers, Stdio and Sse based. The sample shows how to use the Stdio based server, which get's run locally, in this case by using [npx](https://docs.npmjs.com/cli/v8/commands/npx).
Some other common runners are [uvx](https://docs.astral.sh/uv/guides/tools/), for python servers and [docker](https://www.docker.com/), for containerized servers.
The code shown works the same for a Sse server, only then a MCPSsePlugin needs to be used instead of the MCPStdioPlugin. For Streamable HTTP server, MCPStreamableHttpPlugin can be used.
The reverse, using Semantic Kernel as a server, can be found in the [demos/mcp_server](../../demos/mcp_server/) folder.
## Running the samples
1. Depending on the sample you want to run:
1. [Docker](https://www.docker.com/products/docker-desktop/) installed, for the samples that use the Github MCP server.
1. [uv](https://docs.astral.sh/uv/getting-started/installation/) installed, for the samples that use the local MCP server.
2. The Github MCP Server uses a Github Personal Access Token (PAT) to authenticate, see [the documentation](https://github.com/modelcontextprotocol/servers/tree/main/src/github) on how to create one.
1. Check the comment at the start of the sample you want to run, for the appropriate environment variables to set.
1. Install Semantic Kernel with the mcp extra:
```bash
pip install semantic-kernel[mcp]
```
4. Run any of the samples:
```bash
cd python/samples/concepts/mcp
python <name>.py
```
@@ -0,0 +1,138 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from azure.identity import AzureCliCredential
from semantic_kernel.agents import ChatCompletionAgent, ChatHistoryAgentThread
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
from semantic_kernel.connectors.mcp import MCPStreamableHttpPlugin
"""
The following sample demonstrates how to create a chat completion agent that
answers questions about Github using a Semantic Kernel Plugin from a MCP server.
It uses the Azure OpenAI service to create a agent, so make sure to
set the required environment variables for the Azure AI Foundry service:
- AZURE_OPENAI_CHAT_DEPLOYMENT_NAME
- Optionally: AZURE_OPENAI_API_KEY
If this is not set, it's also possible to pass AsyncTokenCredential to the service, e.g. AzureCliCredential.
"""
# Simulate a conversation with the agent
USER_INPUTS = [
"How do I make a Python chat completion request in Semantic Kernel using Azure OpenAI?",
]
async def main():
# 1. Create the agent
async with MCPStreamableHttpPlugin(
name="LearnSite",
description="Learn Docs Plugin",
url="https://learn.microsoft.com/api/mcp",
) as learn_plugin:
agent = ChatCompletionAgent(
service=AzureChatCompletion(credential=AzureCliCredential()),
name="DocsAgent",
instructions="Answer questions about the Microsoft's Semantic Kernel SDK.",
plugins=[learn_plugin],
)
for user_input in USER_INPUTS:
# 2. Create a thread to hold the conversation
# If no thread is provided, a new thread will be
# created and returned with the initial response
thread: ChatHistoryAgentThread | None = None
print(f"# User: {user_input}")
# 3. Invoke the agent for a response
response = await agent.get_response(messages=user_input, thread=thread)
print(f"# {response.name}: {response} ")
thread = response.thread
# 4. Cleanup: Clear the thread
await thread.delete() if thread else None
"""
Sample output:
# User: How do I make a Python chat completion request in Semantic Kernel using Azure OpenAI?
# DocsAgent: To make a **Python chat completion request in Semantic Kernel using Azure OpenAI**, follow these steps:
---
### 1. Install Semantic Kernel
```bash
pip install semantic-kernel
```
---
### 2. Import Necessary Libraries
```python
import semantic_kernel as sk
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
```
---
### 3. Initialize the Kernel and Add Azure OpenAI Service
```python
# Initialize the kernel
kernel = sk.Kernel()
# Set your Azure OpenAI details
deployment_name = "your-chat-deployment"
endpoint = "https://your-resource-name.openai.azure.com/"
api_key = "your-azure-openai-api-key"
# Add Azure Chat Completion service
kernel.add_chat_service(
"azure_chat",
AzureChatCompletion(
deployment_name=deployment_name,
endpoint=endpoint,
api_key=api_key,
),
)
```
---
### 4. Create a Chat History and Send a Request
```python
# Create an initial chat history
history = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What can you do?"},
]
# Get chat completion
result = kernel.chat.complete(
chat_history=history,
max_tokens=100,
temperature=0.7,
top_p=0.95,
)
print(result)
```
---
## Example Summary
This makes a chat completion request to Azure OpenAI through Semantic Kernel in Python. You can add more user/assistant
turns to `history`.
"""
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,119 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from pathlib import Path
from azure.identity import AzureCliCredential
from semantic_kernel.agents import ChatCompletionAgent, ChatHistoryAgentThread
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
from semantic_kernel.connectors.mcp import MCPStdioPlugin
from semantic_kernel.core_plugins.time_plugin import TimePlugin
"""
The following sample demonstrates how to create a chat completion agent that
answers questions about Github using a Semantic Kernel Plugin from a MCP server.
It uses the Azure OpenAI service to create a agent, so make sure to
set the required environment variables for the Azure AI Foundry service:
- AZURE_OPENAI_CHAT_DEPLOYMENT_NAME
- Optionally: AZURE_OPENAI_API_KEY
If this is not set, it's also possible to pass AsyncTokenCredential to the service, e.g. AzureCliCredential.
"""
async def main():
# 1. Create the agent
async with (
MCPStdioPlugin(
name="Menu",
description="Menu plugin, for details about the menu, call this plugin.",
command="uv",
args=[
f"--directory={str(Path(os.path.dirname(__file__)).joinpath('servers'))}",
"run",
"menu_agent_server.py",
],
env={
"AZURE_OPENAI_CHAT_DEPLOYMENT_NAME": os.getenv("AZURE_OPENAI_CHAT_DEPLOYMENT_NAME"),
"AZURE_OPENAI_ENDPOINT": os.getenv("AZURE_OPENAI_ENDPOINT"),
},
) as restaurant_agent,
MCPStdioPlugin(
name="Booking",
description="Restaurant Booking Plugin",
command="uv",
args=[
f"--directory={str(Path(os.path.dirname(__file__)).joinpath('servers'))}",
"run",
"restaurant_booking_agent_server.py",
],
env={
"AZURE_OPENAI_CHAT_DEPLOYMENT_NAME": os.getenv("AZURE_OPENAI_CHAT_DEPLOYMENT_NAME"),
"AZURE_OPENAI_ENDPOINT": os.getenv("AZURE_OPENAI_ENDPOINT"),
},
) as booking_agent,
):
agent = ChatCompletionAgent(
service=AzureChatCompletion(credential=AzureCliCredential()),
name="PersonalAssistant",
instructions="Help the user with restaurant bookings.",
plugins=[restaurant_agent, booking_agent, TimePlugin()],
)
# 2. Create a thread to hold the conversation
# If no thread is provided, a new thread will be
# created and returned with the initial response
thread: ChatHistoryAgentThread | None = None
while True:
user_input = input("User: ")
if user_input.lower() == "exit":
break
# 3. Invoke the agent for a response
response = await agent.get_response(messages=user_input, thread=thread)
print(f"# {response.name}: {response} ")
thread = response.thread
# 4. Cleanup: Clear the thread
await thread.delete() if thread else None
"""
User: what restaurants can I choose from?
# PersonalAssistant: Here are the available restaurants you can choose from:
1. **The Farm**: A classic steakhouse with a rustic atmosphere.
2. **The Harbor**: A seafood restaurant with a view of the ocean.
3. **The Joint**: A casual eatery with a diverse menu.
Let me know if you would like to make a booking or need more information about any specific restaurant!
User: the farm sounds nice, what are the specials there?
# PersonalAssistant: The specials at The Farm are:
- **Special Entree:** T-bone steak
- **Special Salad:** Caesar Salad
- **Special Drink:** Old Fashioned
Let me know if you'd like to make a booking or if you need any more information!
User: That entree sounds great, how much does it cost?
# PersonalAssistant: The cost of the T-bone steak at The Farm is $9.99. Would you like to proceed with a booking?
User: yes, for 2 people tomorrow
# PersonalAssistant: I can confirm a booking for 2 people at The Farm for tomorrow, April 17, 2025. What time would you
like the reservation?
User: at 2000
# PersonalAssistant: I apologize, but the booking at The Farm for tomorrow at 20:00 has been denied. However,
I was able to confirm bookings at the following restaurants:
- **The Harbor**: Booking confirmed.
- **The Joint**: Booking confirmed.
If you'd like to book at one of these restaurants or try a different time or restaurant, just let me know!
User: try 21.00
# PersonalAssistant: Your table for 2 people at The Farm has been successfully booked for tomorrow, April 17, 2025,
at 21:00. Enjoy your meal! If you need anything else, feel free to ask.
User: exit
"""
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,128 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from azure.identity import AzureCliCredential
from semantic_kernel.agents import ChatCompletionAgent, ChatHistoryAgentThread
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
from semantic_kernel.connectors.mcp import MCPStdioPlugin
"""
The following sample demonstrates how to create a chat completion agent that
answers questions about Github using a Semantic Kernel Plugin from a MCP server.
It uses the Azure OpenAI service to create a agent, so make sure to
set the required environment variables for the Azure AI Foundry service:
- AZURE_OPENAI_CHAT_DEPLOYMENT_NAME
- Optionally: AZURE_OPENAI_API_KEY
If this is not set, it's also possible to pass AsyncTokenCredential to the service, e.g. AzureCliCredential.
"""
# Simulate a conversation with the agent
USER_INPUTS = [
"What are the latest 5 python issues in Microsoft/semantic-kernel?",
"Are there any untriaged python issues?",
"What is the status of issue #10785?",
]
async def main():
# 1. Create the agent
async with MCPStdioPlugin(
name="Github",
description="Github Plugin",
command="docker",
args=["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server"],
env={"GITHUB_PERSONAL_ACCESS_TOKEN": os.getenv("GITHUB_PERSONAL_ACCESS_TOKEN")},
) as github_plugin:
agent = ChatCompletionAgent(
service=AzureChatCompletion(credential=AzureCliCredential()),
name="IssueAgent",
instructions="Answer questions about the Microsoft semantic-kernel github project.",
plugins=[github_plugin],
)
for user_input in USER_INPUTS:
# 2. Create a thread to hold the conversation
# If no thread is provided, a new thread will be
# created and returned with the initial response
thread: ChatHistoryAgentThread | None = None
print(f"# User: {user_input}")
# 3. Invoke the agent for a response
response = await agent.get_response(messages=user_input, thread=thread)
print(f"# {response.name}: {response} ")
thread = response.thread
# 4. Cleanup: Clear the thread
await thread.delete() if thread else None
"""
Sample output:
GitHub MCP Server running on stdio
# User: What are the latest 5 python issues in Microsoft/semantic-kernel?
# IssueAgent: Here are the latest 5 Python issues in the
[Microsoft/semantic-kernel](https://github.com/microsoft/semantic-kernel) repository:
1. **[Issue #11358](https://github.com/microsoft/semantic-kernel/pull/11358)**
**Title:** Python: Bump Python version to 1.27.0 for a release.
**Created by:** [moonbox3](https://github.com/moonbox3)
**Created at:** April 3, 2025
**State:** Open
**Comments:** 1
**Description:** Bump Python version to 1.27.0 for a release.
2. **[Issue #11357](https://github.com/microsoft/semantic-kernel/pull/11357)**
**Title:** .Net: Version 1.45.0
**Created by:** [markwallace-microsoft](https://github.com/markwallace-microsoft)
**Created at:** April 3, 2025
**State:** Open
**Comments:** 0
**Description:** Version bump for release 1.45.0.
3. **[Issue #11356](https://github.com/microsoft/semantic-kernel/pull/11356)**
**Title:** .Net: Fix bug in sqlite filter logic
**Created by:** [westey-m](https://github.com/westey-m)
**Created at:** April 3, 2025
**State:** Open
**Comments:** 0
**Description:** Fix bug in sqlite filter logic.
4. **[Issue #11355](https://github.com/microsoft/semantic-kernel/issues/11355)**
**Title:** .Net: [MEVD] Validate that the collection generic key parameter corresponds to the model
**Created by:** [roji](https://github.com/roji)
**Created at:** April 3, 2025
**State:** Open
**Comments:** 0
**Description:** We currently have validation for the TKey generic type parameter passed to the collection type,
and we have validation for the key property type on the model.
5. **[Issue #11354](https://github.com/microsoft/semantic-kernel/issues/11354)**
**Title:** .Net: How to add custom JsonSerializer on a builder level
**Created by:** [PawelStadnicki](https://github.com/PawelStadnicki)
**Created at:** April 3, 2025
**State:** Open
**Comments:** 0
**Description:** Inquiry about adding a custom JsonSerializer for handling F# types within the SDK.
If you need more details about a specific issue, let me know!
# User: Are there any untriaged python issues?
# IssueAgent: There are no untriaged Python issues in the Microsoft semantic-kernel repository.
# User: What is the status of issue #10785?
# IssueAgent: The status of issue #10785 in the Microsoft Semantic Kernel repository is **open**.
- **Title**: Port dotnet feature: Create MCP Sample
- **Created at**: March 4, 2025
- **Comments**: 0
- **Labels**: python
You can view the issue [here](https://github.com/microsoft/semantic-kernel/issues/10785).
"""
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,116 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import logging
import os
from pathlib import Path
from semantic_kernel.agents import ChatCompletionAgent
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
from semantic_kernel.connectors.mcp import MCPStdioPlugin
# set this lower or higher depending on your needs
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
"""
The following sample demonstrates how to use a MCP Server that requires sampling
to generate release notes from a list of issues.
It uses the OpenAI service to create a agent, so make sure to
set the required environment variables for the Azure AI Foundry service:
- OPENAI_API_KEY
- OPENAI_CHAT_MODEL_ID
"""
PR_MESSAGES = """* Python: Add ChatCompletionAgent integration tests by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11430
* Python: Update Doc Gen demo based on latest agent invocation api pattern by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11426
* Python: Update Python min version in README by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11428
* Python: Fix `TypeError` when required is missing in MCP tools inputSchema by @KanchiShimono in https://github.com/microsoft/semantic-kernel/pull/11458
* Python: Update chromadb requirement from <0.7,>=0.5 to >=0.5,<1.1 in /python by @dependabot in https://github.com/microsoft/semantic-kernel/pull/11420
* Python: Bump google-cloud-aiplatform from 1.86.0 to 1.87.0 in /python by @dependabot in https://github.com/microsoft/semantic-kernel/pull/11423
* Python: Support Auto Function Invocation Filter for AzureAIAgent and OpenAIAssistantAgent by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11460
* Python: Improve agent integration tests by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11475
* Python: Allow Kernel Functions from Prompt for image and audio content by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11403
* Python: Introducing SK as a MCP Server by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11362
* Python: sample using GitHub MCP Server and Azure AI Agent by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11465
* Python: allow settings to be created directly by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11468
* Python: Bug fix for azure ai agent truncate strategy. Add sample. by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11503
* Python: small code improvements in code of call automation sample by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11477
* Added missing import asyncio to agent with plugin python by @sphenry in https://github.com/microsoft/semantic-kernel/pull/11472
* Python: version updated to 1.28.0 by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11504"""
async def main():
# 1. Create the agent
async with MCPStdioPlugin(
name="ReleaseNotes",
description="SK Release Notes Plugin",
command="uv",
args=[
f"--directory={str(Path(os.path.dirname(__file__)).parent.parent.joinpath('demos', 'mcp_server'))}",
"run",
"mcp_server_with_sampling.py",
],
sampling_auto_approve=True,
) as plugin:
agent = ChatCompletionAgent(
service=OpenAIChatCompletion(),
name="IssueAgent",
instructions="For the messages supplied, call the release_notes_prompt function to get the broader "
"prompt, then call the run_prompt function to get the final output, return that without any other text."
"Do not add any other text to the output, or rewrite the output from run_prompt.",
plugins=[plugin],
)
print(f"# Task: {PR_MESSAGES}")
# 3. Invoke the agent for a response
response = await agent.get_response(messages=PR_MESSAGES)
print(str(response))
# 4. Cleanup: Clear the thread
await response.thread.delete()
"""
# Task: * Python: Add ChatCompletionAgent integration tests by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11430
* Python: Update Doc Gen demo based on latest agent invocation api pattern by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11426
* Python: Update Python min version in README by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11428
* Python: Fix `TypeError` when required is missing in MCP tools inputSchema by @KanchiShimono in https://github.com/microsoft/semantic-kernel/pull/11458
* Python: Update chromadb requirement from <0.7,>=0.5 to >=0.5,<1.1 in /python by @dependabot in https://github.com/microsoft/semantic-kernel/pull/11420
* Python: Bump google-cloud-aiplatform from 1.86.0 to 1.87.0 in /python by @dependabot in https://github.com/microsoft/semantic-kernel/pull/11423
* Python: Support Auto Function Invocation Filter for AzureAIAgent and OpenAIAssistantAgent by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11460
* Python: Improve agent integration tests by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11475
* Python: Allow Kernel Functions from Prompt for image and audio content by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11403
* Python: Introducing SK as a MCP Server by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11362
* Python: sample using GitHub MCP Server and Azure AI Agent by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11465
* Python: allow settings to be created directly by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11468
* Python: Bug fix for azure ai agent truncate strategy. Add sample. by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11503
* Python: small code improvements in code of call automation sample by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11477
* Added missing import asyncio to agent with plugin python by @sphenry in https://github.com/microsoft/semantic-kernel/pull/11472
* Python: version updated to 1.28.0 by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11504
Heres a summary of the recent changes and contributions made to the Microsoft Semantic Kernel repository:
1. **Integration Tests**:
- Added integration tests for `ChatCompletionAgent` by @moonbox3 ([PR #11430](https://github.com/microsoft/semantic-kernel/pull/11430)).
- Improved agent integration tests by @moonbox3 ([PR #11475](https://github.com/microsoft/semantic-kernel/pull/11475)).
2. **Documentation and Demos**:
- Updated the Doc Gen demo to align with the latest agent invocation API pattern by @moonbox3 ([PR #11426](https://github.com/microsoft/semantic-kernel/pull/11426)).
- Small code improvements made in the code of the call automation sample by @eavanvalkenburg ([PR #11477](https://github.com/microsoft/semantic-kernel/pull/11477)).
3. **Version Updates**:
- Updated the minimum Python version in the README by @moonbox3 ([PR #11428](https://github.com/microsoft/semantic-kernel/pull/11428)).
- Updated `chromadb` requirement to allow versions >=0.5 and <1.1 by @dependabot ([PR #11420](https://github.com/microsoft/semantic-kernel/pull/11420)).
- Bumped `google-cloud-aiplatform` from 1.86.0 to 1.87.0 by @dependabot ([PR #11423](https://github.com/microsoft/semantic-kernel/pull/11423)).
- Version updated to 1.28.0 by @eavanvalkenburg ([PR #11504](https://github.com/microsoft/semantic-kernel/pull/11504)).
4. **Bug Fixes**:
- Fixed a `TypeError` in the MCP tools input schema when the required field is missing by @KanchiShimono ([PR #11458](https://github.com/microsoft/semantic-kernel/pull/11458)).
- Bug fix for Azure AI agent truncate strategy with an added sample by @moonbox3 ([PR #11503](https://github.com/microsoft/semantic-kernel/pull/11503)).
- Added a missing import for `asyncio` in the agent with plugin Python by @sphenry ([PR #11472](https://github.com/microsoft/semantic-kernel/pull/11472)).
"""
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,108 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from pathlib import Path
from azure.identity.aio import AzureCliCredential
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
from semantic_kernel.connectors.mcp import MCPStdioPlugin
from semantic_kernel.functions import KernelArguments
"""
The following sample demonstrates how to create a chat completion agent that
answers questions about Github using a Local Agent with two local MCP Servers.
It uses the Azure AI Foundry Agent service to create a agent, so make sure to
set the required environment variables for the Azure AI Foundry service:
- AZURE_AI_AGENT_PROJECT_CONNECTION_STRING
- AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME
"""
USER_INPUTS = [
"list the latest 10 issues that have the label: triage and python and are open",
"""generate release notes with this list:
* Python: Add ChatCompletionAgent integration tests by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11430
* Python: Update Doc Gen demo based on latest agent invocation api pattern by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11426
* Python: Update Python min version in README by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11428
* Python: Fix `TypeError` when required is missing in MCP tools inputSchema by @KanchiShimono in https://github.com/microsoft/semantic-kernel/pull/11458
* Python: Update chromadb requirement from <0.7,>=0.5 to >=0.5,<1.1 in /python by @dependabot in https://github.com/microsoft/semantic-kernel/pull/11420
* Python: Bump google-cloud-aiplatform from 1.86.0 to 1.87.0 in /python by @dependabot in https://github.com/microsoft/semantic-kernel/pull/11423
* Python: Support Auto Function Invocation Filter for AzureAIAgent and OpenAIAssistantAgent by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11460
* Python: Improve agent integration tests by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11475
* Python: Allow Kernel Functions from Prompt for image and audio content by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11403
* Python: Introducing SK as a MCP Server by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11362
* Python: sample using GitHub MCP Server and Azure AI Agent by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11465
* Python: allow settings to be created directly by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11468
* Python: Bug fix for azure ai agent truncate strategy. Add sample. by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11503
* Python: small code improvements in code of call automation sample by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11477
* Added missing import asyncio to agent with plugin python by @sphenry in https://github.com/microsoft/semantic-kernel/pull/11472
* Python: version updated to 1.28.0 by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11504""",
]
async def main():
# Load the MCP Servers as Plugins
async with (
# 1. Login to Azure and create a Azure AI Project Client
AzureCliCredential() as creds,
AzureAIAgent.create_client(credential=creds) as client,
MCPStdioPlugin(
name="Github",
description="Github Plugin",
command="docker",
args=["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server"],
env={"GITHUB_PERSONAL_ACCESS_TOKEN": os.getenv("GITHUB_PERSONAL_ACCESS_TOKEN")},
) as github_plugin,
MCPStdioPlugin(
name="ReleaseNotes",
description="SK Release Notes Plugin",
command="uv",
args=[
f"--directory={str(Path(os.path.dirname(__file__)).parent.parent.joinpath('demos', 'mcp_server'))}",
"run",
"mcp_server_with_prompts.py",
],
) as release_notes_plugin,
):
# 3. Create the agent, with the MCP plugin and the thread
agent = AzureAIAgent(
client=client,
definition=await client.agents.create_agent(
model=AzureAIAgentSettings().model_deployment_name,
name="GithubAgent",
instructions="You interact with the user to help them with the Microsoft semantic-kernel github "
"project. You have dedicated tools for this, including one to write release notes, "
"make sure to use that when needed. The repo is always semantic-kernel (aka SK) with owner Microsoft. "
"and when doing lists, always return 5 items and sort descending by created or updated"
"You are specialized in Python, so always include label, python, in addition to the other labels.",
),
plugins=[github_plugin, release_notes_plugin], # add the sample plugin to the agent
)
# Create a thread to hold the conversation
# If no thread is provided, a new thread will be
# created and returned with the initial response
thread: AzureAIAgentThread | None = None
for user_input in USER_INPUTS:
print(f"# User: {user_input}", end="\n\n")
first_chunk = True
async for response in agent.invoke_stream(
messages=user_input,
thread=thread,
arguments=KernelArguments(owner="microsoft", repo="semantic-kernel"),
):
if first_chunk:
print(f"# {response.name}: ", end="", flush=True)
first_chunk = False
print(response.content, end="", flush=True)
thread = response.thread
print()
# Cleanup: Clear the thread
await thread.delete() if thread else None
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,100 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from azure.identity.aio import AzureCliCredential
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
from semantic_kernel.connectors.mcp import MCPStdioPlugin
"""
The following sample demonstrates how to create a AzureAIAgent that
answers questions about Github using a Semantic Kernel Plugin from a MCP server.
It uses the Azure AI Foundry Agent service to create a agent, so make sure to
set the required environment variables for the Azure AI Foundry service:
- AZURE_AI_AGENT_PROJECT_CONNECTION_STRING
- AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME
"""
async def main():
async with (
# 1. Login to Azure and create a Azure AI Project Client
AzureCliCredential() as creds,
AzureAIAgent.create_client(credential=creds) as client,
# 2. Create the MCP plugin
MCPStdioPlugin(
name="github",
description="Github Plugin",
command="docker",
args=["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server"],
env={"GITHUB_PERSONAL_ACCESS_TOKEN": os.getenv("GITHUB_PERSONAL_ACCESS_TOKEN")},
) as github_plugin,
):
# 3. Create the agent, with the MCP plugin and the thread
agent = AzureAIAgent(
client=client,
definition=await client.agents.create_agent(
model=AzureAIAgentSettings.create().model_deployment_name,
name="GithubAgent",
instructions="You are a microsoft/semantic-kernel Issue Triage Agent. "
"You look at all issues that have the tag: 'triage' and 'python'."
"When you find one that is untriaged, you will suggest a new assignee "
"based on the issue description, look at recent closed PR's for issues in the same area. "
"You will also suggest additional context if needed, like related issues or a bug fix. ",
),
plugins=[github_plugin], # add the sample plugin to the agent
)
thread: AzureAIAgentThread | None = None
# 4. Print instructions and set the initial user input
print("Starting Azure AI Agent with MCP Plugin sample...")
print("Once the first prompt is answered, you can further ask questions, use `exit` to exit.")
user_input = "Find the latest untriaged, unassigned issues and suggest new assignees."
print(f"# User: {user_input}")
try:
while user_input.lower() != "exit":
# 5. Invoke the agent for a response
response = await agent.get_response(messages=user_input, thread=thread)
print(f"# {response.name}: {response} ")
thread = response.thread
# 6. Get a new user input
user_input = input("# User: ")
finally:
# 7. Cleanup: Clear the thread
await thread.delete() if thread else None
await client.agents.delete_agent(agent.definition.id)
"""
Sample output:
GitHub MCP Server running on stdio
Starting Azure AI Agent with MCP Plugin sample...
Once the first prompt is answered, you can further ask questions, use `exit` to exit.
# User: Find the latest untriaged, unassigned issues and suggest new assignees.
# GithubAgent: Here are the latest untriaged and unassigned issues that are tagged with Python:
1. **[Issue #11459](https://github.com/microsoft/semantic-kernel/issues/11459)**
- **Title:** Python: Bug: The provided example is incorrect
- **Description:** There are apparent mistakes in the provided Python examples concerning shared and
non-shared stateful configurations.
- **Assignee Suggestion:** Assign to **eavanvalkenburg** based on prior involvement with Python-related code and
recent PRs focusing on bug fixes.
2. **[Issue #11465](https://github.com/microsoft/semantic-kernel/issues/11465)**
- **Title:** Python: sample using GitHub MCP Server and Azure AI Agent
- **Description:** This adds a sample demonstrating how to use MCP tools with the Azure AI Agent.
- **Assignee Suggestion:** Assign to **eavanvalkenburg** who is associated with the issue.
### Summary of Suggested Assignees:
- **Issue #11459**: **eavanvalkenburg**
- **Issue #11465**: **eavanvalkenburg**
It seems that I cannot update the assignees directly due to authentication issues. You can use this information
as you see fit to assign these issues. If you need further assistance or specific context for each issue,
please let me know!
"""
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,112 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from pathlib import Path
from semantic_kernel.agents import ChatCompletionAgent, ChatHistoryAgentThread
from semantic_kernel.connectors.ai import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.ollama import OllamaChatCompletion
from semantic_kernel.connectors.mcp import MCPStdioPlugin
from semantic_kernel.functions import KernelArguments
"""
The following sample demonstrates how to create a chat completion agent that
answers questions about Github using a Local Agent with two local MCP Servers.
It uses a Ollama Chat Completion to create a agent, so make sure to
set the required environment variables for the Azure AI Foundry service:
- OLLAMA_CHAT_MODEL_ID
"""
USER_INPUTS = [
"list the latest 10 issues that have the label: triage and python and are open",
"""generate release notes with this list:
* Python: Add ChatCompletionAgent integration tests by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11430
* Python: Update Doc Gen demo based on latest agent invocation api pattern by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11426
* Python: Update Python min version in README by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11428
* Python: Fix `TypeError` when required is missing in MCP tools inputSchema by @KanchiShimono in https://github.com/microsoft/semantic-kernel/pull/11458
* Python: Update chromadb requirement from <0.7,>=0.5 to >=0.5,<1.1 in /python by @dependabot in https://github.com/microsoft/semantic-kernel/pull/11420
* Python: Bump google-cloud-aiplatform from 1.86.0 to 1.87.0 in /python by @dependabot in https://github.com/microsoft/semantic-kernel/pull/11423
* Python: Support Auto Function Invocation Filter for AzureAIAgent and OpenAIAssistantAgent by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11460
* Python: Improve agent integration tests by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11475
* Python: Allow Kernel Functions from Prompt for image and audio content by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11403
* Python: Introducing SK as a MCP Server by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11362
* Python: sample using GitHub MCP Server and Azure AI Agent by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11465
* Python: allow settings to be created directly by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11468
* Python: Bug fix for azure ai agent truncate strategy. Add sample. by @moonbox3 in https://github.com/microsoft/semantic-kernel/pull/11503
* Python: small code improvements in code of call automation sample by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11477
* Added missing import asyncio to agent with plugin python by @sphenry in https://github.com/microsoft/semantic-kernel/pull/11472
* Python: version updated to 1.28.0 by @eavanvalkenburg in https://github.com/microsoft/semantic-kernel/pull/11504""",
]
async def main():
# Load the MCP Servers as Plugins
async with (
MCPStdioPlugin(
name="Github",
description="Github Plugin",
command="docker",
args=["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server"],
env={"GITHUB_PERSONAL_ACCESS_TOKEN": os.getenv("GITHUB_PERSONAL_ACCESS_TOKEN")},
) as github_plugin,
MCPStdioPlugin(
name="ReleaseNotes",
description="SK Release Notes Plugin",
command="uv",
args=[
f"--directory={str(Path(os.path.dirname(__file__)).parent.parent.joinpath('demos', 'mcp_server'))}",
"run",
"mcp_server_with_prompts.py",
],
) as release_notes_plugin,
):
# Create the agent
agent = ChatCompletionAgent(
# Using the OllamaChatCompletion service
service=OllamaChatCompletion(),
name="GithubAgent",
instructions="You interact with the user to help them with the Microsoft semantic-kernel github project. "
"You have dedicated tools for this, including one to write release notes, "
"make sure to use that when needed. The repo is always semantic-kernel (aka SK) with owner Microsoft. "
"and when doing lists, always return 5 items and sort descending by created or updated"
"You are specialized in Python, so always include label, python, in addition to the other labels.",
plugins=[github_plugin, release_notes_plugin],
function_choice_behavior=FunctionChoiceBehavior.Auto(
filters={
# exclude a bunch of functions because the local models have trouble with too many functions
"included_functions": [
"Github-list_issues",
"ReleaseNotes-release_notes_prompt",
]
}
),
)
print(f"Agent uses Ollama with the {agent.service.ai_model_id} model")
# Create a thread to hold the conversation
# If no thread is provided, a new thread will be
# created and returned with the initial response
thread: ChatHistoryAgentThread | None = None
for user_input in USER_INPUTS:
print(f"# User: {user_input}", end="\n\n")
first_chunk = True
async for response in agent.invoke_stream(
messages=user_input,
thread=thread,
arguments=KernelArguments(owner="microsoft", repo="semantic-kernel"),
):
if first_chunk:
print(f"# {response.name}: ", end="", flush=True)
first_chunk = False
print(response.content, end="", flush=True)
thread = response.thread
print()
# Cleanup: Clear the thread
await thread.delete() if thread else None
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,122 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import logging
import os
from samples.concepts.setup.chat_completion_services import Services, get_chat_completion_service_and_request_settings
from semantic_kernel import Kernel
from semantic_kernel.connectors.ai import FunctionChoiceBehavior
from semantic_kernel.connectors.mcp import MCPStdioPlugin
from semantic_kernel.contents import ChatHistory
from semantic_kernel.utils.logging import setup_logging
"""
This sample demonstrates how to build a conversational chatbot
using Semantic Kernel,
it creates a Plugin from a MCP server config and adds it to the kernel.
The chatbot is designed to interact with the user, call MCP tools
as needed, and return responses.
To run this sample, make sure to run:
`pip install semantic-kernel[mcp]`
or install the mcp package manually.
In addition, different MCP Stdio servers need different commands to run.
For example, the Github plugin requires `npx`, others use `uvx` or `docker`.
Make sure those are available in your PATH.
"""
# System message defining the behavior and persona of the chat bot.
system_message = """
You are a chat bot. And you help users interact with Github.
You are especially good at answering questions about the Microsoft semantic-kernel project.
You can call functions to get the information you need.
"""
setup_logging()
logging.getLogger("semantic_kernel.connectors.mcp").setLevel(logging.DEBUG)
# Create and configure the kernel.
kernel = Kernel()
# You can select from the following chat completion services that support function calling:
# - Services.OPENAI
# - Services.AZURE_OPENAI
# - Services.AZURE_AI_INFERENCE
# - Services.ANTHROPIC
# - Services.BEDROCK
# - Services.GOOGLE_AI
# - Services.MISTRAL_AI
# - Services.OLLAMA
# - Services.ONNX
# - Services.VERTEX_AI
# - Services.DEEPSEEK
# Please make sure you have configured your environment correctly for the selected chat completion service.
chat_service, settings = get_chat_completion_service_and_request_settings(Services.OPENAI)
# Configure the function choice behavior. Here, we set it to Auto, where auto_invoke=True by default.
# With `auto_invoke=True`, the model will automatically choose and call functions as needed.
settings.function_choice_behavior = FunctionChoiceBehavior.Auto()
kernel.add_service(chat_service)
# Create a chat history to store the system message, initial messages, and the conversation.
history = ChatHistory()
history.add_system_message(system_message)
async def chat() -> bool:
"""
Continuously prompt the user for input and show the assistant's response.
Type 'exit' to exit.
"""
try:
user_input = input("User:> ")
except (KeyboardInterrupt, EOFError):
print("\n\nExiting chat...")
return False
if user_input.lower().strip() == "exit":
print("\n\nExiting chat...")
return False
history.add_user_message(user_input)
result = await chat_service.get_chat_message_content(history, settings, kernel=kernel)
if result:
print(f"Mosscap:> {result}")
history.add_message(result)
return True
async def main() -> None:
# Create a plugin from the MCP server config and add it to the kernel.
# The MCP server plugin is defined using the MCPStdioPlugin class.
# The command and args are specific to the MCP server you want to run.
# For example, the Github MCP Server uses `npx` to run the server.
# There are also MCPSsePlugin and MCPStreamableHttpPlugin, which take a URL.
async with MCPStdioPlugin(
name="Github",
description="Github Plugin",
command="docker",
args=["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server"],
env={"GITHUB_PERSONAL_ACCESS_TOKEN": os.getenv("GITHUB_PERSONAL_ACCESS_TOKEN")},
) as github_plugin:
# instead of using this async context manager, you can also use:
# await github_plugin.connect()
# and then await github_plugin.close() at the end of the program.
# Add the plugin to the kernel.
kernel.add_plugin(github_plugin)
# Start the chat loop.
print("Welcome to the chat bot!\n Type 'exit' to exit.\n")
chatting = True
while chatting:
chatting = await chat()
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,176 @@
# /// script # noqa: CPY001
# dependencies = [
# "semantic-kernel[mcp]",
# ]
# ///
# Copyright (c) Microsoft. All rights reserved.
import argparse
import logging
from typing import Annotated, Any, Literal
import anyio
from azure.identity import AzureCliCredential
from semantic_kernel.agents import ChatCompletionAgent
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
from semantic_kernel.functions import kernel_function
logger = logging.getLogger(__name__)
"""
This sample demonstrates how to expose an Agent as a MCP server.
To run this sample, set up your MCP host (like Claude Desktop or VSCode Github Copilot Agents)
with the following configuration:
```json
{
"mcpServers": {
"sk": {
"command": "uv",
"args": [
"--directory=<path to sk project>/semantic-kernel/python/samples/demos/mcp_server",
"run",
"agent_mcp_server.py"
],
"env": {
"AZURE_AI_AGENT_PROJECT_CONNECTION_STRING": "<your azure connection string>",
"AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME": "<your azure model deployment name>",
}
}
}
}
```
Alternatively, you can run this as a SSE server, by setting the same environment variables as above,
and running the following command:
```bash
uv --directory=<path to sk project>/semantic-kernel/python/samples/demos/mcp_server \
run agent_mcp_server.py --transport sse --port 8000
```
This will start a server that listens for incoming requests on port 8000.
In both cases, uv will make sure to install semantic-kernel with the mcp extra for you in a temporary venv.
"""
def parse_arguments():
parser = argparse.ArgumentParser(description="Run the Semantic Kernel MCP server.")
parser.add_argument(
"--transport",
type=str,
choices=["sse", "stdio"],
default="stdio",
help="Transport method to use (default: stdio).",
)
parser.add_argument(
"--port",
type=int,
default=None,
help="Port to use for SSE transport (required if transport is 'sse').",
)
return parser.parse_args()
# Define a simple plugin for the sample
class RestaurantPlugin:
"""A sample Menu Plugin used for the sample."""
@kernel_function(description="List the available restaurants.")
def list_restaurants(self) -> Annotated[str, "Returns a list of available restaurants."]:
return """
1. The Farm: a classic steakhouse with a rustic atmosphere.
2. The Harbor: a seafood restaurant with a view of the ocean.
3. The Joint: a casual eatery with a diverse menu.
"""
@kernel_function(description="Provides a list of specials from the menu.")
def get_specials(
self, restaurant: Literal["The Farm, The Harbor, The Joint"]
) -> Annotated[str, "Returns the specials from the menu."]:
match restaurant:
case "The Farm":
return """
Special Entree: T-bone steak
Special Salad: Caesar Salad
Special Drink: Old Fashioned
"""
case "The Harbor":
return """
Special Soup: Lobster Bisque
Special Salad: Cobb Salad
Special Drink: Mai Tai
"""
case "The Joint":
return """
Special Burger: Avocado and Jalapeno Burger
Special Salad: Greek Salad
Special Drink: Milkshake Strawberry
"""
case _:
return "No specials available for this restaurant."
@kernel_function(description="Provides the price of the requested menu item.")
def get_item_price(
self,
restaurant: Literal["The Farm, The Harbor, The Joint"],
menu_item: Annotated[str, "The name of the menu item."],
) -> Annotated[str, "Returns the price of the menu item."]:
match restaurant:
case "The Farm":
return "$9.99"
case "The Harbor":
return "$12.99"
case "The Joint":
return "$8.99"
case _:
return "No price available for this restaurant."
async def run(transport: Literal["sse", "stdio"] = "stdio", port: int | None = None) -> None:
agent = ChatCompletionAgent(
service=AzureChatCompletion(credential=AzureCliCredential()),
name="Host",
instructions="Answer questions about the menu for different restaurants, use the list_restaurants function "
"to get the list of restaurants.",
plugins=[RestaurantPlugin()], # add the sample plugin to the agent
)
server = agent.as_mcp_server()
if transport == "sse" and port is not None:
import nest_asyncio
import uvicorn
from mcp.server.sse import SseServerTransport
from starlette.applications import Starlette
from starlette.routing import Mount, Route
sse = SseServerTransport("/messages/")
async def handle_sse(request):
async with sse.connect_sse(request.scope, request.receive, request._send) as (
read_stream,
write_stream,
):
await server.run(read_stream, write_stream, server.create_initialization_options())
starlette_app = Starlette(
debug=True,
routes=[
Route("/sse", endpoint=handle_sse),
Mount("/messages/", app=sse.handle_post_message),
],
)
nest_asyncio.apply()
uvicorn.run(starlette_app, host="0.0.0.0", port=port) # nosec
elif transport == "stdio":
from mcp.server.stdio import stdio_server
async def handle_stdin(stdin: Any | None = None, stdout: Any | None = None) -> None:
async with stdio_server() as (read_stream, write_stream):
await server.run(read_stream, write_stream, server.create_initialization_options())
await handle_stdin()
if __name__ == "__main__":
args = parse_arguments()
anyio.run(run, args.transport, args.port)
@@ -0,0 +1,150 @@
# /// script # noqa: CPY001
# dependencies = [
# "semantic-kernel[mcp]",
# ]
# ///
# Copyright (c) Microsoft. All rights reserved.
import argparse
import logging
from random import random
from typing import Annotated, Any, Literal
import anyio
from azure.identity import AzureCliCredential
from semantic_kernel.agents import ChatCompletionAgent
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
from semantic_kernel.functions import kernel_function
logger = logging.getLogger(__name__)
"""
This sample demonstrates how to expose an Agent as a MCP server.
To run this sample, set up your MCP host (like Claude Desktop or VSCode Github Copilot Agents)
with the following configuration:
```json
{
"mcpServers": {
"sk": {
"command": "uv",
"args": [
"--directory=<path to sk project>/semantic-kernel/python/samples/demos/mcp_server",
"run",
"agent_mcp_server.py"
],
"env": {
"AZURE_AI_AGENT_PROJECT_CONNECTION_STRING": "<your azure connection string>",
"AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME": "<your azure model deployment name>",
}
}
}
}
```
Alternatively, you can run this as a SSE server, by setting the same environment variables as above,
and running the following command:
```bash
uv --directory=<path to sk project>/semantic-kernel/python/samples/demos/mcp_server \
run agent_mcp_server.py --transport sse --port 8000
```
This will start a server that listens for incoming requests on port 8000.
In both cases, uv will make sure to install semantic-kernel with the mcp extra for you in a temporary venv.
"""
def parse_arguments():
parser = argparse.ArgumentParser(description="Run the Semantic Kernel MCP server.")
parser.add_argument(
"--transport",
type=str,
choices=["sse", "stdio"],
default="stdio",
help="Transport method to use (default: stdio).",
)
parser.add_argument(
"--port",
type=int,
default=None,
help="Port to use for SSE transport (required if transport is 'sse').",
)
return parser.parse_args()
# Define a simple plugin for the sample
class BookingPlugin:
"""A sample Booking Plugin used for the sample."""
@kernel_function(description="Asks for a booking, will return 'confirmed' or 'denied'.")
def book_a_table(
self,
restaurant: Annotated[Literal["The Farm, The Harbor, The Joint"], "The name of the restaurant."],
day: Annotated[str, "Day of the week"],
time: Annotated[int, "The hour of the booking (whole hours only)"],
number_of_guests: Annotated[int, "The number of guests."],
) -> Annotated[str, "Confirmed or denied."]:
if time < 12 or time > 23:
return "denied"
odds = 0.5 if number_of_guests > 4 else 0.9
if time < 12 or time > 21:
odds = min(1.0, odds * 1.5)
if day in ["Friday", "Saturday"]:
odds = max(0.0, min(1.0, odds * 0.8))
match restaurant:
case "The Farm":
odds = max(0.0, odds * 0.5)
case "The Harbor":
odds = max(0.0, odds * 0.7)
case "The Joint":
odds = min(1.0, odds * 1.2)
return "confirmed" if random() < odds else "denied" # nosec
async def run(transport: Literal["sse", "stdio"] = "stdio", port: int | None = None) -> None:
agent = ChatCompletionAgent(
service=AzureChatCompletion(credential=AzureCliCredential()),
name="Booker",
instructions="Create a booking for the user, this is for the following restaurants: "
"The Farm, The Harbor, The Joint. ",
plugins=[BookingPlugin()], # add the sample plugin to the agent
)
server = agent.as_mcp_server()
if transport == "sse" and port is not None:
import nest_asyncio
import uvicorn
from mcp.server.sse import SseServerTransport
from starlette.applications import Starlette
from starlette.routing import Mount, Route
sse = SseServerTransport("/messages/")
async def handle_sse(request):
async with sse.connect_sse(request.scope, request.receive, request._send) as (
read_stream,
write_stream,
):
await server.run(read_stream, write_stream, server.create_initialization_options())
starlette_app = Starlette(
debug=True,
routes=[
Route("/sse", endpoint=handle_sse),
Mount("/messages/", app=sse.handle_post_message),
],
)
nest_asyncio.apply()
uvicorn.run(starlette_app, host="0.0.0.0", port=port) # nosec
elif transport == "stdio":
from mcp.server.stdio import stdio_server
async def handle_stdin(stdin: Any | None = None, stdout: Any | None = None) -> None:
async with stdio_server() as (read_stream, write_stream):
await server.run(read_stream, write_stream, server.create_initialization_options())
await handle_stdin()
if __name__ == "__main__":
args = parse_arguments()
anyio.run(run, args.transport, args.port)