MCP和Function Calling:基础知识与实践

在人工智能领域,MCP(Managed Context Protocol)和Function Calling是两个重要的概念,它们在AI应用中发挥着不同的作用。下面我们将以简单易懂的方式介绍它们的基础知识,并提供实例和代码示例,以帮助读者更好地理解。

1. 目的和范围

  • MCP:MCP是一个通用协议标准,类似于USB-C接口,允许AI模型与不同平台、不同数据源之间进行标准化的通信。这使得AI系统更加开放和互操作
  • Function Calling:Function Calling是特定模型或平台的功能扩展,允许LLM调用预定义函数以执行特定操作。它通常局限于特定的模型或平台

2. 执行方式

  • MCP:MCP协议是异步的,发送请求后程序不会等待结果,而是继续执行其他代码,等结果出来再处理。这适合处理时间较长的任务
  • Function Calling:Function Calling是同步的,调用函数后程序会一直等待函数执行完并返回结果,才继续执行后续代码。这适合需要立即得到结果的场景

3. 应用场景

  • MCP:适合处理复杂、多步骤的任务,如网络请求、文件读写等。例如,使用MCP可以让AI模型与数据库进行交互,获取数据并处理
  • Function Calling:适合需要立即得到结果,并且后续代码依赖这个结果的场景。例如,查询天气信息或执行简单的数学计算

4. 灵活性和开放性

  • MCP:更开放和灵活,可用于各种服务和AI Agent的集成。这意味着开发者可以轻松地将不同的服务接入到AI系统中
  • Function Calling:相对受限,取决于平台提供的功能定义。这意味着开发者需要依赖特定平台的API和功能

代码示例

Function Calling示例(Python)

python 复制代码
def get_weather(location):
    # 查询天气信息的函数
    return f"{location} 的天气是晴天"

# 调用函数
weather = get_weather("北京")
print(weather)

MCP协议示例(Python)

python 复制代码
import json
import requests

def fetch_data(url):
    # 使用MCP协议发送请求获取数据
    headers = {"Content-Type": "application/json"}
    payload = {"url": url}
    response = requests.post("http://mcp-server.com/fetch", headers=headers, data=json.dumps(payload))
    return response.json()

# 获取数据
data = fetch_data("https://example.com")
print(data)

总结

  • MCP:是一个通用标准协议,旨在构建开放的AI生态系统,适合处理复杂任务。
  • Function Calling:是特定模型的功能扩展,适用于特定的应用场景,需要立即得到结果。

要基于 OpenAI 使用 Model Context Protocol (MCP),你需要了解 MCP 的基本架构和功能。MCP 是一种标准化协议,允许 AI 模型与外部工具和数据源进行交互,而无需为每个工具编写自定义代码。以下是一个使用 MCP 的基本示例,展示如何连接到一个 MCP 服务器并调用工具。

MCP 基本概念

  • MCP 主机:请求数据或操作的 AI 模型(例如 Azure OpenAI GPT)。
  • MCP 客户端:AI 模型内部的组件,负责与 MCP 服务器通信。
  • MCP 服务器:连接 AI 模型与外部系统(如数据库或 API)的中间件。

示例代码

这个示例使用 Python 和 MCP 库来连接到一个 MCP 服务器,并调用一个名为 get_forecast 的工具。我们假设你已经安装了必要的库,并且有一个 MCP 服务器脚本(例如 server.py)。

依赖库

你需要安装以下库:

bash 复制代码
pip install mcp openai

MCP 客户端代码

python 复制代码
import asyncio
import os
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from openai import OpenAI

# 加载环境变量
load_dotenv()

