深度解析:Anthropic MCP 協議

正如 LSP 成爲了 IDE 的通用標準一樣,Anthropic 正在將 MCP 打造成 LLM 集成的開放標準。

前段時間 OpenAI 發佈了一個實時訪問第三方應用的功能來爲 ChatGPT 提供上下文(ChatGPT 升級爲實時協作助手),沒想到 Claude 這麼快就帶來了一個 LLM 協議標準,直接將 AI 能力拉滿(現在下結論爲時尚早)。不過當我看完整個協議以及簡單上手體驗後,我想說:“真牛逼,它以一種非入侵方式最大限度獲取到系統權限來拓展 AI 的能力邊界”!

模型上下文協議(MCP)是 Anthropic 推出的開放標準,旨在通過統一的客戶端-服務器架構解決 LLM 應用與數據源連接的難題。它支持通過同一協議訪問本地資源(如數據庫、文件)和遠程資源(如 Slack、GitHub API),無需定製集成。MCP 不僅共享數據,還可公開工具和交互模板,且內置安全性,確保資源由服務器完全掌控。目前 MCP 支持本地運行,未來將引入企業級認證的遠程支持,實現團隊間的安全共享。通過 Claude 桌面應用,開發者可在短時間內集成 MCP,快速連接多種數據源,推動 AI 集成的標準化發展。

MCP 簡介

近日,Model Context Protocol[1](MCP,模型上下文協議)正式開源。作爲一項連接 AI 助手與數據系統的新標準,MCP 的誕生旨在解決當前 AI 模型因數據孤島限制而無法充分發揮潛力的難題。這項由 Claude 推動的技術創新爲開發者提供了一個開放的、統一的解決方案,使 AI 系統能夠與多種內容存儲庫、業務工具和開發環境高效對接,顯著提升模型的響應質量與相關性。

背景

解決碎片化問題,爲 AI 打開數據大門。

當前,AI 助手已成爲主流工具,模型能力的進步使推理和質量得以迅速提升。然而,數據訪問的瓶頸依然存在。每個數據源需要獨立的定製集成,這種碎片化的方式不僅效率低下,還限制了 AI 的可擴展性。

MCP 的出現就是爲了改變現狀。它作爲一個通用的開放協議,爲數據源與 AI 系統之間的連接提供了統一標準,替代複雜的多源整合方式。這種設計極大簡化了數據接入過程,降低開發者的工作量,同時讓 AI 系統能夠更加全面和準確地訪問數據,推動系統從孤立走向協同。

MCP 核心

MCP 的架構清晰且開放,開發者可以通過 MCP 服務器對外提供數據,或構建 MCP 客戶端,將 AI 應用與這些服務器連接。爲推動開發者快速上手,MCP 開源了以下三大核心工具:

此外,Claude 3.5 Sonnet 模型還支持快速開發 MCP 服務器,使個人和企業能夠以最低的門檻實現與重要數據集的對接。

行業動態

目前,MCP 已被 Block 和 Apollo 等企業率先應用,並逐步融入 Zed[2](Zed MCP 源碼實現 context_server/protocol.rs[3])、Replit[4]、Codeium[5] 和 Sourcegraph[6] 等開發工具平臺。這些公司通過 MCP 增強 AI 對上下文的理解能力,使 AI 能夠在編碼任務中高效檢索相關信息,生成更準確、更具功能性的代碼。

Block 的首席技術官 Dhanji R. Prasanna 表示:“在 Block,開源不僅僅是一種開發模式,它是我們工作的基石,更是一種承諾——致力於創造能夠推動深遠變革、造福公衆的技術。像 Model Context Protocol 這樣的開源技術,是將 AI 與現實應用連接起來的橋樑,確保創新以開放、透明和協作爲核心。我們非常高興能參與這一協議的開發,並藉助它構建自主化系統,讓人們擺脫機械性任務的束縛,專注於更具創造性的工作。”

通過 MCP,開發者不再需要爲每個數據源維護獨立的連接器,而是可以基於標準協議構建一套通用的解決方案。隨着生態系統的不斷完善,AI 系統將能夠在不同工具和數據集之間保持上下文一致性,爲企業和開發者帶來更具前景的技術架構。

未來展望

Claude 團隊表示,他們致力於將 MCP 打造成一個協作性的開源生態系統,鼓勵開發者、企業以及早期技術探索者共同參與,推動具有上下文感知能力的 AI 工具走向更廣闊的未來。

開發者目前可以通過 Claude 桌面應用快速部署 MCP 服務,也可以根據官方提供的快速入門指南構建自己的 MCP 解決方案。同時,開源社區已開放了連接器和實現的代碼庫,支持開發者貢獻自己的擴展功能。

隨着 MCP 的普及,AI 系統將更好地突破數據隔離的限制,真正實現與現實環境的無縫對接。對於技術領域而言,這無疑是一次重要的里程碑,也爲 AI 生態的可持續發展帶來了全新可能。

lencx 演示

視頻詳情

我自己根據文檔幾分鐘就跑通了本地數據庫連接,在開始前需要做一些額外準備:

📌 前置條件

  • macOS 或 Windows 系統

  • 已安裝最新版本的 Claude 桌面應用(當前爲 0.7.1 版本)

  • uv[7] 0.4.18 或更高版本(可通過 uv --version 檢查)

  • Git(git --version 檢查)

  • SQLite(sqlite3 --version 檢查)

如果系統環境不存在 uv、Git、SQLite,可通過以下方式在命令行中進行安裝:

macOS 安裝

# Using Homebrew
brew install uv git sqlite3

# Or download directly:
# uv: https://docs.astral.sh/uv/
# Git: https://git-scm.com
# SQLite: https://www.sqlite.org/download.html

Windows 安裝

# Using winget
winget install --id=astral-sh.uv -e
winget install git.git sqlite.sqlite

# Or download directly:
# uv: https://docs.astral.sh/uv/
# Git: https://git-scm.com
# SQLite: https://www.sqlite.org/download.html

操作步驟

Step 1:創建測試數據庫

macOS 請執行以下命令(路徑:/Users/YOUR_USERNAME/test.db):

sqlite3 ~/test.db <<EOF
CREATE TABLE products (
  id INTEGER PRIMARY KEY,
  name TEXT,
  price REAL
);

INSERT INTO products (name, price) VALUES
  ('Widget', 19.99),
  ('Gadget', 29.99),
  ('Gizmo', 39.99),
  ('Smart Watch', 199.99),
  ('Wireless Earbuds', 89.99),
  ('Portable Charger', 24.99),
  ('Bluetooth Speaker', 79.99),
  ('Phone Stand', 15.99),
  ('Laptop Sleeve', 34.99),
  ('Mini Drone', 299.99),
  ('LED Desk Lamp', 45.99),
  ('Keyboard', 129.99),
  ('Mouse Pad', 12.99),
  ('USB Hub', 49.99),
  ('Webcam', 69.99),
  ('Screen Protector', 9.99),
  ('Travel Adapter', 27.99),
  ('Gaming Headset', 159.99),
  ('Fitness Tracker', 119.99),
  ('Portable SSD', 179.99);
EOF

Windows 用戶執行以下命令(路徑:C:\\Users\\YOUR_USERNAME\\test.db):

$sql = @'
CREATE TABLE products (
  id INTEGER PRIMARY KEY,
  name TEXT,
  price REAL
);

INSERT INTO products (name, price) VALUES
  ('Widget', 19.99),
  ('Gadget', 29.99),
  ('Gizmo', 39.99),
  ('Smart Watch', 199.99),
  ('Wireless Earbuds', 89.99),
  ('Portable Charger', 24.99),
  ('Bluetooth Speaker', 79.99),
  ('Phone Stand', 15.99),
  ('Laptop Sleeve', 34.99),
  ('Mini Drone', 299.99),
  ('LED Desk Lamp', 45.99),
  ('Keyboard', 129.99),
  ('Mouse Pad', 12.99),
  ('USB Hub', 49.99),
  ('Webcam', 69.99),
  ('Screen Protector', 9.99),
  ('Travel Adapter', 27.99),
  ('Gaming Headset', 159.99),
  ('Fitness Tracker', 119.99),
  ('Portable SSD', 179.99);
'@

cd ~
& sqlite3 test.db $sql

Step 2:配置 Claude 應用

配置文件路徑:

文件可通過命令打開,也可以通過 Claude 設置界面打開(點擊 編輯配置(Edit Config) 按鈕)。

用自己喜歡的編輯器將以下內容複製到 claude_desktop_config.json 中。注意將 /Users/lencx/test.db 路徑改爲自己的本機文件路徑。

{
  "mcpServers": {
    "sqlite": {
      "command": "uvx",
      "args": [
        "mcp-server-sqlite",
        "--db-path",
        "/Users/lencx/test.db"
      ]
    }
  }
}

這裏告訴 Claude 桌面應用:

Step 3:測試一下

將以下 Prompt 發送給 Claude,來驗證一切是否正常:

Can you connect to my SQLite database and tell me what products are available, and their prices?

如果一切正常,Claude 將連接到 SQLite MCP 服務器,然後查詢本地數據庫,使用格式化方式呈現出結果。

你還可以測試這些 Prompt:

運行原理

當你通過 MCP 與 Claude 桌面應用交互時,會經過以下步驟:

  1. 服務器發現:Claude 桌面應用在啓動時會連接到你配置的 MCP 服務器。

  2. 協議握手:當你詢問數據時,Claude 桌面應用會:

  1. 交互流程

在安全性方面:

這一設計確保了在使用 Claude 分析或交互本地數據時,用戶始終保持對數據訪問和操作的完全控制權,同時最大限度保障數據安全性。

常見問題

如果 Claude 桌面應用中沒有顯示內容,可以通過以下步驟排查問題:首先,檢查是否啓用了 MCP,點擊聊天框旁的 🔌 圖標,展開 “已安裝的 MCP 服務器”(Installed MCP Servers)確認配置的服務器是否顯示。然後導航到 Claude > Settings… 打開 “開發者(Developer)” 標籤頁驗證配置。最後完全退出並重啓 Claude 桌面應用以確保更改生效。

如果遇到 MCP 或數據庫錯誤,可以檢查 Claude 桌面應用的日誌,運行命令 tail -n 20 -f ~/Library/Logs/Claude/mcp*.log 查看最近的日誌信息。也可以測試數據庫連接,例如運行 sqlite3 ~/test.db ".tables" 確認數據庫是否正常工作。常見的修復方法包括檢查配置文件中的文件路徑、驗證數據庫文件的權限,以及確保 SQLite 已正確安裝。通過這些步驟,可以有效解決大部分問題。

MCP 協議詳解

官方文檔內容很長,爲了方便大家對 MCP 有一個全面瞭解,我對文檔做了簡單梳理。需要注意:目前文檔主要適配 macOS,其他系統指南將在晚些時候給出。

快速開始

目前 MCP 有三種方式可以幫助你快速開始,Python 或 TypeScript 選一個自己比較熟悉的構建服務即可。

開發工具

開發 MCP 服務器或將其與應用程序集成時,有效的調試至關重要。所以 MCP 提供了幾種不同層次的調試工具:

概念:核心架構(Core architecture)

MCP 遵循客戶端 - 服務器架構(client-server),其中:

核心組件

協議層(Protocol layer)

協議層負責消息的封裝、請求 / 響應的關聯,以及高層通信模式的管理。 主要類包括: Protocol  、ClientServer 等。以 Protocol 類爲例(TypeScript 版):

class Protocol<Request, Notification, Result> {
    // Handle incoming requests
    setRequestHandler<T>(schema: T, handler: (request: T, extra: RequestHandlerExtra) => Promise<Result>): void

    // Handle incoming notifications
    setNotificationHandler<T>(schema: T, handler: (notification: T) => Promise<void>): void

    // Send requests and await responses
    request<T>(request: Request, schema: T, options?: RequestOptions): Promise<T>

    // Send one-way notifications
    notification(notification: Notification): Promise<void>
}

傳輸層(Transport layer)

傳輸層負責客戶端和服務器之間的實際通信。MCP 支持多種傳輸機制:

所有傳輸機制都採用 JSON-RPC 2.0 協議進行消息交換。詳細的 MCP 消息格式規範可參考相關文檔。

消息類型(Message types)

MCP 定義了以下主要消息類型:

Connection 生命週期

初始化(Initialization)

消息交換(Message exchange)

初始化後,支持以下通信模式:

終止連接(Termination)

任一方可以終止連接:

錯誤處理(Error handling)

錯誤通過以下方式傳播:

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

SDK 和應用程序可以自定義 -32000 以上的錯誤碼。

代碼示例

以下是實現 MCP 服務器的基本代碼示例:

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new Server({
  name: "example-server",
  version: "1.0.0"
}, {
  capabilities: {
    resources: {}
  }
});

