最近,“MCP”这个关键词频繁出现在各大AI技术文章与评论区中,热度持续飙升。相信不少小伙伴和我一样,最初对它仅有模糊的认知。经过一番深入学习,我决定将干货整理出来,带大家全方位吃透MCP的使用方法,还准备了超详细的示例代码,手把手教你上手!

一、深度解析:MCP究竟是什么?

MCP,全称为Model Context Protocol,即模型上下文协议。它诞生于2024年11月25日,由Anthropic正式发布。简单来说,MCP就是AI世界里的“通用语言”和“标准接口”。

想象一下,在AI应用开发过程中,我们常常需要将各种数据源(如本地文件、数据库)、工具(数据分析工具、文件处理工具等)与AI模型连接起来。但此前,不同的连接方式缺乏统一标准,就像不同形状的插头无法通用。而MCP的出现,定义了应用程序和AI模型之间交换上下文信息的标准方式,成为了一个中间协议层。

这就好比USB - C接口的出现,让不同设备都能通过相同的接口连接,实现数据传输和功能拓展。MCP的目标就是让AI模型能够以一致的方式连接各类资源和工具,使得AI应用程序的开发和集成变得更加简单、高效和统一。mcp architecture

二、为什么MCP如此重要?

在MCP诞生之前,我们在向AI模型传递信息时,往往采用较为原始的方式。比如,为了让模型处理特定数据,需要人工从数据库筛选、使用工具检索信息,再手动粘贴到prompt中。随着问题复杂度不断增加,这种手工操作的方式变得越来越困难,效率极低。

后来,许多LLM平台推出了function call功能,允许模型在需要时调用预定义函数获取数据或执行操作,一定程度上提升了自动化水平。然而,function call存在明显局限性:

  • 平台依赖性强:不同LLM平台(如OpenAI、Google)的function call API实现差异巨大,开发者在切换模型时,需要花费大量时间和精力重写代码,适配成本极高。
  • 其他问题:还存在安全性、交互性等方面的不足。

而MCP的出现,完美解决了这些痛点,它就像AI模型的“万能转接头”,具备以下显著优势:

  • 丰富的生态:MCP提供了大量现成的插件,开发者和用户可以直接使用这些插件,快速为AI模型拓展功能,无需从头开发。
  • 高度统一性:不局限于特定的AI模型,只要是支持MCP的模型,都可以灵活切换使用,大大降低了对单一平台的依赖。
  • 强大的数据安全保障:用户的敏感数据可以留在自己的电脑上,无需全部上传到云端。因为我们可以自行设计数据传输接口,精确控制哪些数据需要传递给模型,有效保护数据隐私和安全。

三、手把手教学:用户如何使用MCP?

对于普通用户而言,无需深入了解MCP的底层实现原理,重点关注如何便捷地使用这一强大特性即可。

使用MCP的具体操作,可以参考官方文档《For Claude Desktop Users》。按照文档步骤完成配置后,就可以在Claude中进行测试。例如,输入“Can you write a poem and save it to my desktop?”,Claude会在请求你的权限后,在本地新建一个文件保存诗歌📄。

此外,官方还提供了众多现成的MCP Servers,涵盖各种实用工具。用户只需要根据自己的需求,选择希望接入的工具,按照指引完成接入操作,就能轻松让AI模型调用这些工具,实现丰富的功能。比如官方介绍的filesystem工具,它允许Claude像在本地文件系统中一样,自由读取和写入文件。workflow

四、MCP架构与原理剖析

(一)MCP的核心组件

MCP由三个核心组件构成:HostClientServer。我们通过一个实际场景来理解它们的工作机制: 假设你在Claude Desktop(作为Host)中询问:“我桌面上有哪些文档?”

  • Host:负责接收用户的提问,并与Claude模型进行交互,它就像是用户与模型之间的桥梁。
  • Client:当Claude模型判断需要访问文件系统获取信息时,Host中内置的MCP Client会被激活。Client的任务是与合适的MCP Server建立连接,传递请求并接收响应。
  • Server:在这个例子中,文件系统MCP Server会被调用。它负责执行实际的文件扫描操作,访问桌面目录,并将找到的文档列表返回。

