# How to Connect MCP Servers as Tools in aisuite: A Complete Integration Guide

> Learn how to connect MCP servers as tools in aisuite using MCPClient and tool_wrapper. Integrate your MCP servers seamlessly into LLM workflows.

- Repository: [Andrew Ng/aisuite](https://github.com/andrewyng/aisuite)
- Tags: how-to-guide
- Published: 2026-07-28

---

**aisuite converts any MCP (Model Context Protocol) server into callable Python tools that LLMs can invoke using the `MCPClient` class from [`aisuite/mcp/client.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/client.py) and the wrapper system in [`aisuite/mcp/tool_wrapper.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/tool_wrapper.py).**

The `andrewyng/aisuite` library provides native support for the Model Context Protocol, allowing you to connect MCP servers as tools in aisuite workflows. This integration bridges external tool ecosystems—whether local command-line utilities or remote HTTP APIs—into aisuite's unified interface for LLM interactions.

## MCP Integration Architecture

The MCP implementation in aisuite relies on four specialized components that handle configuration, connection, and tool wrapping:

| Component | Source File | Key Function |
|-----------|-------------|--------------|
| **Configuration validation** | [`aisuite/mcp/config.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/config.py) | `validate_mcp_config()` parses transport settings and fills defaults |
| **Connection management** | [`aisuite/mcp/client.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/client.py) | `MCPClient` class handles stdio processes or HTTP clients |
| **Tool adaptation** | [`aisuite/mcp/tool_wrapper.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/tool_wrapper.py) | `MCPToolWrapper` converts MCP schemas into Python callables |
| **Schema conversion** | [`aisuite/mcp/schema_converter.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/schema_converter.py) | Translates JSON-Schema into Python type annotations |

When you connect MCP servers as tools in aisuite, the `MCPClient` discovers available remote tools via the MCP protocol, then wraps each tool using `create_mcp_tool_wrapper()` to produce Python functions compatible with aisuite's `Tools` class.

## Transport Configuration: HTTP vs stdio

aisuite supports two transport mechanisms for MCP servers, validated in [`aisuite/mcp/config.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/config.py) (lines 81-104):

**HTTP Transport** requires:
- `server_url`: The endpoint hosting the MCP server
- Optional: `headers`, `timeout`

**stdio Transport** requires:
- `command`: The executable to spawn
- Optional: `args`, `env`, `cwd`

The `validate_mcp_config()` function ensures exactly one transport type is specified and all required fields are present.

```python

# HTTP transport configuration

http_config = {
    "type": "mcp",
    "name": "weather-api",
    "server_url": "http://localhost:8000/mcp/v1",
    "timeout": 30.0,
}

# stdio transport configuration  

stdio_config = {
    "type": "mcp", 
    "name": "filesystem",
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-filesystem", "/docs"],
}

```

## Creating MCPClient Instances

You can instantiate `MCPClient` either from a configuration dictionary or directly with transport parameters.

### Method 1: From Configuration Dictionary

Use `MCPClient.from_config()` (defined in [`aisuite/mcp/client.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/client.py), lines 71-77) when working with dict-based configs:

```python
from aisuite.mcp import MCPClient

config = {
    "type": "mcp",
    "name": "api-server",
    "server_url": "http://localhost:8000/mcp/v1",
    "allowed_tools": ["get_weather", "forecast"],  # Optional filtering

}

mcp = MCPClient.from_config(config)

```

### Method 2: Direct Instantiation

Create the client directly for stdio-based servers or when you need fine-grained control:

```python
from aisuite.mcp import MCPClient

# stdio-based MCP server

mcp = MCPClient(
    command="python",
    args=["mcp_server.py"],
    name="local-tools",
)

# HTTP-based MCP server

mcp = MCPClient(
    server_url="https://api.example.com/mcp/v1",
    name="remote-api",
)

```