// Handle requests
server.setRequestHandler(ListResourcesRequestSchema, async () => {
  return {
    resources: [
      {
        uri: "example://resource",
        name: "Example Resource"
      }
    ]
  };
});

// Connect transport
const transport = new StdioServerTransport();
await server.connect(transport);

概念:資源(Resources)

資源是模型上下文協議(MCP)的核心組件之一,允許服務器將數據和內容暴露給客戶端,以便用作 LLM 交互的上下文信息。MCP 資源設計爲由應用程序控制,這意味着客戶端應用程序可以決定資源的使用方式和時機。例如:

所以資源代表 MCP 服務器希望向客戶端提供的任何類型的數據,包括:

每個資源通過唯一的 URI 標識,可以包含文本或二進制數據。

資源 URI

資源通過以下格式的 URI 進行標識([協議]://[主機]/[路徑]):

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

示例:

協議和路徑結構由 MCP 服務器實現定義,服務器也可以自定義 URI 方案。

資源類型

資源可以包含以下兩種內容類型:

資源發現

客戶端主要通過兩種方式發現可用資源:

資源更新

MCP 通過兩種機制支持資源的實時更新:

📌 最佳實踐

使用清晰且具有描述性的資源名稱和 URI,提供有助於 LLM 理解的資源描述,併爲已知資源設置合適的 MIME 類型。動態內容可以通過資源模板實現,而對於頻繁變化的資源,建議使用訂閱機制。此外,應優雅地處理錯誤,提供明確的錯誤信息,對於大規模資源列表可以使用分頁,並在適當情況下對資源內容進行緩存。URI 在處理前需要驗證,同時記錄任何自定義的 URI 方案以便後續參考。

在暴露資源時,安全性至關重要。必須驗證所有資源 URI,實施適當的訪問控制,並清理文件路徑以防止目錄遍歷攻擊。對二進制數據的處理需特別謹慎,可以考慮爲資源讀取操作設置速率限制並對資源訪問進行審計。傳輸中的敏感數據應加密,MIME 類型需要驗證,同時爲長時間運行的讀取操作設置超時機制。最後,資源的清理操作也應妥善處理,確保系統穩定性和安全性。

代碼實現

以下是在 MCP 服務器中實現資源支持的簡單示例:

const server = new Server({
  name: "example-server",
  version: "1.0.0"
}, {
  capabilities: {
    resources: {}
  }
});

// List available resources
server.setRequestHandler(ListResourcesRequestSchema, async () => {
  return {
    resources: [
      {
        uri: "file:///logs/app.log",
        name: "Application Logs",
        mimeType: "text/plain"
      }
    ]
  };
});

// Read resource contents
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
  const uri = request.params.uri;

  if (uri === "file:///logs/app.log") {
    const logContents = await readLogFile();
    return {
      contents: [
        {
          uri,
          mimeType: "text/plain",
          text: logContents
        }
      ]
    };
  }

  throw new Error("Resource not found");
});

概念:Prompts

Prompts 允許服務器定義可重用的 prompt 模板和工作流,方便客戶端呈現給用戶和 LLM。這是一種強大的方法,可以標準化並共享常見的 LLM 交互。Prompts 設計爲由用戶控制,這意味着它們從服務器暴露給客戶端,供用戶顯式選擇使用。

MCP 中的 Prompts 是預定義的模板,具備以下功能:

Prompt 結構定義

