Agno开发教程(十):在Tools中使用MCP(Model Context Protocol)

228 阅读26分钟

📚 教程概述

本教程将详细介绍如何在Agno框架中将MCP(Model Context Protocol)作为工具集成到Agent中。通过MCP Tools,你的AI Agent可以无缝连接到各种外部MCP服务器,使用它们提供的工具和资源。我们将使用DeepSeek和Qwen模型进行演示,提供完整可运行的代码示例。

📖 目录

  1. MCP Tools简介
  2. 环境配置和依赖安装
  3. MCP Tools基础配置
  4. 实际代码示例
  5. 常见MCP Server集成
  6. 高级使用场景
  7. 最佳实践和注意事项

1. MCP Tools简介

1.1 什么是MCP Tools?

MCP Tools 是Agno框架中用于连接外部MCP服务器的工具类。通过MCP Tools,你可以让Agent访问任何符合MCP协议的服务器提供的工具和资源。

核心概念

  • 🔌 Agno作为MCP Client:Agent通过MCPTools连接外部MCP服务器
  • 🛠️ 工具自动发现:自动发现MCP服务器提供的所有工具
  • 📦 统一接口:使用标准化的方式调用各种外部服务
  • 🔗 多服务器支持:一个Agent可以连接多个MCP服务器

1.2 MCP Tools在Agno中的角色

┌─────────────────────────────────────────────┐
│           Agno Agent (MCP Client)           │
│                                             │
│  ┌────────────────────────────────────┐   │
│  │         Agent Configuration        │   │
│  │  - Model: DeepSeek/Qwen           │   │
│  │  - Tools: [fs_tools]              │   │
│  └────────────────────────────────────┘   │
│                    ↓                        │
│  ┌────────────────────────────────────┐   │
│  │      MCPTools (async context)      │   │
│  │  - 启动MCP服务器                    │   │
│  │  - 发现可用工具                     │   │
│  │  - 调用工具并返回结果               │   │
│  └────────────────────────────────────┘   │
└─────────────────┬───────────────────────────┘
                  │ MCP Protocol (stdio)
        ┌─────────┴──────────┐
        ↓                    ↓
┌────────────────┐  ┌────────────────┐
│  MCP Server 1  │  │  MCP Server 2  │
│  (文件系统)    │  │  (GitHub API)  │
└────────────────┘  └────────────────┘

1.3 为什么使用异步上下文管理器?

使用 async with 的优势

  1. 自动资源管理:自动启动和关闭MCP服务器连接
  2. 异常安全:即使出现异常也能正确清理资源
  3. 异步支持:完全支持Python异步编程模式
  4. 代码简洁:无需手动管理连接生命周期

2. 环境配置和依赖安装

2.1 前置要求

  • Python 3.11+
  • Node.js 18+ (用于运行MCP服务器)
  • DeepSeek API密钥 或 Qwen API密钥

2.2 安装依赖

# 安装Agno框架及相关依赖
pip install agno python-dotenv

# 安装常用MCP服务器
npm install -g @modelcontextprotocol/server-filesystem
npm install -g @modelcontextprotocol/server-github
npm install -g @modelcontextprotocol/server-brave-search
npm install -g dingtalk-mcp@latest

2.3 设置API密钥

创建 .env 文件:

# DeepSeek API密钥
DEEPSEEK_API_KEY=your_deepseek_api_key_here
# Qwen API密钥
DASHSCOPE_API_KEY=your_dashscope_api_key_here
# GitHub Token (用于GitHub MCP Server)
GITHUB_TOKEN=your_github_token_here
# Brave Search API Key
BRAVE_API_KEY=your_brave_api_key_here
# Slack Bot Token
DINGTALK_Client_ID=your dingtalk app client id
DINGTALK_Client_Secret=your dingtalk app cliengt secret

在Python中加载环境变量:

from dotenv import load_dotenv
load_dotenv()

3. MCP Tools基础配置

3.1 MCPTools类的基本用法

import asyncio
from agno.tools.mcp import MCPTools
from agno.agent import Agent
from agno.models.deepseek import DeepSeek

async def basic_example():
    # 使用async with上下文管理器
    async with MCPTools(
        # MCP服务器启动命令(使用npx运行)
        "npx -y @modelcontextprotocol/server-filesystem /path/to/directory",
        # 可选:指定要使用的工具
        include_tools=["read_file", "list_directory"]
    ) as mcp_tools:
        
        # 创建Agent并添加MCP工具
        agent = Agent(
            name="Assistant",
            model=DeepSeek(),
            tools=[mcp_tools],  # 🔑 关键:将MCP工具传递给Agent
            markdown=True
        )
        
        # 使用Agent
        await agent.aprint_response("列出目录中的文件")

# 运行异步函数
asyncio.run(basic_example())

3.2 配置参数详解

参数类型说明必需
commandstrnpx命令启动MCP服务器(第一个位置参数)
include_toolsList[str]要包含的工具列表,留空则包含所有
exclude_toolsList[str]要排除的工具列表
envDict[str, str]环境变量

3.3 命令格式说明

标准格式

MCPTools("npx -y @modelcontextprotocol/server-name [参数]")

参数说明

  • npx: Node.js包执行器
  • -y: 自动确认安装(如果服务器未安装)
  • @modelcontextprotocol/server-name: MCP服务器包名
  • [参数]: 服务器特定参数(如文件路径、API密钥等)

3.4 最小化示例

"""
最简单的MCP Tools使用示例
"""
import asyncio
from agno.agent import Agent
from agno.models.deepseek import DeepSeek
from agno.tools.mcp import MCPTools
from dotenv import load_dotenv

load_dotenv()

