什么是模型上下文协议(MCP)
为什么要创建 MCP?需要标准集成层
模型上下文协议 (MCP) 旨在解决构建代理 AI 应用程序中的一个根本性挑战:将孤立的大型语言模型 (LLM) 连接到外部世界。默认情况下,LLM 是强大的推理引擎,但其知识是静态的,与训练截止日期相关,并且缺乏访问实时数据或在外部系统中执行操作的原生能力。
传统上,将 LLM 连接到外部系统通常通过直接的自定义 API 集成来实现。这种方法很有效,但它要求每个应用程序开发人员学习每个工具的特定 API,编写代码来处理查询和解析结果,并随着时间的推移维护这种连接。随着 AI 应用程序和可用工具数量的增加,这为采用更标准化和更高效的方法提供了机会。
MCP 提供了这种标准化协议,其灵感来自于经过验证的标准,例如用于 Web 服务的 REST 和用于开发人员工具的语言服务器协议 (LSP)。MCP 为这种连接层建立了一种通用语言,而不是迫使每个应用程序开发人员都成为每种工具的 API 专家。
这使得关注点得以清晰分离。它为平台和工具提供商打开了大门,使他们能够通过本质上对 LLM 友好的单一、可重复使用的 MCP 服务器来展示他们的服务。维护集成的责任可以从单个 AI 应用程序开发者转移到外部系统的所有者。这形成了一个强大且可互操作的生态系统,其中任何兼容的应用程序都可以连接到任何兼容的工具,从而大大简化了开发和维护。

MCP 的工作原理:核心架构
MCP 架构
MCP 在客户端-服务器模型上运行,旨在将推理引擎 (LLM) 与一系列外部功能相连接。该架构从 LLM 开始,逐步公开使其能够与外界交互的组件。

该架构由三个关键组件组成:
- 主机是想要通过 MCP 访问数据的 LLM 应用程序(例如 Claude Desktop、IDE、AI 代理)。
- 服务器是轻量级程序,每个程序都通过 MCP 公开特定功能。
- 客户端在主机应用程序内部与服务器维护 1:1 连接。
MCP 客户端或主机

