Skip to content

2.5 MCP 服务器特性:提示词 / 资源 / 工具

MCP 服务器支持三大核心特性:

特性控制方式描述示例
提示词用户控制由用户选择调用的提示词模板斜杠命令、菜单选项
资源应用控制由客户端附加和管理的上下文数据文件内容、数据库表结构
工具模型控制暴露给大模型用于执行操作的函数API 请求、文件写入

可以把服务器的特性理解为”积木块”或”乐高”:

虽然每个特性(积木)本身很简单,但通过组合这些特性,可以构建出复杂的功能(就像用积木搭建城堡)。每个特性都有其特定的用途,不能被简化为更基础的操作。

2.5.1 什么是提示词

MCP 为服务器向客户端暴露提示词提供了一种标准方式。提示词允许服务器提供与大模型交互的结构化消息和指令。客户端可以发现可用的提示词,检索其内容,并提供自定义参数来使用它们。

提示词被设计为由用户控制,这意味着它们从服务器暴露给客户端之后,由用户来进行选择和使用。通常,在客户端的 UI 界面中,用户通过输入命令来触发提示词,用户可以自然地发现和调用可用的提示词。

例如,用户可以输入斜杠命令来调出可用的提示词模板,如图 2-11 所示。

图 2-11:用户输入命令调用提示词

2.5.2 提示词交互示例

  1. 服务器声明提示词特性

支持提示词特性的 MCP 服务器,需要在服务器定义时声明此项能力。

{
"capabilities": {
"prompts": {
"listChanged": true
}
}
}

"listChanged": true 表示服务器支持在提示词发生变化时发送通知。

  1. 客户端获取提示词列表

客户端给服务器发送一个 prompts/list 请求来获取服务器定义的提示词列表,请求示例如下:

{
"jsonrpc": "2.0",
"id": 1,
"method": "prompts/list",
"params": {
"cursor": "optional-cursor-value"
}
}

服务器收到请求后,返回提示词列表,响应示例如下:

{
"jsonrpc": "2.0",
"id": 1,
"result": {
"prompts": [
{
"name": "code_review",
"description": "Asks the LLM to analyze code quality and suggest improvements",
"arguments": [
{
"name": "code",
"description": "The code to review",
"required": true
}
]
}
],
"nextCursor": "next-page-cursor"
}
}

如果服务器定义的提示词过多,希望客户端通过分页参数来分批次查询,可以在响应提示词列表时,通过 result.nextCursor 字段来控制分页。

客户端在下一次请求中,带上服务器上一次返回的 result.nextCursor 值,作为新请求的 params.cursor 值来继续获取服务器的下一批提示词列表。

  1. 客户端获取单个提示词

客户端给服务器发送一个 prompts/get 请求来获取某个特定提示词的内容,请求示例如下:

{
"jsonrpc": "2.0",
"id": 2,
"method": "prompts/get",
"params": {
"name": "code_review",
"arguments": {
"code": "def hello():\n print('world')"
}
}
}

服务器收到请求后,拼凑请求参数,返回提示词内容,响应示例如下:

{
"jsonrpc": "2.0",
"id": 2,
"result": {
"description": "Code review prompt",
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "Please review this Python code:\ndef hello():\n print('world')"
}
}
]
}
}
  1. 服务器发送提示词变更通知

服务器在提示词发生变化时,向客户端发送提示词变更通知,通知示例如下:

{
"jsonrpc": "2.0",
"method": "notifications/prompts/list_changed"
}

客户端在接到通知后,应该重新请求服务器获取提示词列表。

  1. 提示词交互示例

客户端与服务器关于提示词的交互示例,如图 2-12 所示。

图 2-12:客户端与服务器提示词交互示例

2.5.3 什么是资源

MCP 为服务器向客户端暴露资源提供了一种标准方式。资源允许服务器共享为大模型提供上下文的数据,例如文件、数据库结构或特定的应用程序信息。每个资源由一个 URI(Uniform Resource Identifier,统一资源标识符) 进行唯一标识。

MCP 中的资源被设计为由应用驱动,也就是说由主机来根据其自身的需求,把服务器的资源融入到其上下文。例如,主机可以这样实现:

  • 通过一个列表或者目录树,显示可用资源
  • 允许用户搜索和筛选可用资源
  • 整合资源到上下文

2.5.4 资源交互示例

  1. 服务器声明资源特性

支持暴露资源的 MCP 服务器,需要在服务器定义时声明此项能力。

{
"capabilities": {
"resources": {
"subscribe": true,
"listChanged": true
}
}
}

此项能力支持两个可选项:

  • subscribe:是否允许客户端订阅和接收单个资源的变更通知
  • listChanged:当资源列表发生变化时,服务器是否会通知客户端

subscribelistChanged 都是可选的,服务器可以支持其中任何一个,或者两个都支持。

  1. 客户端获取资源列表

客户端给服务器发送一个 resources/list 请求来获取服务器定义的资源列表,请求示例如下:

{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/list",
"params": {
"cursor": "optional-cursor-value"
}
}

服务器收到请求后,返回资源列表,响应示例如下:

{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resources": [
{
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"description": "Primary application entry point",
"mimeType": "text/x-rust"
}
],
"nextCursor": "next-page-cursor"
}
}

