人工智能|大模型—— 框架 ——一文详解MCP(从原理到实践)
最近 MCP 这个关键词逐渐活跃在我所浏览的一些文章及评论区中。突然发现我对它仅有粗糙的理解,我决定深入学习并记录一下。在阅读这篇文章前,我也简单地浏览了现有介绍 MCP 的文章。我发现大部分文章停留在“翻译” https://modelcontextprotocol.io/ 网站中的内容,或者花时间在绝大部分用户不关心的技术细节上(还有一些纯 AI 文)。因此,我将从使用者的角度出发,分享实用内容,并以一个示例展示 MCP 的开发过程与实际应用作为结尾。本篇旨在回答以下三个问题:
- 什么是 MCP?
- 为什么需要 MCP?
- 作为用户,我们如何使用/开发 MCP?
一、什么是MCP
MCP起源于2024年11月25日Anthropic发布的文章:Introducing the Model Context Protocol。MCP(Model Context Protocol,模型上下文协议)定义了应用程序和 AI 模型之间交换上下文信息的方式。这使得开发者能够以一致的方式将各种数据源、工具和功能连接到 AI 模型(一个中间协议层),就像 USB-C 让不同设备能够通过相同的接口连接一样。MCP的目标是创建一个通用标准,使AI应用程序的开发和集成变得更加简单和统一。
所谓一图胜千言,我这里引用一些制作的非常精良的图片来帮助理解:

可以看出,MCP就是以更标准的方式让 LLM Chat 使用不同工具,更简单的可视化如下图所示,这样你应该更容易理解“中间协议层”的概念了。Anthropic旨在实现 LLM Tool Call 的标准。

