抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Model Context Protocol(MCP)是一个标准化协议,旨在简化客户端与服务器间的资源管理、动态提示交互及通信。

简介

MCP是24年底才被提出来的一项新协议,主要是对AI的外部方法调用的一种补充。官方分别设计了两种数据传输方式——stdio和sse(服务器事件),大模型时代大家仿佛对sse过多的吹捧,所以MCP也倾向于使用sse,不过笔者在这里有不同看法,传统的全双工的websocket也有对应优势,后续有空单独开一篇文章说说。

摘要

本篇文章的主要在介绍MCP,以下是其主要结构:

资源管理

支持文本(UTF-8编码)与二进制(Base64编码)资源,通过URI(如file:///report.pdf)唯一标识。客户端可通过静态列表(resources/list)或动态模板发现资源,并订阅实时更新(如内容变更通知)

提示(Prompt)

提供可复用的交互模板,支持参数化(如编程语言、时间范围)。客户端通过prompts/get调用提示,并嵌入动态资源(如日志、代码文件),服务端返回结构化内容(含文本或资源引用)。

通信协议

基于JSON-RPC 2.0,支持请求、响应、通知三种消息类型,内置stdio(本地工具)和SSE(流式传输)等通信方式,允许自定义传输实现。连接生命周期涵盖初始化(版本协商)、信息交换(请求-响应/通知)及终止流程。

资源

资源定义

MCP在资源方面类似于RESTful的定义,有助于客户端发现并读取用户资源。

资源类型

资源可以包含两种类型的内容:

文件资源

UTF-8 编码的文本数据:源代码、配置文件、日志文件、JSON/XML、纯文本等。

二进制资源

base64编码的原始二进制数据:图片、PDF、音频文件、视频文件、其他非文本格式。

资源URI

资源使用遵循[protocol]://[host]/[path]格式的URI来标识。例如

1
2
3
`file:///home/user/documents/report.pdf` 
`postgres://database/customers/schema`
`screen://localhost/display1`

协议路径结构由 MCP 服务器实现定义。服务器可以定义自己的自定义 URI 方案。

资源发现

客户端可以通过两种主要方法发现可用资源:直接资源资源模板

直接资源

服务器通过resources/list端点公开具体资源的列表,每个资源格式:

资源定义格式
1
2
3
4
5
6
{
uri: string; // Unique identifier for the resource
name: string; // Human-readable name
description?: string; // Optional description
mimeType?: string; // Optional MIME type
}

资源模板

对于动态资源,服务器可以公开URI模板,客户端可以使用它来构建有效资源URI:

动态资源模板定义格式
1
2
3
4
5
6
{
uriTemplate: string; // URI template following RFC 6570
name: string; // Human-readable name for this type
description?: string; // Optional description
mimeType?: string; // Optional MIME type for all matching resources
}

读取资源

要读取资源,客户端需要使用资源 URI 发出resources/read请求。

服务器以资源内容列表进行响应:

服务器资源响应定义格式
1
2
3
4
5
6
7
8
9
10
11
12
{
contents: [
{
uri: string; // The URI of the resource
mimeType?: string; // Optional MIME type

// One of:
text?: string; // For text resources
blob?: string; // For binary resources (base64 encoded)
}
]
}

资源更新

MCP通过两种机制实现资源的实时更新功能:列出更改内容变更

列出更改

当可用资源列表(内容数量)发生变化时,服务器可以通过notifications/resources/list_changed通知通知客户端。

内容变更

客户可以订阅特定的资源更新:

  1. 客户端使用资源 URI 发送resources/subscribe
  2. 当资源发生变化时,服务器发送notifications/resources/updated
  3. 客户端可以使用resources/read获取最新内容
  4. 客户端可以使用resources/unsubscribe取消订阅

资源最佳实践

Prompt

MCP可以创建可以重复使用的Prompt和工作流程。

Prompt结构

title
1
2
3
4
5
6
7
8
9
10
11
{
name: string; // Unique identifier for the prompt
description?: string; // Human-readable description
arguments?: [ // Optional list of arguments
{
name: string; // Argument identifier
description?: string; // Argument description
required?: boolean; // Whether argument is required
}
]
}

发现提示

客户端可以通过prompt/list 发现可用提示:

title
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Request
{
method: "prompts/list"
}

// Response
{
prompts: [
{
name: "analyze-code",
description: "Analyze code for potential improvements",
arguments: [
{
name: "language",
description: "Programming language",
required: true
}
]
}
]
}

使用提示

要使用提示,客户端需要发出 prompts/get 请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Request
{
method: "prompts/get",
params: {
name: "analyze-code",
arguments: {
language: "python"
}
}
}

// Response
{
description: "Analyze Python code for potential improvements",
messages: [
{
role: "user",
content: {
type: "text",
text: "Please analyze the following Python code for potential improvements:\n\n```python\ndef calculate_sum(numbers):\n total = 0\n for num in numbers:\n total = total + num\n return total\n\nresult = calculate_sum([1, 2, 3, 4, 5])\nprint(result)\n```"
}
}
]
}

动态提示

提示可以是动态的,包括:

嵌入资源上下文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"name": "analyze-project",
"description": "Analyze project logs and code",
"arguments": [
{
"name": "timeframe",
"description": "Time period to analyze logs",
"required": true
},
{
"name": "fileUri",
"description": "URI of code file to review",
"required": true
}
]
}

