V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
JustW
V2EX  ›  程序员

探索 MCP-我的学习与实践笔记

  •  4
     
  •   JustW · 42 天前 · 6435 次点击
    这是一个创建于 42 天前的主题,其中的信息可能已经有所发展或是发生改变。

    👋 今天我们要一起探索 Model Context Protocol (MCP)!你可能听说过各种 AI 大模型,比如 ChatGPT 、文心一言等等,它们能聊天、写代码、甚至画画,简直无所不能!

    🤔 但是,你有没有想过,这些 AI 大模型是怎么跟现实世界交互的呢?比如,你怎么让 AI 帮你查天气、订机票、控制家里的智能灯泡?这时候,MCP 就派上用场啦!

    🌟 MCP 就像一个“万能插座”,让 AI 大模型可以安全、方便地连接各种各样的“电器”(也就是我们说的工具,比如查天气的 API 、控制灯泡的程序等等)。有了 MCP ,你的 AI 就能真正地“动起来”,而不仅仅是“说起来”!

    🧐 你是否曾梦想过,你的 AI 助手不仅能和你聊天,还能帮你完成各种实际任务?比如,当你对 AI 说“帮我预订明天早上 8 点飞往北京的航班”时,它真的能帮你订好机票,而不是仅仅回复你“好的,正在为您搜索航班信息……”?

    本文将带你从零开始,用 Python 搭建一个简单的 MCP 应用,让你亲身体验 AI 调用工具的魅力!

    💡 MCP 核心概念

    在正式开始写代码之前,我们需要先了解几个 MCP 的核心概念:

    • MCP (Model Context Protocol): 模型上下文协议。它不是一个具体的软件,而是一套“规则”或者“约定”。这套规则定义了 AI 模型(比如大型语言模型 LLM )如何与外部世界(各种工具、服务、数据)安全、高效地交互。你可以把它想象成一个“翻译官”,让 AI 听懂各种“方言”(不同的工具/服务的接口),也能让各种工具/服务听懂 AI 的“指令”。
    • 核心思想: 将 AI 模型的功能和对接到 AI 模型的工具(tool),数据(resource),提示(prompt)分离开, 独立部署, 让 AI 可以随意连接各种工具,数据以及使用各种提示!
    • MCP 主机 (MCP Host): 运行 AI 模型和 MCP 客户端的应用程序。常见的 MCP 主机有:
      • Claude Desktop: Anthropic 公司的桌面客户端,内置了 MCP 支持。
      • IDE 集成: 像 VS Code 、Cursor 等 IDE 可以通过插件支持 MCP 。
      • 自定义应用: 你自己开发的任何集成了 MCP 客户端的应用程序。
    • MCP 客户端 (MCP Client): 负责与 MCP 服务器通信的组件。它通常集成在 MCP 主机中。客户端的主要职责是:
      • 发现和连接 MCP 服务器。
      • 向 MCP 服务器请求可用的工具、资源、提示等信息。
      • 根据 AI 模型的指令,调用 MCP 服务器提供的工具。
      • 将工具的执行结果返回给 AI 模型。
    • MCP 服务器 (MCP Server): 提供具体功能(工具)和数据(资源)的程序。你可以把它想象成一个“技能包”,AI 模型可以通过 MCP 客户端“调用”这些技能。MCP 服务器可以:
      • 访问本地数据(文件、数据库等)。
      • 调用远程服务( Web API 等)。
      • 执行自定义的逻辑。
    • 本地数据源 (Local Data Source): 位于 MCP 服务器本地的数据,如文件、数据库等。
    • 远程服务 (Remote Service): MCP 服务器通过网络访问的服务,如各种 Web API 。
    • 资源 (Resource): 服务端提供的数据,比如天气信息、歌曲列表等等。
    • 工具 (Tool): 服务端提供的功能,比如查询天气、播放音乐等等。
    • Prompt: 预设的提示, 用于引导 AI 输出.

    image-20250320165955929

    🛠️ 准备工作

    在开始之前,我们需要准备一些工具:

    1. Python 环境: 确保你已经安装了 Python 3.10 或更高版本。
    2. 文本编辑器: 推荐使用 VS Code ,因为它有很多好用的插件,可以帮助我们更高效地编写代码。
    3. 终端: 在 Windows 上可以使用 PowerShell 或 CMD ,在 macOS 或 Linux 上可以使用 Terminal 。
    4. 一点点耐心和好奇心! 😉

    🏗️ 搭建 MCP 服务端

    我们的第一个任务是搭建一个 MCP 服务端。这个服务端会提供一个简单的“计算器”工具,让 AI 可以进行加法运算。下面以 windows 电脑为例,其他系统请参考: https://modelcontextprotocol.io/quickstart

    1. 创建项目目录:

      在 powershell 中执行下面的命令

      mkdir mcp-demo
      cd mcp-demo
      
    2. 创建虚拟环境 (推荐):

      用 uv 创建,更方便快捷! uv 通常指一个环境配置工具,用于简化开发环境的搭建流程。

      powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
      

      image-20250320185339119

      有的可能需要手动配置环境变量,可以参考控制台给出的提示进行配置!

      image-20250320185700725

      下面为创建目录以及激活环境,安装依赖!

      # Create a new directory for our project
      uv init calculate
      cd calculate
      
      # Create virtual environment and activate it
      uv venv
      .venv\Scripts\activate
      
      # Install dependencies
      uv add mcp[cli] httpx
      
      # Create our server file
      new-item calculate.py
      

    image-20250320185810239

    1. 打开刚刚创建的目录,并编写以下代码:

      image-20250320190113103

      from mcp.server.fastmcp import FastMCP
      
      # 创建 FastMCP 服务端实例,命名为 "add-server"
      mcp = FastMCP("add-server")
      
      # 使用 @mcp.tool() 装饰器定义一个名为 "add" 的工具
      @mcp.tool()
      def add(a: int, b: int) -> int:
          """
          计算两个整数的和。
      
          Args:
              a: 第一个整数。
              b: 第二个整数。
      
          Returns:
              两个整数的和。
          """
          return a + b
      
      # 主程序入口
      if __name__ == "__main__":
          # 启动服务端,使用 stdio 作为传输方式
          mcp.run(transport='stdio')
      
    2. 运行命令测试:

      mcp dev calculate.py
      

      如果一切正常,你应该能在终端看到类似下面的输出:

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

      这表示你的 MCP 服务已经成功启动了!访问终端输出的地址,即可进行调试!

      image-20250320190729603

    3. 客户端调用:

      我这里使用的是 cursor,更多支持的客户端可以查看 https://modelcontextprotocol.io/clients

      image-20250320191812621

      image-20250320191949133

      这里的路径请调整为自己的路径,注意必须使用绝对路径

      {
          "mcpServers": {
            "add-server": {
              "command": "E://mcp-demo//calculate//.venv//Scripts//python.exe",
              "args": ["E://mcp-demo//calculate//calculate.py"]
            }
          }
        }
      

      配置之后,启用刚刚添加的 mcp server, 对话框中选择 agent,然后提问即可,注意,启用时会自动启动一个控制台,请不要关闭! 这个一旦关闭,Cursor 就检测不到你的 MCP 工具

      image-20250320192141894

    Cherry Studio 中进行调用本地 mcp server,使用 uvx 始终不成功,最终使用下面方式实现! 有知道原因的可以留言指导我一下!! 参考文档: https://vaayne.com/posts/2025/how-to-use-mcp-in-cherry-studio/

    image-20250320192750523

    📱 搭建 MCP 客户端

    接下来,我们要搭建一个 MCP 客户端,参考代码见下面这个地址中的 main.py!

    代码地址: https://github.com/modelcontextprotocol/python-sdk/tree/main/examples/clients/simple-chatbot/mcp_simple_chatbot

    那么,这份代码是怎么把它们串起来,让 AI 帮你调用工具的呢?主要分三步:

    1. 🎁 把工具清单告诉 AI

    首先,我们要让 AI 知道 MCP Server 都有哪些工具可用。这一步就像是给 AI 一份“工具清单”。

    这份代码里,有一个 Tool 类,专门用来描述工具的信息,包括:

    • name(工具名称):比如 "image_generator"(图片生成器)
    • description(工具描述):告诉 AI 这个工具是干嘛的,比如“根据你的描述生成一张图片”
    • input_schema(输入格式):告诉 AI 使用这个工具需要提供哪些信息,比如“图片的描述”

    然后,format_for_llm() 方法会把这些信息整理成一段通俗易懂的文字,就像这样:

    Tool: image_generator
    Description: 根据你的描述生成一张图片
    Arguments:
    - description: 你想要生成的图片是什么样的? (required)
    

    看到了吧?这份“工具清单”是不是很清晰? AI 一看就知 道有哪些工具可以用,以及每个工具怎么用。

    ChatSession 类的 start 方法中,程序会:

    1. 从每个 MCP Server 获取工具列表。
    2. 将所有工具的信息格式化成一段文字(tools_description)。
    3. 把这段文字放到一个“系统提示”(system_message)里,告诉 AI:“你有这些工具可以用哦!”

    image-20250320194038055

    2. 🤔 AI 分析你的需求,决定用哪个工具

    现在,AI 已经知道了有哪些工具可用。接下来,当你向 AI 提问时,它就会分析你的需求,看看需不需要调用工具。

    比如,你问:“帮我画一张日落时海滩的图片。”

    AI 会想:“嗯,这个需求跟‘图片生成器’工具很匹配,我应该调用它。”

    但是,AI 怎么告诉程序它要调用哪个工具呢?这里有一个关键的约定:

    AI 必须按照特定的 JSON 格式回复!

    代码里的 system_message 特别强调了这一点:

    IMPORTANT: When you need to use a tool, you must ONLY respond with the exact JSON object format below, nothing else:

    {
    "tool": "tool-name",
    "arguments": {
      "argument-name": "value"
    }
    }
    

    也就是说,如果 AI 想调用“图片生成器”工具,它必须回复一段类似这样的 JSON:

    {
        "tool": "image_generator",
        "arguments": {
            "description": "日落时海滩的图片"
        }
    }
    

    ChatSessionprocess_llm_response方法专门处理 AI 的 JSON 回复. 检查是否包含 "tool" 和 "arguments" 键。

    image-20250320194146542

    3. 🛠️ 执行工具调用,获取结果

    最后一步,就是根据 AI 的指示,真正地去调用工具了。

    ChatSession 类的 process_llm_response 方法会:

    1. 接收到 AI 的回复。
    2. 尝试把回复解析成 JSON 格式。
    3. 如果解析成功,并且发现 AI 要调用工具:
      • 找出是哪个 MCP Server 提供了这个工具。
      • 调用 Server 类的 execute_tool 方法,执行工具。
      • 把工具的执行结果返回给 AI 。

    Server 类的 execute_tool 方法负责与 MCP Server 通信,发送工具调用请求,并获取结果。它还有重试机制,确保工具调用更可靠。

    最后,AI 会根据工具的返回结果,用自然语言给你一个最终的答复。

    image-20250320194216632

    整个过程就像这样:

    1. 你向 AI 提问。
    2. AI 分析你的问题,看看需不需要调用工具。
    3. 如果需要,AI 会按照约定的 JSON 格式回复,告诉程序要调用哪个工具,以及参数是什么。
    4. 程序解析 AI 的回复,找到对应的 MCP Server ,执行工具调用。
    5. 程序把工具的执行结果返回给 AI 。
    6. AI 根据工具的返回结果,给你一个最终的答复。

    是不是很简单?通过这种方式,AI 就可以借助 MCP Server 的各种工具,完成更复杂的任务,变得更加强大!

    演示

    image-20250320194958122

    image-20250320194804597

    启动代码通过对话就可以实现工具的调用了,然后可以自行调整上面的 API 调用地址和模型以及提示词进行测试,我个人测试可能还是 gemini 这个模型调用成功率高一些!

    ✨ 总结与展望

    通过这个简单的例子,相信你已经对 MCP 有了一个初步的了解。MCP 的强大之处在于,它可以让 AI 大模型与各种各样的工具和服务连接起来,从而实现更加复杂和强大的功能。

    • 跨平台: MCP 不仅仅支持 python, 还有 TS/JS, Java 等版本! 让你可以用自己最熟悉的语言进行开发!
    • 安全性: MCP 服务器可以控制权限, 保证你的数据安全!
    • 错误处理: 要记得在实际开发中, 对用户的输入,以及 AI 的返回做校验, 保证程序的稳定!
    • 异步处理: MCP 支持异步操作,这对于处理耗时任务(如网络请求、数据库查询)非常重要。

    未来,你可以尝试:

    • 添加更多工具: 比如查询天气、搜索新闻、控制智能家居等等。
    • 使用不同的客户端: 比如将 MCP 集成到你的 Web 应用、手机 App 中。
    • 探索更高级的 MCP 特性: 比如资源管理、Prompt 系统等等。

    MCP 的世界充满了无限可能,期待你用它创造出更多有趣、有用的 AI 应用!✨

    如果你在学习过程中遇到任何问题,或者有任何想法和建议,欢迎随时与我交流!😊

    最后

    给大家推荐一些关于 mcp server 好用的网站!

    教程

    mcp server 资源站

    第 1 条附言  ·  36 天前

    关于http的形式,改成sse的方式即可,代码来自 https://www.v2ex.com/t/1120709?p=1#reply14

    from mcp.server.fastmcp import FastMCP
    
    # Create an MCP server
    mcp = FastMCP(
        "Demo",
        debug=True,
        log_level='INFO',
        host="0.0.0.0",
        port=8000,
    )
    
    
    # Add an addition tool
    @mcp.tool()
    def add(a: int, b: int) -> int:
        """Add two numbers"""
        return a + b
    
    
    # Add a dynamic greeting resource
    @mcp.resource("greeting://{name}")
    def get_greeting(name: str) -> str:
        """Get a personalized greeting"""
        return f"Hello, {name}!"
    
    
    if __name__ == '__main__':
        mcp.run('sse')
    
    
    第 2 条附言  ·  35 天前
    44 条回复    2025-04-29 21:22:14 +08:00
    Unmurphy
        1
    Unmurphy  
       42 天前
    刚好,最近也要学习,
    tserial
        2
    tserial  
       42 天前 via iPhone
    总结的很好,也是刚接触
    kidyang
        3
    kidyang  
       41 天前 via iPhone
    🐮
    934831065ldc
        4
    934831065ldc  
       41 天前
    按照你的思路,都将 mcp server 的工具都拼接到 system 里面,如果有 1 万个工具,10 万工具,那 system message 是不是要爆掉了?
    guansixu
        5
    guansixu  
       41 天前
    感觉工具的调用跟 function call 有点像,只是 function call 是写在代码里面的函数
    birdhk
        6
    birdhk  
       41 天前
    最近刚在学,有个疑问,比如我想让大模型使用 get 请求获取一个 url 的信息并让他分析,这应该用 resource 还是 tool 呢?
    fredweili
        7
    fredweili  
       41 天前
    手工点赞,正想看看这个
    SilenceLL
        8
    SilenceLL  
       41 天前
    @guansixu 不同层级的东西,function call 更定制化一些,mcp 比较通用。不过现在其他家如谷歌还没跟进,说不定谷歌也想搞一个协议,本身这玩意就是谁流传的广谁就赢了。
    JustW
        9
    JustW  
    OP
       41 天前
    @934831065ldc 是的,会出现这个问题
    JustW
        10
    JustW  
    OP
       41 天前
    @birdhk 按官方的写法,应该是放资源里,操作类的就是用 tool.就是个规范,不是硬性要求.
    codingKingKong
        11
    codingKingKong  
       41 天前
    @JustW 如果是这样的话, 感觉就有点太怪了, 由 mcp-server 来维护这个声明, 由 client 扫描接入的 tools 说明, 支持特殊配置感觉会更正常一些
    JustW
        12
    JustW  
    OP
       41 天前
    @codingKingKong 客户端的代码就是你说的这个逻辑吧.
    lpdink
        13
    lpdink  
       41 天前
    @934831065ldc 对 mcp 工具的选择性召回是必要的,总归 RAG 生态现在也做的很好,接过来用在将来是必然的
    ASHYWHISPER
        14
    ASHYWHISPER  
       41 天前
    🙏感谢博主的启蒙。
    HomeZane
        15
    HomeZane  
       41 天前
    话说每个 mcp 都要启动一个服务的方式让我很难受,难道没有大善人提供线上 mcp 的服务吗
    JustW
        16
    JustW  
    OP
       41 天前
    @HomeZane 有啊.文章末尾的资源站就是呀
    HomeZane
        17
    HomeZane  
       41 天前
    @JustW #16 资源站的不都是需要本地部署吗?
    ppddtt
        18
    ppddtt  
       40 天前
    uvx 不成功的 可以先在 terminal 中安装一遍
    zhaoxj58
        19
    zhaoxj58  
       40 天前
    写的很好,赞一个
    ChristopherY
        20
    ChristopherY  
       39 天前
    没太理解,为什么你的例子中服务端实现了一个简单的加法工具,客户端又是一个 chatbot
    JustW
        21
    JustW  
    OP
       39 天前 via Android
    @ChristopherY 两个例子是单独的,客户端的代码中调用的是官方的 server ,没有调用自己的。主要是了解一下如何通过 API 调用 mcp server
    ChristopherWu
        22
    ChristopherWu  
       38 天前
    aiprotocolshub.com

    其实不只有 MCP 一种协议,我用上面的网站都整理起来了。LCEL 比 MCP 早很多



    | 协议 | 主要优势 | 主要劣势 | 最佳使用场景 | 实现复杂度 |
    | :--------------- | :------------------------------------------------------- | :----------------------------------------------------- | :------------------------------------ | :--------- |
    | Function Calling | 标准化的函数调用格式强大的参数验证与多种 API 和工具兼容 | 依赖于准确的函数描述复杂参数可能出错需要额外的错误处理 | 工具调用、API 集成、数据检索任务 | 中等 |
    | ChatML | 清晰的角色定义广泛的行业支持简化多轮对话管理 | 元数据支持有限无官方标准规范多模态内容支持不完善 | 聊天机器人、客服系统、多轮对话应用 | 低 |
    | MCP | 支持复杂的多智能体协作灵活的智能体通信路由可扩展性强 | 实现复杂资源消耗较高调试难度大 | 多智能体系统、协作任务、复杂问题解决 | 高 |
    | ReAct | 结合推理和行动能力提高复杂任务处理能力增强对环境的适应性 | 需要精心设计的提示模板可能陷入推理循环 Token 消耗较大 | 推理密集型任务、需要环境交互的场景 | 中等 |
    | LCEL | 组件化和可重用性强强大的链式调用能力丰富的内置组件 | 学习曲线较陡峭依赖 LangChain 生态灵活性有一定局限 | 数据处理管道、复杂工作流、构建 RAG 系统 | 中高 |
    ChristopherY
        23
    ChristopherY  
       38 天前
    @JustW 那用加法工具这个例子来说,我看代码中只创建了 server ,没有见 client 怎么写?还是说会自动创建对应的 client ?
    JustW
        24
    JustW  
    OP
       38 天前
    @ChristopherY 工具自带,cursor 和 cherry studio 自己实现了,所以能直接用, 创建 client 的方式在下面搭建客户端那个 github 中地址有单独的代码.
    crazychang
        25
    crazychang  
       37 天前
    # 逻辑流程:Client → LLM → Tool (if JSON) → Return

    def client_process(input_data):
    # 第一步:客户端将输入数据发送给 LLM
    llm_response = llm_process(input_data)

    # 第二步:判断 LLM 返回值是否为 JSON 格式
    if is_json(llm_response): # 如果是 JSON
    # 第三步:解析 JSON 并调用工具处理
    result = tool_process(parse_json(llm_response))
    else:
    # 第四步:如果不是 JSON ,直接返回 LLM 的响应
    result = llm_response

    return result # 返回最终结果

    是这个意思吧😮
    JustW
        26
    JustW  
    OP
       37 天前
    是的,重点就是第一步,去获取了所有的 mcp server,拼接在输入数据中了.
    pozhenzi998
        27
    pozhenzi998  
       37 天前
    3000 端口可以改吗?怎么改呢?
    EMMMMMMMMM
        28
    EMMMMMMMMM  
       36 天前
    @JustW mcp Server 只能是本地启动的一个进程吗? 是否可以通过 http 接口的方式调用?
    lanfeng579
        29
    lanfeng579  
       36 天前
    请教一个问题,我怎么把我写的 mcp Serve 发布到网络上面给别人调用呢,目前这一步 网上也没有撒具体的资料,还是弄成传统微服务的方式 http 调用吗?
    JustW
        30
    JustW  
    OP
       36 天前
    @pozhenzi998 补上了,文章最下面
    JustW
        31
    JustW  
    OP
       36 天前
    @lanfeng579 补上了,文章最下面
    JustW
        32
    JustW  
    OP
       36 天前
    @EMMMMMMMMM 补上了,文章最下面
    EMMMMMMMMM
        33
    EMMMMMMMMM  
       36 天前
    @JustW 那感觉不合理啊,mcp 的适用场景不应该是这样吧。 一个综合性的工具, 有成百上千个工具,应该是正常的哇
    EMMMMMMMMM
        34
    EMMMMMMMMM  
       36 天前 via Android
    按照楼主的 Demo 跑了下来,感觉 MCP 本身没做啥事情,只是定义了一个接口协议?
    JustW
        35
    JustW  
    OP
       36 天前 via Android
    @EMMMMMMMMM 这是现阶段的一个问题,看后面咋解决吧,比如 cherry studio 里面是在对话时选用那几个 mcp server 启用。
    evilStart
        36
    evilStart  
       36 天前
    为什么我觉得你这篇像是 AI 生成的😅
    JustW
        37
    JustW  
    OP
       36 天前 via Android
    @evilStart 我写大纲,AI 润色。🤔🤔
    JustW
        38
    JustW  
    OP
       36 天前 via Android
    @EMMMMMMMMM 对呀,文章开头就写了,定义了一个规范。
    voidmnwzp
        39
    voidmnwzp  
       34 天前 via iPhone
    所谓的 mcp 听起来更像是代理请求
    5aSx5Lia
        40
    5aSx5Lia  
       33 天前
    thanks, 最近写的很容易理解,楼主这部分内容我大概花了两天才从 github discussion 和 docs 上理解到,特别是那张 hub 的图片
    housex
        41
    housex  
       31 天前
    文章实操性挺高,概念梳理的也很清楚, 正在学习这块,那天偶然看到一个可以将 HTML 内容部署到 EdgeOne Pages (类似 Cloudflare Pages )并获取可公开访问的 URL 的 MCP 服务,感觉 ai 大背景下 mcp 服务的连接作用是尤其重要了。
    housex
        42
    housex  
       31 天前
    奥,忘记贴链接里,道友们感兴趣可以看下,将 HTML 内容部署到 EdgeOne Pages (类似 Cloudflare Pages )并获取可公开访问的 URL 的 MCP 服务地址: https://glama.ai/mcp/servers/@TencentEdgeOne/edgeone-pages-mcp
    popvlovs
        43
    popvlovs  
       22 天前
    @934831065ldc 以 cursor 为例,限制 40 个 tools
    [img]( )
    chaoziCoder
        44
    chaoziCoder  
       2 天前
    棒,特别是对 MCP 如何连接 AI 与各种工具的详细解释,让我对其潜力有了更深的理解。推荐下我的 MCP 导航站( https://mcpdb.org),希望能帮助更多人探索 MCP 的世界!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2265 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 15:05 · PVG 23:05 · LAX 08:05 · JFK 11:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.