async def run_agent(message: str, file_path: str) -> None:
    async with (
        # 配置文件系统MCP工具
        MCPTools(
            f"npx -y @modelcontextprotocol/server-filesystem {file_path}",
            include_tools=[
                "list_allowed_directories",
                "list_directory",
                "read_file",
            ],
        ) as fs_tools,
    ):
        # 创建Agent
        agent = Agent(
            name="File Assistant",
            model=DeepSeek(),
            tools=[fs_tools],
            instructions=["你是一个文件管理助手"],
            markdown=True,
            read_tool_call_history=True
        )
        
        # 执行任务
        await agent.aprint_response(message)

if __name__ == "__main__":
    asyncio.run(run_agent(
        "列出目录中的所有文件", 
        "你的文件夹"
    ))

4. 实际代码示例

4.1 示例1:文件系统操作Agent(DeepSeek)

完整的文件管理助手,支持读取、写入、搜索文件。

文件名file_agent_deepseek.py

"""
Agno MCP Tools示例:文件系统操作Agent
使用DeepSeek模型和MCP文件系统服务器
"""

import asyncio
import os
from dotenv import load_dotenv
from agno.agent import Agent
from agno.models.deepseek import DeepSeek
from agno.tools.mcp import MCPTools

load_dotenv()

async def file_operations_demo():
    """文件操作演示"""
    
    # 设置允许访问的目录
    workspace_path = "/Users/yourname/Documents/test_folder"
    
    async with MCPTools(
        f"npx -y @modelcontextprotocol/server-filesystem {workspace_path}",
        include_tools=[
            "list_allowed_directories",  # 列出允许访问的目录
            "list_directory",            # 列出目录内容
            "read_file",                 # 读取文件
            "write_file",                # 写入文件
            "create_directory",          # 创建目录
            "move_file",                 # 移动文件
            "search_files",              # 搜索文件
            "get_file_info",             # 获取文件信息
        ]
    ) as fs_tools:
        
        # 创建文件管理Agent
        agent = Agent(
            name="DeepSeek File Manager",
            model=DeepSeek(),
            tools=[fs_tools],
            instructions=[
                "你是一个专业的文件管理助手",
                "你可以帮助用户:",
                "- 列出目录内容",
                "- 读取和写入文件",
                "- 创建和管理目录",
                "- 搜索文件",
                "- 移动和重命名文件",
                "在执行危险操作(如删除)前,先向用户确认",
                "用清晰的格式展示文件信息"
            ],
            markdown=True,
            read_tool_call_history=True
        )
        
        print("=" * 60)
        print("📁 DeepSeek文件管理Agent启动")
        print("=" * 60)
        
        # 测试场景1:列出目录内容
        print("\n🔍 测试1:列出目录内容")
        await agent.aprint_response("列出当前目录中的所有文件和文件夹")
        
        # 测试场景2:创建文件
        print("\n✏️ 测试2:创建新文件")
        await agent.aprint_response(
            "创建一个名为'hello_mcp.txt'的文件,内容为'Hello from MCP Tools!'"
        )
        
        # 测试场景3:读取文件
        print("\n📖 测试3:读取文件内容")
        await agent.aprint_response("读取hello_mcp.txt的内容")
        
        # 测试场景4:搜索文件
        print("\n🔎 测试4:搜索文件")
        await agent.aprint_response("搜索所有.txt文件并显示它们的路径")
        
        # 测试场景5:文件信息
        print("\n📊 测试5:获取文件详细信息")
        await agent.aprint_response("获取hello_mcp.txt的详细信息,包括大小、创建时间等")

async def main():
    await file_operations_demo()

if __name__ == "__main__":
    asyncio.run(main())

运行效果

📁 DeepSeek文件管理Agent启动
============================================================

🔍 测试1:列出目录内容
当前目录包含以下文件和文件夹:
- 📁 projects/
- 📄 hello_mcp.txt (125 bytes)
- 📄 notes.md (2.3 KB)

✏️ 测试2:创建新文件
✅ 已成功创建文件 hello_mcp.txt
内容:Hello from MCP Tools!

📖 测试3:读取文件内容
文件内容:Hello from MCP Tools!

4.2 示例2:GitHub操作Agent(Qwen)

通过MCP连接GitHub,管理仓库、Issues、PRs等。

文件名github_agent_qwen.py

"""
Agno MCP Tools示例:GitHub操作Agent
使用Qwen模型和MCP GitHub服务器
"""

import asyncio
import os
from dotenv import load_dotenv
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.mcp import MCPTools

load_dotenv()

async def github_operations_demo():
    """GitHub操作演示"""
    
    # 设置GitHub Token环境变量
    github_token = os.getenv("GITHUB_TOKEN")
    if not github_token:
        print("❌ 错误:请设置GITHUB_TOKEN环境变量")
        return
    
    async with MCPTools(
        "npx -y @modelcontextprotocol/server-github",
        include_tools=[
            "search_repositories",        # 搜索仓库
            "get_file_contents",          # 获取文件内容
            "list_commits",               # 列出提交记录
            "create_issue",               # 创建Issue
            "create_pull_request",        # 创建PR
            "list_issues",                # 列出Issues
            "fork_repository",            # Fork仓库
            "create_branch",              # 创建分支
        ],
        env={"GITHUB_PERSONAL_ACCESS_TOKEN": github_token}
    ) as github_tools:
        
        # 创建GitHub管理Agent
        agent = Agent(
            name="Qwen GitHub Manager",
            model=OpenAIChat(
                id="qwen-max-latest",
                api_key=os.getenv("DASHSCOPE_API_KEY"),
                base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
            ),
            tools=[github_tools],
            instructions=[
                "你是一个GitHub管理助手",
                "你可以帮助用户:",
                "- 搜索和浏览GitHub仓库",
                "- 查看文件内容和提交历史",
                "- 创建和管理Issues",
                "- 创建和审查Pull Requests",
                "- Fork仓库和创建分支",
                "使用专业的技术语言,提供清晰的反馈",
                "在创建资源(如Issue、PR)前,向用户确认详情"
            ],
            markdown=True,
            read_tool_call_history=True
        )
        
        print("=" * 60)
        print("🐙 Qwen GitHub管理Agent启动")
        print("=" * 60)
        
        # 测试场景1:搜索仓库
        print("\n🔍 测试1:搜索仓库")
        await agent.aprint_response("搜索关于'agno framework'的仓库,显示前3个结果")
        
        # 测试场景2:查看仓库文件
        print("\n📂 测试2:查看仓库文件")
        await agent.aprint_response(
            "查看phidatahq/agno仓库的README.md文件,总结主要内容"
        )
        
        # 测试场景3:列出Issues
        print("\n📋 测试3:列出Issues")
        await agent.aprint_response(
            "列出phidatahq/agno仓库中最近的5个open状态的issues,"
            "显示标题、创建者和创建时间"
        )
        
        # 测试场景4:查看提交历史
        print("\n📜 测试4:查看提交历史")
        await agent.aprint_response(
            "查看phidatahq/agno仓库最近10次提交,总结主要改动"
        )

