Python----MCP(MCP 简介、uv工具、创建MCP流程、MCP客户端接入Qwen、MCP客户端接入vLLM)

一、MCP 简介

Model Context Protocol (MCP)是一个开放协议,它为应用程序向 LLM 提供上下文的方式进行了标准化。你可以将 MCP 想象成 AI 应用程序的 USB-C 接口。就像 USB-C 为设备连接各种外设和配件提供了标准化的方式一样,MCP 为 AI 模型连接各种数据源和工具提供了标准化的接口。

MCP 帮助你在 LLM 的基础上构建代理(agents)和复杂的工作流。LLM 经常需要与数据和工具集成,而 MCP 提供了:

  • 持续增长的预构建集成列表,LLM 可直接使用

  • 灵活切换不同的 LLM 提供商和厂商

  • 在你的基础设施内安全地处理数据的最佳实践

MCP解决的最大痛点,就是Agent开发中调用外部工具的技术门槛过高的问题。

  • MCP Hosts: 如 Claude Desktop、IDE 或 AI 工具,希望通过 MCP 访问数据的程序
  • MCP Clients: 维护与服务器一对一连接的协议客户端
  • MCP Servers: 轻量级程序,通过标准的 Model Context Protocol 提供特定能力
  • 本地数据源: MCP 服务器可安全访问的计算机文件、数据库和服务
  • 远程服务: MCP 服务器可连接的互联网上的外部系统(如通过 APIs)

二、uv工具

MCP开发要求借助uv进行虚拟环境创建和依赖管理。uv 是一个Python 依赖管理工具,类似于 pipconda,但它更快、更高效,并且可以更好地管理 Python 虚拟环境和依赖项。它的核心目标是替代 pipvenvpip-tools,提供更好的性能和更低的管理开销。

uv 的特点:

  1. 速度更快:相比 pip,uv 采用 Rust 编写,性能更优。

  2. 支持 PEP 582:无需 virtualenv,可以直接使用 pypackages 进行管理。

  3. 兼容 pip:支持 requirements.txt 和 pyproject.toml 依赖管理。

  4. 替代 venv:提供 uv venv 进行虚拟环境管理,比 venv 更轻量。

  5. 跨平台:支持 Windows、macOS 和 Linux。

三、创建MCP流程

3.1、安装uv

python 复制代码
pip install uv

3.2、安装mcp

python 复制代码
pip install mcp

3.3、为项目创建一个新目录(以weather为例)

python 复制代码
uv init weather
python 复制代码
cd weather

3.4、创建虚拟环境并激活

python 复制代码
uv venv
python 复制代码
source .venv/bin/activate

3.5、安装依赖项

python 复制代码
uv add "mcp[cli]" httpx

3.6、创建服务器文件

python 复制代码
touch weather.py

3.7、编写基础 MCP 客户端

创建 client.py

python 复制代码
import asyncio  # Python 内置的异步编程库,让 MCP 可以非阻塞地执行任务
from mcp import ClientSession  # 管理 MCP 客户端会话
from contextlib import AsyncExitStack  # 自动管理资源,确保程序退出时正确关闭 MCP 连接


class MCPClient:
    def __init__(self):
        """初始化 MCP 客户端"""
        self.session = None # 暂时不连接 MCP 服务器,后续可以修改来真正连接。
        self.exit_stack = AsyncExitStack() #管理 MCP 客户端的资源,确保程序退出时可以正确释放资源。
# - 这个函数不会真的连接 MCP 服务器,只是打印一条信息,表示客户端已经初始化。
    async def connect_to_mock_server(self):
        """模拟 MCP 服务器的连接(暂不连接真实服务器)"""
        print("✅ MCP 客户端已初始化,但未连接到服务器")
# 交互式聊天循环
    async def chat_loop(self):
        """运行交互式聊天循环"""
        print("\nMCP 客户端已启动!输入 'quit' 退出")

        while True:
            try:
                query = input("\nQuery: ").strip()
                if query.lower() == 'quit':
                    break
                print(f"\n🤖 [Mock Response] 你说的是:{query}")
            except Exception as e:
                print(f"\n⚠️ 发生错误: {str(e)}")

    async def cleanup(self):
        """清理资源"""
        await self.exit_stack.aclose()# 确保程序退出时正确关闭 MCP 连接

async def main():
    client = MCPClient()# 创建一个 MCP 客户端实例
    try:
        await client.connect_to_mock_server()#初始化 MCP 客户端(暂不连接服务器)
        await client.chat_loop()#启动交互式聊天。
    finally:
        await client.cleanup()

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

这段代码能够初始化 MCP 客户端(但不连接服务器),并提供一个 交互式 CLI ,可以输入查询(但只返回模拟回复),通过输入 quit 退出程序。需要注意的是,此时客户端没有关联任何大模型,因此只会重复用户的输入。

四、MCP客户端接入Qwen

创建.env文件

python 复制代码
BASE_URL=https://api.siliconflow.cn/v1
MODEL=Qwen/Qwen3-8B  
OPENAI_API_KEY="sk-kjutyipwobagmkhdzgxszqusfueaquhhrzvyuasyedwqfzkbrrv"
#替换成自己的api密钥,使用的是硅基流动

客户端代码

python 复制代码
import asyncio
import os
from openai import OpenAI
from dotenv import load_dotenv
from contextlib import AsyncExitStack

# 加载 .env 文件,确保 API Key 受到保护
load_dotenv()

