Skip to main content

Overview

The Model Context Protocol (MCP) is a standardized protocol for exposing tools and resources to AI agents. Qwen-Agent supports MCP integration, allowing you to connect to any MCP-compatible server and use its tools seamlessly.

Quick Start

Here’s an example using an MCP SQLite server (examples/assistant_mcp_sqlite_bot.py:27):
from qwen_agent.agents import Assistant

llm_cfg = {'model': 'qwen-max'}
system = 'You are a database assistant with database query capabilities'

tools = [{
    "mcpServers": {
        "sqlite": {
            "command": "uvx",
            "args": [
                "mcp-server-sqlite",
                "--db-path",
                "test.db"
            ]
        }
    }
}]

bot = Assistant(
    llm=llm_cfg,
    system_message=system,
    function_list=tools
)

messages = [{'role': 'user', 'content': 'How many tables are in the database?'}]
for response in bot.run(messages):
    print(response)

What is MCP?

MCP provides a standard way for servers to expose:
  • Tools: Functions that agents can call
  • Resources: Data sources and APIs
  • Prompts: Pre-defined prompt templates
Benefits:
  • ✅ Standardized protocol across different tools
  • ✅ Easy integration with existing MCP servers
  • ✅ Community-maintained server ecosystem
  • ✅ Automatic tool discovery and registration

MCP Configuration Format

MCP servers are configured using a specific format in the function_list:
{
    "mcpServers": {
        "server_name": {
            "command": "command_to_run",
            "args": ["arg1", "arg2", ...],
            "env": {"ENV_VAR": "value"}  # Optional
        }
    }
}

Configuration Structure

FieldTypeDescription
mcpServersdictContainer for MCP server configurations
server_namestrUnique identifier for the server
commandstrCommand to launch the MCP server
argslistCommand-line arguments
envdictOptional environment variables

Available MCP Servers

The MCP ecosystem includes many pre-built servers:

Database Servers

SQLite

tools = [{
    "mcpServers": {
        "sqlite": {
            "command": "uvx",
            "args": [
                "mcp-server-sqlite",
                "--db-path",
                "database.db"
            ]
        }
    }
}]

PostgreSQL

tools = [{
    "mcpServers": {
        "postgres": {
            "command": "uvx",
            "args": ["mcp-server-postgres"],
            "env": {
                "POSTGRES_CONNECTION": "postgresql://user:pass@localhost/dbname"
            }
        }
    }
}]

File System

tools = [{
    "mcpServers": {
        "filesystem": {
            "command": "uvx",
            "args": [
                "mcp-server-filesystem",
                "--allowed-directories",
                "/path/to/safe/directory"
            ]
        }
    }
}]
tools = [{
    "mcpServers": {
        "brave_search": {
            "command": "uvx",
            "args": ["mcp-server-brave-search"],
            "env": {
                "BRAVE_API_KEY": "your_api_key"
            }
        }
    }
}]

Complete Example: Database Assistant

Here’s a complete application using MCP (examples/assistant_mcp_sqlite_bot.py):
from qwen_agent.agents import Assistant
from qwen_agent.gui import WebUI

def init_agent_service():
    llm_cfg = {'model': 'qwen-max'}
    system = 'You act as a database assistant with database query capabilities'
    
    tools = [{
        "mcpServers": {
            "sqlite": {
                "command": "uvx",
                "args": [
                    "mcp-server-sqlite",
                    "--db-path",
                    "test.db"
                ]
            }
        }
    }]
    
    bot = Assistant(
        llm=llm_cfg,
        name='Database Assistant',
        description='Database query assistant',
        system_message=system,
        function_list=tools
    )
    
    return bot

def app_gui():
    bot = init_agent_service()
    chatbot_config = {
        'prompt.suggestions': [
            'How many tables are in the database?',
            'Create a student table with name and age',
            'Add a student named Han Meimei, 6 years old',
        ]
    }
    WebUI(bot, chatbot_config=chatbot_config).run()

if __name__ == '__main__':
    app_gui()

Multiple MCP Servers

You can configure multiple MCP servers simultaneously:
tools = [{
    "mcpServers": {
        # Database access
        "sqlite": {
            "command": "uvx",
            "args": ["mcp-server-sqlite", "--db-path", "data.db"]
        },
        # File system access
        "filesystem": {
            "command": "uvx",
            "args": [
                "mcp-server-filesystem",
                "--allowed-directories",
                "/workspace"
            ]
        },
        # Web search
        "search": {
            "command": "uvx",
            "args": ["mcp-server-brave-search"],
            "env": {"BRAVE_API_KEY": "your_key"}
        }
    }
}]

