引言
在第二篇文章中,我们讲了MCP的通信协议和数据传输。
那么在第三篇文章中,我们就来讲讲服务端 的核心原语,MCP 原语是 MCP 中最重要的概念。它们定义了客户端和服务器之间 可以相互提供哪些信息。这些原语明确规定了可以与 AI 应用共享 的上下文信息类型以及可以执行的操作范围。这和我们之前提到的核心能力息息相关,所以看懂这一篇非常重要,让我们接下来一起看看吧。
如果你对前面的内容感兴趣,可以点击这里跳转
MCP (Model Context Protocol) 技术理解 - 第一篇
MCP (Model Context Protocol) 技术理解 - 第二篇
服务端的三个核心原语
MCP 定义了服务器可以公开的三个核心原语:
- Tools:AI应用可以调用用来执行操作的可执行函数(例如,文件操作、API 调用、数据库查询)
- Resources:为AI应用提供上下文信息的数据源(例如,文件内容、数据库记录、API 响应)
- Prompts:可重用的模板,有助于构建与LLM的交互(例如,系统提示、少样本示例)
接下来我们来各自详细地介绍三种核心原语:
Tools
Tools是定义在模式中的接口 ,LLM可以调用这些接口。MCP 使用 JSON Schema 进行验证。每个Tool都执行单一操作,并具有明确定义的输入和输出。工具可能需要在执行前获得用户许可,这有助于确保用户对模型执行的操作保持控制
我们其实在前面已经说的很明白了,LLM可以通过Tools接口来替我们执行操作,而不止于仅仅给我们回复该怎么做。但是要注意的是我们实现Tools接口应该要保持单一职责原则,即一个Tool就保证它自己的功能,不要混杂着其他操作在其中。
下面是官方给的Tool的方法:
| 方法 | 目的 | 返回 |
|---|---|---|
tools/list |
探索可用工具 | 包含模式的工具定义数组 |
tools/call |
执行特定工具 | 工具执行结果 |
那么该如何定义一个Tool呢?下面是一个示例:
json
{
name: "searchFlights",
description: "Search for available flights",
inputSchema: {
type: "object",
properties: {
origin: { type: "string", description: "Departure city" },
destination: { type: "string", description: "Arrival city" },
date: { type: "string", format: "date", description: "Travel date" }
},
required: ["origin", "destination", "date"]
}
}
来个示例吧,假如我们想搜索某地到某地的对应日期的所有航班,我们的该如何调用,下面是例子: 查询多家航空公司并返回结构化的航班选项
less
searchFlights(origin: "NYC", destination: "Barcelona", date: "2024-06-15")
工具由模型控制,这意味着模型可以自动发现并调用它们。但是要注意的是,调用工具是一个很敏感的操作,我们对敏感操作要保证人为监督。
为了确保信任和安全,应用程序可以通过各种机制实现用户控制,例如:
- 在用户界面中显示可用工具,使用户能够定义在特定交互中是否应显示某个工具。
- 针对单个工具执行的审批对话框
- 用于预先批准某些安全操作的权限设置。
- 活动日志显示所有工具执行及其结果
通过权限校验和安全性确认,我们就可以保证某些敏感的Tool calling不会被滥用。
Resources
Resources提供结构化的信息访问,人工智能应用程序可以检索这些信息并将其作为上下文提供给模型。
那么Resources是如何运作的? Resources可以从文件、API、数据库或AI理解上下文所需的任何其他来源获取数据。应用程序可以直接访问这些信息,并决定如何使用它们------无论是选择相关部分、使用embedding进行搜索,还是将所有信息传递给模型。
MCP是如何"发现"Resources的?
Resources支持两种发现模式:
-
直接资源 - 指向特定数据的固定 URI。例如:
calendar://events/2024- 返回 2024 年的日历可用性 -
资源模板------带有参数的动态 URI,可实现灵活的查询。示例:
travel://activities/{city}/{category}- 按城市和类别返回活动travel://activities/barcelona/museums- 返回巴塞罗那所有博物馆
值得注意的是,每个 resource 有唯一的 URI 标识 ,支持文本和二进制内容,这里很重要🧐
那么Resources有什么方法?
| 方法 | 目的 | 返回 |
|---|---|---|
resources/list |
列出可用的直接资源 | 资源描述符数组 |
resources/templates/list |
发现资源模板 | 资源模板定义数组 |
resources/read |
获取资源内容 | 包含元数据的资源数据 |
resources/subscribe |
监控资源变化 | 订阅确认 |
不好懂?我们来看个例子缓解一下:)
以旅行规划为例,资源为AI应用程序提供相关信息的访问权限:
- 日历数据 (
calendar://events/2024)- 检查用户日程以保证可行性 - 旅行证件 (
file:///Documents/Travel/passport.pdf)- 获取重要文件 - 以往行程 (
trips://history/barcelona-2023) - 参考过去的旅行和偏好
AI 应用会检索这些资源并决定如何处理它们,无论是使用embedding或关键词搜索选择数据子集,还是将原始数据直接传递给模型。在这种情况下,它向模型提供日历数据、天气信息和旅行偏好,使模型能够检查可用性、查找天气模式并参考过去的旅行偏好。
资源模板示例:
json
{
"uriTemplate": "weather://forecast/{city}/{date}",
"name": "weather-forecast",
"title": "Weather Forecast",
"description": "Get weather forecast for any city and date",
"mimeType": "application/json"
}
{
"uriTemplate": "travel://flights/{origin}/{destination}",
"name": "flight-search",
"title": "Flight Search",
"description": "Search available flights between cities",
"mimeType": "application/json"
}
这些模板支持灵活的查询方式。例如,用户可以查询任意城市/日期组合的天气预报。对于航班查询,用户可以搜索任意两个机场之间的航线。当用户输入"NYC"作为机场,origin并尝试输入"Bar"作为destination机场时,系统可以建议"巴塞罗那 (BCN)"或"巴巴多斯 (BGI)"
Prompts
Prompts提供可重用的模板。它们允许 MCP 服务器作者为域提供参数化提示符,或展示如何最佳地使用 MCP 服务器。
那么Prompts是如何运作的?Prompts是结构化的模板,用于定义预期输入和交互模式。它们由用户控制,需要显式调用而非自动触发。Prompts可以感知上下文,引用可用Resource和Tools来创建全面的工作流程。与Resources类似,Prompts支持参数补全,帮助用户发现有效的参数值。
| 方法 | 目的 | 返回 |
|---|---|---|
prompts/list |
发现可用提示 | 提示描述符数组 |
prompts/get |
获取提示详情 | 包含参数的完整提示定义 |
那么Prompts到底有什么用呢?简单来说,prompt是一个预定义的、可重用的提示词模板,能够帮助用户快速调用常见的 AI 交互模式,也就是为常见任务提供结构化模板。
这里的关键词是"常见任务","结构化模板"。
听不懂?来个例子吧,我们还是以假期规划为例子
我们可以为"计划一次假期"编写以下的prompts
json
{
"name": "plan-vacation",
"title": "Plan a vacation",
"description": "Guide through vacation planning process",
"arguments": [
{ "name": "destination", "type": "string", "required": true },
{ "name": "duration", "type": "number", "description": "days" },
{ "name": "budget", "type": "number", "required": false },
{ "name": "interests", "type": "array", "items": { "type": "string" } }
]
}
难道我们不支持非结构化的输入输出吗?系统并非不接受非结构化的自然语言输入,而是支持:
- 选择"计划假期"模板
- 结构化输入:巴塞罗那,7 天,3000 美元,["海滩"、"建筑"、"美食"]
- 基于模板的一致工作流程执行
prompts由用户控制,需要显式调用。该协议赋予实现者自由,使其能够设计出与应用程序环境相协调的自然界面。其关键原则包括:
- 轻松发现可用prompts
- 对每个prompts的功能进行清晰描述
- 自然参数输入及验证
- 透明显示prompts的底层模板
应用程序通常通过各种用户界面模式显示prompts信息,例如:
- 斜杠命令(输入"/"可查看可用提示,例如 /plan-vacation)
- 用于可搜索访问的命令面板
- 常用提示的专用用户界面按钮
- 上下文菜单提供相关提示
以notion为例子,这些都是你能直接使用的prompts模板

小结
这一篇我们讲了服务器的三个核心原语,每一个都在MCP里面发挥至关重要的作用,理解这一块非常重要!下一篇我们讲客户端的核心原语。