class MCPClient:
    def __init__(self):
        
        """初始化 MCP 客户端"""
        self.exit_stack = AsyncExitStack()
        self.openai_api_key = os.getenv("OPENAI_API_KEY")  # 读取 OpenAI API Key
        self.base_url = os.getenv("BASE_URL")  # 读取 BASE YRL
        self.model = os.getenv("MODEL")  # 读取 model
        
        if not self.openai_api_key:
            raise ValueError("❌ 未找到 OpenAI API Key,请在 .env 文件中设置 OPENAI_API_KEY")
            
        self.client = OpenAI(api_key=self.openai_api_key, base_url=self.base_url) 
        

    async def process_query(self, query: str) -> str:
        """调用 OpenAI API 处理用户查询"""
        messages = [{"role": "system", "content": "你是一个智能助手,帮助用户回答问题。"},
                    {"role": "user", "content": query}]
        
        try:
            # 调用 OpenAI API
            response = await asyncio.get_event_loop().run_in_executor(
                None,
                lambda: self.client.chat.completions.create(
                    model=self.model,
                    messages=messages
                )
            )
            return response.choices[0].message.content
        except Exception as e:
            return f"⚠️ 调用 OpenAI API 时出错: {str(e)}"

    async def chat_loop(self):
        """运行交互式聊天循环"""
        print("\n🤖 MCP 客户端已启动!输入 'quit' 退出")

        while True:
            try:
                query = input("\n你: ").strip()
                if query.lower() == 'quit':
                    break
                
                response = await self.process_query(query)  # 发送用户输入到 OpenAI API
                print(f"\n🤖 OpenAI: {response}")

            except Exception as e:
                print(f"\n⚠️ 发生错误: {str(e)}")

    async def cleanup(self):
        """清理资源"""
        await self.exit_stack.aclose()

async def main():
    client = MCPClient()
    try:
        await client.chat_loop()
    finally:
        await client.cleanup()

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

五、MCP客户端接入vLLM

启动vllm

python 复制代码
python -m vllm.entrypoints.openai.api_server --port 10222 --model /home/AI_big_model/models/Qwen/Qwen2.5-7B-Instruct --served-model-name Qwen2.5-7B-Instruct

.env

python 复制代码
BASE_URL=http://127.0.0.1:10222/v1
MODEL=Qwen2.5-7B-Instruct
API_KEY=EMPTY

客户端不变

python 复制代码
import asyncio
import os
from openai import OpenAI
from dotenv import load_dotenv
from contextlib import AsyncExitStack

# 加载 .env 文件,确保 API Key 受到保护
load_dotenv()

class MCPClient:
    def __init__(self):
        
        """初始化 MCP 客户端"""
        self.exit_stack = AsyncExitStack()
        self.api_key = os.getenv("API_KEY")  # 读取 API Key
        self.base_url = os.getenv("BASE_URL")  # 读取 BASE YRL
        self.model = os.getenv("MODEL")  # 读取 model
        
        if not self.api_key:
            raise ValueError("❌ 未找到 API Key,请在 .env 文件中设置 api_key")
            
        self.client = OpenAI(api_key=self.api_key, base_url=self.base_url) 
        

    async def process_query(self, query: str) -> str:
        """调用 OpenAI API 处理用户查询"""
        messages = [{"role": "system", "content": "你是一个智能助手,帮助用户回答问题。"},
                    {"role": "user", "content": query}]
        
        try:
            # 调用 OpenAI API
            response = await asyncio.get_event_loop().run_in_executor(
                None,
                lambda: self.client.chat.completions.create(
                    model=self.model,
                    messages=messages
                )
            )
            return response.choices[0].message.content
        except Exception as e:
            return f"⚠️ 调用 OpenAI API 时出错: {str(e)}"

    async def chat_loop(self):
        """运行交互式聊天循环"""
        print("\n🤖 MCP 客户端已启动!输入 'quit' 退出")

        while True:
            try:
                query = input("\n你: ").strip()
                if query.lower() == 'quit':
                    break
                
                response = await self.process_query(query)  # 发送用户输入到 OpenAI API
                print(f"\n🤖 OpenAI: {response}")

            except Exception as e:
                print(f"\n⚠️ 发生错误: {str(e)}")

    async def cleanup(self):
        """清理资源"""
        await self.exit_stack.aclose()

async def main():
    client = MCPClient()
    try:
        await client.chat_loop()
    finally:
        await client.cleanup()

if __name__ == "__main__":
    asyncio.run(main())
相关推荐
Blossom.1186 分钟前
移动端部署噩梦终结者:动态稀疏视觉Transformer的量化实战
java·人工智能·python·深度学习·算法·机器学习·transformer
FPGA小迷弟8 分钟前
ChatGPT回答用AI怎么怎么赚钱
大数据·人工智能
轻微的风格艾丝凡9 分钟前
卷积的直观理解
人工智能·深度学习·神经网络·算法·计算机视觉·matlab·cnn
AiXed36 分钟前
PC微信协议之AES-192-GCM算法
前端·数据库·python
月下倩影时37 分钟前
视觉进阶篇——机器学习训练过程(手写数字识别,量大管饱需要耐心)
人工智能·学习·机器学习
PixelMind39 分钟前
【超分辨率专题】HYPIR:扩散模型先验与 GAN 对抗训练相结合的新型图像复原框架
人工智能·生成对抗网络·扩散模型·图像复原
灵光通码1 小时前
神经网络基本概念
python·神经网络
说私域1 小时前
从裂变能力竞争到技术水平竞争:开源AI智能名片链动2+1模式S2B2C商城小程序对微商企业竞争格局的重塑
人工智能·小程序·开源
xybDIY1 小时前
基于 Tuya.AI 开源的大模型构建智能聊天机器人
人工智能·机器人·开源
武子康3 小时前
Java-171 Neo4j 备份与恢复 + 预热与执行计划实战
java·开发语言·数据库·性能优化·系统架构·nosql·neo4j