async def main():
    await github_operations_demo()

if __name__ == "__main__":
    asyncio.run(main())

GitHub工具说明

工具名称功能示例用法
search_repositories搜索GitHub仓库搜索Python AI框架
get_file_contents获取文件内容读取README.md
list_commits列出提交记录查看最近的提交
create_issue创建Issue报告bug或提建议
create_pull_request创建PR提交代码修改
list_issues列出Issues查看待解决问题
fork_repositoryFork仓库创建仓库副本
create_branch创建分支开始新功能开发

4.3 示例3:多MCP服务器集成

同时使用多个MCP服务器,实现复杂的工作流。

文件名multi_mcp_agent.py

"""
Agno MCP Tools示例:多MCP服务器集成
同时使用文件系统、GitHub和搜索工具
"""

import asyncio
import os
from dotenv import load_dotenv
from agno.agent import Agent
from agno.models.deepseek import DeepSeek
from agno.tools.mcp import MCPTools

load_dotenv()

async def multi_server_demo():
    """多服务器集成演示"""
    
    workspace_path = "/Users/yourname/projects"
    
    # 🔑 关键:使用逗号分隔多个async with语句
    async with (
        # MCP Server 1: 文件系统
        MCPTools(
            f"npx -y @modelcontextprotocol/server-filesystem {workspace_path}",
            include_tools=["read_file", "write_file", "list_directory", "search_files"]
        ) as fs_tools,
        
        # MCP Server 2: GitHub
        MCPTools(
            "npx -y @modelcontextprotocol/server-github",
            include_tools=["get_file_contents", "search_repositories", "create_issue"],
            env={"GITHUB_PERSONAL_ACCESS_TOKEN": os.getenv("GITHUB_TOKEN")}
        ) as github_tools,
        
        # MCP Server 3: Brave搜索(可选)
        # MCPTools(
        #     "npx -y @modelcontextprotocol/server-brave-search",
        #     include_tools=["brave_web_search"],
        #     env={"BRAVE_API_KEY": os.getenv("BRAVE_API_KEY")}
        # ) as search_tools,
    ):
        
        # 创建多功能开发助手
        agent = Agent(
            name="DeepSeek Dev Assistant",
            model=DeepSeek(),
            tools=[fs_tools, github_tools],  # 🔑 传递多个工具
            instructions=[
                "你是一个全能的开发助手",
                "你可以:",
                "1. 操作本地文件系统(读写文件、管理目录)",
                "2. 管理GitHub仓库(查看代码、创建Issues)",
                "3. 协调本地开发和远程仓库的工作流",
                "根据任务自动选择合适的工具",
                "提供详细的操作反馈"
            ],
            markdown=True,
            read_tool_call_history=True
        )
        
        print("=" * 60)
        print("🚀 多MCP工具开发助手启动")
        print("=" * 60)
        
        # 复杂任务1:从GitHub下载文件到本地
        print("\n📥 任务1:协调GitHub和本地文件系统")
        await agent.aprint_response("""
        请执行以下任务:
        1. 从phidatahq/agno仓库获取README.md的内容
        2. 在本地创建一个文件保存该内容,命名为agno_readme_backup.md
        3. 确认文件已成功创建
        """)
        
        # 复杂任务2:代码分析和问题报告
        print("\n🔍 任务2:代码审查和问题跟踪")
        await agent.aprint_response("""
        请执行以下任务:
        1. 读取本地的main.py文件
        2. 分析代码,识别潜在的问题或改进点
        3. 如果发现重要问题,起草一个GitHub Issue的内容
           (标题和详细描述,但不要实际创建)
        """)
        
        # 复杂任务3:项目同步
        print("\n🔄 任务3:项目文件比对")
        await agent.aprint_response("""
        请执行以下任务:
        1. 列出本地项目目录的文件结构
        2. 对比一个GitHub仓库的文件结构
        3. 报告差异(哪些文件只在本地,哪些只在远程)
        """)

async def main():
    await multi_server_demo()

if __name__ == "__main__":
    asyncio.run(main())

多服务器集成的优势

  • ✅ 一个Agent可以跨多个数据源工作
  • ✅ 自动协调不同工具完成复杂任务
  • ✅ 统一的接口,无缝切换工具
  • ✅ 提高Agent的能力和灵活性

4.4 示例4:Brave搜索Agent

使用Brave搜索MCP服务器进行网络研究。

文件名brave_search_agent.py

"""
Agno MCP Tools示例:Brave搜索Agent
使用Brave Search MCP服务器进行网络研究
"""

import asyncio
import os
from dotenv import load_dotenv
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.mcp import MCPTools

load_dotenv()

