Model Context Protocol(MCP)模型上下文协议

Source


前言

在Agent时代,将Agent确立为大模型未来发展的核心方向时,Function Calling技术尤为关键。这项技术通过工具赋能大模型,使其能够突破固有能力的限制。具体而言,大模型可借此实现实时信息查询、检索网络信息或调用企业内部API等功能。

一、什么是MCP

MCP(Model Context Protocol,模型上下文协议)是 Anthropic 于 2024 年 11 月 25 日提出并开源的一项新标准协议,专为LLM设计的开放、标准化通信协议,标准化了应用程序向 LLM 提供上下文的方式,旨在实现LLM与外部数据源、工具之间的高效交互,核心目标是解决传统集成中的“MxN”问题(即M个模型与N个工具之间的复杂集成)

在这里插入图片描述

MCP核心组件如下:

  • Host:宿主程序,即当前使用的大模型的载体应用,比如 Claude Desktop、Cursor、CherryStudio等。
  • Client:MCP 客户端,即负责与 MCP Server 进行通信的组件,内置在 Host 中,比如 CherryStudio 就已经内置了,直接录入 MCP Server 后即可实现调用。
  • Server:MCP 服务器,即实际提供外部数据和外部能力的组件,一般在 Host 外部,可以是本地文件的封装,也可以是远程 REST 接口的封装。
  • Local Data Source:您的计算机文件、数据库和服务,MCP 服务器可以安全访问,这里可以实现通用的认证,不用单独为每个API进行权限控制。
  • Remote Service:MCP 服务器可以连接的互联网外部系统,或者说其他服务商提供的MCP,如高德地图、搜索引擎等。

官网:https://modelcontextprotocol.io/introduction

二、MCP的作用

为什么有了Function Calling还会出现MCP呢?

首先我认识MCP出现是必然的。MCP是提出一种标准,是大模型与工具(服务/API)之间通信所遵循的标准,可以对大模型和工具进行解偶,可以让不管是用户还是大模型厂商还是服务提供商更加专注于本身的功能创新,摆脱适配的问题。

如ChatGPT的GPTPlugins不能直接在Claude中使用。

对于大模型应用开发人员,常会在大模型中集成了某个外部能力,比如Gitee代码仓库操作,但大模型A中集成的代码在大模型B中可能不能直接使用,这会造成整体工作的大量重复和浪费,也就是上文提到的“MxN”的问题。所以,MCP的出现就是解决了这个问题。

三、MCP与Function call对比

首先他俩的最终目标是一致的,都是为了给大模型赋能,让大模型应用更好的落地。

Function call是一种给大模型赋能的方法,实现了大模型可以调用外部工具。

MCP给大模型提供了一个“万能工具箱”,不管使用的是什么模型,都可以随意调用你所需要的工具,工具可能来自不同的厂商,但是都没有任何问题。

举个例子:

想象一下你(用户)正在和一个非常聪明的助手(LLM)交流,你想让他帮你出一份旅游攻略

无MCP情况下,你可能需要写很多代码,先分别从天气API、车票API、地图API获取数据,然后把这些杂乱的信息(可能格式各不相同)一股脑儿地塞给助手,助手需要费力地去理解这些不同来源、不同格式的数据。如果换一个助手模型,或者增加一个新的数据源(比如美团API),你可能又要重写很多集成代码。

有MCP情况下,每个厂商按照MCP标准把数据整成标准格式,这些API把这些已经符合 MCP 标准的、结构化的数据一起提供给助手(LLM)。助手接收到这些信息时,因为它们都遵循同一个标准协议 (MCP),所以它能更容易、更高效地理解这些数据,它们的结构都是我认识的标准样子。然后助手基于这些结构化、标准化的上下文信息,更容易地为你撰写销售策略报告。

总的来说:

  • Function Calling: 是 LLM“向外看”,主动请求执行一个具体任务的方式。好比打电话
  • MCP: 是“向内看”,规范外部世界如何提供信息给 LLM 的标准方式。好比一个标准化的信息收件箱和阅读格式

四、构建一个简单的MCP DEMO

官方提供的SDK有以下几种,这里我使用的 Python SDK

在这里插入图片描述

环境准备

这里我使用的conda管理虚拟环境

conda env list
# conda environments:
#
base                     /Users/lpp/workspace/software/miniconda3
common                   /Users/lpp/workspace/software/miniconda3/envs/common
llmenv                *  /Users/lpp/workspace/software/miniconda3/envs/llmenv

conda create -n mcpenv python=3.12 # conda创建虚拟环境

conda activate mcpenv # 激活虚拟环境

python -V # 查看py版本
Python 3.12.9

pip install "mcp[cli]" # 安装SDK

mcp version # 验证
MCP version 1.6.0

实现MCP Server

一个最简单的demo,用于获取本机文件列表。

import os
from mcp.server.fastmcp import FastMCP

mcp = FastMCP()  # 初始化 MCP 服务实例

# 定义getfile函数,返回指定路径下的文件
@mcp.tool() # 装饰器,与langchain中tool作用一样,将函数封装成大模型可以识别的工具
def get_files(path):
    """
    获取指定路径下文件列表
    :param path: 路径
    :return: 文件列表
    """
    return os.listdir(os.path.expanduser(path))

if __name__ == "__main__":
    mcp.run(transport='stdio')  # 启动服务,使用标准输入输出通信,也可以是see,HTTP模式

运行 Server

mcp dev first_MCPserver.py

运行结果如下:
在这里插入图片描述

首次访问 http://127.0.0.1:6274 🚀可能会发现connet无法连接,在console控制台看到报错,如下图:

在这里插入图片描述

报错spawn uv ENOENT 意思是缺少 uv 命令,安装即可

pip install uv

在这里插入图片描述

启动成功后就可以进行访问web了,
因为我们写的是tool,所以选择Tools菜单进行测试。

在这里插入图片描述

MCP Client端配置

这里我使用的是CherryStdio

最新版:

在这里插入图片描述
老版本:

在这里插入图片描述
首次打开MCP服务器配置,红色方框位置会提示安装uvbun,点击安装按钮即可。

可能会有人有疑问,为什么server端安装了uv,这里还要安装,这里说一下,cherrystudio默认从他根目录下bin读取命令,刚刚我们的uv命令是安装在了py虚拟环境,相当于隔离的两个环境。当然,也可以使用操作系统层面的环境变量,只需要一个uv就可以了。

MacOS默认安装在~/.cherrystudio/bin

在这里插入图片描述

这里我使用uv命令一直报错,一直无法连接MCPServer,网上基本都是说环境的问题,我尝试了几种方法也没有解决。

在这里插入图片描述

但从网上看到有大佬直接使用python去运行,测试可行!

配置如下:
在这里插入图片描述
配置文件如下:
在这里插入图片描述

验证

这里需要注意两点

  1. 要选择支持function calling调用的模型
    在这里插入图片描述
  2. 添加MCP服务器
    在这里插入图片描述

配置好了就可以提问了

在这里插入图片描述
可以看到大模型调用了我们在Server端封装的get_files工具,并且输出正确。

总结

除了工具之外,还有资源、提示词,大家可以参考官网样例试验学习。当然还有 sse http调用模式也可以玩玩。

最后给大家分享一个MCP Server仓库,里面所有的MCP都是基于Typescript MCP SDK 或 Python MCP SDK 实现的,可以供大家使用和学习。