2025-03-27
AI
00

目录

第一部分 概述
1.1 为什么选择 MCP?
1.2 一般架构
1.3 基于MCP的集成架构
第二部分 MCP概念
2.1 核心架构
2.1.1 核心组件
2.1.2 连接生命周期
2.1.2.1 初始化
2.1.2.2 消息交换
2.1.2.3 终止
2.1.3 错误处理
2.2 Resources(资源)
2.2.1 资源URI
2.2.2 资源类型
2.2.3 资源发现
2.2.4 读取资源
2.2.5 资源更新
2.3 Prompts(提示)
2.3.1 提示结构
2.3.2 发现提示
2.3.3 使用提示
2.4 Tools(工具)
2.5 Roots(根目录)
2.5.1 什么是根目录?
2.5.2 为什么使用根目录?
2.5.3 根目录的工作原理
2.6 Transports(传输)
2.6.1 消息格式
2.6.2 内置传输类型
2.6.3 自定义传输
第三部分 MCP常用地址

第一部分 概述

MCP(Model Context Protocol )是一个开放协议,标准化了应用程序如何为大型语言模型(LLMs)提供上下文。可以将MCP想象成AI应用程序的USB-C接口。正如USB-C提供了连接设备与各种外设和配件的标准化方式,MCP提供了一种标准化方式,将AI模型与不同的数据源和工具连接起来。

1.1 为什么选择 MCP?

MCP可以帮助你在大型语言模型(LLMs)之上构建代理和复杂的工作流。LLMs经常需要与数据和工具集成,而MCP提供了以下优势:

  • 一个不断增长的预构建集成列表,LLM可以直接连接这些集成。
  • 在不同的LLM提供商和供应商之间切换的灵活性。
  • 在基础设施内确保数据安全的最佳实践。

1.2 一般架构

MCP基于客户端-服务器架构,核心思想是主机应用程序可以连接到多个服务器:

01.png

  • MCP 主机:应用程序如ClaudeIDEAI工具,通常需要通过MCP协议访问数据。
  • MCP 客户端:这些客户端与服务器保持直接连接,用于处理实际的协议通信。
  • MCP 服务器:轻量级程序,每个程序通过标准化的模型上下文协议暴露特定的功能。
  • 本地数据源:计算机上的文件、数据库和服务,MCP 服务器可以安全地访问这些数据。
  • 远程服务:通过互联网可访问的外部系统(例如,通过API),MCP服务器可以连接到这些服务。

1.3 基于MCP的集成架构

640.webp

相对于LLM应用直连外部资源,这里主要多了一个中间层(MCP Server),以及连接这个中间层的(MCP Client)。

第二部分 MCP概念

2.1 核心架构

MCP建立在一个灵活且可扩展的架构之上,能够实现大型语言模型(LLM)应用程序与集成之间的无缝通信。

MCP采用客户端-服务器架构,其中:

  • Hosts:是发起连接的LLM应用程序(例如Claude Desktop或IDE)。
  • Clients:在宿主应用程序内与服务器保持一对一连接。
  • Servers:向客户端提供上下文、工具和提示。

02.png

