forked from microsoft/mcp-for-beginners
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient.py
More file actions
99 lines (90 loc) · 3.61 KB
/
client.py
File metadata and controls
99 lines (90 loc) · 3.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
# client.py
from mcp.client.streamable_http import streamablehttp_client
from mcp import ClientSession
import asyncio
import mcp.types as types
from mcp.shared.session import RequestResponder
import requests
import logging
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger('mcp_client')
class LoggingCollector:
def __init__(self):
self.log_messages: list[types.LoggingMessageNotificationParams] = []
async def __call__(self, params: types.LoggingMessageNotificationParams) -> None:
self.log_messages.append(params)
logger.info("MCP Log: %s - %s", params.level, params.data)
logging_collector = LoggingCollector()
port = 8000
async def message_handler(
message: RequestResponder[types.ServerRequest, types.ClientResult]
| types.ServerNotification
| Exception,
) -> None:
logger.info("Received message: %s", message)
if isinstance(message, Exception):
logger.error("Exception received!")
raise message
elif isinstance(message, types.ServerNotification):
logger.info("NOTIFICATION: %s", message)
elif isinstance(message, RequestResponder):
logger.info("REQUEST_RESPONDER: %s", message)
else:
logger.info("SERVER_MESSAGE: %s", message)
async def main():
logger.info("Starting client...")
async with streamablehttp_client(f"http://localhost:{port}/mcp") as (
read_stream,
write_stream,
session_callback,
):
async with ClientSession(
read_stream,
write_stream,
logging_callback=logging_collector,
message_handler=message_handler,
) as session:
id_before = session_callback()
logger.info("Session ID before init: %s", id_before)
await session.initialize()
id_after = session_callback()
logger.info("Session ID after init: %s", id_after)
logger.info("Session initialized, ready to call tools.")
tool_result = await session.call_tool("process_files", {"message": "hello from client"})
logger.info("Tool result: %s", tool_result)
if logging_collector.log_messages:
logger.info("Collected log messages:")
for log in logging_collector.log_messages:
logger.info("Log: %s", log)
def stream_progress(message="hello", url="http://localhost:8000/stream"):
params = {"message": message}
logger.info("Connecting to %s with message: %s", url, message)
try:
with requests.get(url, params=params, stream=True, timeout=10) as r:
r.raise_for_status()
logger.info("--- Streaming Progress ---")
for line in r.iter_lines():
if line:
# Still print the streamed content to stdout for visibility
decoded_line = line.decode().strip()
print(decoded_line)
logger.debug("Stream content: %s", decoded_line)
logger.info("--- Stream Ended ---")
except requests.RequestException as e:
logger.error("Error during streaming: %s", e)
if __name__ == "__main__":
import sys
if len(sys.argv) > 1 and sys.argv[1] == "mcp":
# MCP client mode
logger.info("Running MCP client...")
asyncio.run(main())
else:
# Classic HTTP streaming client mode
logger.info("Running classic HTTP streaming client...")
stream_progress()
# Don't run both by default, let the user choose the mode