{
  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

客戶端可以通過 prompts/list 端點發現可用的 prompt:

// Request(請求)
{
  method: "prompts/list"
}

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

使用 Prompts

要使用 prompts,客戶端需要發出 prompts/get 請求:

// 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

Prompts 可以是動態的,主要有兩種:

📌 最佳實踐

在實現 prompts 功能時,應使用清晰且具有描述性的 prompt 名稱,爲 prompt 及其參數提供詳細說明,並驗證所有必需參數的完整性。同時,應優雅地處理缺失參數的情況,並考慮爲 prompt 模板實現版本控制。在適當情況下,可以緩存動態內容,記錄參數的預期格式,並考慮 prompt 的可組合性。此外,需實現錯誤處理機制,並使用多種輸入場景對 prompt 進行充分測試。

prompt 可通過多種方式集成到客戶端用戶界面,包括斜槓命令、快捷操作、上下文菜單項、命令面板入口、引導式工作流和交互式表單。對於 prompt 的更新和變更,服務器可以通過 prompts.listChanged 能力通知客戶端,通過 notifications/prompts/list_changed 類型發送通知,客戶端則需重新獲取 prompt 列表。

在安全性方面,需驗證所有參數的合法性並清理用戶輸入以防止惡意內容,同時考慮對 prompt 調用進行速率限制,實施訪問控制並審計 prompt 使用情況。對於敏感數據,應適當加密和保護,驗證生成內容的安全性,併爲 prompt 處理設置超時機制。此外,需注意 prompt 注入攻擊的風險,並記錄和公開安全需求文檔以保障 prompt 的可靠性和安全性。

代碼示例

以下是在 MCP 服務器中實現 prompts 的完整示例:

import { Server } from "@modelcontextprotocol/sdk/server";
import {
  ListPromptsRequestSchema,
  GetPromptRequestSchema
} from "@modelcontextprotocol/sdk/types";

const PROMPTS = {
  "git-commit": {
    name: "git-commit",
    description: "Generate a Git commit message",
    arguments: [
      {
        name: "changes",
        description: "Git diff or description of changes",
        required: true
      }
    ]
  },
  "explain-code": {
    name: "explain-code",
    description: "Explain how code works",
    arguments: [
      {
        name: "code",
        description: "Code to explain",
        required: true
      },
      {
        name: "language",
        description: "Programming language",
        required: false
      }
    ]
  }
};

const server = new Server({
  name: "example-prompts-server",
  version: "1.0.0"
}, {
  capabilities: {
    prompts: {}
  }
});

// List available prompts
server.setRequestHandler(ListPromptsRequestSchema, async () => {
  return {
    prompts: Object.values(PROMPTS)
  };
});

// Get specific prompt
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
  const prompt = PROMPTS[request.params.name];
  if (!prompt) {
    throw new Error(`Prompt not found: ${request.params.name}`);
  }

  if (request.params.name === "git-commit") {
    return {
      messages: [
        {
          role: "user",
          content: {
            type: "text",
            text: `Generate a concise but descriptive commit message for these changes:\n\n${request.params.arguments?.changes}`
          }
        }
      ]
    };
  }

  if (request.params.name === "explain-code") {
    const language = request.params.arguments?.language || "Unknown";
    return {
      messages: [
        {
          role: "user",
          content: {
            type: "text",
            text: `Explain how this ${language} code works:\n\n${request.params.arguments?.code}`
          }
        }
      ]
    };
  }

  throw new Error("Prompt implementation not found");
});

概念:工具(Tools)

工具是模型上下文協議(MCP)中的一項強大功能,允許服務器向客戶端暴露可執行的功能。通過工具,LLM 可以與外部系統交互、執行計算並在現實世界中採取行動。

工具設計爲由模型控制,這意味着工具從服務器暴露給客戶端,供 AI 模型自動調用(通常需要人類介入進行授權)。MCP 中的工具允許服務器暴露可被客戶端調用的可執行功能,這些功能可供 LLM 用於執行動作。工具的關鍵特性包括:

與資源類似,工具通過唯一的名稱標識,並可以包含描述以指導其使用。然而,與資源不同的是,工具代表動態操作,可以修改狀態或與外部系統交互。

工具結構定義

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

工具模式

以下是服務器可以提供的一些工具類型的示例。

系統操作(System operations):與本地系統交互的工具

{
  name: "execute_command",
  description: "Run a shell command",
  inputSchema: {
    type: "object",
    properties: {
      command: { type: "string" },
      args: { type: "array", items: { type: "string" } }
    }
  }
}

API 集成(API integrations):包裝外部 API 的工具

{
  name: "github_create_issue",
  description: "Create a GitHub issue",
  inputSchema: {
    type: "object",
    properties: {
      title: { type: "string" },
      body: { type: "string" },
      labels: { type: "array", items: { type: "string" } }
    }
  }
}

數據處理(Data processing):轉換或分析數據的工具

{
  name: "analyze_csv",
  description: "Analyze a CSV file",
  inputSchema: {
    type: "object",
    properties: {
      filepath: { type: "string" },
      operations: {
        type: "array",
        items: {
          enum: ["sum", "average", "count"]
        }
      }
    }
  }
}

代碼示例

以下是在 MCP 服務器中實現基本工具的示例:

const server = new Server({
  name: "example-server",
  version: "1.0.0"
}, {
  capabilities: {
    tools: {}
  }
});

