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

173 天前
 JustW

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

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

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

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

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

💡 MCP 核心概念

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

🛠️ 准备工作

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

  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"
    

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

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

    # 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
    

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

    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 服务已经成功启动了!访问终端输出的地址,即可进行调试!

  3. 客户端调用:

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

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

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

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

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

📱 搭建 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 类,专门用来描述工具的信息,包括:

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

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

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

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

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

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" 键。

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

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

ChatSession 类的 process_llm_response 方法会:

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

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

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

整个过程就像这样:

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

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

演示

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

✨ 总结与展望

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

未来,你可以尝试:

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

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

最后

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

教程

mcp server 资源站

9307 次点击
所在节点    程序员
45 条回复
JustW
170 天前
@ChristopherY 两个例子是单独的,客户端的代码中调用的是官方的 server ,没有调用自己的。主要是了解一下如何通过 API 调用 mcp server
ChristopherWu
170 天前
aiprotocolshub.com

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



| 协议 | 主要优势 | 主要劣势 | 最佳使用场景 | 实现复杂度 |
| :--------------- | :------------------------------------------------------- | :----------------------------------------------------- | :------------------------------------ | :--------- |
| Function Calling | 标准化的函数调用格式强大的参数验证与多种 API 和工具兼容 | 依赖于准确的函数描述复杂参数可能出错需要额外的错误处理 | 工具调用、API 集成、数据检索任务 | 中等 |
| ChatML | 清晰的角色定义广泛的行业支持简化多轮对话管理 | 元数据支持有限无官方标准规范多模态内容支持不完善 | 聊天机器人、客服系统、多轮对话应用 | 低 |
| MCP | 支持复杂的多智能体协作灵活的智能体通信路由可扩展性强 | 实现复杂资源消耗较高调试难度大 | 多智能体系统、协作任务、复杂问题解决 | 高 |
| ReAct | 结合推理和行动能力提高复杂任务处理能力增强对环境的适应性 | 需要精心设计的提示模板可能陷入推理循环 Token 消耗较大 | 推理密集型任务、需要环境交互的场景 | 中等 |
| LCEL | 组件化和可重用性强强大的链式调用能力丰富的内置组件 | 学习曲线较陡峭依赖 LangChain 生态灵活性有一定局限 | 数据处理管道、复杂工作流、构建 RAG 系统 | 中高 |
ChristopherY
169 天前
@JustW 那用加法工具这个例子来说,我看代码中只创建了 server ,没有见 client 怎么写?还是说会自动创建对应的 client ?
JustW
169 天前
@ChristopherY 工具自带,cursor 和 cherry studio 自己实现了,所以能直接用, 创建 client 的方式在下面搭建客户端那个 github 中地址有单独的代码.
crazychang
169 天前
# 逻辑流程: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
169 天前
是的,重点就是第一步,去获取了所有的 mcp server,拼接在输入数据中了.
pozhenzi998
168 天前
3000 端口可以改吗?怎么改呢?
EMMMMMMMMM
168 天前
@JustW mcp Server 只能是本地启动的一个进程吗? 是否可以通过 http 接口的方式调用?
lanfeng579
167 天前
请教一个问题,我怎么把我写的 mcp Serve 发布到网络上面给别人调用呢,目前这一步 网上也没有撒具体的资料,还是弄成传统微服务的方式 http 调用吗?
JustW
167 天前
@pozhenzi998 补上了,文章最下面
JustW
167 天前
@lanfeng579 补上了,文章最下面
JustW
167 天前
@EMMMMMMMMM 补上了,文章最下面
EMMMMMMMMM
167 天前
@JustW 那感觉不合理啊,mcp 的适用场景不应该是这样吧。 一个综合性的工具, 有成百上千个工具,应该是正常的哇
EMMMMMMMMM
167 天前
按照楼主的 Demo 跑了下来,感觉 MCP 本身没做啥事情,只是定义了一个接口协议?
JustW
167 天前
@EMMMMMMMMM 这是现阶段的一个问题,看后面咋解决吧,比如 cherry studio 里面是在对话时选用那几个 mcp server 启用。
evilStart
167 天前
为什么我觉得你这篇像是 AI 生成的😅
JustW
167 天前
@evilStart 我写大纲,AI 润色。🤔🤔
JustW
167 天前
@EMMMMMMMMM 对呀,文章开头就写了,定义了一个规范。
voidmnwzp
165 天前
所谓的 mcp 听起来更像是代理请求
5aSx5Lia
164 天前
thanks, 最近写的很容易理解,楼主这部分内容我大概花了两天才从 github discussion 和 docs 上理解到,特别是那张 hub 的图片

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1119962

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX