forked from microsoft/mcp-for-beginners
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient_example_python.py
More file actions
150 lines (120 loc) · 5.61 KB
/
client_example_python.py
File metadata and controls
150 lines (120 loc) · 5.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
"""
Complete Python MCP Client Example
This client demonstrates how to:
1. Connect to an MCP server using stdio transport
2. List available tools and resources
3. Call calculator tools
4. Handle responses from the server
"""
import asyncio
import json
from mcp import ClientSession, StdioServerParameters, types
from mcp.client.stdio import stdio_client
class MCPCalculatorClient:
def __init__(self):
# Create server parameters for stdio connection
self.server_params = StdioServerParameters(
command="python", # Executable
args=["../01-first-server/solution/python/server.py"], # Server script
env=None, # Optional environment variables
)
async def run(self):
"""Main client execution function"""
print("🚀 Starting MCP Python Client...")
try:
async with stdio_client(self.server_params) as (read, write):
async with ClientSession(read, write) as session:
print("📡 Connecting to MCP server...")
# Initialize the connection
await session.initialize()
print("✅ Connected to MCP server successfully!")
# List available tools
await self.list_tools(session)
# Test calculator operations
await self.test_calculator_operations(session)
# List and test resources
await self.list_and_test_resources(session)
print("\n✨ Client operations completed successfully!")
except Exception as e:
print(f"❌ Error running MCP client: {e}")
raise
async def list_tools(self, session: ClientSession):
"""List all available tools on the server"""
print("\n📋 Listing available tools:")
try:
tools = await session.list_tools()
for tool in tools.tools:
print(f" - {tool.name}: {tool.description}")
except Exception as e:
print(f" Error listing tools: {e}")
async def test_calculator_operations(self, session: ClientSession):
"""Test various calculator operations"""
print("\n🧮 Testing Calculator Operations:")
operations = [
("add", {"a": 5, "b": 3}, "Add 5 + 3"),
("subtract", {"a": 10, "b": 4}, "Subtract 10 - 4"),
("multiply", {"a": 6, "b": 7}, "Multiply 6 × 7"),
("divide", {"a": 20, "b": 4}, "Divide 20 ÷ 4"),
("help", {}, "Help Information"),
]
for tool_name, arguments, description in operations:
try:
result = await session.call_tool(tool_name, arguments=arguments)
result_text = self.extract_text_result(result)
if tool_name == "help":
print(f"\n📖 {description}:")
print(result_text)
else:
print(f"{description} = {result_text}")
except Exception as e:
print(f" Error calling {tool_name}: {e}")
async def list_and_test_resources(self, session: ClientSession):
"""List and test reading resources"""
print("\n📄 Listing available resources:")
try:
resources = await session.list_resources()
for resource in resources.resources:
print(f" - {resource.name}: {resource.description}")
print(f" URI: {resource.uri}")
# Test reading a resource if available
if resources.resources:
first_resource = resources.resources[0]
print(f"\n📖 Reading resource: {first_resource.name}")
try:
content = await session.read_resource(first_resource.uri)
print(f"Resource content: {content}")
except Exception as e:
print(f" Error reading resource: {e}")
else:
print(" No resources available")
except Exception as e:
print(f" Error listing resources: {e}")
def extract_text_result(self, result) -> str:
"""
Extract text content from a tool result object.
This method attempts to extract the text content from the `content` attribute
of the result object. If no text content is found, it falls back to converting
the result to a string. If an error occurs during extraction, it returns "No result".
Args:
result: The result object returned by a tool, which may contain a `content` attribute
with text or other types of data.
Returns:
A string representing the extracted text content, or a fallback string if no text is found.
"""
try:
if hasattr(result, 'content') and result.content:
for content_item in result.content:
if hasattr(content_item, 'text') and content_item.text:
return content_item.text
elif hasattr(content_item, 'type') and content_item.type == "text":
return getattr(content_item, 'text', str(content_item))
# Fallback: try to convert to string
return str(result)
except Exception:
return "No result"
async def main():
"""Entry point for the client"""
client = MCPCalculatorClient()
await client.run()
if __name__ == "__main__":
asyncio.run(main())