bot = Assistant(
    llm={'model': 'qwen-max'},
    function_list=tools
)

Combining MCP with Other Tools

MCP tools work alongside built-in tools:
from qwen_agent.agents import Assistant

tools = [
    # Built-in tool
    'code_interpreter',
    
    # MCP server
    {
        "mcpServers": {
            "sqlite": {
                "command": "uvx",
                "args": ["mcp-server-sqlite", "--db-path", "data.db"]
            }
        }
    }
]

bot = Assistant(
    llm={'model': 'qwen-max'},
    function_list=tools
)

# Agent can now use both code_interpreter AND sqlite tools
messages = [{
    'role': 'user',
    'content': 'Query the database and visualize the results with matplotlib'
}]

for response in bot.run(messages):
    print(response)

How MCP Integration Works

The MCP integration process (qwen_agent/tools/base.py:218):
1. Agent initialization

2. MCPManager.initConfig()

3. Launch MCP server process

4. Discover available tools

5. Register tools in function_map

6. Tools available for agent use

Tool Registration

When you add an MCP server to function_list:
# Agent.__init__ detects mcpServers key
if isinstance(tool, dict) and 'mcpServers' in tool:
    # Initialize MCP connection
    tools = MCPManager().initConfig(tool)
    
    # Register each discovered tool
    for tool in tools:
        self.function_map[tool.name] = tool

Creating Custom MCP Servers

You can create your own MCP servers in any language:

Python Example

from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool

# Create server
app = Server("my-custom-server")

# Define a tool
@app.tool()
async def calculate_sum(a: int, b: int) -> int:
    """Calculate the sum of two numbers."""
    return a + b

# Run server
if __name__ == "__main__":
    stdio_server(app)

Using Your Custom Server

tools = [{
    "mcpServers": {
        "my_server": {
            "command": "python",
            "args": ["my_custom_server.py"]
        }
    }
}]

bot = Assistant(
    llm={'model': 'qwen-max'},
    function_list=tools
)

Environment Configuration

Pass environment variables to MCP servers:
tools = [{
    "mcpServers": {
        "api_server": {
            "command": "uvx",
            "args": ["mcp-server-api"],
            "env": {
                "API_KEY": "your_secret_key",
                "API_ENDPOINT": "https://api.example.com",
                "DEBUG": "true"
            }
        }
    }
}]
Environment variables are passed securely to the MCP server process and are not exposed in logs or responses.

Security Considerations

Security Best Practices
  • Only use trusted MCP servers from verified sources
  • Limit file system access with --allowed-directories
  • Store API keys in environment variables, not in code
  • Review server source code before deployment
  • Use minimal permissions for database connections
  • Monitor server resource usage

Safe Configuration Example

import os

tools = [{
    "mcpServers": {
        "filesystem": {
            "command": "uvx",
            "args": [
                "mcp-server-filesystem",
                "--allowed-directories",
                "/safe/workspace/only",  # Restrict access
                "--readonly"  # Read-only mode
            ]
        },
        "database": {
            "command": "uvx",
            "args": ["mcp-server-postgres"],
            "env": {
                # Use environment variables
                "POSTGRES_CONNECTION": os.getenv('DB_CONNECTION')
            }
        }
    }
}]

Troubleshooting

Server Not Found

Error: Command 'uvx' not found
Solution: Install uvx (uv package runner):
pip install uv

Connection Failed

Error: Failed to connect to MCP server
Solution: Verify the server command works standalone:
uvx mcp-server-sqlite --db-path test.db

Tool Not Appearing

# Check if tools were registered
bot = Assistant(llm={'model': 'qwen-max'}, function_list=[mcp_config])
print(bot.function_map.keys())  # Should show MCP tools

Database Connection Issues

# Test database connection first
import sqlite3
conn = sqlite3.connect('test.db')
print("Database accessible")
conn.close()

Best Practices

MCP Integration Tips
  • Test MCP servers independently before integration
  • Use descriptive server_name values for clarity
  • Keep server configurations in separate config files
  • Document required environment variables
  • Implement error handling for server failures
  • Monitor server logs during development

MCP Server Resources

Official Servers

  • mcp-server-sqlite: SQLite database access
  • mcp-server-postgres: PostgreSQL database access
  • mcp-server-filesystem: File system operations
  • mcp-server-brave-search: Web search via Brave API
  • mcp-server-github: GitHub repository access

Installation

# Using uvx (recommended)
uvx mcp-server-sqlite --help

# Or install globally
pip install mcp-server-sqlite

Next Steps

Build docs developers (and LLMs) love