async def search_research_demo():
    """搜索研究演示"""
    
    brave_api_key = os.getenv("BRAVE_API_KEY")
    if not brave_api_key:
        print("❌ 错误:请设置BRAVE_API_KEY环境变量")
        print("获取API密钥: https://brave.com/search/api/")
        return
    
    async with MCPTools(
        "npx -y @modelcontextprotocol/server-brave-search",
        include_tools=[
            "brave_web_search",    # 网页搜索
            "brave_local_search",  # 本地搜索
        ],
        env={"BRAVE_API_KEY": brave_api_key}
    ) as search_tools:
        
        # 创建搜索研究Agent
        agent = Agent(
            name="Qwen Search Researcher",
            model=OpenAIChat(
                id="qwen-max-latest",
                api_key=os.getenv("DASHSCOPE_API_KEY"),
                base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
            ),
            tools=[search_tools],
            instructions=[
                "你是一个专业的网络研究助手",
                "使用Brave搜索获取最新、准确的信息",
                "对搜索结果进行深度分析和总结",
                "提供信息来源链接",
                "用清晰的Markdown结构呈现研究结果",
                "区分事实和观点",
                "标注信息的时效性"
            ],
            markdown=True,
            read_tool_call_history=True
        )
        
        print("=" * 60)
        print("🔎 Brave搜索研究Agent启动")
        print("=" * 60)
        
        # 研究任务1:技术主题深度研究
        print("\n📚 研究任务1:技术主题深度研究")
        await agent.aprint_response("""
        研究'Model Context Protocol (MCP)':
        1. 搜索MCP的最新发展和特性
        2. 总结核心功能和应用场景
        3. 列出主要的实现和工具
        4. 提供相关资源链接
        """)
        
        # 研究任务2:对比分析
        print("\n⚖️ 研究任务2:技术对比分析")
        await agent.aprint_response("""
        对比DeepSeek和Qwen模型:
        1. 搜索两个模型的官方信息
        2. 比较它们的参数规模、能力和特点
        3. 分析各自的优势和适用场景
        4. 总结选择建议
        """)
        
        # 研究任务3:实时资讯
        print("\n📰 研究任务3:实时资讯收集")
        await agent.aprint_response("""
        搜索2024年AI领域的重要进展:
        1. 查找最近3个月的重大AI新闻
        2. 按时间顺序整理
        3. 突出最具影响力的突破
        4. 提供新闻来源
        """)
        
        # 研究任务4:特定问题解决
        print("\n💡 研究任务4:问题解决方案")
        await agent.aprint_response("""
        搜索'如何优化Python异步性能':
        1. 查找最佳实践和技巧
        2. 收集代码示例
        3. 总结常见陷阱
        4. 推荐学习资源
        """)

async def main():
    await search_research_demo()

if __name__ == "__main__":
    asyncio.run(main())

Brave搜索工具特性

  • 🌐 实时网络搜索
  • 🔍 高质量搜索结果
  • 📊 结构化数据返回(标题、摘要、URL)
  • 🚫 无广告干扰
  • 🔒 隐私保护

5. 常见MCP Server集成

5.1 文件系统 (Filesystem)

安装

npm install -g @modelcontextprotocol/server-filesystem

使用示例

async with MCPTools(
    f"npx -y @modelcontextprotocol/server-filesystem {directory_path}",
    include_tools=[
        "read_file",              # 读取文件
        "read_multiple_files",    # 批量读取
        "write_file",             # 写入文件
        "create_directory",       # 创建目录
        "list_directory",         # 列出目录
        "move_file",              # 移动文件
        "search_files",           # 搜索文件
        "get_file_info",          # 文件信息
    ]
) as fs_tools:
    agent = Agent(model=DeepSeek(), tools=[fs_tools])

5.2 GitHub

安装

npm install -g @modelcontextprotocol/server-github

使用示例

async with MCPTools(
    "npx -y @modelcontextprotocol/server-github",
    include_tools=[
        "create_or_update_file",  # 创建/更新文件
        "search_repositories",    # 搜索仓库
        "create_repository",      # 创建仓库
        "get_file_contents",      # 获取文件内容
        "create_issue",           # 创建Issue
        "create_pull_request",    # 创建PR
        "fork_repository",        # Fork仓库
        "create_branch",          # 创建分支
    ],
    env={"GITHUB_PERSONAL_ACCESS_TOKEN": os.getenv("GITHUB_TOKEN")}
) as github_tools:
    agent = Agent(model=DeepSeek(), tools=[github_tools])

5.3 Brave搜索

安装

npm install -g @modelcontextprotocol/server-brave-search

使用示例

async with MCPTools(
    "npx -y @modelcontextprotocol/server-brave-search",
    include_tools=["brave_web_search", "brave_local_search"],
    env={"BRAVE_API_KEY": os.getenv("BRAVE_API_KEY")}
) as search_tools:
    agent = Agent(model=DeepSeek(), tools=[search_tools])

5.4 Google Maps

安装

npm install -g @modelcontextprotocol/server-google-maps

使用示例

async with MCPTools(
    "npx -y @modelcontextprotocol/server-google-maps",
    include_tools=[
        "geocode",               # 地址转坐标
        "reverse_geocode",       # 坐标转地址
        "search_places",         # 搜索地点
        "get_directions",        # 获取路线
        "get_distance_matrix",   # 计算距离矩阵
    ],
    env={"GOOGLE_MAPS_API_KEY": os.getenv("GOOGLE_MAPS_API_KEY")}
) as maps_tools:
    agent = Agent(model=DeepSeek(), tools=[maps_tools])
    await agent.aprint_response("从北京天安门到故宫的步行路线")

5.5 PostgreSQL数据库

安装

npm install -g @modelcontextprotocol/server-postgres

使用示例

async with MCPTools(
    "npx -y @modelcontextprotocol/server-postgres",
    include_tools=[
        "query",               # 执行SQL查询
        "list_tables",         # 列出所有表
        "describe_table",      # 查看表结构
        "execute",             # 执行SQL语句
    ],
    env={"POSTGRES_CONNECTION_STRING": os.getenv("DATABASE_URL")}
) as db_tools:
    agent = Agent(model=DeepSeek(), tools=[db_tools])
    await agent.aprint_response("查询users表中注册时间最近的10个用户")