MCP 客户端或主机是编排 LLM 与一个或多个 MCP 服务器之间的交互的应用程序。客户端至关重要;它包含特定于应用的逻辑。虽然服务器提供基础功能,但客户端负责使用这些功能。它通过以下功能实现这一目标:
- 提示组装:收集来自不同服务器的上下文以构建 LLM 的最终有效提示
- 状态管理:在多次交互中维护对话历史和用户上下文
- 编排:决定向哪些服务器查询哪些信息,并在 LLM 决定使用工具时执行逻辑
MCP 客户端通过标准网络请求(通常通过 HTTPS)连接到已知的服务器终端。该协议的强大之处在于它标准化了它们之间的通信合同。该协议本身与语言无关,采用基于 JSON 的格式。因此,任何客户端,无论基于何种语言构建,都可以与任何服务器正确通信。
MCP 服务器
MCP 服务器是一个后端程序,充当特定数据源或工具的标准化包装器。它实现了 MCP 规范,以便通过网络公开诸如可执行工具或数据资源之类的功能。本质上,它将特定服务(如数据库查询或第三方 REST API)的独特协议转换为 MCP 的通用语言,使任何 MCP 客户端都可以理解。
动手实践:如何创建您的第一个 MCP 服务器?
让我们以公开工具的服务器为例(有关工具的更多信息请参见下文)。此服务器需要处理来自客户端的两个主要请求:
- 安装 SDK。
# Python pip install mcp # Node.js npm 安装 @modelcontextprotocol/sdk # 或者探索规范 git clone https://github.com/modelcontextprotocol/specification
- 创建您的第一个服务器。
from mcp.server.fastmcp import FastMCP import asyncio mcp = FastMCP("weather-server") @mcp.tool() async def get_weather(city: str) -> str: """Get weather for a city.""" return f"Weather in {city}: Sunny, 72°F" if __name__ == "__main__": mcp.run() - 连接到 Claude Desktop。
{ "mcpServers": { "weather": { "command": "python", "args": ["/full/path/to/weather_server.py"], "env": {} } } }
正式 SDK 和资源
您可以使用正式开源 SDK 开始构建自己的 MCP 客户端和服务器:
MCP 工具
工具是 MCP 服务器向客户端公开的特定可执行功能。与被动的数据资源(如文件或文档)不同,工具代表了 LLM 可以决定调用的操作,例如发送电子邮件、创建项目工单或查询实时数据库。
工具以以下方式与服务器交互:MCP 服务器声明其提供的工具。例如,Elastic 服务器将公开一个“list_indices”工具,定义其名称、用途和所需参数(例如,“list_indices”、“get_mappings”、“get_shards”和“搜索”)。
客户端连接到服务器并发现这些可用的工具。客户端将可用工具作为其系统提示或上下文的一部分提供给 LLM。当 LLM 的输出表明有意使用某个工具时,客户端会解析这一信息,并向相应的服务器发出正式请求,以使用指定的参数执行该工具。
动手实践:低级 MCP 服务器实现
虽然低级别示例有助于理解协议的机制,但大多数开发者会使用正式 SDK 来构建服务器。SDK 处理协议的模板部分(如消息解析和请求路由),使您能够专注于工具的核心逻辑。
以下示例使用正式 MCP Python SDK 创建一个公开 get_current_time 工具的简单服务器。这种方法比低级实现要简洁得多,也更具声明性。
导入异步
导入日期时间
从输入导入 AsyncIterator
从 mcp.server 导入(
MCPServer,
工具,
工具,
)
# --- 工具实现 ---
# SDK 中的 @tool 修饰器处理注册和模式生成。
# 我们定义一个简单的异步函数,它将作为 MCP 工具公开。
@tool
async def get_current_time() -> AsyncIterator[str]:
"""
以 ISO 8601 字符串形式返回当前 UTC 时间和日期。
此文档字符串自动用作 LLM 的工具描述。
“””
# SDK 需要一个异步迭代器,因此我们返回结果。
yield datetime.datetime.now(datetime.timezone.utc).isoformat()
# --- 服务器定义 ---
# 我们创建 MCPServer 的一个实例,将我们想要公开的工具传递给它。
# SDK 会自动发现任何用 @tool 装饰的函数。
服务器 = MCPServer(
工具=[
# SDK 会自动选取我们的装饰函数。
Tool.from_callable(get_current_time),
],
)
# --- 主执行块 ---
# SDK 提供了运行服务器的主要入口点。
# 这处理了所有底层通信逻辑(stdio、HTTP 等)。
async def main() -> None:
"""运行简单工具服务器。"""
等待 SERVER.run()
如果 __name__ == "__main__":
asyncio.run(main())
这个实际示例演示了使用 SDK 构建 MCP 服务器的强大功能:
- @tool 装饰器:此装饰器自动将 get_current_time 函数注册为 MCP 工具。它会检查函数的签名和文档字符串,以生成协议所需的模式和描述,从而无需您手动编写。
- MCPServer 实例:MCPServer 类是 SDK 的核心。您只需提供一个要公开的工具列表,它将自动完成剩下的工作。
- SERVER.run():此单一命令启动服务器并管理所有低级通信,包括处理不同的传输方法,如 stdio 或 HTTP。
如您所见,SDK 几乎抽象掉了协议的所有复杂性,使您能够仅用几行 Python 代码定义强大的工具。
3 个核心基元

MCP 通过定义服务器可以公开的三个核心基元来标准化 LLM 与外界交互的方式。这些基元提供了一个将 LLM 连接到外部功能的完整系统。
- 资源:提供上下文
- 功能:数据访问
- 类比:GET 终端
- 资源是为 LLM 提供上下文的主要机制。它们代表模型可以检索和使用的数据来源,以便为其响应提供信息,例如文档、数据库记录或搜索查询的结果。它们通常是只读操作。
- 工具:启用操作
- 功能:操作与计算
- 类比:POST 或 PUT 终端
- 工具是允许 LLM 执行操作并对外部系统产生直接影响的可执行函数。这使得代理能够超越简单的数据检索,执行诸如发送电子邮件、创建项目工单或调用第三方 API 等操作。
- 提示:引导互动
- 功能:交互模板
- 类比:工作流方案
- 提示是可重复使用的模板,用于指导 LLM 与用户或系统的交互。它们允许开发人员标准化常见或复杂的对话流,确保模型表现出更一致和可靠的行为。
模型上下文协议本身
核心概念
MCP 为 LLM 应用程序(主机)提供了一种与外部数据和功能(服务器)集成的标准化方法。该规范基于 JSON-RPC 2.0 消息格式构建,并定义了一组必需和可选组件,以实现丰富且有状态的交互。
核心协议和功能
MCP 的核心在于标准化通信层。所有实现必须支持基础协议和生命周期管理。
- 基本协议:所有通信使用标准的 JSON-RPC 消息(请求、响应和通知)。
- 服务器功能:服务器可以向客户端提供以下功能的任意组合:
- 资源:供用户或模型使用的上下文数据
- 提示:模板化消息和工作流
- 工具:供 LLM 调用的可执行函数
- 客户端功能:客户端可以向服务器提供这些功能,以实现更高级的双向工作流:
- 采样:允许服务器启动代理行为或递归 LLM 交互
- 信息请求:使服务器能够向用户请求其他信息
MCP 基础协议
MCP 建立在基本协议和生命周期管理的必要基础上。客户端和服务器之间的所有通信都必须遵守 JSON-RPC 2.0 规范,该规范定义了三种消息类型:
- 请求:发送以启动操作。它们需要一个唯一的字符串或整数 ID 来进行跟踪,并且不能在同一会话中重复使用 ID。
- 响应:为回复请求而发送。它们必须包含原始请求的 ID,并包含成功操作的“结果”对象或失败的“错误”对象。
- 通知:无需 ID 即可发送的单向消息,不需要接收者的响应。
客户端功能:启用高级工作流
对于更复杂的双向通信,客户端还可以向服务器提供功能:
- 采样:采样允许服务器通过客户端向 LLM 请求推理。这是一个强大的功能,可以实现多步骤代理工作流,其中工具可能需要向 LLM“询问问题”以在完成其任务之前获取更多信息。
- 信息请求:信息请求为服务器提供了一种正式机制,用于向最终用户请求更多信息。这对于在执行操作之前可能需要澄清或确认的交互式工具来说至关重要。
服务器功能:公开功能
服务器通过一组标准化功能向客户端公开其功能。服务器可以实现以下任意组合:
- 工具:工具是使 LLM 执行操作的主要机制。它们是服务器公开的可执行函数,允许 LLM 与外部系统交互,例如调用第三方 API、查询数据库或修改文件。
- 资源:资源表示 LLM 可以检索的上下文数据来源。与执行操作的工具不同,资源主要用于只读数据检索。它们是将 LLM 扎根于实时外部信息的机制,构成高级 RAG 管道的关键部分。
- 提示:服务器可以提供预定义的提示模板,供客户端使用。这使得常见、复杂或高度优化的提示能够实现标准化和共享,从而确保交互的一致性。
安全与信任
该规范对安全高度重视,明确了实施者应遵循的关键原则。该协议本身无法强制执行这些规则;责任在于应用程序开发人员。
- 用户同意与控制:用户必须明确同意并保留对所有数据访问和工具调用的控制权。清晰的授权 UI 至关重要。
- 数据隐私:未经明确同意,主机不得将用户数据传输到服务器,并且必须实施适当的访问控制措施。
- 工具安全:工具调用代表任意代码执行,必须谨慎对待。主机在调用任何工具之前必须获得用户的明确同意。
为什么 MCP 如此重要?
MCP 的核心优势在于其对模型和工具之间的通信和交互层的标准化。这为开发者创造了一个可预测且可靠的生态系统。标准化的关键领域包括:
- 统一连接器 API:一个用于连接任何外部服务的单一且一致的接口
- 标准化上下文:用于传递关键信息(如会话历史记录、嵌入、工具输出和长期记忆)的通用消息格式
- 工具调用协议:调用外部工具的约定请求和响应模式,确保可预测性
- 数据流控制:内置规则用于过滤、优先级排序、流式处理和批量处理上下文,以优化提示构建
- 安全和身份验证模式:用于 API 密钥或 OAuth 身份验证、速率限制和加密的常见挂钩,用于确保数据交换的安全
- 生命周期和路由规则:定义何时获取上下文、缓存多长时间以及如何在系统之间路由数据的约定
- 元数据和可观测性:统一的元数据字段,可在所有连接的模型和工具中实现一致的日志记录、指标和分布式跟踪
- 扩展点:定义用于添加自定义逻辑的挂钩,例如预处理和后处理步骤、自定义验证规则和插件注册
大规模扩展:解决“M×N”或乘积扩展集成难题
在快速发展的 AI 领域,开发人员面临着重大的集成挑战。AI 应用程序 (M) 需要访问大量外部数据源和工具 (N),从数据库和搜索引擎到 API 和代码存储库。在没有标准化协议的情况下,开发人员被迫解决“M×N 问题”,为每个应用程序到源的组合构建和维护独特的自定义集成。
这种方法会导致几个关键问题:
- 开发人员重复工作:团队在每个新的 AI 应用程序中反复解决相同的集成问题,浪费了宝贵的时间和资源。
- 令人难以应对的复杂性:不同的数据源以独特的方式处理类似的功能,从而形成了一个复杂且不一致的集成层。
- 过度维护:缺乏标准化导致了定制集成生态系统的脆弱性。单个工具的 API 的小更新或更改就可能会导致连接中断,需要持续的被动维护。
MCP 将这个 M×N 问题转换为更简单的 M+N 方程。通过创建通用标准,开发人员只需构建 M 个客户端(用于其应用程序)和 N 个服务器(用于其工具),从而大幅降低复杂性和维护开销。
比较代理方法
MCP 并不是检索增强生成 (RAG) 等流行模式或 LangChain 等框架的替代方案;它是一种基础连接协议,能够增强这些模式和框架的功能,使其更加模块化且易于维护。它通过标准化集成的“最后一英里”,解决了将应用程序连接到外部工具的普遍问题。
以下是 MCP 融入现代 AI 堆栈的方式:
为高级 RAG 提供支持
标准 RAG 功能强大,但通常连接到静态向量数据库。对于更高级的用例,您需要从实时的复杂系统中检索动态信息。
- 没有 MCP:开发人员必须编写自定义代码以将其 RAG 应用程序直接连接到搜索 API (如 Elasticsearch)的特定查询语言。
- 使用 MCP:搜索系统通过标准的 MCP 服务器展示其功能。RAG 应用程序现在可以使用简单、可重复使用的 MCP 客户端查询此实时数据源,而无需了解底层系统的具体 API。这使得 RAG 实现更简洁,并且将来更易于替换其他数据源。
与代理框架(例如 LangChain、LangGraph)集成
代理框架为构建应用程序逻辑提供了强大的工具,但它们仍然需要一种连接到外部工具的方式。
- 备选方案:
- 自定义代码:从头开始编写直接集成,这需要大量的工程工作和持续维护
- 特定于框架的工具包:使用预先构建的连接器或为特定框架编写自定义包装器(这会对该框架的架构产生依赖性,并将您锁定在其生态系统中。)
- MCP 的优势:MCP 提供了一个开放、通用的标准。工具提供商可以为其产品创建单个 MCP 服务器。现在,任何框架——LangChain、LangGraph 或定制的解决方案——都可以使用通用的 MCP 客户端与该服务器进行交互。这种方法更高效,并且防止了供应商锁定。
为什么协议可以简化一切
最终,MCP 的价值在于提供一种开放、标准化的替代方案,以应对集成的两个极端:
- 编写自定义代码容易出现问题且维护成本高昂。
- 使用特定于框架的包装器会形成一个半封闭的生态系统并产生对供应商的依赖。
MCP 将集成的所有权转移给外部系统的所有者,使他们能够提供单一、稳定的 MCP 终端。应用程序开发人员随后可以直接使用这些终端,从而大幅简化构建、扩展和维护强大、上下文感知型 AI 应用程序所需的工作量。
Elasticsearch MCP 服务器入门

如何:实现 Elasticsearch MCP 服务器
Elastic 为 Elasticsearch 开发了一个 MCP 服务器,使您能够轻松地将数据连接到任何兼容 MCP 的主机。通过服务器,您可以授予模型访问查询索引、检查映射和执行搜索的权限。
设置服务器非常简单。此 MCP 服务器作为 Docker 镜像提供,位于 docker.elastic.co/mcp/elasticsearch,它支持 MCP 的 stdio、SSE 和 streamable-HTTP 协议。
Claude Desktop 的配置如下:
{
"mcpServers": {
"elasticsearch-mcp-server": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "ES_URL", "-e", "ES_API_KEY",
"docker.elastic.co/mcp/elasticsearch",
"stdio"
],
"env": {
"ES_URL": "<elasticsearch-cluster-url>",
"ES_API_KEY": "<elasticsearch-api-key>"
}
}
}
}
MCP 服务器在 stdio 模式下使用此命令启动:
docker run -i --rm -e ES_URL -e ES_API_KEY docker.elastic.co/mcp/elasticsearch stdio
按照我们的 GitHub 存储库中的其余步骤进行操作。
与我们一起探讨 MCP 和 AI
深入了解 Elastic 的构建
随时了解与 AI 和智能搜索应用程序相关的所有信息。探索我们的资源,了解更多有关使用 Elastic 进行构建的信息。
立即通过免费的实践研讨会“MCP 与 Elasticsearch MCP Server 简介”开始构建。