Calling Methods
Complete the StdioClient class with all remaining methods.
In this step, we'll add all the remaining methods to complete our StdioClient class.
We'll add them sequentially - just keep appending to the class.
Your stdio_client.py currently has the StdioClient class
ending with supports_resource_subscriptions(). We'll add all new methods
right after that, still inside the class.
Step 1: Add the Generic Call Method
Instead of writing separate code for each MCP method, we create a generic
call method that handles request/response logic.
Edit: stdio_client.py
Add this method inside the StdioClient class, after supports_resource_subscriptions:
def call(self, method: str, params: Optional[dict] = None) -> Any:
"""
Call an MCP method and return the result.
Args:
method: The MCP method name (e.g., "tools/list")
params: Optional parameters for the method
Returns:
The result from the server response
Raises:
RuntimeError: If not connected or initialized
"""
if not self.initialized:
raise RuntimeError("Client not initialized. Call initialize() first.")
# Send request and get response
response = self.send_request(method, params)
# Check for error response
if "error" in response:
error = response["error"]
raise RuntimeError(f"MCP Error {error.get('code')}: {error.get('message')}")
# Return the result
return response.get("result")
Step 2: Add Method Wrappers
With a generic call method, we can create convenient wrappers
for specific MCP methods.
Edit: stdio_client.py
Continue appending to the StdioClient class:
def call_tool(self, name: str, arguments: Optional[dict] = None) -> Any:
"""
Call a tool on the server.
Args:
name: The tool name
arguments: Arguments to pass to the tool
Returns:
The tool's result content
"""
result = self.call("tools/call", {
"name": name,
"arguments": arguments or {}
})
return result.get("content", [])
def read_resource(self, uri: str) -> Any:
"""
Read a resource from the server.
Args:
uri: The resource URI
Returns:
The resource contents
"""
result = self.call("resources/read", {"uri": uri})
return result.get("contents", [])
def get_prompt(self, name: str, arguments: Optional[dict] = None) -> Any:
"""
Get a prompt from the server.
Args:
name: The prompt name
arguments: Arguments for the prompt
Returns:
The prompt messages
"""
result = self.call("prompts/get", {
"name": name,
"arguments": arguments or {}
})
return result.get("messages", [])
Step 3: Add List Methods
Finally, add methods to list available tools, resources, and prompts. These return simple dictionaries for now - we'll add proper dataclasses in the next step.
Edit: stdio_client.py
Continue appending to the StdioClient class:
def list_tools(self) -> List[dict]:
"""
List all tools available on the server.
Returns:
List of tool dictionaries
"""
if not self.has_tools():
return []
result = self.call("tools/list")
return result.get("tools", [])
def list_resources(self) -> List[dict]:
"""
List all resources available on the server.
Returns:
List of resource dictionaries
"""
if not self.has_resources():
return []
result = self.call("resources/list")
return result.get("resources", [])
def list_prompts(self) -> List[dict]:
"""
List all prompts available on the server.
Returns:
List of prompt dictionaries
"""
if not self.has_prompts():
return []
result = self.call("prompts/list")
return result.get("prompts", [])
Class Complete!
Your StdioClient class is now complete with all the methods needed
to interact with an MCP server.
Your stdio_client.py should now look like this:
imports...
class StdioClient:
__init__, connect, disconnect
send_request, send_notification
__enter__, __exit__
initialize
has_tools, has_resources, has_prompts
supports_resource_subscriptions
call # Added in Step 1
call_tool, read_resource, get_prompt # Added in Step 2
list_tools, list_resources, list_prompts # Added in Step 3
# End of file
Error Handling
When using these methods, handle errors appropriately:
try:
result = client.call_tool("add_numbers", {"a": 5, "b": 3})
print(f"Result: {result}")
except RuntimeError as e:
if "MCP Error -32601" in str(e):
print("Method not found - server doesn't support this")
elif "MCP Error -32602" in str(e):
print("Invalid parameters")
else:
print(f"Error: {e}")
-32700: Parse error
-32600: Invalid request
-32601: Method not found
-32602: Invalid params
-32603: Internal error