Source code for src.marcus_mcp.client
"""Simple Marcus MCP Client.
A wrapper around the MCP protocol for calling Marcus tools.
"""
import json
import sys
from typing import Any, Dict, Optional
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
[docs]
class SimpleMarcusClient:
"""Simple client for interacting with Marcus MCP server."""
[docs]
def __init__(self, server_module: str = "src.marcus_mcp.server"):
self.server_module = server_module
self.client_context: Any = None
self.read_stream: Any = None
self.write_stream: Any = None
self.session: Optional[ClientSession] = None
self._initialized = False
[docs]
async def initialize(self) -> None:
"""Initialize the MCP client connection."""
if self._initialized:
return
# Start the MCP server as a subprocess
server_params = StdioServerParameters(
command=sys.executable, # Use current Python interpreter
args=["-m", self.server_module],
env={},
)
# Create client context
self.client_context = stdio_client(server_params)
self.read_stream, self.write_stream = await self.client_context.__aenter__()
# Create and initialize session
self.session = ClientSession(self.read_stream, self.write_stream)
await self.session.initialize()
self._initialized = True
[docs]
async def call_tool(
self, tool_name: str, arguments: Dict[str, Any]
) -> Optional[Dict[str, Any]]:
"""Call a Marcus MCP tool."""
if not self._initialized:
await self.initialize()
try:
# Call the tool
if self.session is None:
return None
result = await self.session.call_tool(tool_name, arguments)
# Parse the result
if result and result.content:
# MCP tools return content as a list
if isinstance(result.content, list) and len(result.content) > 0:
content = result.content[0]
if hasattr(content, "text"):
# Try to parse as JSON
try:
parsed_json = json.loads(content.text)
if isinstance(parsed_json, dict):
return parsed_json
return {"result": parsed_json}
except json.JSONDecodeError:
# Return as plain text if not JSON
return {"result": content.text}
return {"result": str(content)}
return None
except Exception as e:
import sys
print(f"Error calling tool {tool_name}: {e}", file=sys.stderr)
return None
[docs]
async def close(self) -> None:
"""Close the client connection."""
if self.client_context:
await self.client_context.__aexit__(None, None, None)
self._initialized = False