5.6 Puppeteer(浏览器自动化)

安装

npm install -g @modelcontextprotocol/server-puppeteer

使用示例

async with MCPTools(
    "npx -y @modelcontextprotocol/server-puppeteer",
    include_tools=[
        "puppeteer_navigate",     # 访问网页
        "puppeteer_screenshot",   # 截图
        "puppeteer_click",        # 点击元素
        "puppeteer_fill",         # 填写表单
        "puppeteer_evaluate",     # 执行JS
    ]
) as web_tools:
    agent = Agent(model=DeepSeek(), tools=[web_tools])
    await agent.aprint_response("访问example.com并截图保存")

5.7 Memory(知识库)

安装

npm install -g @modelcontextprotocol/server-memory

使用示例

async with MCPTools(
    "npx -y @modelcontextprotocol/server-memory",
    include_tools=[
        "store_memory",       # 存储知识
        "search_memory",      # 搜索知识
        "delete_memory",      # 删除知识
        "list_memories",      # 列出所有知识
    ]
) as memory_tools:
    agent = Agent(model=DeepSeek(), tools=[memory_tools])
    await agent.aprint_response("记住:我喜欢Python编程")

6. 高级使用场景

6.1 场景1:全栈开发助手

集成文件系统、GitHub、搜索和数据库。

"""
全栈开发助手:多工具协作
"""

import asyncio
import os
from dotenv import load_dotenv
from agno.agent import Agent
from agno.models.deepseek import DeepSeek
from agno.tools.mcp import MCPTools

load_dotenv()

async def fullstack_dev_assistant():
    workspace = "/Users/yourname/projects/my_app"
    
    async with (
        # 本地文件系统
        MCPTools(
            f"npx -y @modelcontextprotocol/server-filesystem {workspace}",
            include_tools=["read_file", "write_file", "list_directory", "search_files"]
        ) as fs_tools,
        
        # GitHub管理
        MCPTools(
            "npx -y @modelcontextprotocol/server-github",
            include_tools=["get_file_contents", "create_issue", "create_pull_request"],
            env={"GITHUB_PERSONAL_ACCESS_TOKEN": os.getenv("GITHUB_TOKEN")}
        ) as github_tools,
        
        # 网络搜索
        MCPTools(
            "npx -y @modelcontextprotocol/server-brave-search",
            include_tools=["brave_web_search"],
            env={"BRAVE_API_KEY": os.getenv("BRAVE_API_KEY")}
        ) as search_tools,
        
        # 数据库管理
        MCPTools(
            "npx -y @modelcontextprotocol/server-postgres",
            include_tools=["query", "list_tables", "describe_table"],
            env={"POSTGRES_CONNECTION_STRING": os.getenv("DATABASE_URL")}
        ) as db_tools,
    ):
        agent = Agent(
            name="Fullstack Dev Assistant",
            model=DeepSeek(),
            tools=[fs_tools, github_tools, search_tools, db_tools],
            instructions=[
                "你是一个全栈开发专家助手",
                "你可以:",
                "1. 管理本地项目文件和代码",
                "2. 与GitHub仓库交互(查看、创建Issue/PR)",
                "3. 搜索技术文档和解决方案",
                "4. 查询和分析数据库",
                "5. 协调完整的开发工作流",
                "根据任务智能选择工具组合",
                "提供详细的技术建议和最佳实践"
            ],
            markdown=True,
            read_tool_call_history=True
        )
        
        print("🚀 全栈开发助手已启动\n")
        
        # 复杂开发任务
        await agent.aprint_response("""
        我正在开发一个用户认证功能,请帮我:
        1. 搜索JWT认证的Python最佳实践
        2. 检查数据库中users表的结构
        3. 在本地创建auth.py文件,实现JWT认证逻辑
        4. 从GitHub上类似项目学习实现方式
        5. 如果发现本地代码有问题,起草改进建议
        """)

if __name__ == "__main__":
    asyncio.run(fullstack_dev_assistant())

6.2 场景2:数据分析管道

数据库查询 → 分析 → 报告 → 通知。

"""
数据分析管道:自动化数据分析和报告
"""

import asyncio
import os
from datetime import datetime
from dotenv import load_dotenv
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.mcp import MCPTools

load_dotenv()

async def data_analysis_pipeline():
    report_dir = "/Users/yourname/reports"
    
    async with (
        # 数据库连接
        MCPTools(
            "npx -y @modelcontextprotocol/server-postgres",
            include_tools=["query", "list_tables"],
            env={"POSTGRES_CONNECTION_STRING": os.getenv("DATABASE_URL")}
        ) as db_tools,
        
        # 文件系统(保存报告)
        MCPTools(
            f"npx -y @modelcontextprotocol/server-filesystem {report_dir}",
            include_tools=["write_file", "list_directory"]
        ) as fs_tools,
        
        # 钉钉通知
        MCPTools(
            "npx -y dingtalk-mcp@latest",
            include_tools=["post_message"],
            env={
                "DINGTALK_Client_ID": os.getenv("DINGTALK_Client_ID"),
                "DINGTALK_Client_Secret": os.getenv("DINGTALK_Client_Secret")
            }
        ) as dingding_tools,
    ):
        agent = Agent(
            name="Data Analyst",
            model=OpenAIChat(
                id="qwen-max-latest",
                api_key=os.getenv("DASHSCOPE_API_KEY"),
                base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
            ),
            tools=[db_tools, fs_tools, dingding_tools],
            instructions=[
                "你是一个专业的数据分析师",
                "工作流程:",
                "1. 从数据库查询数据",
                "2. 进行统计分析和可视化描述",
                "3. 生成Markdown格式的分析报告",
                "4. 将报告保存到本地文件",
                "5. 在钉钉发送报告摘要和链接",
                "使用清晰的数据呈现格式",
                "提供洞察和建议"
            ],
            markdown=True,
            read_tool_call_history=True
        )
        
        print("📊 数据分析管道已启动\n")
        
        # 自动化分析任务
        current_date = datetime.now().strftime("%Y年%m月")
        await agent.aprint_response(f"""
        执行{current_date}的销售数据分析:
        
        1. 从sales表查询本月的所有销售数据
        2. 计算以下指标:
           - 总销售额
           - 平均订单金额
           - 订单数量
           - Top 10畅销产品
           - 销售趋势(周同比)
        3. 生成详细的分析报告(Markdown格式)
        4. 将报告保存为 monthly_sales_report_{datetime.now().strftime('%Y%m')}.md
        5. 使用钉钉发送报告摘要到群消息中
        """)

