掘金 人工智能 前天 10:28
MCP从开发到应用实践(入门篇)
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文旨在帮助读者快速了解、开发和使用模型上下文协议(MCP)。MCP是由Anthropic公司开源,用于标准化应用程序如何向大型语言模型(LLMs)提供上下文。它类似于AI应用的USB-C接口,提供了一种标准化的方式来连接AI模型到不同的数据源和工具。MCP通过预构建集成、统一接口、数据安全保障和LLM提供商的灵活性,简化了在LLMs上构建代理和复杂工作流的过程。文章详细介绍了MCP的架构、关键概念(如资源、工具、提示、采样和根)以及通信方式,并提供了实际操作步骤,包括环境搭建、代码编写和调试,最后以Cherry studio和Vscode为例演示了MCP的使用。

💡**MCP的核心作用:** MCP(模型上下文协议)是一种由Anthropic公司开源的协议,旨在标准化应用程序向大型语言模型(LLMs)提供上下文的方式,可以理解为AI应用的“USB-C”接口,用于连接AI模型到不同的数据源和工具。

🛠️**MCP的架构与组件:** MCP架构包含主机(Host)、客户端(Client)和服务器(Server)。主机与大模型直接交互,客户端将外部需求转换为MCP协议格式,服务器则处理主机请求并提供服务,如数据查询和文件操作。

🔑**MCP的关键概念:** MCP的关键概念包括:资源(Resources),用于公开服务器中的数据和内容给LLM;工具(Tools),使LLM能够通过服务器执行操作,与外部系统交互;提示(Prompts),创建可重用的提示模板和工作流;采样(Sampling),允许服务器通过客户端请求LLM完成任务;根(Roots),用于定义服务器可以运行的边界。

⚙️**MCP的实战构建与使用:** 文章详细介绍了如何使用uv进行环境搭建,包括初始化工程、创建Python虚拟环境、配置pyproject.toml以及安装依赖。同时,提供了stdio和Sse两种方式的快速编码示例,并演示了如何通过Cherry studio和Vscode配置和使用MCP服务,包括配置模型、MCP服务以及进行对话使用。

[TOC]

介绍

帮助小白快速认识、开发和使用MCP。其实我也是小白哦,若有问题或错误欢迎指出,感谢

1. 什么是MCP

MCP(Model Context Protocol)即模型上下文协议,是由 Anthropic 公司于 2024 年底开源发布, 用于标准化应用程序如何向大型语言模型(LLMs)提供上下文。将 MCP 想象成 AI 应用的 USB-C 接口。就像 USB-C 提供了一种标准化的方式来连接设备到各种外设和配件一样,MCP 提供了一种标准化的方式来连接 AI 模型到不同的数据源和工具。

2. 为什么用MCP

MCP 帮助你在 LLMs 上构建代理和复杂的工作流。LLMs 经常需要与数据和工具集成,而 MCP 提供了:

3. MCP、智能体、大模型 关系

4. MCP 架构与组件

Client 和 Server 之间使用双向的 JSON-RPC 2.0 进行通信。当前支持 stdio 和 Streamable HTTP 两种传输机制。

5. MCP关键概念

**Resources 资源:**将服务器中的数据和内容公开给 LLM,

它允许服务器公开可由客户端读取并用作 LLM 交互上下文的数据和内容。

**Tools 工具:**使 LLM 能够通过您的服务器执行操作

它使服务器能够向客户端公开可执行功能。通过工具,LLM 可以与外部系统交互、执行计算并在现实世界中采取行动。(执行者,API)

Prompts 提示: 创建可重用的提示模板和工作流

使服务器能够定义可重用的提示模板和工作流,客户端可以轻松地向用户和 LLM 显示这些模板和工作流。它们提供了一种强大的方法来标准化和共享常见的 LLM 交互。

**Sampling 采样:**让您的服务器从 LLM 请求完成

它允许服务器通过客户端请求 LLM 完成,从而在维护安全性和隐私性的同时实现复杂的代理行为。

MCP Server 可以发起请求到 MCP Client,再MCP Client 接收到请求后,执行相应的动作,比如:人工确认或者是调用大模型等。

**Roots 根:**用于定义服务器可以运行的边界。它们为客户端提供了一种将相关资源及其位置通知服务器的方法。

根是客户端建议服务器应该关注的 URI。当客户端连接到服务器时,它会声明服务器应该使用哪些根。虽然 root 主要用于文件系统路径,但 root 可以是任何有效的 URI,包括 HTTP URL。

    Project directories 项目目录Repository locations 存储库位置API endpoints API 终端节点Configuration locations 配置位置Resource boundaries 资源边界

**Transports 运输:**模型上下文协议 (MCP) 中的传输为客户端和服务器之间的通信提供了基础。传输处理消息发送和接收方式的基本机制。

MCP 使用 JSON-RPC 2.0 作为其传输格式。传输层负责将 MCP 协议消息转换为 JSON-RPC 格式进行传输,并将收到的 JSON-RPC 消息转换回 MCP 协议消息。