跟获取提示词列表的逻辑一致,获取资源列表也支持分页控制。

  1. 客户端读取单个资源

客户端给服务器发送一个 resources/read 请求来获取某个特定资源的内容,请求示例如下:

{
"jsonrpc": "2.0",
"id": 2,
"method": "resources/read",
"params": {
"uri": "file:///project/src/main.rs"
}
}

服务器收到请求后,根据资源定位符,返回对应的资源内容,响应示例如下:

{
"jsonrpc": "2.0",
"id": 2,
"result": {
"contents": [
{
"uri": "file:///project/src/main.rs",
"mimeType": "text/x-rust",
"text": "fn main() {\n println!(\"Hello world!\");\n}"
}
]
}
}
  1. 客户端获取资源模板列表

MCP 允许客户端通过资源模板动态获取服务器的资源。

客户端给服务器发送一个 resources/templates/list 请求来获取服务器定义的资源模板列表,请求示例如下:

{
"jsonrpc": "2.0",
"id": 3,
"method": "resources/templates/list"
}

服务器收到请求后,返回资源模板列表,响应示例如下:

{
"jsonrpc": "2.0",
"id": 3,
"result": {
"resourceTemplates": [
{
"uriTemplate": "file:///{path}",
"name": "Project Files",
"description": "Access files in the project directory",
"mimeType": "application/octet-stream"
}
]
}
}

客户端可以根据需求,拼凑 uriTemplate 的参数来动态获取服务器的资源。

  1. 服务器发送资源列表变更通知

当服务器资源列表发生变化时,声明了 listChanged 能力的服务器应给客户端发送通知,通知示例如下:

{
"jsonrpc": "2.0",
"method": "notifications/resources/list_changed"
}

客户端在接到服务器的资源列表变更通知时,应该重新请求服务器获取资源列表。

  1. 客户端订阅资源更新通知

声明了 subscribe 能力的服务器,允许客户端订阅对某个资源的变更通知。

客户端订阅资源变更通知,请求示例如下:

{
"jsonrpc": "2.0",
"id": 4,
"method": "resources/subscribe",
"params": {
"uri": "file:///project/src/main.rs"
}
}

服务器在接到客户端对某个资源的订阅通知请求时,应该把客户端订阅的资源 URI 缓存起来,给客户端返回订阅成功消息,响应示例如下:

{
"jsonrpc": "2.0",
"id": 4,
"result": {}
}
  1. 客户端发送资源更新通知

当客户端订阅的资源内容发送变化时,服务器应该给客户端发送资源变更通知,通知示例如下:

{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"uri": "file:///project/src/main.rs"
}
}

客户端在接到服务器对某个资源的变更通知时,应该使用通知里的资源 URI,再次请求服务器获取该资源的最新内容。

  1. 资源交互示例

客户端与服务器关于资源的交互示例,如图 2-13 所示。

图 2-13:客户端与服务器资源交互示例

2.5.5 什么是工具

MCP 允许服务器暴露可供大模型调用的各类工具。工具让大模型能够跟外部系统交互,比如查询数据库、调用 API 或者执行计算。每一个工具有唯一的标识名和对其功能的描述。

MCP 中的工具设计为由模型控制,这意味着大模型可以根据其对上下文的理解和用户输入的内容自动发现和选择工具。

从信任和安全角度考虑,工具调用应该让用户感知,并且用户应该要有拒绝调用工具的权利。实现工具调用的应用应该:

  • 提供清晰的 UI,以明确展示哪些工具被暴露给大模型
  • 当工具被调用时,视觉呈现上要有明确的提示
  • 弹框提示用户确认对工具的调用操作

2.5.6 工具交互示例

  1. 服务器声明工具特性

支持工具特性的 MCP 服务器,需要在服务器定义时声明此项能力。

{
"capabilities": {
"tools": {
"listChanged": true
}
}
}

"listChanged": true 表示服务器支持在工具列表发生变化时发送通知。

  1. 客户端获取工具列表

客户端给服务器发送一个 tools/list 请求来获取服务器定义的工具列表,请求示例如下:

{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {
"cursor": "optional-cursor-value"
}
}

服务器收到请求后,返回工具列表,响应示例如下:

{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "get_weather",
"description": "Get current weather information for a location",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name or zip code"
}
},
"required": ["location"]
}
}
],
"nextCursor": "next-page-cursor"
}
}

获取工具列表跟获取提示词列表一样,支持分页控制。

  1. 客户端调用工具

客户端给服务器发送一个 tools/call 请求来调用某个工具,请求示例如下:

{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"location": "New York"
}
}
}

服务器收到请求后,根据工具名和参数,调用工具,返回工具调用结果,响应示例如下:

{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy"
}
],
"isError": false
}
}
  1. 服务器发送工具列表变更通知

当服务器可用的工具列表发生变化时,服务器给客户端发送工具列表变更通知,通知示例如下:

{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed"
}

客户端在接到服务器的工具变更通知时,应该重新请求服务器获取工具列表。

  1. 工具交互示例

客户端与服务器关于工具的交互示例,如图 2-14 所示。

图 2-14:客户端与服务器工具交互示例