// Define available tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [{
      name: "calculate_sum",
      description: "Add two numbers together",
      inputSchema: {
        type: "object",
        properties: {
          a: { type: "number" },
          b: { type: "number" }
        },
        required: ["a", "b"]
      }
    }]
  };
});

// Handle tool execution
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  if (request.params.name === "calculate_sum") {
    const { a, b } = request.params.arguments;
    return {
      toolResult: a + b
    };
  }
  throw new Error("Tool not found");
});

概念:採樣(Sampling)

採樣是 MCP 的一項強大功能,允許服務器通過客戶端請求 LLM 完成,從而實現複雜的代理行爲,同時保持安全性和隱私性。目前 Claude 桌面客戶端尚未支持此功能。

採樣流程包括以下步驟:

  1. 服務器向客戶端發送 sampling/createMessage 請求

  2. 客戶端審查請求內容,並可以對其進行修改

  3. 客戶端向 LLM 請求補全內容

  4. 客戶端對生成的補全內容進行審查

  5. 客戶端將結果返回給服務器

這種 “人類參與” 的設計確保用戶對 LLM 可訪問的數據和生成的內容保持控制權。

消息格式定義

採樣請求使用標準化的消息格式:

{
  messages: [
    {
      role: "user" | "assistant",
      content: {
        type: "text" | "image",

        // For text:
        text?: string,

        // For images:
        data?: string,             // base64 encoded
        mimeType?: string
      }
    }
  ],
  modelPreferences?: {
    hints?: [{
      name?: string                // Suggested model name/family
    }],
    costPriority?: number,         // 0-1, importance of minimizing cost
    speedPriority?: number,        // 0-1, importance of low latency
    intelligencePriority?: number  // 0-1, importance of capabilities
  },
  systemPrompt?: string,
  includeContext?: "none" | "thisServer" | "allServers",
  temperature?: number,
  maxTokens: number,
  stopSequences?: string[],
  metadata?: Record<string, unknown>
}

請求參數

消息(Messages)

messages 數組包含需要發送給 LLM 的對話歷史。每條消息包括:

模型偏好(Model preferences)

modelPreferences 對象允許服務器指定模型選擇偏好:

客戶端根據這些偏好和可用模型最終決定模型選擇。

系統提示(System prompt)

systemPrompt 是一個可選字段,允許服務器請求特定的系統提示。客戶端可以修改或忽略此字段。

上下文包含(Context inclusion)

includeContext 參數指定 MCP 上下文的包含範圍:

客戶端最終決定實際包含的上下文內容。

採樣參數(Sampling parameters)

可以使用以下參數微調 LLM 的採樣行爲:

響應格式

客戶端返回完成結果結構體定義:

{
  model: string,  // Name of the model used
  stopReason?: "endTurn" | "stopSequence" | "maxTokens" | string,
  role: "user" | "assistant",
  content: {
    type: "text" | "image",
    text?: string,
    data?: string,
    mimeType?: string
  }
}

以下是向客戶請求採樣的示例:

{
  "method": "sampling/createMessage",
  "params": {
    "messages": [
      {
        "role": "user",
        "content": {
          "type": "text",
          "text": "What files are in the current directory?"
        }
      }
    ],
    "systemPrompt": "You are a helpful file system assistant.",
    "includeContext": "thisServer",
    "maxTokens": 100
  }
}

📌 最佳實踐

在實現採樣功能時,應提供清晰且結構良好的提示,恰當地處理文本和圖像內容,並設置合理的標記數限制(token limits)。通過 includeContext 參數包含相關上下文,並在使用響應前進行驗證,同時優雅地處理錯誤。此外,應考慮對採樣請求實施速率限制,記錄預期的採樣行爲,使用多種模型參數進行測試,並監控採樣成本。

採樣功能設計考慮了人類監督。對於提示,客戶端應向用戶展示擬定的提示內容,用戶可以修改或拒絕提示,系統提示則可以被過濾或修改,上下文包含由客戶端控制。對於生成結果,客戶端應向用戶展示結果,用戶可以修改或拒絕生成結果,客戶端也可以過濾或修改結果,並由用戶決定使用的模型。

在安全性方面,需要驗證消息內容的合法性,清理敏感信息,並實施速率限制和數據傳輸加密。同時,妥善處理用戶數據隱私,審計採樣請求,控制成本暴露風險,設置超時機制,並優雅地處理模型錯誤。