class MCPClient:
    def __init__(self):
        self.openai_api_key = os.getenv("OPENAI_API_KEY")
        self.base_url = os.getenv("BASE_URL")
        self.model = os.getenv("MODEL")
        
        if not self.openai_api_key:
            raise ValueError("未找到 OpenAI API Key")
        
        self.client = OpenAI(api_key=self.openai_api_key, base_url=self.base_url)
        self.session = None

    async def connect_to_server(self, server_script_path: str):
        is_python = server_script_path.endswith('.py')
        is_js = server_script_path.endswith('.js')
        
        if not (is_python or is_js):
            raise ValueError("服务器脚本必须是 .py 或 .js 文件")
        
        command = "python" if is_python else "node"
        server_params = StdioServerParameters(command=command, args=[server_script_path], env=None)
        
        stdio_transport = await asyncio.create_task(stdio_client(server_params))
        self.stdio, self.write = stdio_transport
        self.session = await ClientSession(self.stdio, self.write).initialize()

        # 列出 MCP 服务器上的工具
        response = await self.session.list_tools()
        tools = response.tools
        print("\n已连接到服务器,支持以下工具:", [tool.name for tool in tools])

    async def process_query(self, query: str) -> str:
        messages = [{"role": "user", "content": query}]
        
        # 获取可用的工具
        response = await self.session.list_tools()
        available_tools = [{"type": "function", "function": {"name": tool.name, "description": tool.description, "input_schema": tool.inputSchema}} for tool in response.tools]
        
        # 调用 OpenAI API 并传递工具信息
        response = self.client.chat.completions.create(model=self.model, messages=messages, tools=available_tools)
        
        # 处理工具调用
        if response.choices[0].finish_reason == "tool_calls":
            tool_call = response.choices[0].message.tool_calls
            tool_name = tool_call.function.name
            tool_args = json.loads(tool_call.function.arguments)
            
            # 执行工具调用
            result = await self.session.call_tool(tool_name, tool_args)
            print(f"\n\n[Calling tool {tool_name} with args {tool_args}]\n\n")
            
            # 将结果返回给用户
            return result.content.text
        
        return response.choices[0].message.content

    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)
                print(f"\n🤖 OpenAI: {response}")
            except Exception as e:
                print(f"\n⚠️ 发生错误: {str(e)}")

async def main():
    if len(sys.argv) < 2:
        print("Usage: python client.py <path_to_server_script>")
        sys.exit(1)
    
    client = MCPClient()
    try:
        await client.connect_to_server(sys.argv[1])
        await client.chat_loop()
    except Exception as e:
        print(f"\n⚠️ 发生错误: {str(e)}")

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

运行示例

  1. 启动 MCP 服务器 :确保你有一个 MCP 服务器脚本(例如 server.py),并且它已经配置好工具(如 get_forecast)。

  2. 运行客户端脚本:使用以下命令运行客户端脚本,传入服务器脚本路径作为参数。

    bash 复制代码
    python client.py server.py
  3. 与 AI 交互 :在客户端终端中输入查询,例如"北京今天天气如何?",如果配置了相应的工具(如 get_forecast),MCP 将自动调用该工具并返回结果。

注意事项

  • 确保 .env 文件中正确配置了 OpenAI API Key 和 Base URL。
  • MCP 服务器脚本需要正确配置并运行,以提供工具访问功能。
  • 本示例使用了简化的错误处理和日志记录,实际应用中应添加更全面的异常处理和日志记录。
相关推荐
Fanxt_Ja22 分钟前
【LeetCode】算法详解#2 ---和为k的子数组
java·数据结构·算法·leetcode·idea·哈希表
熊峰峰28 分钟前
1.3 斐波那契数列模型:LeetCode 746. 使用最小花费爬楼梯
算法·leetcode·动态规划
SuperYing37 分钟前
前端候选人突围指南:让面试官主动追着要简历的五大特质(个人总结版)
前端·面试
藍海琴泉43 分钟前
贪心算法经典应用:最优答疑调度策略详解与Python实现
算法·贪心算法
脏脏a1 小时前
C语言函数递归
c语言·算法
百渡ovO1 小时前
【蓝桥杯】每日练习 Day 16,17
c++·算法·图论
梁下轻语的秋缘1 小时前
每日c/c++题 备战蓝桥杯(二分答案模版)
c语言·c++·学习·算法·蓝桥杯
Moment1 小时前
前端性能指标 —— CLS
前端·javascript·面试
溟洵1 小时前
【C/C++算法】从浅到深学习---分治算法之快排思想(图文兼备 + 源码详解)
c语言·c++·算法
修修修也1 小时前
【算法手记7】拼三角
数据结构·学习·算法·刷题