if __name__ == "__main__":
    asyncio.run(data_analysis_pipeline())

6.3 场景3:智能运维助手

监控 + 日志分析 + 自动修复 + 告警。

"""
智能运维助手:自动化监控和问题处理
"""

import asyncio
import os
from dotenv import load_dotenv
from agno.agent import Agent
from agno.models.deepseek import DeepSeek
from agno.tools.mcp import MCPTools

load_dotenv()

async def devops_assistant():
    log_dir = "/var/log/myapp"
    
    async with (
        # 数据库监控
        MCPTools(
            "npx -y @modelcontextprotocol/server-postgres",
            include_tools=["query"],
            env={"POSTGRES_CONNECTION_STRING": os.getenv("DATABASE_URL")}
        ) as db_tools,
        
        # 日志文件访问
        MCPTools(
            f"npx -y @modelcontextprotocol/server-filesystem {log_dir}",
            include_tools=["read_file", "search_files", "list_directory"]
        ) as fs_tools,
        
        # 钉钉通知
        MCPTools(
            "npx -y dingtalk-mcp@latest",
            include_tools=["post_message"],
            env={
                "DINGTALK_Client_ID": os.getenv("DINGTALK_Client_ID"),
                "DINGTALK_Client_Secret": os.getenv("DINGTALK_Client_Secret")
            }
        ) as dingding_tools,
        
        # GitHub Issue跟踪
        MCPTools(
            "npx -y @modelcontextprotocol/server-github",
            include_tools=["create_issue", "list_issues"],
            env={"GITHUB_PERSONAL_ACCESS_TOKEN": os.getenv("GITHUB_TOKEN")}
        ) as github_tools,
    ):
        agent = Agent(
            name="DevOps Assistant",
            model=DeepSeek(),
            tools=[db_tools, fs_tools, dingding_tools, github_tools],
            instructions=[
                "你是一个智能运维助手",
                "你的职责:",
                "1. 监控系统健康状态",
                "2. 分析日志识别问题",
                "3. 提供问题诊断和修复建议",
                "4. 发送告警通知",
                "5. 创建Issue跟踪问题",
                "按问题严重程度分类:",
                "- 🔴 Critical: 立即通知并创建Issue",
                "- 🟡 Warning: 记录并建议检查",
                "- 🟢 Info: 仅记录",
                "提供清晰的问题描述和解决步骤"
            ],
            markdown=True,
            show_tool_calls=True,
            read_tool_call_history=True
        )
        
        print("🔧 智能运维助手已启动\n")
        
        # 健康检查任务
        await agent.aprint_response("""
        执行系统健康检查:
        
        1. 查询数据库性能指标(慢查询、连接数、表大小)
        2. 分析最近1小时的应用日志,识别ERROR和WARNING
        3. 检查是否有异常模式或频繁错误
        4. 如果发现Critical问题:
           - 在钉钉群发送告警消息
           - 在GitHub创建Issue记录问题详情
        5. 生成健康检查报告摘要
        """)

if __name__ == "__main__":
    asyncio.run(devops_assistant())

6.4 场景4:内容创作工作流

研究 → 写作 → 审核 → 发布。

"""
内容创作工作流:自动化内容生产
"""

import asyncio
import os
from datetime import datetime

from agno.models.dashscope import DashScope
from dotenv import load_dotenv
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.mcp import MCPTools

load_dotenv()


async def content_creation_workflow():
    content_dir = "/Users/yourname/blog"

    async with (
        # 网络研究
        MCPTools(
            "npx -y @modelcontextprotocol/server-brave-search",
            include_tools=["brave_web_search"],
            env={"BRAVE_API_KEY": os.getenv("BRAVE_API_KEY")}
        ) as search_tools,

        # 本地写作
        MCPTools(
            f"npx -y @modelcontextprotocol/server-filesystem {content_dir}",
            include_tools=["write_file", "read_file", "list_directory"]
        ) as fs_tools,

        # GitHub发布
        MCPTools(
            "npx -y @modelcontextprotocol/server-github",
            include_tools=["create_or_update_file", "get_file_contents"],
            env={"GITHUB_PERSONAL_ACCESS_TOKEN": os.getenv("GITHUB_TOKEN")}
        ) as github_tools,
    ):
        agent = Agent(
            name="Content Creator",
            model=DashScope(
                id="qwen3-max",
                base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
            ),
            tools=[search_tools, fs_tools, github_tools],
            instructions=[
                "你是一个专业的技术内容创作者",
                "创作流程:",
                "1. 研究主题:使用搜索收集资料",
                "2. 撰写文章:创建高质量的技术文章",
                "3. 本地保存:保存为Markdown文件",
                "4. 发布:推送到GitHub博客仓库",
                "写作风格:",
                "- 清晰易懂,适合技术读者",
                "- 包含代码示例和实践建议",
                "- 结构化组织,使用标题和列表",
                "- 添加元数据(日期、标签、分类)"
            ],
            markdown=True,
            read_tool_call_history=True
        )

        print("✍️ 内容创作工作流已启动\n")

        # 完整创作任务
        topic = "Python异步编程最佳实践"
        date_str = datetime.now().strftime("%Y-%m-%d")

        await agent.aprint_response(f"""
        创作一篇关于'{topic}'的技术博文:

        1. 研究阶段:
           - 搜索最新的Python异步编程资料
           - 收集最佳实践和常见陷阱
           - 查找代码示例

        2. 写作阶段:
           - 撰写一篇2000字左右的文章
           - 包含至少3个代码示例
           - 添加实用建议和注意事项
           - 包含文章元数据:
             ```yaml
             ---
             title: {topic}
             date: {date_str}
             tags: [Python, 异步编程, asyncio]
             category: 编程技术
             ---
        3. 保存阶段:
            - 保存为 posts/{date_str}-python-async-best-practices.md

        4. 发布阶段:
             - 推送到GitHub仓库 username/tech-blog
             - 路径: content/posts/{date_str}-python-async-best-practices.md
        请完成整个创作和发布流程。
    """)