为保证阅读的流畅性,本文将 MCP Host / Client / Server 的定义后置。初学者/用户可暂不关注这些概念,不影响对 MCP 的使用。
二、为什么需要MCP
我认为 MCP 的出现是 prompt engineering 发展的产物。更结构化的上下文信息对模型的performance 提升是显著的。我们在构造 prompt 时,希望能提供一些更 specific 的信息(比如本地文件,数据库,一些网络实时信息等)给模型,这样模型更容易理解真实场景中的问题。
想象一下没有 MCP 之前我们会怎么做?我们可能会人工从数据库中筛选或者使用工具检索可能需要的信息,手动的粘贴到 prompt 中。随着我们要解决的问题越来越复杂,手工把信息引入到 prompt 中会变得越来越困难。为了克服手工 prompt 的局限性,许多 LLM 平台(如 OpenAI、Google)引入了 function call 功能。这一机制允许模型在需要时调用预定义的函数来获取数据或执行操作,显著提升了自动化水平。但是 function call 也有其局限性(我对于 function call vs MCP 的理解不一定成熟,欢迎大家补充),我认为重点在于 function call 平台依赖性强,不同 LLM 平台的 function call API 实现差异较大。例如,OpenAI 的函数调用方式与 Google 的不兼容,开发者在切换模型时需要重写代码,增加了适配成本。除此之外,还有安全性,交互性等问题。
数据与工具本身是客观存在的,只不过我们希望将数据连接到模型的这个环节可以更智能更统一。Anthropic 基于这样的痛点设计了 MCP,充当 AI 模型的"万能转接头",让 LLM 能轻松的获取数据或者调用工具。更具体的说 MCP 的优势在于:
- 生态 - MCP 提供很多现成的插件,你的 AI 可以直接使用。
- 统一性 - 不限制于特定的 AI 模型,任何支持 MCP 的模型(或者说是工具,如windsuf、cursor)都可以灵活切换。
- 数据安全 - 你的敏感数据留在自己的电脑上,不必全部上传。(因为我们可以自行设计接口确定传输哪些数据)
三、MCP的类型
MCP (Model Context Protocol) 是 Anthropic 推出的标准化 LLM 与外部工具通信协议,内置两种核心传输方式:
| 对比维度 | STDIO (标准输入 / 输出) 传输 | Streamable HTTP/SSE 传输 |
|---|---|---|
| 核心定位 | 本地 "面对面" 通信,单进程直连 | 远程 "电话热线" 通信,跨网络连接 |
| 连接方式 | 进程间直接通过标准 I/O 流传递消息 | 基于 HTTP 协议,支持 Server-Sent Events |
| 适用场景 | 本地模型与工具集成 (如 IDE 插件、桌面助手)、低延迟需求场景 | 远程服务器访问、多客户端共享服务、云端部署场景 |
| 并发支持 | 通常服务单个客户端 | 支持多个客户端同时连接 |
| 网络开销 | 无网络开销,延迟低至微秒级 | 存在网络传输延迟,需处理网络波动 |
| 安全特性 | 依赖本地系统权限隔离 | 可通过 HTTPS 加密传输,支持细粒度访问控制 |
| 实现复杂度 | 最简单,无需网络配置 | 中等,需处理 HTTP 连接管理和状态保持 |
四、如何使用MCP
(一)Claude APP
对于用户来说,我们并不关心 MCP 是如何实现的,通常我们只考虑如何更简单的用上这一特性。具体的使用方式参考官方文档:For Claude Desktop Users。这里不再赘述,配置成功后可以在 Claude 中测试:Can you write a poem and save it to my desktop? Claude 会请求你的权限后在本地新建一个文件。并且官方也提供了非常多现成的 MCP Servers,你只需要选择你希望接入的工具,然后接入即可。比如官方介绍的 filesystem 工具,它允许 Claude 读取和写入文件,就像在本地文件系统中一样。(二)Cursor
鉴于cursor需要收费,如果有账号或采用破解版工具的,软件配置可参考博文(MCP Server 开发实战指南(Python版) - Ryan_zheng - 博客园)自行配置,此处不再赘述。
(三)VSCode+Cline
详细的配置与使用请参考博文(使用MCP连接通义千问与ComfyUI实现文生图并自动发布小红书-开发者社区-阿里云)
(四)PyCharm
在 PyCharm 中部署 MCP(Model Context Protocol)服务可分为两个核心场景:使用 PyCharm 内置 MCP 服务器(连接 IDE 功能)和开发自定义 MCP 服务(实现 AI 模型上下文交互)。以下是详细分步操作,确保你能快速完成部署并验证可用性。
(1)安装uv包
此步骤需要科学上网
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"(2)创建项目目录
uv init mcp-server cd mcp-server(3)创建并激活虚拟环境
uv venv source .venv/bin/activate # Windows环境中使用以下命令: .venv\Scripts\activate(4)安装依赖
uv add "mcp[cli]" httpx(5)创建服务器实现文件
touch main.py # windows下使用:ni main.py(6)构建工具函数(Stdio)
为了让大模型能访问市面上主流框架的技术文档,我们主要通过用户输入的 query,结合指定 site 特定域名的谷歌搜索进行搜索相关网页,并对相关网页进行解析提取网页文本并返回。mcp server封装如下(Stdio):
# main.py from mcp.server.fastmcp import FastMCP from dotenv import load_dotenv import httpx import json import os from bs4 import BeautifulSoup from typing import Any import httpx from mcp.server.fastmcp import FastMCP from starlette.applications import Starlette from mcp.server.sse import SseServerTransport from starlette.requests import Request from starlette.routing import Mount, Route from mcp.server import Server import uvicorn load_dotenv() mcp = FastMCP("Agentdocs") USER_AGENT = "Agentdocs-app/1.0" SERPER_URL = "https://google.serper.dev/search" docs_urls = { "langchain": "python.langchain.com/docs", "llama-index": "docs.llamaindex.ai/en/stable", "autogen": "microsoft.github.io/autogen/stable", "agno": "docs.agno.com", "openai-agents-sdk": "openai.github.io/openai-agents-python", "mcp-doc": "modelcontextprotocol.io", "camel-ai": "docs.camel-ai.org", "crew-ai": "docs.crewai.com" } async def search_web(query: str) -> dict | None: payload = json.dumps({"q": query, "num": 2}) headers = { "X-API-KEY": os.getenv("SERPER_API_KEY"), "Content-Type": "application/json", } async with httpx.AsyncClient() as client: try: response = await client.post( SERPER_URL, headers=headers, data=payload, timeout=30.0 ) response.raise_for_status() return response.json() except httpx.TimeoutException: return {"organic": []} async def fetch_url(url: str): async with httpx.AsyncClient() as client: try: response = await client.get(url, timeout=30.0) soup = BeautifulSoup(response.text, "html.parser") text = soup.get_text() return text except httpx.TimeoutException: return "Timeout error" @mcp.tool() async def get_docs(query: str, library: str): """ 搜索给定查询和库的最新文档。 支持 langchain、llama-index、autogen、agno、openai-agents-sdk、mcp-doc、camel-ai 和 crew-ai。 参数: query: 要搜索的查询 (例如 "React Agent") library: 要搜索的库 (例如 "agno") 返回: 文档中的文本 """ if library not in docs_urls: raise ValueError(f"Library {library} not supported by this tool") query = f"site:{docs_urls[library]} {query}" results = await search_web(query) if len(results["organic"]) == 0: return "No results found" for result in results["organic"]: text += await fetch_url(result["link"]) return text if __name__ == "__main__": mcp.run(transport="stdio") 启动该脚本的命令如下:
uv run main.py(--)构建工具函数(SSE)
from mcp.server.fastmcp import FastMCP from dotenv import load_dotenv import httpx import json import os from bs4 import BeautifulSoup from typing import Any import httpx from mcp.server.fastmcp import FastMCP from starlette.applications import Starlette from mcp.server.sse import SseServerTransport from starlette.requests import Request from starlette.routing import Mount, Route from mcp.server import Server import uvicorn load_dotenv() mcp = FastMCP("docs") USER_AGENT = "docs-app/1.0" SERPER_URL = "https://google.serper.dev/search" docs_urls = { "langchain": "python.langchain.com/docs", "llama-index": "docs.llamaindex.ai/en/stable", "autogen": "microsoft.github.io/autogen/stable", "agno": "docs.agno.com", "openai-agents-sdk": "openai.github.io/openai-agents-python", "mcp-doc": "modelcontextprotocol.io", "camel-ai": "docs.camel-ai.org", "crew-ai": "docs.crewai.com" } async def search_web(query: str) -> dict | None: payload = json.dumps({"q": query, "num": 2}) headers = { "X-API-KEY": os.getenv("SERPER_API_KEY"), "Content-Type": "application/json", } async with httpx.AsyncClient() as client: try: response = await client.post( SERPER_URL, headers=headers, data=payload, timeout=30.0 ) response.raise_for_status() return response.json() except httpx.TimeoutException: return {"organic": []} async def fetch_url(url: str): async with httpx.AsyncClient() as client: try: response = await client.get(url, timeout=30.0) soup = BeautifulSoup(response.text, "html.parser") text = soup.get_text() return text except httpx.TimeoutException: return "Timeout error" @mcp.tool() async def get_docs(query: str, library: str): """ 搜索给定查询和库的最新文档。 支持 langchain、llama-index、autogen、agno、openai-agents-sdk、mcp-doc、camel-ai 和 crew-ai。 参数: query: 要搜索的查询 (例如 "React Agent") library: 要搜索的库 (例如 "agno") 返回: 文档中的文本 """ if library not in docs_urls: raise ValueError(f"Library {library} not supported by this tool") query = f"site:{docs_urls[library]} {query}" results = await search_web(query) if len(results["organic"]) == 0: return "No results found" for result in results["organic"]: text += await fetch_url(result["link"]) return text ## sse传输 def create_starlette_app(mcp_server: Server, *, debug: bool = False) -> Starlette: """Create a Starlette application that can serve the provided mcp server with SSE.""" sse = SseServerTransport("/messages/") async def handle_sse(request: Request) -> None: async with sse.connect_sse( request.scope, request.receive, request._send, # noqa: SLF001 ) as (read_stream, write_stream): await mcp_server.run( read_stream, write_stream, mcp_server.create_initialization_options(), ) return Starlette( debug=debug, routes=[ Route("/sse", endpoint=handle_sse), Mount("/messages/", app=sse.handle_post_message), ], ) if __name__ == "__main__": mcp_server = mcp._mcp_server import argparse parser = argparse.ArgumentParser(description='Run MCP SSE-based server') parser.add_argument('--host', default='0.0.0.0', help='Host to bind to') parser.add_argument('--port', type=int, default=8020, help='Port to listen on') args = parser.parse_args() # Bind SSE request handling to MCP server starlette_app = create_starlette_app(mcp_server, debug=True) uvicorn.run(starlette_app, host=args.host, port=args.port) 启动命令:
uv run main.py --host 0.0.0.0 --port 8020 以上 MCP server 代码直接在你的云服务器跑即可。
(7)客户端配置
①Cline插件
设置-插件-marketplace-搜索Cline工具并安装-重启pycharm-右侧工具栏点击Cline-添加mcp server