整个流程如下:用户提问→Claude Desktop(Host)→Claude模型→判断需要文件信息→激活MCP Client连接→文件系统MCP Server→执行扫描操作→返回结果→Claude模型生成回答→在Claude Desktop显示答案。

这种架构设计的优势在于,开发者只需专注于开发对应的MCP Server,无需关心Host和Client的实现细节,就能让AI模型在不同场景下灵活调用各种工具和数据源。

(二)模型如何确定工具的选用?

  1. 模型如何智能选择工具当用户提出问题后,模型通过prompt工程来确定使用哪些工具。以MCP官方提供的client example为例,简化后的代码如下:
import asyncio
from typing import Any

# 省略了无关的代码
asyncdef start(self):
    # 初始化所有的mcp server
    for server in self.servers:
        await server.initialize()

    # 获取所有的tools命名为all_tools
    all_tools = []
    for server in self.servers:
        tools = await server.list_tools()
        all_tools.extend(tools)

    # 将所有的tools的功能描述格式化成字符串供LLM使用
    # tool.format_for_llm() 我放到了这段代码最后,方便阅读。
    tools_description = "\n".join(
        [tool.format_for_llm() for tool in all_tools]
    )

    # 这里就不简化了,以供参考,实际上就是基于prompt和当前所有工具的信息
    # 询问LLM(Claude)应该使用哪些工具。
    system_message = (
        "You are a helpful assistant with access to these tools:\n\n"
        f"{tools_description}\n"
        "Choose the appropriate tool based on the user's question. "
        "If no tool is needed, reply directly.\n\n"
        "IMPORTANT: When you need to use a tool, you must ONLY respond with "
        "the exact JSON object format below, nothing else:\n"
        "{\n"
        '    "tool": "tool-name",\n'
        '    "arguments": {\n'
        '        "argument-name": "value"\n'
        "    }\n"
        "}\n\n"
        "After receiving a tool's response:\n"
        "1. Transform the raw data into a natural, conversational response\n"
        "2. Keep responses concise but informative\n"
        "3. Focus on the most relevant information\n"
        "4. Use appropriate context from the user's question\n"
        "5. Avoid simply repeating the raw data\n\n"
        "Please use only the tools that are explicitly defined above."
    )
    messages = [{"role": "system", "content": system_message}]

    whileTrue:
        # Final... 假设这里已经处理了用户消息输入.
        messages.append({"role": "user", "content": user_input})

        # 将system_message和用户消息输入一起发送给LLM
        llm_response = self.llm_client.get_response(messages)

       ... # 后面和确定使用哪些工具无关


class Tool:
    """Represents a tool with its properties and formatting."""

    def __init__(
        self, name: str, description: str, input_schema: dict[str, Any]
    ) -> None:
        self.name: str = name
        self.description: str = description
        self.input_schema: dict[str, Any] = input_schema

    # 把工具的名字 / 工具的用途(description)和工具所需要的参数(args_desc)转化为文本
    def format_for_llm(self) -> str:
        """Format tool information for LLM.

        Returns:
            A formatted string describing the tool.
        """
        args_desc = []
        if"properties"in self.input_schema:
            for param_name, param_info in self.input_schema["properties"].items():
                arg_desc = (
                    f"- {param_name}: {param_info.get('description', 'No description')}"
                )
                if param_name in self.input_schema.get("required", []):
                    arg_desc += " (required)"
                args_desc.append(arg_desc)

        returnf"""
 Tool: {self.name}
 Description: {self.description}
 Arguments:
 {chr(10).join(args_desc)}
 """

