chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
# Running this sample
|
||||
|
||||
You're recommended to install `uv` but it's not a must, see [instructions](https://docs.astral.sh/uv/#highlights)
|
||||
|
||||
## -0- Create a virtual environment
|
||||
|
||||
```bash
|
||||
python -m venv venv
|
||||
```
|
||||
|
||||
## -1- Activate the virtual environment
|
||||
|
||||
```bash
|
||||
venv\Scripts\activate
|
||||
```
|
||||
|
||||
## -2- Install the dependencies
|
||||
|
||||
```bash
|
||||
pip install "mcp[cli]" openai
|
||||
```
|
||||
|
||||
## -3- Run the sample
|
||||
|
||||
|
||||
```bash
|
||||
python client.py
|
||||
```
|
||||
|
||||
You should see output similar to:
|
||||
|
||||
```text
|
||||
[02/18/26 13:16:34] INFO Processing request of type ListToolsRequest server.py:720
|
||||
result: {"id": 1, "name": "paprika", "description": "**Product Description: Paprika - The Vibrant Red Wonder**\n\nElevate your culinary creations with our premium paprika, the jewel of spices that bursts with color, flavor, and nutrition. Harvested from the finest red, juicy peppers, our paprika is meticulously ground to preserve its rich, vibrant hue and aromatic essence, making it an essential ingredient in any kitchen.\n\nEach sprinkle of our paprika adds a delightful warmth and a subtle sweetness to a variety of dishes, from savory stews to vibrant salads and mouthwatering marinades. Its radiant red color not only enhances the visual appeal of your meals but also signifies the freshness and quality of the peppers used. \n\nRich in antioxidants and packed with vitamins, paprika not only tantalizes your taste buds but also contributes to a healthy lifestyle. Whether you're a professional chef or a home cook, this versatile spice will inspire your creativity and add a beautiful, flavorful touch to everything you whip up.\n\nDiscover the magic of our red, juicy paprika\u2014a spice that transforms ordinary dishes into"}
|
||||
```
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
"""
|
||||
cd to the `examples/snippets/clients` directory and run:
|
||||
uv run client
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from pydantic import AnyUrl
|
||||
|
||||
from mcp import ClientSession, StdioServerParameters, types
|
||||
from mcp.client.stdio import stdio_client
|
||||
from mcp.shared.context import RequestContext
|
||||
|
||||
import os
|
||||
from openai import OpenAI
|
||||
|
||||
# Create server parameters for stdio connection
|
||||
server_params = StdioServerParameters(
|
||||
command="python", # Using python to run the server
|
||||
args=["server.py"]
|
||||
)
|
||||
|
||||
async def call_llm(prompt: str, system_prompt: str) -> str:
|
||||
client = OpenAI(
|
||||
base_url="https://models.github.ai/inference",
|
||||
api_key=os.environ["GITHUB_TOKEN"],
|
||||
)
|
||||
|
||||
response = client.chat.completions.create(
|
||||
messages=[
|
||||
{
|
||||
"role": "system",
|
||||
"content": system_prompt,
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": prompt,
|
||||
}
|
||||
],
|
||||
model="openai/gpt-4o-mini",
|
||||
temperature=1,
|
||||
max_tokens=200,
|
||||
top_p=1
|
||||
)
|
||||
|
||||
return response.choices[0].message.content
|
||||
|
||||
|
||||
# Optional: create a sampling callback
|
||||
async def handle_sampling_message(
|
||||
context: RequestContext[ClientSession, None], params: types.CreateMessageRequestParams
|
||||
) -> types.CreateMessageResult:
|
||||
print(f"Sampling request: {params.messages}")
|
||||
|
||||
message = params.messages[0].content.text
|
||||
|
||||
# todo, call an actual llm and change below
|
||||
response = await call_llm(message, "You're a helpful assistant, keep to the topic, don't make things up too much but definitely create a compelling product description")
|
||||
|
||||
return types.CreateMessageResult(
|
||||
role="assistant",
|
||||
content=types.TextContent(
|
||||
type="text",
|
||||
text=response,
|
||||
),
|
||||
model="gpt-3.5-turbo",
|
||||
stopReason="endTurn",
|
||||
)
|
||||
|
||||
|
||||
async def run():
|
||||
async with stdio_client(server_params) as (read, write):
|
||||
async with ClientSession(read, write, sampling_callback=handle_sampling_message) as session:
|
||||
# Initialize the connection
|
||||
await session.initialize()
|
||||
|
||||
# List available prompts
|
||||
# prompts = await session.list_prompts()
|
||||
# print(f"Available prompts: {[p.name for p in prompts.prompts]}")
|
||||
|
||||
# # Get a prompt (greet_user prompt from fastmcp_quickstart)
|
||||
# if prompts.prompts:
|
||||
# prompt = await session.get_prompt("greet_user", arguments={"name": "Alice", "style": "friendly"})
|
||||
# print(f"Prompt result: {prompt.messages[0].content}")
|
||||
|
||||
# # List available resources
|
||||
# resources = await session.list_resources()
|
||||
# print(f"Available resources: {[r.uri for r in resources.resources]}")
|
||||
|
||||
# List available tools
|
||||
# tools = await session.list_tools()
|
||||
# print(f"Available tools: {[t.name for t in tools.tools]}")
|
||||
|
||||
# # Read a resource (greeting resource from fastmcp_quickstart)
|
||||
# resource_content = await session.read_resource(AnyUrl("greeting://World"))
|
||||
# content_block = resource_content.contents[0]
|
||||
# if isinstance(content_block, types.TextContent):
|
||||
# print(f"Resource content: {content_block.text}")
|
||||
|
||||
# Call a tool (create_product tool from fastmcp_quickstart)
|
||||
result = await session.call_tool("create_product", arguments={"product_name": "paprika", "keywords": "red, juicy, vegetable"})
|
||||
print("result:", result.content[0].text)
|
||||
|
||||
result = await session.call_tool("get_products", arguments={})
|
||||
print("result:", result.content[0].text)
|
||||
|
||||
# result_unstructured = result.content[0]
|
||||
# if isinstance(result_unstructured, types.TextContent):
|
||||
# print(f"Tool result: {result_unstructured.text}")
|
||||
# result_structured = result.structuredContent
|
||||
# print(f"Structured tool result: {result_structured}")
|
||||
|
||||
|
||||
def main():
|
||||
"""Entry point for the client script."""
|
||||
asyncio.run(run())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,75 @@
|
||||
from starlette.applications import Starlette
|
||||
from starlette.routing import Mount, Host
|
||||
|
||||
from mcp.server.fastmcp import Context, FastMCP
|
||||
|
||||
from mcp.server.session import ServerSession
|
||||
from mcp.types import SamplingMessage, TextContent
|
||||
|
||||
import json
|
||||
|
||||
|
||||
from uuid import uuid4
|
||||
from typing import List
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
mcp = FastMCP("My App")
|
||||
|
||||
class Product(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
description: str
|
||||
|
||||
def __init__(self, name: str, description: str):
|
||||
super().__init__(
|
||||
id=len(products) + 1,
|
||||
name=name,
|
||||
description=description
|
||||
)
|
||||
|
||||
products: List[Product] = []
|
||||
|
||||
@mcp.tool()
|
||||
async def create_product(product_name: str, keywords: str, ctx: Context[ServerSession, None]) -> str:
|
||||
"""Create a product and generate a product description using LLM sampling."""
|
||||
|
||||
product = Product(name=product_name, description="")
|
||||
|
||||
prompt = f"Create a product description about {product_name} described by as {keywords}"
|
||||
|
||||
result = await ctx.session.create_message(
|
||||
messages=[
|
||||
SamplingMessage(
|
||||
role="user",
|
||||
content=TextContent(type="text", text=prompt),
|
||||
)
|
||||
],
|
||||
max_tokens=100,
|
||||
)
|
||||
|
||||
|
||||
product.description = result.content.text
|
||||
|
||||
products.append(product)
|
||||
|
||||
# return the complete product
|
||||
return json.dumps({
|
||||
"id": product.id,
|
||||
"name": product.name,
|
||||
"description": product.description
|
||||
})
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Starting server...")
|
||||
mcp.run()
|
||||
|
||||
|
||||
# Mount the SSE server to the existing ASGI server
|
||||
app = Starlette(
|
||||
routes=[
|
||||
Mount('/', app=mcp.sse_app()),
|
||||
]
|
||||
)
|
||||
|
||||
# run app with: uvicorn 03-GettingStarted/12-sampling/solution/python/server:app --port 8000
|
||||
Reference in New Issue
Block a user