if __name__ == "__main__":
    asyncio.run(content_creation_workflow())

7. 最佳实践和注意事项

7.1 资源管理

✅ 使用异步上下文管理器

# ✅ 推荐:自动管理资源
async with MCPTools("npx -y @modelcontextprotocol/server-filesystem /path") as tools:
    agent = Agent(tools=[tools], ...)
    await agent.aprint_response("任务")
# MCP服务器自动关闭

# ❌ 不推荐:手动管理(容易忘记清理)
tools = MCPTools("npx -y @modelcontextprotocol/server-filesystem /path")
agent = Agent(tools=[tools], ...)
# 需要手动调用 await tools.close()

✅ 多服务器管理

# ✅ 推荐:使用逗号分隔多个上下文
async with (
    MCPTools("command1") as tools1,
    MCPTools("command2") as tools2,
    MCPTools("command3") as tools3,
):
    agent = Agent(tools=[tools1, tools2, tools3], ...)

7.2 工具选择策略

使用 include_tools 精确控制

# ✅ 推荐:只包含需要的工具
async with MCPTools(
    "npx -y @modelcontextprotocol/server-filesystem /path",
    include_tools=["read_file", "write_file", "list_directory"]  # 明确列出
) as tools:
    pass

# ⚠️ 谨慎:包含所有工具(可能导致工具过多,影响选择效率)
async with MCPTools(
    "npx -y @modelcontextprotocol/server-filesystem /path"
    # 不设置include_tools,将包含所有工具
) as tools:
    pass

使用 exclude_tools 排除不需要的

async with MCPTools(
    "npx -y @modelcontextprotocol/server-filesystem /path",
    exclude_tools=["delete_file", "move_file"]  # 排除危险操作
) as tools:
    pass

7.3 错误处理

处理MCP服务器启动失败

import asyncio
from agno.tools.mcp import MCPTools

async def safe_mcp_init():
    try:
        async with MCPTools(
            "npx -y @modelcontextprotocol/server-filesystem /path",
            include_tools=["read_file"]
        ) as tools:
            agent = Agent(tools=[tools], ...)
            await agent.aprint_response("任务")
            
    except Exception as e:
        print(f"❌ MCP服务器启动失败: {e}")
        print("请检查:")
        print("1. Node.js是否已安装")
        print("2. MCP服务器包是否已安装")
        print("3. 路径和权限是否正确")
        # 回退方案
        agent = Agent(model=DeepSeek(), ...)  # 不使用MCP工具

处理工具调用失败

agent = Agent(
    name="Robust Agent",
    model=DeepSeek(),
    tools=[mcp_tools],
    instructions=[
        "如果工具调用失败,尝试以下策略:",
        "1. 检查参数是否正确",
        "2. 尝试使用替代工具",
        "3. 向用户说明无法完成并解释原因",
        "4. 提供手动操作的建议"
    ]
)

7.4 性能优化

1. 减少工具调用次数

# ✅ 优化:批量操作
agent = Agent(
    instructions=[
        "尽可能使用批量操作工具",
        "例如:read_multiple_files而不是多次read_file"
    ]
)

# 示例任务
await agent.aprint_response("""
读取以下文件的内容:
- file1.txt
- file2.txt
- file3.txt
请使用批量读取功能一次性获取
""")

2. 限制工具调用深度

agent = Agent(
    model=DeepSeek(),
    tools=[mcp_tools],
    max_tool_calls=5,  # 限制最多调用5次工具
    instructions=["在最少的工具调用次数内完成任务"]
)

3. 缓存常用查询

from functools import lru_cache

@lru_cache(maxsize=100)
async def cached_query(query_string):
    """缓存数据库查询结果"""
    # 实现缓存逻辑
    pass

7.5 安全性

✅ 使用环境变量存储敏感信息

# ✅ 推荐
from dotenv import load_dotenv
load_dotenv()

async with MCPTools(
    "npx -y @modelcontextprotocol/server-github",
    env={"GITHUB_PERSONAL_ACCESS_TOKEN": os.getenv("GITHUB_TOKEN")}
) as tools:
    pass

# ❌ 不要硬编码
async with MCPTools(
    "npx -y @modelcontextprotocol/server-github",
    env={"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxx"}  # 危险!
) as tools:
    pass

✅ 限制文件系统访问范围

# ✅ 推荐:限制在特定目录
safe_dir = "/Users/yourname/safe_workspace"
async with MCPTools(
    f"npx -y @modelcontextprotocol/server-filesystem {safe_dir}"
) as tools:
    pass

# ❌ 危险:允许访问根目录
async with MCPTools(
    "npx -y @modelcontextprotocol/server-filesystem /"  # 危险!
) as tools:
    pass

✅ 审核工具权限

agent = Agent(
    tools=[mcp_tools],
    instructions=[
        "在执行以下操作前需要用户确认:",
        "- 删除文件或目录",
        "- 修改重要配置",
        "- 发送外部消息",
        "- 执行数据库写入操作"
    ]
)

7.6 调试技巧

启用详细日志

