# How to Integrate MCP (Model Context Protocol) Servers with aisuite

> Learn to integrate MCP servers with aisuite. Discover how aisuite exposes external tools to LLMs using MCP for seamless server lifecycle management and configuration.

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

---

**aisuite exposes external tools to LLMs through MCP servers by passing a configuration dictionary with `"type": "mcp"` to the `tools` parameter in `client.chat.completions.create()`, which `validate_mcp_config()` processes before `MCPClient` handles the server lifecycle.**

The aisuite library provides a unified interface for interacting with large language models across multiple providers. When you integrate MCP servers with aisuite, you can extend LLM capabilities with external tools without managing complex server boilerplate. The configuration follows the `MCPConfig` TypedDict defined in [`aisuite/mcp/config.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/config.py), enabling both stdio and HTTP transport methods.

## Understanding the MCP Configuration Schema

The foundation of MCP integration lies in the configuration dictionary structure. In [`aisuite/mcp/config.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/config.py), the `MCPConfig` TypedDict defines the expected schema that aisuite uses to initialize tool connections. When a request is sent to `client.chat.completions.create`, the library examines each entry in the `tools` list. If an entry has `"type": "mcp"`, aisuite passes it to `validate_mcp_config()` for processing.

### Transport Type Detection

The configuration supports two mutually exclusive transport methods. At lines 95-100 of [`aisuite/mcp/config.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/config.py), `validate_mcp_config()` ensures exactly one transport is specified:

- **stdio transport**: Use the `"command"` field to specify an executable that runs the MCP server locally
- **HTTP transport**: Use the `"server_url"` field to connect to a remote MCP server endpoint

## Validating and Processing MCP Configurations

The `validate_mcp_config()` function in [`aisuite/mcp/config.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/config.py) performs five critical validation steps:

1. **Type and name verification**: Ensures the config type is `"mcp"` and that a non-empty `"name"` is supplied
2. **Transport detection**: Identifies whether the configuration uses stdio (`"command"` field) or HTTP (`"server_url"` field), validating that exactly one is present
3. **Field validation**: Verifies transport-specific requirements, such as ensuring `command` is a string or `server_url` starts with `http://` or `https://`
4. **Default application**: Applies default values for optional parameters including `timeout_seconds`, `response_bytes_cap`, `use_tool_prefix`, and `lazy_connect` (defined at lines 42-46)
5. **Normalization**: Returns a normalized dictionary at line 86 that the MCP client can consume

## MCPClient Lifecycle and Tool Discovery

After validation, the normalized configuration is instantiated via `MCPClient.from_config()` in [`aisuite/mcp/client.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/client.py). This client automatically:

- Starts the MCP server process for stdio transport or prepares the HTTP endpoint
- Discovers available tools through the `list_tools()` method
- Wraps each remote tool as a callable that the LLM can invoke via the standard tool-calling protocol

The following code from [`aisuite/client.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/client.py) illustrates how configs are transformed into callable tools:

```python
if isinstance(tool_entry, dict) and tool_entry.get("type") == "mcp":
    cfg = validate_mcp_config(tool_entry)          # aisuite/mcp/config.py

    mcp = MCPClient.from_config(cfg)               # aisuite/mcp/client.py

    tools.extend(mcp.get_callable_tools())

```

