This guide explains how to integrate external tools and services using MCP (Model Context Protocol) servers with the HelpingAI Python SDK.
The Model Context Protocol (MCP) is a standardized communication protocol that enables the HelpingAI SDK to interact seamlessly with external tool servers. By integrating MCP servers, you can significantly extend the capabilities of your AI models, allowing them to access and utilize a diverse range of external tools, services, and data sources beyond their inherent knowledge.
MCP facilitates a clear separation of concerns: your AI model focuses on reasoning and decision-making, while specialized MCP servers handle the execution of specific tasks (e.g., fetching real-time data, running code, interacting with external APIs). This modular approach enhances the flexibility, scalability, and maintainability of AI-powered applications.
To leverage the full capabilities of MCP integration, you need to install the mcp Python package. This package provides the necessary client-side components to communicate with MCP servers.
The easiest way to install mcp along with the HelpingAI SDK is by specifying the mcp extra during installation:
pip install "HelpingAI[mcp]"This command ensures that all required dependencies for MCP functionality are installed automatically.
If you prefer to install mcp separately, you can do so using pip:
pip install -U mcpAfter installation, you can verify that the mcp package is correctly installed by running a simple Python command:
python -c "import mcp; print(mcp.__version__)"If the installation was successful, this command should print the installed version of the mcp package.
ImportError: Could not import mcp: This error indicates that the mcp package is not installed or not accessible in your Python environment. Ensure you have run the pip install command correctly.For more advanced troubleshooting or specific environment setups, refer to the official mcp package documentation.
MCP servers are configured within the tools parameter of your client.chat.completions.create() call. The configuration is a Python list containing dictionaries, where one of these dictionaries must have the key "mcpServers". The value associated with "mcpServers" is itself a dictionary, defining one or more MCP server instances.
Each entry within the "mcpServers" dictionary represents a single MCP server, identified by a user-defined server_name (e.g., "time_server", "remote_tool"). The configuration for each server specifies how the SDK should connect to it.
Stdio (Standard Input/Output) servers are typically local command-line applications that communicate with the SDK via their standard I/O streams. This is a common setup for running local tools or services.
Configuration Parameters:
command (str, required): The executable command to run the MCP server. This command must be accessible in your system's PATH or specified with its absolute path.args (List[str], optional): A list of command-line arguments to pass to the command.env (Dict[str, str], optional): A dictionary of environment variables to set for the server process.Example:
tools_config_stdio = [
{
"mcpServers": {
"time_server": {
"command": "uvx",
"args": ["mcp-server-time", "--local-timezone=America/New_York"],
"env": {"DEBUG_MODE": "true"}
},
"file_system_server": {
"command": "npx", # Example using npx for Node.js based MCP server
"args": ["mcp-server-fs", "--root-dir=/tmp/my_data"]
}
}
}
]
# Pass this configuration to the chat completions create method {#pass-this-configuration-to-the-chat-completions-create-method}
# response = client.chat.completions.create( {#response-clientchatcompletionscreate}
# model="Dhanishtha-2.0-preview", {#modeldhanishtha-20-preview}
# messages=[{"role": "user", "content": "What time is it in New York?"}], {#messagesrole-user-content-what-time-is-it-in-new-york}
# tools=tools_config_stdio {#toolstools_config_stdio}
# ) {#}HTTP-based MCP servers expose their functionalities over a network, typically using Server-Sent Events (SSE) or a custom streamable HTTP protocol. This is suitable for remote services or microservices.
Configuration Parameters:
url (str, required): The base URL of the MCP server endpoint.type (Literal["sse", "streamable-http"], optional): The communication protocol type."sse" (default): Uses Server-Sent Events for communication."streamable-http": Uses a custom streamable HTTP protocol, often for more efficient bidirectional communication.headers (Dict[str, str], optional): A dictionary of HTTP headers to include in requests to the server (e.g., for authentication tokens).sse_read_timeout (int, optional): For SSE connections, the timeout in seconds for reading data from the stream. Defaults to 300 seconds.Example:
tools_config_http = [
{
"mcpServers": {
"remote_tool_sse": {
"url": "https://api.example.com/mcp/tools/sse",
"type": "sse",
"headers": {"Authorization": "Bearer your_sse_token"},
"sse_read_timeout": 600
},
"remote_tool_streamable": {
"url": "https://api.example.com/mcp/tools/stream",
"type": "streamable-http",
"headers": {"X-API-Key": "your_stream_api_key"}
}
}
}
]
# Pass this configuration to the chat completions create method {#pass-this-configuration-to-the-chat-completions-create-method}
# response = client.chat.completions.create( {#response-clientchatcompletionscreate}
# model="Dhanishtha-2.0-preview", {#modeldhanishtha-20-preview}
# messages=[{"role": "user", "content": "Fetch data from the remote tool."}], {#messagesrole-user-content-fetch-data-from-the-remote-tool}
# tools=tools_config_http {#toolstools_config_http}
# ) {#}Once MCP servers are configured, the tools they expose become available to your AI model just like any other tool defined using the @tools decorator or Fn class. The SDK automatically handles the underlying communication with the MCP server, abstracting away the complexities of the protocol.
Tools provided by MCP servers follow a specific naming convention within the HelpingAI SDK:
{server_name}-{tool_name}
{server_name}: This is the name you assigned to the MCP server in your configuration (e.g., "time_server", "remote_tool_sse").{tool_name}: This is the actual name of the tool as advertised by the MCP server itself (e.g., "now", "fetch_data").For example, if you configure a time_server that exposes a tool named now, the SDK will make it available as time_server-now.
This example demonstrates how to use an MCP tool (assuming a time_server is configured to provide a now tool) within a chat completion and handle its execution.
from HelpingAI import HAI
from HelpingAI.tools import get_tools # To get tools defined with @tools or Fn
import json
client = HAI()
# 1. Define your MCP server configuration {#1-define-your-mcp-server-configuration}
mcp_tools_config = [
{
"mcpServers": {
"time_server": {
"command": "uvx", # Assuming uvx and mcp-server-time are installed
"args": ["mcp-server-time"]
}
}
}
]
# 2. Combine with any other tools you might have {#2-combine-with-any-other-tools-you-might-have}
# For this example, we'll just use the MCP tools {#for-this-example-well-just-use-the-mcp-tools}
all_tools_for_model = mcp_tools_config # Or get_tools() + mcp_tools_config
# 3. Make a chat completion request, including the MCP tools {#3-make-a-chat-completion-request-including-the-mcp-tools}
messages = [
{"role": "user", "content": "What is the current time?"}
]
print("\n--- Initial Chat Completion Request ---")
response = client.chat.completions.create(
model="Dhanishtha-2.0-preview",
messages=messages,
tools=all_tools_for_model,
tool_choice="auto"
)
message = response.choices[0].message
# 4. Handle the model's response (check for tool calls) {#4-handle-the-models-response-check-for-tool-calls}
if message.tool_calls:
print("\n--- Model wants to call tools ---")
tool_messages_for_follow_up = []
for tool_call in message.tool_calls:
function_name = tool_call.function.name
function_args_str = tool_call.function.arguments
print(f"Model called tool: {function_name} with arguments: {function_args_str}")
try:
# Parse arguments (MCP tools typically expect JSON arguments)
function_args = json.loads(function_args_str)
# Execute the MCP tool using client.call()
# The client automatically routes the call to the correct MCP server
tool_result = client.call(function_name, function_args)
print(f"Tool execution result: {tool_result}")
# Create a tool response message to send back to the model
tool_messages_for_follow_up.append({
"role": "tool",
"tool_call_id": tool_call.id,
"name": function_name,
"content": json.dumps(tool_result) # Tool output should be a string
})
except json.JSONDecodeError:
error_content = f"Error: Invalid JSON arguments for tool {function_name}: {function_args_str}"
print(error_content)
tool_messages_for_follow_up.append({
"role": "tool",
"tool_call_id": tool_call.id,
"name": function_name,
"content": error_content
})
except Exception as e:
error_content = f"Error executing MCP tool {function_name}: {e}"
print(error_content)
tool_messages_for_follow_up.append({
"role": "tool",
"tool_call_id": tool_call.id,
"name": function_name,
"content": error_content
})
# 5. Continue the conversation with the tool results
print("\n--- Continuing Chat with Tool Results ---")
follow_up_response = client.chat.completions.create(
model="Dhanishtha-2.0-preview",
messages=messages + [message] + tool_messages_for_follow_up,
tools=all_tools_for_model, # Keep tools available for potential further calls
tool_choice="auto"
)
print("\n--- Final Model Response ---")
print(follow_up_response.choices[0].message.content)
else:
print("\n--- Model did not call any tools ---")
print(f"Model's response: {message.content}")You can also call MCP tools directly using client.call():
client.configure_tools(tools) # Configure the tools first
result = client.call("time_server-now", {})
print(result)Some MCP servers provide access to data sources called resources. The SDK automatically creates tools for listing and reading these resources:
{server_name}-list_resources: Lists available resources.{server_name}-read_resource: Reads a resource by its URI.# List resources from the 'my_server' {#list-resources-from-the-my_server}
resources = client.call("my_server-list_resources", {})
# Read a specific resource {#read-a-specific-resource}
content = client.call("my_server-read_resource", {"uri": "resource_uri"})The SDK is designed to handle MCP-related errors gracefully. If the mcp package is not installed, an ImportError will be raised. Connection errors and other issues are wrapped in the standard HAIError exceptions.