2.1.1 核心组件

  • 协议层:协议层负责消息封装、请求/响应关联以及高级通信模式。
  • 传输层:传输层负责客户端与服务器之间的实际通信。MCP支持多种传输机制:
    • 标准输入/输出传输(Stdio transport
      • 使用标准输入/输出进行通信。
      • 适用于本地进程。
    • 带有服务器发送事件(SSE)的HTTP传输
      • 使用服务器发送事件进行服务器到客户端的消息传递。
      • 使用HTTP POST进行客户端到服务器的消息传递。

相关信息

所有传输机制均使用JSON-RPC 2.0来交换消息。有关模型上下文协议消息格式的详细信息,可查看官网说明或JSON-RPC 2.0协议详解

  • 消息类型MCP主要有以下几种消息类型:
    • 请求(Requests):期望从另一端获得响应。
    • 结果(Results):对请求的成功响应。
    • 错误(Errors):表示请求失败。
    • 通知(Notifications):单向消息,不期望响应。

2.1.2 连接生命周期

2.1.2.1 初始化

03.png

  1. 客户端发送initialize请求,包含协议版本和功能。
  2. 服务器响应其协议版本和功能。
  3. 客户端发送initialized通知作为确认。
  4. 开始正常的消息交换。

2.1.2.2 消息交换

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

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

2.1.2.3 终止

任一方都可以终止连接:

  • 通过close()进行干净的关闭。
  • 传输断开连接。
  • 出现错误条件。

2.1.3 错误处理

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

ts
enum ErrorCode { // Standard JSON-RPC error codes ParseError = -32700, InvalidRequest = -32600, MethodNotFound = -32601, InvalidParams = -32602, InternalError = -32603 }

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

2.2 Resources(资源)

资源是MCP的核心原语,允许服务器向客户端暴露数据和内容,这些数据和内容可以被客户端读取,并用作与大型语言模型(LLM)交互的上下文。

资源代表了MCP服务器希望向客户端提供的任何类型的数据。这可以包括:

  • 文件内容
  • 数据库记录
  • API响应
  • 实时系统数据
  • 截图和图片
  • 日志文件
  • 以及其他更多内容

每个资源都通过一个唯一的URI进行标识,并且可以包含文本或二进制数据。

2.2.1 资源URI

资源通过URI进行标识,其格式如下:

[protocol]://[host]/[path]

例如:

  • file:///home/user/documents/report.pdf
  • postgres://database/customers/schema
  • screen://localhost/display1

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

2.2.2 资源类型

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

  • 文本资源:文本资源包含UTF-8编码的文本数据。这些适用于:
    • 源代码
    • 配置文件
    • 日志文件
    • JSON/XML数据
    • 纯文本
  • 二进制资源:二进制资源包含以base64编码的原始二进制数据。这些适用于:
    • 图像
    • PDF文件
    • 音频文件
    • 视频文件
    • 其他非文本格式

2.2.3 资源发现

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

  • 直接资源:服务器通过resources/list端点暴露一组具体的资源。每个资源包括:
json
{ uri: string; // Unique identifier for the resource name: string; // Human-readable name description?: string; // Optional description mimeType?: string; // Optional MIME type }
  • 资源模板:对于动态资源,服务器可以暴露URI模板,客户端可以使用这些模板构建有效的资源URI
json
{ 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 }

2.2.4 读取资源

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

服务器会返回资源内容的列表:

json
{ 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) } ] }

提示

服务器可能会对一个resources/read请求返回多个资源。例如,当读取一个目录时,这可以用来返回目录内的文件列表。

2.2.5 资源更新

MCP通过两种机制支持资源的实时更新:

  • 列表变更:服务器可以通过notifications/resources/list_changed通知客户端其可用资源列表的变化。
  • 内容变更:客户端可以订阅特定资源的更新:
    1. 客户端发送resources/subscribe请求,包含资源URI
    2. 资源变更时,服务器发送notifications/resources/updated通知。
    3. 客户端可以通过resources/read获取最新内容。
    4. 客户端可以通过resources/unsubscribe取消订阅。

2.3 Prompts(提示)

提示使服务器能够定义可重用的提示模板和工作流,客户端可以轻松地将其展示给用户和大型语言模型(LLM)。它们为标准化和共享常见的LLM交互提供了一种强大的方式。

MCP中的提示是预定义的模板,可以:

  • 接受动态参数
  • 包含来自资源的上下文
  • 链接多个交互
  • 指导特定的工作流
  • 作为UI元素展示(例如斜杠命令)

2.3.1 提示结构

每个提示的定义包括:

json
{ 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 } ] }

2.3.2 发现提示

客户端可以通过prompts/list端点发现可用的提示:

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

2.3.3 使用提示

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

json
// 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```" } } ] }

2.3.4 动态提示

提示可以是动态的,并包含以下内容:

  • 嵌入资源上下文

在处理prompts/get请求时:

json
{ "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请求时:

json
{ "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" } } } ] }
  • 多步骤工作流
ts
const debugWorkflow = { name: "debug-error", async getMessages(error: string) { return [ { role: "user", content: { type: "text", text: `Here's an error I'm seeing: ${error}` } }, { role: "assistant", content: { type: "text", text: "I'll help analyze this error. What have you tried so far?" } }, { role: "user", content: { type: "text", text: "I've tried restarting the service, but the error persists." } } ]; } };

2.4 Tools(工具)

