用MCP Server构建多智能体系统
在本指南中,我们将使用运行在本地的多个MCP(模型上下文协议)服务器构建一个多智能体系统。我们将使用两个服务器:
- 一个从头开始创建的自定义MCP服务器
- 一个从Smithery下载的现成MCP服务器
我们的代理将执行两项主要功能:
- 使用PubMed MCP服务器从PubMed搜索医学论文
- 使用我们定制的记忆MCP服务器编写、更新或删除Markdown格式的记忆文件
对于LLM模型,我们将使用Gemini 2.5 Flash Preview,它可以通过API免费提供给所有人(但有限制)。MCP最近在AI代理生态系统中变得非常流行,其作用类似于AI代理的应用商店,通过标准化的方式使它们能够与工具和服务进行交互。
让我们首先探索什么是MCP服务器以及它们是如何工作的。
1、MCP服务器
2024年11月,Anthropic发布了MCP(模型上下文协议),作为AI社区的一个开放标准。MCP提供了一个精简的框架,使任何大型语言模型(LLM)都能无缝集成到外部数据源和工具中。通过建立标准化协议,MCP创建了一个通用接口,用于连接工具和LLM应用程序,大大简化了以前复杂的集成过程。这一创新允许开发人员构建更强大的AI系统,而无需为每种工具和模型组合创建自定义连接。
MCP由两个主要组件组成:MCP服务器和MCP主机。MCP主机利用MCP客户端建立专用的1:1连接到服务器,而MCP服务器是轻量级程序,暴露特定的功能,如工具、外部数据源或提示。这种架构在MCP生态系统中实现了灵活和模块化的功能。
2、本地自定义MCP服务器
安装
pip install "mcp[cli]"
简单的Markdown记忆代理:
from mcp.server.fastmcp import FastMCP
from dotenv import load_dotenv
import os
import re
import sys
import signal
load_dotenv()
def exit_gracefully(signum, frame):
print("退出MCP服务器...")
sys.exit(0)
signal.signal(signal.SIGINT, exit_gracefully)
# 初始化MCP服务器
mcp = FastMCP(name="memory_mcp",
host="127.0.0.1",
port=5000,
timeout=30)
USER_AGENT = "memory/0.0.1"
# 存储记忆Markdown文件的目录。
MEMORY_DIR = r"{path_to_wanted_memory_location}/memory_files"
if not os.path.exists(MEMORY_DIR):
os.makedirs(MEMORY_DIR)
def memory_file_path(title: str) -> str:
# 移除所有不是字母数字、空格、下划线或连字符的字符。
sanitized = re.sub(r"[^\w\s\-]", "", title).strip()
# 将空格替换为下划线作为文件名。
filename = "_".join(sanitized.split()) + ".md"
return os.path.join(MEMORY_DIR, filename)
@mcp.tool()
async def create_memory(title: str, summary: str) -> str:
"""
创建一个带有给定标题和摘要的记忆文件(Markdown)。
文件以标题开头,并保存为经过清理的文件名。
"""
path = memory_file_path(title)
if os.path.exists(path):
return f"记忆'{title}'已经存在。请使用update_memory添加新内容。"
with open(path, "w", encoding="utf-8") as f:
f.write(f"# {title}\n\n")
f.write(summary)
return f"记忆'{title}'已成功创建。"
@mcp.tool()
async def get_memory_list() -> str:
"""
返回包含内存文件目录中所有记忆标题的字符串,每个标题一行。
"""
titles = []
for file in os.listdir(MEMORY_DIR):
if file.endswith(".md"):
title = file[:-3] # 去掉".md"
titles.append(title)
return "\n".join(titles)
@mcp.tool()
async def update_memory(title: str, additional_summary: str) -> str:
"""
通过追加新内容更新现有的记忆。
如果记忆不存在,则使用提供的内容创建新的记忆。
"""
path = memory_file_path(title)
if os.path.exists(path):
with open(path, "a", encoding="utf-8") as f:
f.write("\n\n" + additional_summary)
return f"记忆'{title}'已成功更新。"
else:
# 如果记忆不存在,则调用create_memory。
return await create_memory(title, additional_summary)
@mcp.tool()
async def delete_memory(title: str) -> str:
"""
删除与给定标题对应的记忆文件。
"""
path = memory_file_path(title)
if os.path.exists(path):
os.remove(path)
return f"记忆'{title}'已成功删除。"
else:
return f"记忆'{title}'不存在。"
@mcp.tool()
async def get_memory(title: str) -> str:
"""
检索与给定标题匹配的记忆文件的完整内容。
如果没有找到精确匹配项,则会搜索标题包含给定字符串的记忆。
"""
# 尝试获取精确匹配项。
path = memory_file_path(title)
if os.path.exists(path):
with open(path, "r", encoding="utf-8") as f:
return f.read()
# 否则,尝试部分匹配搜索。
for file in os.listdir(MEMORY_DIR):
if file.endswith(".md"):
filepath = os.path.join(MEMORY_DIR, file)
with open(filepath, "r", encoding="utf-8") as f:
first_line = f.readline().strip()
if title.lower() in first_line.lower():
with open(filepath, "r", encoding="utf-8") as f_full:
return f_full.read()
return f"未找到与'{title}'匹配的记忆。"
# 如果需要,为LLM设置待办事项列表
@mcp.tool()
async def todo_longterm(action: str, content: str = None) -> str:
"""
管理存储为特殊记忆的长期待办事项列表。
动作:
- 'get':检索当前待办事项列表。
- 'update':向待办事项列表追加新项目。
- 'clear':清除整个待办事项列表。
"""
todo_path = os.path.join(MEMORY_DIR, "todo_longterm.md")
if action == "get":
if os.path.exists(todo_path):
with open(todo_path, "r", encoding="utf-8") as f:
return f.read()
else:
return "没有长期待办事项列表。"
elif action == "update":
if not content:
return "没有提供更新待办事项列表的内容。"
# 将新内容作为项目符号追加。
with open(todo_path, "a", encoding="utf-8") as f:
f.write("\n- " + content)
return "长期待办事项列表已更新。"
elif action == "clear":
with open(todo_path, "w", encoding="utf-8") as f:
f.write("")
return "长期待办事项列表已清除。"
else:
return "无效操作。请使用'get'、'update'或'clear'。"
if __name__ == "__main__":
print("启动MCP服务器...在127.0.0.1:5000")
mcp.run(transport='stdio')
这段代码创建了一个轻量级的AI记忆服务器,用于存储和组织Markdown文件中的信息,充当AI系统简单而强大的“数字大脑”。它允许代理通过记忆文件和待办事项列表等工具创建、更新、搜索和删除基于文本的记忆。虽然这并非一个完美的解决方案,但对于开发而言,它非常简单易用。
3、PubMed服务器安装与Smithery
Smithery是一个全面的平台,用于发现、部署和集成基于多上下文协议(MCP)规范的自主服务。其主要优势包括:
- 提供一个集中式的注册表以发现兼容的MCP服务器
- 提供强大的托管和分发基础设施以支持MCP服务
- 标准化接口简化工具的集成和配置
要本地部署一个流行的PubMed MCP服务器,我们将使用一个由Smithery提供的维护良好的实现,其源代码托管在Github上。
安装仅需几个简单的命令。
让我们从GitHub克隆存储库并安装依赖项。
git clone https://github.com/JackKuo666/PubMed-MCP-Server.git
cd PubMed-MCP-Server
# Then install all the dependencies:
pip install -r requirements.txt
大功告成!我们的服务器现在可以运行了,接下来让我们编写一些使用smolagents的代理,但首先什么是smolagents?
4、Smolagents:构建代理的简单库
在Autogen和Crewai之后,我们现在有了一个更简单却同样强大的库——smolagents。其主要优点包括:
- 简洁性与灵活性——smolagents保持抽象最少,同时允许您使用来自Hugging Face Hub或外部提供商(如OpenAI和Anthropic)的任何大型语言模型。
- 代码与工具调用代理——它支持生成和执行Python代码的代理(代码代理)以及发出结构化的JSON样式的工具调用的代理(工具调用代理)。这使得轻松集成诸如网络搜索、图像生成或自定义工具等功能变得非常容易。
让我们使用Gemini API安装smolagents、litellm和mcp。
pip install google-generativeai
pip install smolagents[litellm]
pip install "smolagents[mcp]"
现在让我们在主机应用程序中配置我们的MCP服务器。
# Configuration Constants
MCP_SERVERS = {
"pubmed": {
"command": "python",
"args": ["{path_to_PubMed_folder}/PubMed-MCP-Server/pubmed_server.py"],
},
"markdown": {
"command": "python",
"args": ["{path_to_custom_mcp}/mcp_memory.py"],
"host": "127.0.0.1",
"port": 5000,
"timeout": 3000,
"env": {"UV_PYTHON": "3.12", **os.environ},
}
}
现在我们已经准备好编写带有MCP服务器的smolagents了。
class AgentManager:
def __init__(self):
self.model = self._initialize_model()
self.history: List[str] = []
def _initialize_model(self) -> LiteLLMModel:
"""Initialize and return the LiteLLM model instance"""
return LiteLLMModel(
model_id="gemini/gemini-2.5-flash-preview-04-17",
api_key=os.getenv('GEMINI_API'),
)
def _create_server_parameters(self, server_name: str) -> StdioServerParameters:
"""Create MCP server parameters from configuration"""
config = MCP_SERVERS[server_name]
return StdioServerParameters(
command=config["command"],
args=config["args"],
host=config.get("host"),
port=config.get("port"),
timeout=config.get("timeout"),
env=config.get("env"),
)
def _handle_rate_limiting(self, start_time: float, loop_count: int) -> tuple:
"""Manage API rate limiting constraints"""
elapsed = time.time() - start_time
if elapsed > 80:
return time.time(), 0
if loop_count >= 8 and elapsed < 60:
print("Rate limit approached. Taking 20-second break...")
time.sleep(20)
return time.time(), 0
return start_time, loop_count
def run_chat_loop(self):
"""Main execution loop for user interaction"""
start_time = time.time()
loop_count = 0
with (
ToolCollection.from_mcp(
self._create_server_parameters("markdown"),
trust_remote_code=True
) as markdown_tools,
ToolCollection.from_mcp(
self._create_server_parameters("pubmed"),
trust_remote_code=True
) as pubmed_tools
):
# Memory Agent Configuration
memory_agent = CodeAgent(
tools=[*markdown_tools.tools],
model=self.model,
max_steps=5,
name="memory_agent",
description=(
"Memory agent that can create and update memories from markdown files. It can also retrieve memories. It can also create and update to-do lists. \
This agent should be called for any memory related tasks and create memory if any information is important. \
All the memories and todo lists are in markdown format. You should always check if there is any useful memory before planning and taking action. Save useful information in memory."
)
)
# Main Agent Configuration
main_agent = CodeAgent(
tools=[*pubmed_tools.tools],
model=self.model,
managed_agents=[memory_agent],
additional_authorized_imports=["time", "numpy", "pandas", "os"],
description=(
"You are the manager agent that create a plan to finish the task then execute it in order to finish it. \
You should call the memory_agent for any memory related tasks like saving important information or remembering other important memories.\
You should always check if there is any useful memory before planning and taking action. \
Before searching the web with search_agent you should always check what kind of memory titles you have."
)
)
while True:
try:
# User input handling
user_input = input("User: ")
self.history.append(f"User: {user_input}")
# Generate agent response
prompt = "\n".join(self.history[-4:]) + "\nAgent: "
response = main_agent.run(prompt)
# Update conversation history
self.history.append(f"Agent: {response}")
print(Text("\n".join(self.history[-4:]), style="green"))
# Rate limiting management
loop_count += 1
start_time, loop_count = self._handle_rate_limiting(start_time, loop_count)
except KeyboardInterrupt:
print("\nExiting chat session...")
break
if __name__ == "__main__":
manager = AgentManager()
manager.run_chat_loop()
AgentManager 类负责协调两个主要组件:一个记忆代理,用于处理基于 Markdown 的笔记/待办事项列表;以及一个主代理,用于在查阅已存储记忆的同时执行与 PubMed 相关的任务。该系统会保存对话历史记录,使用 Google 的 Gemini AI 模型进行处理,并具有自动速率限制功能,以防止 API 过载。通过交互式聊天循环,用户可以发出命令来触发代理之间的协调操作。
5、示例和结果
我想让我的经纪人帮我写一份中级水平的健身训练计划并保存下来,然后我要求经纪人做一些关于背痛的研究,并根据 PubMed 上的文章创建一个新的训练计划。
Markdown 格式的第一个输出是“Intermediate_Gym_Fitness_Program_-_4_Weeks.md
# Intermediate Gym Fitness Program - 4 Weeks
Intermediate Gym Fitness Program - 4 Weeks
This program is designed for individuals with some experience in weight lifting, using typical gym equipment. It focuses on progressive overload to build strength and muscle.
Structure:
- 4 training days per week.
- Split routine focusing on different muscle groups.
- Aim for progressive overload each week (increase weight, reps, or sets).
- Rest 60-90 seconds between sets.
Week 1-4:
Day 1: Push (Chest, Shoulders, Triceps)
1. Barbell Bench Press: 3 sets of 8-12 reps
2. Incline Dumbbell Press: 3 sets of 10-15 reps
3. Overhead Press (Barbell or Dumbbell): 3 sets of 8-12 reps
4. Lateral Raises (Dumbbell or Cable): 3 sets of 12-15 reps
5. Triceps Pushdowns (Cable): 3 sets of 12-15 reps
6. Overhead Triceps Extension (Dumbbell or Cable): 3 sets of 10-15 reps
Day 2: Pull (Back, Biceps)
1. Pull-ups or Lat Pulldowns: 3 sets of 8-12 reps
2. Barbell Rows: 3 sets of 8-12 reps
3. Seated Cable Rows: 3 sets of 10-15 reps
4. Face Pulls: 3 sets of 15-20 reps
5. Barbell Curls: 3 sets of 10-15 reps
6. Hammer Curls (Dumbbell): 3 sets of 10-15 reps
Day 3: Legs (Quads, Hamstrings, Glutes, Calves)
1. Barbell Squats: 3 sets of 8-12 reps
2. Romanian Deadlifts (Barbell or Dumbbell): 3 sets of 8-12 reps
3. Leg Press: 3 sets of 10-15 reps
4. Hamstring Curls (Machine): 3 sets of 12-15 reps
5. Calf Raises (Machine): 3 sets of 15-20 reps
6. Optional: Lunges (Dumbbell or Barbell) or Leg Extensions: 3 sets of 10-15 reps per leg
Day 4: Full Body or Rest (Optional)
Choose one of the options below or take a rest day.
Option A (Full Body Focus):
1. Deadlifts: 1 set of 5 reps (Warm-up sets as needed) OR 3 sets of 6-8 reps if not done on Day 3
2. Barbell Bench Press: 2 sets of 6-8 reps
3. Barbell Rows: 2 sets of 6-8 reps
4. Overhead Press (Barbell): 2 sets of 6-8 reps
5. Barbell Squats: 2 sets of 6-8 reps
Option B (Rest Day): Focus on recovery, light cardio, or stretching.
Important Considerations:
- Warm-up before each session (5-10 minutes of light cardio and dynamic stretching).
- Cool-down after each session (5-10 minutes of static stretching).
- Listen to your body and adjust weights/reps as needed.
- Focus on proper form over lifting heavy weight.
- Ensure adequate nutrition and sleep for recovery and growth.
Progression (Week 2-4):
- Try to increase the weight lifted for main exercises (Bench Press, Rows, Squats, Deadlifts) each week while maintaining good form.
- If you cannot increase weight, aim for more reps within the target range or add an extra set.
- Keep track of your progress in a notebook or app.
Remember to consult with a healthcare professional or certified personal trainer before starting any new fitness program.
然后我们要求根据 PubMed 上关于下背部疼痛的文章进行修改:
# Intermediate Gym Training Program - Lower Back Pain - Month 1
Intermediate Gym Training Program - Month 1 (Lower Back Pain Adaptation)
Important Considerations for Lower Back Pain:
- ALWAYS prioritize proper form over weight. If an exercise causes pain, stop or modify it.
- Listen to your body. Rest when needed.
- Warm-up properly before each session (5-10 minutes of light cardio and dynamic stretching).
- Cool-down after each session (5-10 minutes of static stretching, especially hamstrings, hip flexors, and glutes).
- Consider consulting a physical therapist for personalized advice.
Structure: 3 Gym Sessions per week (e.g., Monday, Wednesday, Friday) + 1-2 optional light cardio/mobility sessions.
Week 1: Focus on mastering form and activating core muscles. Lighter weights.
Week 2: Gradually increase weight or reps if form is perfect and no pain.
Week 3: Continue progressive overload if comfortable.
Week 4: Slightly reduce intensity (deload week) or maintain if feeling good.
Session 1:
- Warm-up
- Goblet Squat: 3 sets of 10-15 reps (Focus on keeping chest up, back straight, and core engaged. May need to use a bench to squat onto initially).
- Glute Bridges: 3 sets of 15-20 reps (Focus on squeezing glutes at the top, maintain a neutral spine).
- Bird-Dog: 3 sets of 10-15 reps per side (Slow and controlled movement, keep core stable).
- Modified Plank (on knees if needed): 3 sets, hold for 30-60 seconds (Maintain straight line from head to knees/feet, don't let hips sag).
- Dumbbell Rows (supported by bench or machine to avoid back strain): 3 sets of 10-12 reps per arm (Focus on squeezing shoulder blade, avoid twisting torso).
- Cool-down
Session 2:
- Warm-up
- Romanian Deadlifts with Dumbbells (focus on hip hinge, slight bend in knees, stop when you feel stretch in hamstrings, do not round back): 3 sets of 10-12 reps.
- Push-ups (on knees if needed, or against a wall): 3 sets of max reps (Keep core engaged, maintain straight line).
- Side Plank (on knees if needed): 3 sets, hold for 30-60 seconds per side.
- Dead Bug: 3 sets of 10-15 reps per side (Keep lower back pressed into the floor, controlled movement).
- Lat Pulldowns (seated, maintain upright posture, avoid arching back): 3 sets of 10-12 reps.
- Cool-down
Session 3:
- Warm-up
- Lunges (forward or reverse, focus on controlled movement, torso upright): 3 sets of 10-12 reps per leg.
- Overhead Press with Dumbbells (seated to reduce back strain): 3 sets of 10-12 reps.
- Russian Twists (feet on floor initially, controlled movement): 3 sets of 15-20 reps per side.
- Cat-Cow Stretch: 3 sets of 10 reps (Gentle movement to improve spinal mobility).
- Bodyweight Squats: 3 sets of 15-20 reps (Focus on form).
- Cool-down
Optional Sessions (1-2 times per week):
- Light cardio (walking, elliptical) for 20-30 minutes.
- Mobility work (gentle stretching for hips, hamstrings, quads, thoracic spine).
- Pilates or Yoga for core strength and flexibility (check for back-friendly classes).
Progression:
- Increase reps before increasing weight.
- Increase weight gradually (smallest increments possible).
- If an exercise becomes easy and pain-free, you can research slightly more challenging variations, but always prioritize safety for your back.
Note: This is a general program. If your pain persists or worsens, consult a healthcare professional or physical therapist.
我们请代理进行更专业水平的练习,并在 PubMed 中查找文章,然后在降价结束时保存几篇文章。
# Professional Level Lower Back Fitness Program
# Professional Level Lower Back Fitness Program
This program is designed for professional athletes with a solid foundation of strength and conditioning, aiming to enhance lower back strength, stability, power, and resilience to support high-level performance and injury prevention. It assumes no current severe lower back pain, but emphasizes listening to the body and proper form.
**Key Principles:**
* **Progressive Overload:** Gradually increase weight, reps, sets, or decrease rest times.
* **Proper Form:** Always prioritize technique over weight.
* **Listen to Your Body:** Rest or modify exercises if pain occurs.
* **Integration:** This program should complement a comprehensive strength and conditioning program.
* **Warm-up:** Always start with a dynamic warm-up.
* **Cool-down:** Finish with static stretching, focusing on hips, glutes, and hamstrings.
**Program Structure (3 Sessions Per Week):**
**Session 1: Strength & Stability Focus**
* **Warm-up:** 5-10 minutes dynamic movements (cat-cow, bird-dog, glute bridges, leg swings).
* **Exercises:**
* **Heavy Barbell Deadlifts:** 3 sets of 3-5 reps (focus on perfect form, bracing core).
* **Back Squats:** 3 sets of 5-8 reps (maintaining a neutral spine).
* **Romanian Deadlifts (RDLs):** 3 sets of 8-10 reps (emphasize hamstring stretch and controlled movement).
* **Good Mornings:** 3 sets of 8-10 reps (lighter weight, focus on hinge pattern and lower back eccentric strength).
* **Cable Wood Chops:** 3 sets of 10-12 reps per side (focus on rotational strength and core stability).
* **Pallof Press:** 3 sets of 10-15 reps per side (anti-rotation exercise).
* **Bird-Dog with added resistance (ankle/wrist weights or band):** 3 sets of 10-12 reps per side.
* **Side Plank with Hip Abduction:** 3 sets of 10-15 reps per side.
* **Cool-down:** Static stretching.
**Session 2: Power & Dynamic Stability Focus**
* **Warm-up:** 5-10 minutes dynamic movements and light plyometrics (pogo hops, squat jumps).
* **Exercises:**
* **Power Cleans or Hang Cleans:** 3 sets of 3-5 reps (explosive movement, requires proper coaching).
* **Kettlebell Swings:** 4 sets of 10-15 reps (focus on powerful hip hinge).
* **Medicine Ball Slams:** 3 sets of 8-10 reps.
* **Rotational Medicine Ball Throws against a wall:** 3 sets of 10-12 reps per side.
* **Single Leg RDLs:** 3 sets of 8-10 reps per leg (improves balance and single-leg strength).
* **Box Jumps (appropriate height):** 3 sets of 5-8 reps (focus on controlled landing).
* **Ab Wheel Rollouts (from knees or toes):** 3 sets of max reps with good form.
* **Russian Twists with weight (medicine ball or plate):** 3 sets of 15-20 reps per side.
* **Cool-down:** Static stretching.
**Session 3: Endurance & Core Strength Focus**
* **Warm-up:** 5-10 minutes dynamic movements.
* **Exercises:**
* **Hyperextensions (Back Extensions):** 3 sets of 15-20 reps (controlled movement). Can add weight if needed.
* **Glute Bridges or Hip Thrusts:** 3 sets of 15-20 reps (can add weight - barbell or band).
* **Plank Variations (e.g., forearm plank, high plank, plank jacks):** 3 sets, hold for 60+ seconds or perform reps with control.
* **Dead Bug:** 3 sets of 15-20 reps per side (focus on controlled movement and core engagement).
* **Bird-Dog:** 3 sets of 15-20 reps per side (focus on stability).
* **Side Plank:** 3 sets, hold for 60+ seconds per side.
* **Lying Leg Raises:** 3 sets of 15-20 reps (focus on lower abs).
* **Cable Face Pulls:** 3 sets of 15-20 reps (helps with upper back posture which affects lower back).
* **Cool-down:** Static stretching.
**Important Considerations for Professional Athletes:**
* **Periodization:** This program is a template. It should be integrated into a periodized training plan that varies intensity and volume based on the competitive season.
* **Sport-Specific Demands:** Exercises should be chosen or modified to mimic the movements and demands of the athlete's specific sport.
* **Recovery:** Adequate rest, nutrition, and sleep are crucial for recovery and adaptation.
* **Monitoring:** Athletes and coaches should monitor for signs of overtraining or injury.
* **Professional Guidance:** This program should be implemented under the supervision of a qualified strength and conditioning coach or sports medicine professional.
**Cited Articles:**
1. Lee, J., Kim, J., Lee, S., & Ha, S. (2024). Latent profile analysis of spinal deep muscle strength and physical fitness in elite Taekwondo athletes. *BMC sports science, medicine & rehabilitation*.
2. Ma, Z., Geok Soh, K., Binti Japar, F., Xu, W., & Zhicheng, P. (2024). Maximizing the performance of badminton athletes through core strength training: Unlocking their full potential using machine learning (ML) modeling. *Heliyon*.
3. Si, X., Zhang, Y., Li, L., & Liang, J. (2025). The effectiveness of pelvic floor muscle training on lumbar function and muscle performance in sedentary women with lower back pain: a randomized controlled trial. *BMC women's health*.
这很好,现在我们可以查看 PubMed 并编写 markdown 文件,现在让我们问一下代理在内存中有什么。
内存检索也运行良好。现在,如果我们想进一步改进,还可以更改 CodeAgent 中的 prompt_templates。
原文链接:Building a Multi-Agent System with Multiple MCP Servers using Smolagents
汇智网翻译整理,转载请标明出处