MCP(Model Context Protocol )是一个开放协议,标准化了应用程序如何为大型语言模型(LLMs)提供上下文。可以将MCP想象成AI应用程序的USB-C接口。正如USB-C提供了连接设备与各种外设和配件的标准化方式,MCP提供了一种标准化方式,将AI模型与不同的数据源和工具连接起来。
MCP可以帮助你在大型语言模型(LLMs)之上构建代理和复杂的工作流。LLMs经常需要与数据和工具集成,而MCP提供了以下优势:
LLM可以直接连接这些集成。LLM提供商和供应商之间切换的灵活性。MCP基于客户端-服务器架构,核心思想是主机应用程序可以连接到多个服务器:

Claude、IDE或AI工具,通常需要通过MCP协议访问数据。API),MCP服务器可以连接到这些服务。
相对于LLM应用直连外部资源,这里主要多了一个中间层(MCP Server),以及连接这个中间层的(MCP Client)。
MCP建立在一个灵活且可扩展的架构之上,能够实现大型语言模型(LLM)应用程序与集成之间的无缝通信。
MCP采用客户端-服务器架构,其中:

MCP支持多种传输机制:
Stdio transport)
SSE)的HTTP传输
HTTP POST进行客户端到服务器的消息传递。相关信息
所有传输机制均使用JSON-RPC 2.0来交换消息。有关模型上下文协议消息格式的详细信息,可查看官网说明或JSON-RPC 2.0协议详解。
MCP主要有以下几种消息类型:

initialize请求,包含协议版本和功能。initialized通知作为确认。初始化完成后,支持以下模式:
任一方都可以终止连接:
close()进行干净的关闭。MCP定义了以下标准错误代码:
tsenum ErrorCode {
  // Standard JSON-RPC error codes
  ParseError = -32700,
  InvalidRequest = -32600,
  MethodNotFound = -32601,
  InvalidParams = -32602,
  InternalError = -32603
}
SDK和应用程序可以在-32000以上定义自己的错误代码。
资源是MCP的核心原语,允许服务器向客户端暴露数据和内容,这些数据和内容可以被客户端读取,并用作与大型语言模型(LLM)交互的上下文。
资源代表了MCP服务器希望向客户端提供的任何类型的数据。这可以包括:
每个资源都通过一个唯一的URI进行标识,并且可以包含文本或二进制数据。
资源通过URI进行标识,其格式如下:
[protocol]://[host]/[path]
例如:
file:///home/user/documents/report.pdfpostgres://database/customers/schemascreen://localhost/display1协议和路径结构由MCP服务器实现定义。服务器可以定义自己的自定义URI方案。
资源可以包含两种类型的内容:
UTF-8编码的文本数据。这些适用于:
JSON/XML数据base64编码的原始二进制数据。这些适用于:
客户端可以通过两种主要方法发现可用资源:
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
}
要读取资源,客户端需要使用资源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请求返回多个资源。例如,当读取一个目录时,这可以用来返回目录内的文件列表。
MCP通过两种机制支持资源的实时更新:
notifications/resources/list_changed通知客户端其可用资源列表的变化。resources/subscribe请求,包含资源URI。notifications/resources/updated通知。resources/read获取最新内容。resources/unsubscribe取消订阅。提示使服务器能够定义可重用的提示模板和工作流,客户端可以轻松地将其展示给用户和大型语言模型(LLM)。它们为标准化和共享常见的LLM交互提供了一种强大的方式。
MCP中的提示是预定义的模板,可以:
UI元素展示(例如斜杠命令)每个提示的定义包括:
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
    }
  ]
}
客户端可以通过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
        }
      ]
    }
  ]
}
要使用提示,客户端需要发起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```"
      }
    }
  ]
}
提示可以是动态的,并包含以下内容:
在处理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"
        }
      }
    }
  ]
}
tsconst 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."
        }
      }
    ];
  }
};
工具是MCP中一个强大的原语,它允许服务器向客户端暴露可执行的功能。通过工具,LLM可以与外部系统交互、执行计算以及在现实世界中采取行动。
MCP中的工具允许服务器暴露可被客户端调用并由LLM用于执行操作的可执行函数。工具的关键特性包括:
tools/list端点列出可用的工具。tools/call端点被调用,服务器执行请求的操作并返回结果。与资源类似,工具通过唯一名称进行标识,并且可以包含描述以指导其使用。然而,与资源不同的是,工具代表动态操作,可以修改状态或与外部系统交互。
每个工具的定义结构如下:
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支持动态工具发现:
notifications/tools/list_changed通知客户端工具的变化。根目录是MCP中的一个概念,用于定义服务器可以操作的边界。它们为客户端提供了一种方式,用于告知服务器相关资源及其位置。
根目录是一个客户端建议服务器关注的URI。当客户端连接到服务器时,它会声明服务器应该使用哪些根目录。根目录主要用于文件系统路径,但也可以是任何有效的URI,包括HTTP URL。
例如,根目录可以是:
file:///home/user/projects/myapphttps://api.example.com/v1根目录有以下几个重要的作用:
当客户端支持根目录时,它会:
roots能力。虽然根目录是信息性的,并不强制执行,但服务器应该:
在MCP中,传输为客户端和服务器之间的通信提供了基础。传输层负责消息发送和接收的底层机制。
MCP使用[JSON-RPC 2.0](https://blog.jianggujin.com/post/19)作为其传输格式。传输层负责将MCP协议消息转换为JSON-RPC格式以进行传输,并将接收到的JSON-RPC消息转换回MCP协议消息。
使用的JSON-RPC消息有三种类型:
json{
  jsonrpc: "2.0",
  id: number | string,
  method: string,
  params?: object
}
json{
  jsonrpc: "2.0",
  id: number | string,
  result?: object,
  error?: {
    code: number,
    message: string,
    data?: unknown
  }
}
json{
  jsonrpc: "2.0",
  method: string,
  params?: object
}
MCP提供了两种标准的传输实现:
标准输入/输出(stdio):通过标准输入和输出流实现通信。这种传输方式特别适用于本地集成和命令行工具。使用stdio的情况:
服务器发送事件(SSE):通过HTTP POST请求实现客户端到服务器的通信,同时支持服务器到客户端的流式传输。使用SSE的情况:
MCP支持为特定需求实现自定义传输。任何传输实现只需符合Transport接口即可:
可以为以下场景实现自定义传输:


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