点击configure-点击Configure MCP Servers-按如下代码进行配置即可。

{ "mcpServers": { "mcp-server": { "command": "uv", "args": [ "--directory", "<你的mcp服务的路径>", "run", "main.py" ] } } } 配置成功后会在Mcp-Servers的服务列表中有显示(成功后有个小绿点),并可以选择此mcp服务是否启用

②Lingma插件(阿里)
由于cline是收费的,成本较高。大家也可以用Lingma(阿里大模型编程工具插件)进行配置,配置过程如下:
设置-插件-marketplace-搜索Lingma工具并安装-重启pycharm-右侧工具栏点击Lingma-插件设置-会话设置(可以自行选择每次询问或者自动执行)


Lingma-个人设置-左键进入MCP服务-添加MCP服务(可以选择手动添加或者配置文件添加,此处以手动添加为例)-



输入相关MCP配置参数-我的服务-查看是否连接成功(成功后会有一个绿色的链接符号+一个绿色的)


(五)OpenCode
自建MCP服务或者调用远程的MCP都可以。配置过程如下:
- 找到opencode配置文件(一般在c盘~.\.config\opencode),如果没有的话可以手动新建,名称是opencode.json
- 在配置文件中编写对应的mcp服务内容(有自己的固定格式(本地 or 远程),如下)
- 如果想继续添加其他的mcp服务,可以在“mcp”键对应的值中进一步添加。例如:我在自建mcp的基础上,添加了一个名为fetch的网页抓取mcp服务,效果如下图
## 本地mcp部署: { "$schema": "https://opencode.ac.cn/config.json", "mcp": { "my-local-mcp-server": { "type": "local", // Or ["bun", "x", "my-mcp-command"] "command": ["npx", "-y", "my-mcp-command"], "enabled": true, "environment": { "MY_ENV_VAR": "my_env_var_value", }, }, }, } ## 相关参数解释 选项 类型 (Type) 必需 描述 type 字符串 Y MCP 服务器连接的类型,必须是 "local"。 command 数组 Y 运行 MCP 服务器的命令和参数。 environment 对象 运行服务器时要设置的环境变量。 enabled 布尔值 在启动时启用或禁用 MCP 服务器。 timeout 数字 从 MCP 服务器获取工具的超时时间(以毫秒为单位)。默认为 5000(5 秒)。 ------------------------------------------------------------------ ## 远程MCP部署: { "$schema": "https://opencode.ac.cn/config.json", "mcp": { "my-remote-mcp": { "type": "remote", "url": "https://my-mcp-server.com", "enabled": true, "headers": { "Authorization": "Bearer MY_API_KEY" } } } } ## 相关参数解释 选项 类型 (Type) 必需 描述 type 字符串 Y MCP服务器连接的类型,必须是 "remote"。 url 字符串 Y 远程 MCP 服务器的 URL。 enabled 布尔值 在启动时启用或禁用 MCP 服务器。 headers 对象 发送请求时附带的标头。 oauth 对象 OAuth 身份验证配置。请参阅下面的 OAuth 部分。 timeout 数字 从 MCP 服务器获取工具的超时时间(以毫秒为单位)。默认为 5000以我本地创建的mcp-server为例,其配置参数如下,启动opencode后若mcp配置成功则会在左下角有一个状态显示,直接输入/mcps也可以进行mcp的启停(空格键可手动启动选定的mcp服务):





五、具体使用
以Langma插件为例,通过插件的对话功能,便能够通过 MCP 获取相关文档信息进行回答。例如,提问问题:
“帮我实现openai-agents-sdk构建agent的代码”

六、后续问题
等遇到其他问题再进一步补充吧,例如:1、把 fastapi接口发布成 mcp工具(https://github.com/tadata-org/fastapi_mcp/blob/main/README_zh-CN.md)等