agent = Agent(
    name="Debug Agent",
    model=DeepSeek(),
    tools=[mcp_tools],
    markdown=True,              # Markdown格式输出
    read_tool_call_history=True # 读取工具调用历史
)

查看MCP服务器输出

import subprocess

# 手动测试MCP服务器
result = subprocess.run(
    ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
    capture_output=True,
    text=True
)
print("stdout:", result.stdout)
print("stderr:", result.stderr)

使用测试模式

async def test_mcp_tools():
    """测试MCP工具是否正常工作"""
    async with MCPTools(
        "npx -y @modelcontextprotocol/server-filesystem /tmp",
        include_tools=["list_directory"]
    ) as tools:
        agent = Agent(model=DeepSeek(), tools=[tools])
        
        # 简单测试任务
        response = await agent.run("列出目录中的文件")
        print(response.content)
        
        assert response.content, "应该返回内容"
        print("✅ MCP工具测试通过")

asyncio.run(test_mcp_tools())

7.7 测试策略

单元测试

import pytest

@pytest.mark.asyncio
async def test_filesystem_mcp():
    """测试文件系统MCP工具"""
    async with MCPTools(
        "npx -y @modelcontextprotocol/server-filesystem /tmp/test",
        include_tools=["list_directory", "read_file"]
    ) as fs_tools:
        agent = Agent(
            model=DeepSeek(),
            tools=[fs_tools]
        )
        
        response = await agent.run("列出目录中的文件")
        assert response.content is not None
        assert len(response.content) > 0

@pytest.mark.asyncio
async def test_multiple_mcp_servers():
    """测试多MCP服务器集成"""
    async with (
        MCPTools("npx -y @modelcontextprotocol/server-filesystem /tmp") as fs,
        MCPTools("npx -y @modelcontextprotocol/server-github") as gh,
    ):
        agent = Agent(model=DeepSeek(), tools=[fs, gh])
        
        response = await agent.run("测试任务")
        assert response is not None

集成测试

@pytest.mark.asyncio
async def test_fullstack_workflow():
    """完整工作流测试"""
    async with (
        MCPTools(f"npx -y @modelcontextprotocol/server-filesystem /tmp") as fs,
        MCPTools("npx -y @modelcontextprotocol/server-github") as gh,
    ):
        agent = Agent(
            model=DeepSeek(),
            tools=[fs, gh],
            instructions=["执行完整的工作流测试"]
        )
        
        # 测试复杂任务
        response = await agent.run("""
        1. 从GitHub读取文件
        2. 保存到本地
        3. 确认文件已创建
        """)
        
        assert "成功" in response.content or "完成" in response.content

7.8 部署建议

Docker部署

Dockerfile:

FROM node:18-slim

# 安装Python
RUN apt-get update && apt-get install -y \
    python3.11 \
    python3-pip \
    && rm -rf /var/lib/apt/lists/*

# 安装MCP服务器
RUN npm install -g \
    @modelcontextprotocol/server-filesystem \
    @modelcontextprotocol/server-github \
    @modelcontextprotocol/server-brave-search \
    @modelcontextprotocol/server-slack

# 设置工作目录
WORKDIR /app

# 安装Python依赖
COPY requirements.txt .
RUN pip3 install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY . .

# 设置环境变量
ENV PYTHONUNBUFFERED=1

# 运行应用
CMD ["python3", "app.py"]

docker-compose.yml:

version: '3.8'

services:
  agno-app:
    build: .
    environment:
      - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY}
      - GITHUB_TOKEN=${GITHUB_TOKEN}
      - BRAVE_API_KEY=${BRAVE_API_KEY}
    volumes:
      - ./workspace:/app/workspace:ro
      - ./output:/app/output
    restart: unless-stopped

生产环境配置

"""
生产环境配置示例
"""

import asyncio
import logging
from agno.agent import Agent
from agno.models.deepseek import DeepSeek
from agno.tools.mcp import MCPTools

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

async def production_agent():
    try:
        async with (
            MCPTools(
                "npx -y @modelcontextprotocol/server-filesystem /app/workspace",
                include_tools=["read_file", "list_directory"]
            ) as fs_tools,
        ):
            agent = Agent(
                name="Production Agent",
                model=DeepSeek(),
                tools=[fs_tools],
                # 生产环境优化
                max_tool_calls=10,
                read_tool_call_history=False,  # 不显示详细调用
                markdown=False
            )
            
            logger.info("Agent started successfully")
            
            # 执行任务
            result = await agent.run("处理任务")
            logger.info(f"Task completed: {result.content[:100]}...")
            
            return result
            
    except Exception as e:
        logger.error(f"Agent error: {e}", exc_info=True)
        raise

if __name__ == "__main__":
    asyncio.run(production_agent())

📝 总结

在本教程中,我们深入学习了:

  1. MCP Tools基础:使用async with上下文管理器
  2. 标准调用方式:npx命令启动MCP服务器
  3. 工具精确控制:include_tools参数指定需要的工具
  4. 丰富示例:文件系统、GitHub、Slack、搜索等
  5. 多工具集成:同时使用多个MCP服务器
  6. 高级场景:全栈开发、数据分析、运维、内容创作
  7. 最佳实践:安全性、性能优化、错误处理、部署

核心要点

  • 🎯 使用 async with:自动管理MCP服务器生命周期
  • 🎯 npx启动服务器npx -y @modelcontextprotocol/server-name [参数]
  • 🎯 精确控制工具:使用include_tools只包含需要的工具
  • 🎯 多工具协作:一个Agent可以同时使用多个MCP服务器
  • 🎯 异步编程:所有操作都是异步的,使用await

下一步学习

  • 📚 探索更多MCP服务器:mcp.so/zh
  • 🔧 开发自定义MCP服务器
  • 🌐 将MCP Tools与Agno的Team、Workflow结合
  • 🚀 在生产环境部署MCP驱动的AI应用

相关资源