採樣支持多種代理式工作流模式,例如讀取和分析資源、基於上下文決策、生成結構化數據、處理多步驟任務以及提供交互式協助。上下文管理應請求最小必要的上下文,清晰組織其結構,處理大小限制,根據需要更新上下文並清理過期內容。可靠的錯誤處理需要捕獲採樣失敗、處理超時錯誤、管理速率限制、驗證響應內容、提供備用行爲並記錄錯誤日誌。

需要注意的是,採樣功能存在一些限制,例如依賴客戶端能力、用戶控制行爲、上下文大小限制、速率限制和成本控制。此外,模型的可用性和響應時間可能會有所不同,並非所有內容類型都被支持。

概念:傳輸(Transports)

傳輸是模型上下文協議(MCP)的核心組件之一,爲客戶端和服務器之間的通信提供基礎。傳輸機制負責處理消息的發送和接收的底層邏輯。

MCP 使用 JSON-RPC 2.0 作爲傳輸格式。傳輸層負責將 MCP 協議消息轉換爲 JSON-RPC 格式進行傳輸,並將接收到的 JSON-RPC 消息還原爲 MCP 協議消息。

JSON-RPC 使用三種類型的消息:

內置傳輸類型

MCP 包括以下兩種標準傳輸實現:

標準輸入 / 輸出(Input/Output,stdio)

stdio 傳輸通過標準輸入和輸出流實現通信,特別適合本地集成和命令行工具。 適用場景:

const server = new Server({
  name: "example-server",
  version: "1.0.0"
}, {
  capabilities: {}
});

const transport = new StdioServerTransport();
await server.connect(transport);

服務器發送事件(SSE:Server-Sent Events)

SSE 傳輸通過 HTTP POST 實現客戶端到服務器的通信,同時支持服務器到客戶端的流式傳輸。 適用場景:

const server = new Server({
  name: "example-server",
  version: "1.0.0"
}, {
  capabilities: {}
});

const transport = new SSEServerTransport("/message", response);
await server.connect(transport);

自定義傳輸(Custom Transports)

MCP 支持輕鬆實現自定義傳輸,以滿足特定需求。任何傳輸實現只需符合 Transport 接口即可。 你可以爲以下場景實現自定義傳輸:

interface Transport {
  // Start processing messages
  start(): Promise<void>;

  // Send a JSON-RPC message
  send(message: JSONRPCMessage): Promise<void>;

  // Close the connection
  close(): Promise<void>;

  // Callbacks
  onclose?: () => void;
  onerror?: (error: Error) => void;
  onmessage?: (message: JSONRPCMessage) => void;
}

錯誤處理(Error Handling)

傳輸實現需要處理各種錯誤場景,包括:

通過設計健壯的錯誤處理機制,可以確保傳輸的穩定性和可靠性。 參考示例:

class ExampleTransport implements Transport {
  async start() {
    try {
      // Connection logic
    } catch (error) {
      this.onerror?.(new Error(`Failed to connect: ${error}`));
      throw error;
    }
  }

  async send(message: JSONRPCMessage) {
    try {
      // Sending logic
    } catch (error) {
      this.onerror?.(new Error(`Failed to send message: ${error}`));
      throw error;
    }
  }
}

📌 最佳實踐

在實現或使用 MCP 傳輸機制時,需要正確管理連接生命週期,確保在連接關閉時清理資源,並使用合適的超時時間。同時,應實現適當的錯誤處理機制,在發送前驗證消息內容,並記錄傳輸事件以便調試。在適當情況下,添加重連邏輯,處理消息隊列中的回壓問題,並持續監控連接的健康狀態。此外,還需要實施必要的安全措施以保證傳輸的可靠性。

在安全方面,需要重點關注身份驗證與授權,包括實現可靠的身份驗證機制、驗證客戶端憑證、使用安全的令牌處理方法以及執行授權檢查。在數據安全層面,應使用 TLS 加密網絡傳輸,保護敏感數據,驗證消息完整性,限制消息大小,並清理輸入數據以防止惡意內容。在網絡安全層面,需實施速率限制、設置合適的超時時間、處理拒絕服務(DoS)攻擊場景、監控異常通信模式,並制定合適的防火牆規則。