For guidance on choosing between the config-dict shortcut versus explicit `MCPClient` instantiation, see the comparison in [`examples/mcp_config_dict_example.py`](https://github.com/andrewyng/aisuite/blob/main/examples/mcp_config_dict_example.py) lines 56-68.

## Configuration Fields Reference

### Required Fields

- **`type`**: Must be `"mcp"` (string)
- **`name`**: Logical identifier for the server (string, required)

### stdio Transport Fields

- **`command`**: Executable that runs the MCP server (e.g., `"npx"`)
- **`args`**: Argument list for the command (e.g., `["@modelcontextprotocol/server-filesystem", "/path"]`)
- **`env`**: Environment variables for the process (optional)
- **`cwd`**: Working directory for the process (optional)

### HTTP Transport Fields

- **`server_url`**: Base URL of the HTTP MCP server (e.g., `"https://mcp.example.com/v1"`)
- **`headers`**: Additional HTTP headers (optional)

### Security and Performance Options

- **`allowed_tools`**: Whitelist of tool names the LLM may call for security restrictions
- **`use_tool_prefix`**: Prefix tool names with `<name>__` to avoid collisions when using multiple servers
- **`timeout_seconds`**: Maximum wait time for tool responses (default: 30 seconds)
- **`response_bytes_cap`**: Upper bound on response size (default: 10 MiB)
- **`lazy_connect`**: Defers connection until the first tool call when set to `True`

## Practical Implementation Examples

### Basic stdio MCP Server Configuration

The following example from [`examples/mcp_config_dict_example.py`](https://github.com/andrewyng/aisuite/blob/main/examples/mcp_config_dict_example.py) (lines 23-38) demonstrates connecting to a filesystem MCP server using npx:

```python
import aisuite as ai
import os

client = ai.Client()

response = client.chat.completions.create(
    model="openai:gpt-4o",
    messages=[{"role": "user", "content": "List all Python files here"}],
    tools=[
        {
            "type": "mcp",
            "name": "filesystem",
            "command": "npx",
            "args": [
                "-y",
                "@modelcontextprotocol/server-filesystem",
                os.getcwd(),
            ],
        }
    ],
    max_turns=2,
)

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

```

### Restricting Available Tools for Security

Limit which tools the LLM can access using the `allowed_tools` field:

```python
{
    "type": "mcp",
    "name": "filesystem",
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-filesystem", os.getcwd()],
    "allowed_tools": ["read_file"],          # only allow file reads

}

```

### Running Multiple MCP Servers with Prefixing

Prevent tool name collisions when using multiple servers:

```python
{
    "type": "mcp",
    "name": "temp_dir",
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-filesystem", temp_dir],
    "use_tool_prefix": True,                # tools become temp_dir__list_directory

}

```

### Combining MCP Servers with Native Python Functions

Mix MCP configurations with regular Python functions in the same tools list:

```python
def get_current_time():
    return "Current time: 2024-01-01 12:00:00"

response = client.chat.completions.create(
    model="openai:gpt-4o",
    messages=[{"role": "user", "content": "What time is it?"}],
    tools=[
        get_current_time,                    # native Python function

        {                                    # MCP config dict

            "type": "mcp",
            "name": "filesystem",
            "command": "npx",
            "args": ["-y", "@modelcontextprotocol/server-filesystem", os.getcwd()],
        },
    ],
    max_turns=3,
)

```

## Summary

- **aisuite/mcp/config.py** defines the `MCPConfig` schema and `validate_mcp_config()` function that processes server configurations
- Transport methods are mutually exclusive: use either `command` for stdio or `server_url` for HTTP connections
- The `MCPClient.from_config()` method in **aisuite/mcp/client.py** handles server lifecycle management and tool discovery
- Configuration options include security controls (`allowed_tools`), performance limits (`timeout_seconds`, `response_bytes_cap`), and multi-server support (`use_tool_prefix`)
- Refer to **examples/mcp_config_dict_example.py** for complete working implementations and **tests/mcp/test_e2e.py** for integration test patterns

## Frequently Asked Questions

### What is the difference between stdio and HTTP transport in MCP configuration?

The stdio transport launches a local subprocess using the `command` and `args` fields, suitable for running local MCP servers like the filesystem example. HTTP transport connects to remote servers via the `server_url` field. According to the validation logic in [`aisuite/mcp/config.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/config.py) lines 95-100, you must specify exactly one transport method, not both.

### How does aisuite validate MCP server configurations?

aisuite validates configurations through the `validate_mcp_config()` function in [`aisuite/mcp/config.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/config.py). This function checks for required fields (`type`, `name`), validates transport-specific parameters, applies default values for optional settings like `timeout_seconds` (default 30s), and ensures URL formats are correct for HTTP transport.

### Can I use multiple MCP servers simultaneously in a single request?

Yes, you can include multiple MCP configuration dictionaries in the `tools` list. To avoid tool name collisions between servers, enable the `use_tool_prefix` option, which prefixes each tool name with the server name (e.g., `servername__toolname`). You can also mix MCP servers with native Python functions in the same tools array.

### What security options are available when integrating MCP servers?

aisuite provides the `allowed_tools` field to whitelist specific tools, preventing the LLM from accessing potentially dangerous operations. For HTTP transport, you can specify custom `headers` for authentication. Additionally, `response_bytes_cap` (default 10 MiB) prevents memory exhaustion from oversized responses.