从代码中可以看出,模型通过将所有工具的具体使用描述(包括工具名称、功能描述、参数说明等)以文本形式传递给它,结合实时的用户问题,来判断应该使用哪些工具。

  1. 工具执行与结果反馈机制当模型分析用户请求后,会判断是否需要调用工具:
  • 无需工具时:模型直接生成自然语言回复。
  • 需要工具时:模型输出结构化JSON格式的工具调用请求。

客户端收到包含结构化JSON格式的工具调用请求后,会根据这个json代码执行对应的工具。如果模型执行了tool call,工具执行的结果会和system prompt、用户消息一起重新发送给模型,请求模型生成最终回复。如果tool call的json代码存在问题或者模型产生幻觉,客户端会跳过无效的调用请求。相关代码逻辑如下:

... # 省略无关的代码
asyncdef start(self):
   ... # 上面已经介绍过了,模型如何选择工具

    whileTrue:
        # 假设这里已经处理了用户消息输入.
        messages.append({"role": "user", "content": user_input})

        # 获取LLM的输出
        llm_response = self.llm_client.get_response(messages)

        # 处理LLM的输出(如果有tool call则执行对应的工具)
        result = await self.process_llm_response(llm_response)

        # 如果result与llm_response不同,说明执行了tool call (有额外信息了)
        # 则将tool call的结果重新发送给LLM进行处理。
        if result != llm_response:
            messages.append({"role": "assistant", "content": llm_response})
            messages.append({"role": "system", "content": result})

            final_response = self.llm_client.get_response(messages)
            logging.info("\nFinal response: %s", final_response)
            messages.append(
                {"role": "assistant", "content": final_response}
            )
        # 否则代表没有执行tool call,则直接将LLM的输出返回给用户。
        else:
            messages.append({"role": "assistant", "content": llm_response})      

通过以上原理分析可知,工具文档至关重要,因为模型依赖工具描述文本来理解和选择工具。同时,虽然从理论上讲任何模型都适配MCP,但非Claude模型由于没有经过专门训练,使用效果和体验可能无法得到有效保证。core

五、实战演练:手把手教你开发MCP Server

对于AI开发者来说,了解如何开发MCP Server是发挥MCP强大功能的关键。下面通过一个简单示例,使用Python实现一个MCP Server,用于统计当前桌面上的txt文件数量并获取对应文件名,即使是初学者也能轻松上手!

(一)前置工作

  1. 安装Claude Desktop。
  2. 确保系统安装Python 3.10及以上版本。
  3. 安装Python MCP SDK 1.2.0及以上版本。

(二)环境配置

这里使用官方推荐的配置方式,借助uv工具(一个用Rust编写的超快速Python包管理器和环境管理工具)进行配置:

# 安装uv
curl -LsSf https://astral.sh/uv/install.sh | sh

# 创建项目目录
uv init txt_counter
cd txt_counter

# 设置Python 3.10+环境
echo"3.11" >.python-version

# 创建虚拟环境并激活
uv venv
source.venv/bin/activate

# Install dependencies
uv add "mcp[cli]" httpx

# Create our server file
touch txt_counter.py

(三)构造一个prompt

在开始编写代码前,先构造一个prompt,明确我们要开发的MCP Server的功能需求:

"""
... (这里是已经引入的domain knowledge,可从MCP Python SDK的README文件等获取相关内容)
"""
打造一个MCP服务器,它能够:
- 功能:
    - 统计当前桌面上的txt文件数量
    - 获取对应文件的名字
要求:
- 不需要给出prompt和resource相关代码。
- 你可以假设我的桌面路径为 /Users/{username}/Desktop

(四)实现MCP Server

以下代码由Claude 3.7生成,实现了我们所需的功能:

import os
from pathlib import Path
from mcp.server.fastmcp import FastMCP

# 创建MCP Server
mcp = FastMCP("桌面TXT文件统计器")

