内容
# MCP Server 实现
一个基于 Flask 的 Model Context Protocol (MCP) 完整实现,用于增强大型语言模型(LLM)通过外部工具的能力。
## 概述
该仓库演示了如何构建一个处理 Model Context Protocol (MCP) 的服务器,这是一种通过直接在模型的文本输出中调用工具来扩展 LLM 能力的方法。与函数调用不同,MCP 将工具定义直接放置在上下文窗口中,并解析模型的自然语言响应以识别工具的使用。
## 特性
- 🔧 **完整的 MCP 实现**:全面的解析、执行和响应处理
- 🌤️ **示例工具**:带有参数验证的天气和计算器工具
- 🔄 **对话流程**:在多次交互中保持上下文
- 🧩 **基于正则表达式的解析**:灵活的文本解析以调用工具
- 🚀 **Flask API**:用于聊天集成的 REST API 端点
## 项目结构
```
mcp_server/
├── app.py # 主 Flask 应用
├── mcp_handler.py # MCP 解析和执行
├── mcp_example.py # 独立的 MCP 示例
├── requirements.txt # 依赖项
├── tools/ # 工具实现
│ ├── __init__.py
│ ├── weather.py # 天气 API 工具
│ └── calculator.py # 计算器工具
└── README.md # 本文件
```
## 安装
1. 克隆仓库:
```bash
git clone https://github.com/yourusername/mcp-server.git
cd mcp-server
```
2. 创建虚拟环境:
```bash
python -m venv venv
source venv/bin/activate # 在 Windows 上: venv\Scripts\activate
```
3. 安装依赖项:
```bash
pip install -r requirements.txt
```
4. 设置环境变量:
```bash
# 创建一个 .env 文件,内容为:
LLM_API_KEY=your_llm_api_key_here
WEATHER_API_KEY=your_weather_api_key_here
FLASK_APP=app.py
FLASK_ENV=development
```
## 使用
### 运行服务器
启动 Flask 开发服务器:
```bash
flask run
```
用于生产环境:
```bash
gunicorn app:app
```
### API 端点
- **POST /chat**:处理带有 MCP 的聊天消息
```bash
curl -X POST http://localhost:5000/chat \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "user",
"content": "波士顿的天气怎么样?"
}
]
}'
```
### 独立示例
运行示例脚本以查看 MCP 的实际应用:
```bash
python mcp_example.py
```
## 工作原理
1. **工具注册**:工具通过其参数和执行逻辑进行注册
2. **工具定义注入**:以 XML 格式的工具描述被添加到提示中
3. **LLM 响应处理**:正则表达式模式识别 LLM 文本输出中的工具调用
4. **工具执行**:解析参数并传递给相应的工具处理程序
5. **结果注入**:工具执行结果被插入回响应中
## MCP 与函数调用的比较
| 特性 | MCP | 函数调用 |
|---------|-----|-----------------|
| 定义位置 | 在提示文本中 | 在 API 参数中 |
| 调用格式 | 自然语言 | 结构化 JSON |
| 实现方式 | 文本解析 | API 集成 |
| 可见性 | 在响应中可见 | 可能被隐藏 |
| 平台支持 | 任何基于文本的 LLM | 需要 API 支持 |
## 示例对话
**用户**:波士顿的天气怎么样?
**LLM**:
```
我来查一下天气。
get_weather(location="Boston, MA", unit="fahrenheit")
```
**处理后**:
```
我来查一下天气。
get_weather(location="Boston, MA", unit="fahrenheit")
来自 get_weather 的结果:
{
"location": "Boston, MA",
"temperature": 72,
"unit": "fahrenheit",
"conditions": "局部多云",
"humidity": 68,
"wind_speed": 5.8
}
```
## 添加您自己的工具
1. 创建一个继承自 `Tool` 的新类
2. 定义参数和执行逻辑
3. 在 MCP 处理程序中注册
示例:
```python
class MyTool(Tool):
def __init__(self):
parameters = [
{
"name": "param1",
"type": "string",
"description": "param1 的描述",
"required": True
}
]
super().__init__(
name="my_tool",
description="我的工具的描述",
parameters=parameters
)
def execute(self, param1):
# 工具逻辑在这里
return {"result": "处理了 " + param1}
```
## MCP 配置和调用流程
1. **工具注册**:
- MCP 工具在处理程序中注册
- 每个工具提供其名称、描述和参数定义
2. **工具定义注入**:
- 工具定义被添加到系统消息中
- 格式遵循 MCP 的 XML 结构
3. **LLM 响应处理**:
- LLM 生成的响应可能包含工具调用
- 模式匹配识别文本中的工具调用
- 工具参数被解析并传递给工具执行方法
4. **工具执行**:
- 使用提供的参数执行工具
- 结果被注入回对话中
5. **对话管理**:
- 带有工具结果的处理响应被添加到对话历史中
- 未来的 LLM 请求包括此历史以提供上下文
## 示例对话
以下是对话的示例:
**用户**:波士顿的天气怎么样?
**系统**:*向 LLM 发送带有 MCP 工具定义的提示*
**LLM 响应**:
```
我来查一下天气。
get_weather(location="Boston, MA", unit="fahrenheit")
```
**MCP 处理程序**:*解析响应,找到工具调用,并执行天气工具*
**工具执行结果**:
```
来自 get_weather 的结果:
{
"location": "Boston, MA",
"temperature": 72,
"unit": "fahrenheit",
"conditions": "局部多云",
"humidity": 68,
"wind_speed": 5.8
}
```
**处理后的响应**(发送回用户):
```
我来查一下天气。
get_weather(location="Boston, MA", unit="fahrenheit")
来自 get_weather 的结果:
{
"location": "Boston, MA",
"temperature": 72,
"unit": "fahrenheit",
"conditions": "局部多云",
"humidity": 68,
"wind_speed": 5.8
}
```
**用户**:你能计算 144 的平方根吗?
**LLM 响应**:
```
我可以为你计算。
calculator(expression="sqrt(144)")
```
**MCP 处理程序**:*解析响应,执行计算器工具*
**工具执行结果**:
```
来自 calculator 的结果:
{
"expression": "sqrt(144)",
"result": 12.0
}
```
**处理后的响应**(发送回用户):
```
我可以为你计算。
calculator(expression="sqrt(144)")
来自 calculator 的结果:
{
"expression": "sqrt(144)",
"result": 12.0
}
144 的平方根是 12。
```
这展示了 MCP 工具使用的完整流程,从 LLM 的基于文本的调用到执行和响应处理。
## 许可证
MIT
## 贡献
欢迎贡献!请随时提交 Pull Request。