6. 通信方式(Transport)

通信方式介绍场景
STDIO标准输入/输出- 本地集成和命令行工具特别有用;- 构建命令行工具;- 本地集成;- 简单的通信;- 使用 shell 脚本
Server-Sent-Events服务端推流,单向- 需要服务端到客户端的流式传输;- 网络受限
Streamable HTTP流式 Http,将替换 SSE。原因高效灵活,支持更大模块的分布式部署

实战

1. 构建MCP

1.1 前置准备

1.2 环境搭建

👉 推荐使用uv docs.astral.sh/uv/getting-…

1.2.1 初始化工程
# 初始化框架uv init mcp-math-demo# 切换目录cd mcp-math-demo# 创建目录(为什么 —> 因为据说是python工程规范)mkdir -p src/example# 将生成的main移动到examplemv main.py src/example
1.2.2 创建py虚拟环境
# 创建虚拟环境(工程中会多一个.venv 文件),并激活环境uv venv# 激活环境,mac和window 有点差异,需注意下source .venv/bin/activate
1.2.3 配置pyproject.toml
....其他已经存在的配置....dependencies = [    "fastmcp>=2.3.4",    "mcp[cli]>=1.6.0"][project.scripts]example = "example.main:main"[[tool.uv.index]]name = "mypypi"url = "https://pypi.tuna.tsinghua.edu.cn/simple"publish-url = "http://your.pypi/"default = true....其他已经存在的配置....
1.2.4 安装依赖
uv pip install -e .
1.2.5 运行代码
# 执行工程代码uv run example# 若成功则打印结果:Hello from mcp-math-demo! 

1.3 快速编码

一下两种方式任选一种,其中Sse方式需要提前启动

1.3.1 Stdio方式

启动命令测试:uv run src/example/server-math-stdio.py

# server-math-stdio.pyfrom mcp.server.fastmcp import FastMCPimport logging # 配置日志记录器logging.basicConfig(    level=logging.INFO,  # 设置日志级别为 INFO    format="%(asctime)s - %(levelname)s - %(message)s"  # 日志格式)logger = logging.getLogger(__name__) # 创建 FastMCP 实例mcp = FastMCP("Math") @mcp.tool()def add(a: int, b: int) -> int:    """Add two numbers"""    logger.info("The add method is called: a=%d, b=%d", a, b)  # 记录加法调用日志    return a + b @mcp.tool()def multiply(a: int, b: int) -> int:    """Multiply two numbers"""    logger.info("The multiply method is called: a=%d, b=%d", a, b)  # 记录乘法调用日志    return a * b if __name__ == "__main__":    logger.info("Start math server through MCP-STDIO")  # 记录服务启动日志    mcp.run(transport="stdio")  # 启动服务并使用标准输入输出通信
1.3.2 Sse方式

👉 该方式需要先启动服务,然后在使用HOST取连接

启动命令测试:uv run src/example/server-math-stdio.py

# server-math-sse.pyfrom mcp.server.fastmcp import FastMCPimport logging # 配置日志记录器logging.basicConfig(    level=logging.INFO,  # 设置日志级别为 INFO    format="%(asctime)s - %(levelname)s - %(message)s"  # 日志格式)logger = logging.getLogger(__name__) # 创建 FastMCP 实例mcp = FastMCP("Math") @mcp.tool()def add(a: int, b: int) -> int:    """Add two numbers"""    logger.info("The add method is called: a=%d, b=%d", a, b)  # 记录加法调用日志    return a + b @mcp.tool()def multiply(a: int, b: int) -> int:    """Multiply two numbers"""    logger.info("The multiply method is called: a=%d, b=%d", a, b)  # 记录乘法调用日志    return a * b if __name__ == "__main__":    logger.info("Start math server through MCP-SSE")  # 记录服务启动日志    mcp.run(transport="sse")  # 启动服务并使用标准输入输出通信    #mcp.run(transport="streamable-http")  # 启动服务并使用标准输入输出通信

1.4 调试MCP

方式一:单独运行调试工具
# 打开命令行执行脚本npx @modelcontextprotocol/inspector@0.6.0

Sse

Stdio

方式二:通过mcp进行调试(实则方式一)
## 这种本质上就是方式一uv run mcp dev server-math-stdio.py

2. 使用MCP

非开发、开发人员视角演示使用,下面是常用标准的MCP配置