处理prompts/get请求时:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "Analyze these system logs and the code file for any issues:"
}
},
{
"role": "user",
"content": {
"type": "resource",
"resource": {
"uri": "logs://recent?timeframe=1h",
"text": "[2024-03-14 15:32:11] ERROR: Connection timeout in network.py:127\n[2024-03-14 15:32:15] WARN: Retrying connection (attempt 2/3)\n[2024-03-14 15:32:20] ERROR: Max retries exceeded",
"mimeType": "text/plain"
}
}
},
{
"role": "user",
"content": {
"type": "resource",
"resource": {
"uri": "file:///path/to/code.py",
"text": "def connect_to_service(timeout=30):\n retries = 3\n for attempt in range(retries):\n try:\n return establish_connection(timeout)\n except TimeoutError:\n if attempt == retries - 1:\n raise\n time.sleep(5)\n\ndef establish_connection(timeout):\n # Connection implementation\n pass",
"mimeType": "text/x-python"
}
}
}
]
}

通信协议

消息格式

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

请求

请求格式
1
2
3
4
5
6
{
jsonrpc: "2.0",
id: number | string,
method: string,
params?: object
}

响应

响应格式
1
2
3
4
5
6
7
8
9
10
{
jsonrpc: "2.0",
id: number | string,
result?: object,
error?: {
code: number,
message: string,
data?: unknown
}
}

通知

通知格式
1
2
3
4
5
{
jsonrpc: "2.0",
method: string,
params?: object
}

错误处理

MCP 定义了以下标准错误代码:

MCP错误代码
1
2
3
4
5
6
7
8
enum ErrorCode {
// Standard JSON-RPC error codes
ParseError = -32700,
InvalidRequest = -32600,
MethodNotFound = -32601,
InvalidParams = -32602,
InternalError = -32603
}

SDK 和应用程序可以定义自己的 -32000 以上的错误代码。

错误通过以下方式传播:

  • 请求的错误响应
  • 传输中的错误事件
  • 协议级错误处理程序

内置传输类型

标准输入/输出 (stdio)

🧷stdio 传输支持通过标准输入和输出流进行通信。这对于本地集成命令行工具特别有用。

服务器发送事件 (SSE)

🧷SSE 传输通过 HTTP POST 请求实现服务器到客户端的流式传输,从而实现客户端到服务器的通信。

自定义传输

🧷MCP 可以轻松实现满足特定需求的自定义传输。任何传输实现只需符合 Transport 接口

连接生命周期

---
title: 生命周期
---
flowchart LR
    Start([开始]) --> 初始化
    初始化 --> 信息交换
    信息交换 --> 终止
    终止 --> Stop([结束])

1.初始化

sequenceDiagram
    participant C as 客户端
    participant S as 服务端
    C ->> S: 初始化请求
    S ->> C: 初始化回复
    C ->> S: 初始化完成通知
    Note over C,S: 连接已建立
  1. 客户端发送带有协议版本和功能initialize请求
  2. 服务器以其协议版本和功能进行响应
  3. 客户端发送initialized通知作为确认
  4. 开始正常信息交换

2.信息交换

初始化后,支持以下模式:

  • 请求-响应:客户端或服务器发送请求,对方响应
  • 通知:任何一方发送单向消息

3.终止

任何一方都可以终止连接:

  • 通过close()彻底关闭
  • 传输断开
  • 错误情况

评论

发现文章有误欢迎指出,感谢你友善的评论😙。