The constructor (lines 98-104 in [`client.py`](https://github.com/andrewyng/aisuite/blob/main/client.py)) automatically detects the transport type and calls `_connect()` to initialize the connection.

## Discovering and Wrapping MCP Tools

Once connected, retrieve callable tool wrappers using `get_callable_tools()`:

```python

# Discover available tools

tools_list = mcp.list_tools()  # Returns raw MCP tool definitions

# Get Python-callable wrappers

callable_tools = mcp.get_callable_tools()  # Returns list of MCPToolWrapper instances

```

The `get_callable_tools()` method (lines 92-100 in [`client.py`](https://github.com/andrewyng/aisuite/blob/main/client.py)) internally calls `create_mcp_tool_wrapper()` from [`aisuite/mcp/tool_wrapper.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/tool_wrapper.py). This wrapper:

1. Extracts parameter descriptions using `extract_parameter_descriptions()`
2. Converts JSON-Schema to Python annotations via `mcp_schema_to_annotations()`
3. Builds a proper `inspect.Signature` (lines 59-70 in [`tool_wrapper.py`](https://github.com/andrewyng/aisuite/blob/main/tool_wrapper.py))
4. Creates a callable that forwards invocations to `MCPClient.call_tool()`

## Using MCP Tools in Chat Completions

Pass the wrapped tools directly to `client.chat.completions.create()`:

```python
import aisuite as ai
from aisuite.mcp import MCPClient

# Setup MCP client

mcp = MCPClient(server_url="http://localhost:8000/mcp/v1", name="weather-api")
tools = mcp.get_callable_tools()

# Use in chat completion

client = ai.Client()
response = client.chat.completions.create(
    model="openai:gpt-4o",
    messages=[{"role": "user", "content": "Give me tomorrow's forecast."}],
    tools=tools,
    max_turns=2,
)

print(response.choices[0].message.content)

```

### Combining MCP Tools with Native Functions

Mix MCP tools with regular Python functions by unpacking the callable list:

```python
import aisuite as ai
from aisuite.mcp import MCPClient
from datetime import datetime

def current_timestamp() -> str:
    """Return the current ISO-8601 timestamp."""
    return datetime.utcnow().isoformat()

mcp = MCPClient(server_url="https://api.example.com/mcp/v1", name="external-api")

client = ai.Client()
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "What time is it and what's the weather?"}],
    tools=[current_timestamp, *mcp.get_callable_tools()],
    max_turns=3,
)

```

### Context Manager for Automatic Cleanup

Use the context manager protocol (implemented in [`client.py`](https://github.com/andrewyng/aisuite/blob/main/client.py) via `__enter__` and `__exit__`) to ensure proper resource cleanup:

```python
from aisuite.mcp import MCPClient
import aisuite as ai

with MCPClient(server_url="http://localhost:8000/mcp/v1", name="demo-api") as mcp:
    client = ai.Client()
    resp = client.chat.completions.create(
        model="openai:gpt-4o",
        messages=[{"role": "user", "content": "List available tools"}],
        tools=mcp.get_callable_tools(),
        max_turns=2,
    )
    print(resp.choices[0].message.content)

# mcp.close() called automatically

```

## Advanced Configuration Options

The MCP integration supports several optional parameters in [`aisuite/mcp/config.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/config.py):

- **`allowed_tools`**: whitelist specific tools by name when calling `get_callable_tools()`
- **`use_tool_prefix`**: namespace tools with the MCP server name to avoid collisions
- **`lazy_connect`**: defer connection until first tool invocation
- **`timeout_seconds`**: set maximum wait time for tool responses
- **`response_bytes_cap`**: limit response size to prevent memory issues

These options are processed during configuration validation and honored by the `MCPClient` initialization logic.

## Summary

- **aisuite/mcp/client.py** contains the `MCPClient` class that manages connections to both HTTP and stdio MCP servers
- **aisuite/mcp/tool_wrapper.py** provides `MCPToolWrapper` to convert MCP tool schemas into Python callables with proper type hints and signatures
- Use `MCPClient.from_config()` for dictionary-based configuration or direct instantiation for programmatic control
- Call `get_callable_tools()` to retrieve wrapped tools ready for `client.chat.completions.create(tools=...)`
- Transport types are validated in **aisuite/mcp/config.py** via `validate_mcp_config()`
- Combine MCP tools with native Python functions by unpacking the callable list with `*mcp.get_callable_tools()`

## Frequently Asked Questions

### What is an MCP server and why use it with aisuite?

An MCP (Model Context Protocol) server exposes external capabilities—such as file system access, API calls, or database queries—through a standardized protocol. When you connect MCP servers as tools in aisuite, you extend LLM capabilities with these external resources without writing custom integration code for each service.

### How do I choose between HTTP and stdio transport?

Choose **stdio transport** (`command`, `args`) when running local MCP server implementations as subprocesses, such as Node.js or Python scripts. Choose **HTTP transport** (`server_url`) when connecting to remote or already-hosted MCP endpoints. The `validate_mcp_config()` function in [`aisuite/mcp/config.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/config.py) enforces that exactly one transport type is specified per configuration.

### Can I filter which MCP tools are exposed to the LLM?

Yes. Pass the `allowed_tools` parameter in your configuration dictionary containing a list of tool names to whitelist. When `get_callable_tools()` executes, it only returns wrappers for tools matching the allowed list, preventing the LLM from accessing restricted functionality.

### How does aisuite handle MCP tool schema conversion?

The `MCPToolWrapper` class in [`aisuite/mcp/tool_wrapper.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/tool_wrapper.py) processes the MCP tool's JSON-Schema definition using utilities from [`aisuite/mcp/schema_converter.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/schema_converter.py). It converts schema types to Python type annotations, extracts parameter descriptions for docstrings, and constructs a proper `inspect.Signature` object so aisuite's tool introspection system can present the tool correctly to the LLM.