{    ## 数学计算 方式一:stdio --> server-math-stdio.py    "math-stdio": {        # 这个也可以是 .venv/bin/python3        "command": "uv",         # Replace with absolute path to your server-math-stdio.py file        "args": ["run","xxxx/src/example/server-math-stdio.py"],        "transport": "stdio",    },    ## 数学计算 方式二:sse  --> server-math-sse.py    "math-sse": {        "url":"http://127.0.0.1:8000/sse",        "transport": "sse"    },}

2.1 Cherry studio

2.1.1 配置模型

这里可以点击硅基流动进行注册获取(新用户有免费额度),或者根据自己实际情况配置

2.1.2 配置MCP服务
2.1.2.1 方式一:stdio

--directoryxxx/mcp-math-demo/src/example/runserver-math-stdio.py
2.1.2.2 方式二:sse

先启动服务:

在配置

2.1.2.3 查看MCP具体工具

2.1.3 选择MCP服务和大模型

2.1.4 对话使用MCP

2.2 Vscode

2.2.1 下载插件

我用的Roo Code,大家可以下载其他插件: Cline ...

2.2.2 配置模型

我这边注册的DeepSeek

2.2.3 配置mcp

注意:

comand:指定可以运行脚本的命令,环境不要混了

args:参数指定绝对路径

transport: 依据实际, stdio|sse

2.2.4 对话 (过程中自动批准MCP)

输入3*3

2.3 Code 代码调用

2.3.1 需要安装依赖
uv add langchain_mcp_adapters langgraph langchain_deepseek
2.3.2 客户端代码 client-langchain.py
import asynciofrom langchain_mcp_adapters.client import MultiServerMCPClientfrom langgraph.prebuilt import create_react_agentfrom example.utils import init_model ## 模型llm = init_model()async def main():     client = MultiServerMCPClient(        {            # # 数学计算 sse  --> server-math-sse.py            "math-sse": {                "url":"http://127.0.0.1:8000/sse",                "transport": "sse"            },            # 数学计算 stdio --> server-math-stdio.py            # "math-stdio": {            #     "command": "python",            #     "args": ["src/example/server-math-stdio.py"],            #     "transport": "stdio",            # }        }    )    tools = await client.get_tools()    agent = create_react_agent(        llm,        tools,        debug=True    )     # 循环接收用户输入    while True:        try:            # 提示用户输入问题            user_input = input("\n请输入您的问题(或输入 'exit' 退出):")            if user_input.lower() == "exit":                print("感谢使用!再见!")                break            # 调用代理处理问题            agent_response = await agent.ainvoke({"messages": [{"role": "user", "content": user_input}]})            print("\n>>>>>>>>>>>>>>>>>>>>>>> 开始输出结果 >>>>>>>>>>>>>>>>>>>>>>>\n")            # 调用抽取的方法处理输出结果            print_optimized_result(agent_response)            print("\n<<<<<<<<<<<<<<<<<<<<<<< 结果输出完成 <<<<<<<<<<<<<<<<<<<<<<<\n")        except Exception as e:            print(f"发生错误:{e}")            continue# 解析并输出结果def print_optimized_result(agent_response):    """    解析代理响应并输出优化后的结果。    :param agent_response: 代理返回的完整响应    """    messages = agent_response.get("messages", [])    steps = []  # 用于记录计算步骤    final_answer = None  # 最终答案     for message in messages:        if hasattr(message, "additional_kwargs") and "tool_calls" in message.additional_kwargs:            # 提取工具调用信息            tool_calls = message.additional_kwargs["tool_calls"]            for tool_call in tool_calls:                tool_name = tool_call["function"]["name"]                tool_args = tool_call["function"]["arguments"]                steps.append(f"调用工具: {tool_name}({tool_args})")        elif message.type == "tool":            # 提取工具执行结果            tool_name = message.name            tool_result = message.content            steps.append(f"{tool_name} 的结果是: {tool_result}")        elif message.type == "ai":            # 提取最终答案            final_answer = message.content     # 打印优化后的结果    print("\n***执行过程***:")    for step in steps:        print(f"- {step}")    if final_answer:        print(f"\n***最终结果***\n> {final_answer}\n") if __name__ == "__main__":    asyncio.run(main())
2.3.3 模型工具类utils.py
from langchain_deepseek import ChatDeepSeek#from langchain.chat_models import init_chat_model#from langchain_core.language_models import BaseChatModeldef init_model():    ## 公网-通义模型    # from langchain_community.chat_models.tongyi import ChatTongyi #dashscope     # llm = ChatTongyi(     #     temperature=0,    #     api_key="sk-XXXX",        #     )    # 公网-Deepseek模型    llm = ChatDeepSeek(        model="deepseek-chat",  # 尝试不同的模型名称        api_key="sk-xxxx"    )     ## 不行坑比较多,可能是版本功能问题,初始化后的llm 总是报各种错误    # llm = load_chat_model(f"{model_provider}/{model_name}",{    #     "api_key": api_key,    #     "base_url": base_url,    #     # enable_auto_tool_choice: True,    #     # tool_call_parser:True    # })    return llm;
2.3.4 调试过程

调用流程分析:

3. 常见问题

4. 相关文档

官网:modelcontextprotocol.io/introductio…

官网:docs.astral.sh/uv/

这里用于启动调试工具 npx @modelcontextprotocol/inspector@0.6.0

5. 总结

6. 附录

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

MCP 模型上下文协议 LLM Anthropic
相关文章