@mcp.tool()
def count_desktop_txt_files() -> int:
    """Count the number of.txt files on the desktop."""
    # Get the desktop path
    username = os.getenv("USER") or os.getenv("USERNAME")
    desktop_path = Path(f"/Users/{username}/Desktop")

    # Count.txt files
    txt_files = list(desktop_path.glob("*.txt"))
    return len(txt_files)

@mcp.tool()
def list_desktop_txt_files() -> str:
    """Get a list of all.txt filenames on the desktop."""
    # Get the desktop path
    username = os.getenv("USER") or os.getenv("USERNAME")
    desktop_path = Path(f"/Users/{username}/Desktop")

    # Get all.txt files
    txt_files = list(desktop_path.glob("*.txt"))

    # Return the filenames
    ifnot txt_files:
        return"No.txt files found on desktop."

    # Format the list of filenames
    file_list = "\n".join([f"- {file.name}"for file in txt_files])
    returnf"Found {len(txt_files)}.txt files on desktop:\n{file_list}"

if __name__ == "__main__":
    # Initialize and run the server
    mcp.run()

(五)测试MCP Server

完成代码编写后,在终端执行以下命令进行测试:

mcp dev txt_counter.py

执行后,会看到类似以下输出:

Starting MCP inspector...
Proxy server listening on port 3000
MCP Inspector is up and running at http://localhost:5173

此时,进入给出的链接(http://localhost:5173),按照页面提示操作,即可查看MCP Server是否正常工作,能否正确统计和列出桌面上的txt文件信息。

(六)接入Claude

最后一步,将开发好的MCP Server接入到Claude Desktop中:

  1. 打开claude_desktop_config.json(MacOS / Linux系统路径为~/Library/Application Support/Claude/claude_desktop_config.json),可以使用code命令(如果你用的是cursor或者vim等编辑器,请使用对应的命令):
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
  1. 在配置文件中添加以下内容,记得将路径和用户名替换为实际信息:
{
  "mcpServers": {
    "txt_counter": {
      "command": "/Users/{username}/.local/bin/uv",
      "args": [
        "--directory",
        "/Users/{username}/work/mcp-learn/code-example-txt", // 你的项目路径(这里是我的)
        "run",
        "txt_counter.py" // 你的MCP Server文件名
      ]
    }
  }
}

其中,uv最好使用绝对路径,推荐使用which uv命令获取。 3. 配置完成后,重启Claude Desktop,如果配置无误,就能在Claude中看到对应的MCP Server。

(七)实际使用

在Claude中输入测试prompt,例如“能推测我当前桌面上txt文件名的含义吗?”,此时Claude可能会请求使用权限,点击“Allow for This Chat”,即可看到MCP Server正常工作,Claude基于MCP Server获取的信息给出回答!

六、总结

MCP(Model Context Protocol)的出现,标志着AI与外部工具和数据交互朝着标准化迈出了重要一步。通过本文,我们深入了解到:

  • MCP的本质:是一个统一的协议标准,类似于AI世界的“USB-C”接口,实现了AI模型与各类数据源、工具的一致连接。
  • MCP的价值:解决了传统function call的平台依赖等问题,提供了更统一、开放、安全、灵活的工具调用机制,让用户和开发者都能从中受益。
  • 使用与开发:普通用户可以借助丰富的现成工具轻松使用MCP;开发者则可以依据清晰的架构和SDK,开发出各种强大的MCP Server。

目前,MCP虽然还处于发展初期,但潜力巨大。随着基于MCP统一标准的生态不断完善,必将推动整个AI领域迈向新的高度!赶紧动手实践起来,探索MCP的无限可能吧!

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

https://img-blog.csdnimg.cn/img_convert/05840567e2912bcdcdda7b15cba33d93.jpeg

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

https://img-blog.csdnimg.cn/img_convert/05840567e2912bcdcdda7b15cba33d93.jpeg

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