99 lines
3.6 KiB
Python
99 lines
3.6 KiB
Python
# 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 |