工具是MCP中一个强大的原语,它允许服务器向客户端暴露可执行的功能。通过工具,LLM可以与外部系统交互、执行计算以及在现实世界中采取行动。

MCP中的工具允许服务器暴露可被客户端调用并由LLM用于执行操作的可执行函数。工具的关键特性包括:

  • 发现:客户端可以通过tools/list端点列出可用的工具。
  • 调用:工具通过tools/call端点被调用,服务器执行请求的操作并返回结果。
  • 灵活性:工具可以是从简单计算到复杂API交互的任何内容。

与资源类似,工具通过唯一名称进行标识,并且可以包含描述以指导其使用。然而,与资源不同的是,工具代表动态操作,可以修改状态或与外部系统交互。

每个工具的定义结构如下

json
{ name: string; // Unique identifier for the tool description?: string; // Human-readable description inputSchema: { // JSON Schema for the tool's parameters type: "object", properties: { ... } // Tool-specific parameters } }

MCP支持动态工具发现

  1. 客户端可以随时列出可用的工具。
  2. 服务器可以通过notifications/tools/list_changed通知客户端工具的变化。
  3. 工具可以在运行时添加或移除。
  4. 工具定义可以更新(尽管这应该谨慎进行)。

2.5 Roots(根目录)

根目录是MCP中的一个概念,用于定义服务器可以操作的边界。它们为客户端提供了一种方式,用于告知服务器相关资源及其位置。

2.5.1 什么是根目录?

根目录是一个客户端建议服务器关注的URI。当客户端连接到服务器时,它会声明服务器应该使用哪些根目录。根目录主要用于文件系统路径,但也可以是任何有效的URI,包括HTTP URL

例如,根目录可以是:

  • file:///home/user/projects/myapp
  • https://api.example.com/v1

2.5.2 为什么使用根目录?

根目录有以下几个重要的作用:

  1. 引导:它们告知服务器相关资源和位置。
  2. 明确性:根目录明确了哪些资源属于你的工作空间。
  3. 组织性:多个根目录允许你同时处理不同的资源。

2.5.3 根目录的工作原理

当客户端支持根目录时,它会:

  1. 在连接时声明roots能力。
  2. 向服务器提供一组建议的根目录。
  3. 在支持的情况下,当根目录发生变化时通知服务器。

虽然根目录是信息性的,并不强制执行,但服务器应该:

  1. 尊重提供的根目录。
  2. 使用根目录URI定位和访问资源。
  3. 优先在根目录边界内执行操作。

2.6 Transports(传输)

MCP中,传输为客户端和服务器之间的通信提供了基础。传输层负责消息发送和接收的底层机制。

2.6.1 消息格式

MCP使用[JSON-RPC 2.0](https://blog.jianggujin.com/post/19)作为其传输格式。传输层负责将MCP协议消息转换为JSON-RPC格式以进行传输,并将接收到的JSON-RPC消息转换回MCP协议消息。

使用的JSON-RPC消息有三种类型:

  • 请求(Requests)
json
{ jsonrpc: "2.0", id: number | string, method: string, params?: object }
  • 响应(Responses)
json
{ jsonrpc: "2.0", id: number | string, result?: object, error?: { code: number, message: string, data?: unknown } }
  • 通知(Notifications)
json
{ jsonrpc: "2.0", method: string, params?: object }

2.6.2 内置传输类型

MCP提供了两种标准的传输实现:

  • 标准输入/输出(stdio):通过标准输入和输出流实现通信。这种传输方式特别适用于本地集成和命令行工具。使用stdio的情况:

    • 构建命令行工具时
    • 实现本地集成时
    • 需要简单的进程间通信时
    • 使用shell脚本时
  • 服务器发送事件(SSE:通过HTTP POST请求实现客户端到服务器的通信,同时支持服务器到客户端的流式传输。使用SSE的情况:

    • 只需要服务器到客户端的流式传输时
    • 在受限网络环境中工作时
    • 实现简单的更新时

2.6.3 自定义传输

MCP支持为特定需求实现自定义传输。任何传输实现只需符合Transport接口即可:

可以为以下场景实现自定义传输:

  • 自定义网络协议
  • 专用通信通道
  • 与现有系统的集成
  • 性能优化

第三部分 MCP常用地址

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:蒋固金

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!