爲有效調試傳輸問題,可啓用調試日誌記錄、監控消息流量、檢查連接狀態並驗證消息格式,同時測試各種錯誤場景。使用網絡分析工具和錯誤跟蹤工具有助於發現問題。此外,可以通過健康檢查和資源使用監控,驗證系統在邊緣情況和高負載條件下的穩定性,從而確保傳輸機制的健壯性和安全性。

LSP 簡介

因 LSP 一定程度上影響了 MCP 的設計理念,所以感覺有必要介紹一下 LSP(非編程人士大概率都沒聽說過)。

概述

語言服務器協議(LSP[13]:Language Server Protocol)是一種開放的、基於 JSON-RPC 的通信協議,用於在編輯器或集成開發環境(IDE)與語言服務器之間進行交互。它提供了編程語言的核心功能,如自動補全、跳轉到定義、查找所有引用、懸停文檔提示等。這一協議通過標準化通信方式,使語言服務器和開發工具之間的協作更加高效。

背景 & 目標

爲特定編程語言提供功能(如自動補全、跳轉到定義、查找引用)需要耗費大量資源,尤其是傳統方式需要針對每種開發工具分別開發插件。這導致重複勞動並增加了開發成本。LSP 的目標是通過標準化協議,解決這一複雜性問題。具體來說:

語言服務器 & 客戶端

通過 LSP,客戶端和語言服務器之間的交互基於 JSON-RPC 格式的消息。

核心功能

協議基礎:JSON-RPC

LSP 的基礎是 JSON-RPC 協議,這種協議定義了請求和響應的結構。在一次典型交互中,客戶端會發送請求給語言服務器,例如請求代碼補全建議,而語言服務器則根據請求返回執行結果或錯誤信息。這種基於輕量級 JSON 數據格式的通信方式,不僅使協議實現簡單高效,還能適配多種開發環境。

請求 & 響應

代碼示例

以下是一個使用 JSON-RPC 進行交互的完整示例:

LSIF

LSIF(語言服務器索引格式)是 LSP 的補充協議(發音類似 “else if”),用於以圖結構存儲編程工件信息。它的目標是支持在開發工具或 Web 界面中進行離線代碼導航,無需本地源代碼(瞭解更多區別 LSP vs LSIF[14])。

LSP 的優勢

例如 CSS LSP 服務器支持 Atom 和 Eclipse 中的 CSS 自動補全。Python、Java 等語言都實現了各自的語言服務器,且已被廣泛應用於主流開發工具中。

當前規範與實現

微軟在覈心 LSP 倉庫中維護了一份語言服務器實現列表,同時社區站點(如 langserver.org[15])提供了關於各語言服務器和客戶端功能的更多信息。

總結

語言服務器協議(LSP)通過標準化語言服務器與開發工具的通信方式,極大地提升了開發效率和工具生態的擴展性。它是語言社區和工具社區之間的橋樑,使開發者能夠以更低成本享受高級編程功能。LSP 的出現標誌着現代開發工具在互操作性和用戶體驗上的一次重要飛躍。而 MCP 的出現,就是要做 LLM 界的 LSP 標準(野心挺大的)。

References

[1]

Model Context Protocol: https://www.anthropic.com/news/model-context-protocol

[2]

Zed: https://zed.dev/blog/mcp

[3]

context_server/protocol.rs: https://github.com/zed-industries/zed/blob/3901d4610115989d1b7e4d5c637a297da8219809/crates/context_server/src/protocol.rs

[4]

Replit: https://replit.com/ai

[5]

Codeium: https://codeium.com

[6]

Sourcegraph: https://sourcegraph.com/blog/cody-supports-anthropic-model-context-protocol

[7]

uv: https://docs.astral.sh/uv/

[8]

MCP Quickstart: https://modelcontextprotocol.io/quickstart

[9]

MCP Python: https://modelcontextprotocol.io/docs/first-server/python

[10]

MCP TypeScript: https://modelcontextprotocol.io/docs/first-server/typescript

[11]

MCP Inspector: https://modelcontextprotocol.io/docs/tools/inspector

[12]

URI 模板: https://datatracker.ietf.org/doc/html/rfc6570

[13]

LSP: https://microsoft.github.io/language-server-protocol

[14]

LSP vs LSIF: https://microsoft.github.io/language-server-protocol/overviews/lsif/overview

[15]

langserver.org: https://langserver.org

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/ASmcjW53HKokdYt1m-xyXA