Client Usage Tutorial
This tutorial will guide you through using the Mojentic MCP client to interact with MCP servers.
Prerequisites
- Python 3.11 or higher
- Mojentic MCP library installed (
pip install mojentic-mcp) - Access to an MCP server (either one you've created or a third-party server)
Basic Client Usage
The Mojentic MCP client provides a simple interface for interacting with MCP servers. Here's a basic example of using the client with an HTTP transport:
import logging
from mojentic_mcp.client import McpClient
from mojentic_mcp.transports import HttpTransport
# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Create an HTTP transport pointing to a local MCP server
# You can use either a full URL:
http_transport = HttpTransport(url="http://localhost:8000/jsonrpc")
# Or host and port (with default path "/jsonrpc"):
# http_transport = HttpTransport(host="localhost", port=8000)
# Or with a custom path:
# http_transport = HttpTransport(host="localhost", port=8000, path="/custom-path")
# Initialize the client with the transport
with McpClient(transports=[http_transport]) as client:
# List all available tools
tools = client.list_tools()
logger.info(f"Discovered {len(tools)} tools:")
for tool in tools:
logger.info(f" - {tool['name']}: {tool.get('description', 'No description')}")
# Call a tool using the dynamic accessor
current_time = client.tools.current_datetime()
logger.info(f"Current datetime: {current_time}")
Understanding the Client
Let's break down the key components of the client:
-
McpClient: The main client class that handles communication with MCP servers.
-
Transports: Classes that handle the actual communication with servers. Mojentic MCP provides two transport types:
HttpTransport: For communicating with HTTP MCP servers-
StdioTransport: For communicating with STDIO MCP servers -
Tool Discovery: The client automatically discovers available tools when initialized.
-
Tool Invocation: Tools can be called using either the dynamic accessor (
client.tools.<tool_name>()) or thecall_toolmethod.
Calling Tools
There are two ways to call tools using the client:
1. Using the Dynamic Accessor
The dynamic accessor provides a more Pythonic way to call tools:
# Call a tool with no parameters
current_time = client.tools.current_datetime()
# Call a tool with parameters
resolved_date = client.tools.resolve_date(date_string="next Friday")
2. Using the call_tool Method
The call_tool method provides a more explicit way to call tools:
# Call a tool with no parameters
current_time = client.call_tool("current_datetime")
# Call a tool with parameters
resolved_date = client.call_tool("resolve_date", date_string="next Friday")
Error Handling
It's important to handle errors when calling tools. Here's an example of error handling:
try:
# This might cause an error if the tool doesn't exist or if the parameters are invalid
result = client.tools.some_tool(param="value")
logger.info(f"Result: {result}")
except Exception as e:
logger.error(f"Error calling tool: {e}")
Working with STDIO Servers
When working with STDIO servers, you typically start the server as a subprocess:
import os
import sys
from mojentic_mcp.client import McpClient
from mojentic_mcp.transports import StdioTransport
# Get the path to the STDIO server script
script_dir = os.path.dirname(os.path.abspath(__file__))
stdio_server_path = os.path.join(script_dir, "stdio_server.py")
# Create a STDIO transport that runs the server script as a subprocess
stdio_transport = StdioTransport(command=[sys.executable, stdio_server_path])
# Initialize the client with the transport
with McpClient(transports=[stdio_transport]) as client:
# The client will automatically start the server subprocess
# and communicate with it over STDIO
# List all available tools
tools = client.list_tools()
print(f"Discovered {len(tools)} tools from STDIO server:")
for tool in tools:
print(f" - {tool['name']}: {tool.get('description', 'No description')}")
# Call tools using the dynamic accessor
current_time = client.tools.current_datetime()
print(f"Current datetime: {current_time}")
Getting Tool Schema
You can get the schema for a specific tool using the get_tool_schema method:
# Get schema for a specific tool
schema = client.get_tool_schema("current_datetime")
if schema:
logger.info(f"Tool 'current_datetime' schema: {schema}")
else:
logger.warning("Tool 'current_datetime' not found")
Advanced Usage: Tool Filtering
If you're working with multiple servers that might have tools with the same name, you can filter tools by transport:
# Get tools from a specific transport
http_tools = client.list_tools(transport=http_transport)
logger.info(f"Discovered {len(http_tools)} tools from HTTP server")
# Call a tool on a specific transport
result = client.call_tool("some_tool", transport=http_transport, param="value")
Best Practices
-
Use Context Managers: Always use the client with a context manager (
withstatement) to ensure proper cleanup. -
Handle Errors: Always handle errors when calling tools, as they might fail for various reasons.
-
Check Tool Availability: Before calling a tool, check if it's available using
list_toolsorget_tool_schema. -
Use Logging: Set up logging to help debug issues with tool calls.
-
Prefer Dynamic Accessor: Use the dynamic accessor (
client.tools.<tool_name>()) for a more Pythonic interface.
Next Steps
- Learn about Multi-Transport Clients for working with multiple servers
- Explore Creating Custom Tools to expose your own functionality
- Check out the API Reference for detailed documentation on the client and transport classes