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

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

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

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

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

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

:light_bulb: 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输出.

:hammer_and_wrench: 准备工作

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

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

:building_construction: 搭建 MCP 服务端

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

  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,更多支持的客户端可以查看 Example Clients - Model Context Protocol

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

    {
        "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始终不成功,最终使用下面方式实现! 有知道原因的可以留言指导我一下!! 参考文档: 如何在 Cherry Studio 中使用 MCP | Vaayne's Tea House

:mobile_phone: 搭建 MCP 客户端

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

代码地址: python-sdk/examples/clients/simple-chatbot/mcp_simple_chatbot at main · modelcontextprotocol/python-sdk · GitHub

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

1. :wrapped_gift: 把工具清单告诉 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:“你有这些工具可以用哦!”

2. :thinking: 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. :hammer_and_wrench: 执行工具调用,获取结果

最后一步,就是根据 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这个模型调用成功率高一些!

:sparkles: 总结与展望

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

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

未来,你可以尝试:

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

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

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

最后

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

教程

mcp server资源站

302 Likes

先收藏再观看 :nerd_face:

3 Likes

mark一下, 感谢大佬分享

3 Likes

看了这么多
就是没有人甩一个
在client看来
每次发送的请求,接收到的响应,再次发送请求的具体内容格式

4 Likes

太强了,大佬

2 Likes

这个在我上面那个客户端代码里面有,可以下载下来跑一下就知道了.

1 Like

我只有deepseek,跑不起来
没结果

3 Likes

好详细呀

2 Likes

你能保存一下每次发送的请求,接收到的响应,再次发送请求的具体内容格式
给我看一下吗?

3 Likes

直接去里面提供的的那个API地址注册个账号,申请个key就能用.
这是返回的结果,结合代码看.

llm_response = self.llm_client.get_response(messages)

llm_response是下面这个


            
Tool: read_query
Description: Execute a SELECT query on the SQLite database
Arguments:
- query: SELECT SQL query to execute (required)


Tool: write_query
Description: Execute an INSERT, UPDATE, or DELETE query on the SQLite database
Arguments:
- query: SQL query to execute (required)


Tool: create_table
Description: Create a new table in the SQLite database
Arguments:
- query: CREATE TABLE SQL statement (required)


Tool: list_tables
Description: List all tables in the SQLite database
Arguments:



Tool: describe_table
Description: Get the schema information for a specific table
Arguments:
- table_name: Name of the table to describe (required)


Tool: append_insight
Description: Add a business insight to the memo
Arguments:
- insight: Business insight discovered from data analysis (required)


Tool: puppeteer_navigate
Description: Navigate to a URL
Arguments:
- url: No description (required)


Tool: puppeteer_screenshot
Description: Take a screenshot of the current page or a specific element
Arguments:
- name: Name for the screenshot (required)
- selector: CSS selector for element to screenshot
- width: Width in pixels (default: 800)
- height: Height in pixels (default: 600)


Tool: puppeteer_click
Description: Click an element on the page
Arguments:
- selector: CSS selector for element to click (required)


Tool: puppeteer_fill
Description: Fill out an input field
Arguments:
- selector: CSS selector for input field (required)
- value: Value to fill (required)


Tool: puppeteer_select
Description: Select an element on the page with Select tag
Arguments:
- selector: CSS selector for element to select (required)
- value: Value to select (required)


Tool: puppeteer_hover
Description: Hover an element on the page
Arguments:
- selector: CSS selector for element to hover (required)


Tool: puppeteer_evaluate
Description: Execute JavaScript in the browser console
Arguments:
- script: JavaScript code to execute (required)


            根据用户的问题选择合适的工具。如果不需要使用工具,请直接回复。

            重要提示:当您需要使用工具时,必须仅以下面的精确JSON对象格式回复,不得有其他内容:

            {
                "tool": "工具名称",
                "arguments": {
                    "参数名": "参数值"
                }
            }

            在收到工具的响应后:
            1. 将原始数据转化为自然、对话式的回复
            2. 保持回复简洁但信息丰富
            3. 专注于最相关的信息
            4. 使用用户问题中的适当上下文
            5. 避免简单重复原始数据

            请仅使用上面明确定义的工具。请分析用户意图,重要提示:当您需要使用工具时,必须仅返回纯JSON对象,不要添加任何Markdown格式、代码块标记,

result是


'```json
{
    "tool": "puppeteer_navigate",
    "arguments": {
        "url": "https://www.wangwangit.com"
    }
}
```'


result = await self.process_llm_response(llm_response)

这个result是

"Tool execution result: meta=None content=[TextContent(type='text', text='Navigated to https://www.wangwangit.com', annotations=None)] isError=False"

3 Likes


那个github的env示例是groq
这个支持??我有grok,前段时间冲了马斯克的x5刀

2 Likes

学习了!

3 Likes

请问这个mcp和常说的AI智能体有什么区别么?

2 Likes

groq 和 grok 是两个

2 Likes

看走眼了

2 Likes

这个groq去网站注册好像也能免费用

1 Like

我的理解是,mcp是相当于一种规范吧,而智能体就是大模型动态调用各种mcp服务。 大家都遵守mcp规范,这样后期构建工具和调用都方便。

2 Likes

唤起浏览器窗口的是哪个mcp服务器啊,我装了好几个,在cherry里用都起不来

1 Like

好像是这个。 puppeteer_navigate

1 Like

这篇文章算是抛砖引玉了,未来可以预见,会有更多MCP的插件接入进来

3 Likes