MCP协议

原理讲解

基础概念

Introduction - Model Context Protocol

  • MCP Host:想要通过 MCP 访问数据的程序,例如 Claude Desktop、IDE 或 AI 工具
  • MCP Clients:与服务器保持 1:1 连接的协议客户端
  • MCP Servers:轻量级程序,每个程序通过标准化模型上下文协议公开特定功能
  • Local Data Sources: MCP 服务器可以安全访问的计算机文件、数据库和服务
  • Remote Services: MCP 服务器可以通过互联网(例如,通过 API)连接的外部系统

核心组件

协议层

协议层处理消息框架,请求/响应链接和高级通信模式。

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

传输层

运输层处理客户与服务器之间的实际通信。 MCP支持多种运输机制:

  1. Stdio transport
    • 使用标准输入/输出进行通信
    • 适用于本地流程的处理
  1. HTTP with SSE transport
    • 使用服务器范围的事件进行服务器到客户消息
    • 使用 http POST方式发送消息,用于客户到服务器消息

所有运输都使用JSON-RPC 2.0交换消息。有关模型上下文协议消息格式的详细信息,请参见规格

消息类型

MCP具有这些主要消息类型:

  1. 请求期望对方有回应:
interface Request {
  method: string;
  params?: { ... };
}
  1. 结果是对请求的成功响应:
interface Result {
  [key: string]: unknown;
}
  1. 错误表明请求失败:
interface Error {
  code: number;
  message: string;
  data?: unknown;
}
  1. 通知是单向消息,不会期望回复:
interface Notification {
  method: string;
  params?: { ... };
}

生命周期

初始化

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

  1. init client, connect server
  2. init model, get tools, query, tool call
  3. tool result -> model
  4. model summary

尝试使用

通过mcp工具读取本地文件内容

  1. clone 官方提供的mcp服务项目:
git clone git@github.com:modelcontextprotocol/servers.git
  1. 构建本地服务:
docker build -t mcp/filesystem -f src/filesystem/Dockerfile .

  1. 镜像构建完成后, 采用LangChain4j进行测试用例构建:
package dev.langchain4j.example.mcp;

import dev.langchain4j.mcp.McpToolProvider;
import dev.langchain4j.mcp.client.DefaultMcpClient;
import dev.langchain4j.mcp.client.McpClient;
import dev.langchain4j.mcp.client.transport.McpTransport;
import dev.langchain4j.mcp.client.transport.stdio.StdioMcpTransport;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.tool.ToolProvider;

import java.io.File;
import java.util.List;

public class McpToolsExampleOverStdio {

    // We will let the AI read the contents of this file

    /**
     * This example uses the `server-filesystem` MCP server to showcase how
     * to allow an LLM to interact with the local filesystem.
     * <p>
     * Running this example requires npm to be installed on your machine,
     * because it spawns the `server-filesystem` as a subprocess via npm:
     * `npm exec @modelcontextprotocol/server-filesystem@0.6.2`.
     * <p>
     * Of course, feel free to swap out the server with any other MCP server.
     * <p>
     * The communication with the server is done directly via stdin/stdout.
     * <p>
     * IMPORTANT: when executing this, make sure that the working directory is
     * equal to the root directory of the project
     * (`langchain4j-examples/mcp-example`), otherwise the program won't be able to find
     * the proper file to read. If you're working from another directory,
     * adjust the path inside the StdioMcpTransport.Builder() usage in the main method.
     */
    public static void main(String[] args) throws Exception {

        ChatLanguageModel model = OpenAiChatModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .baseUrl(System.getenv("OPENAI_API_URL"))
                .modelName("gpt-4o-mini")
                .logRequests(true)
                .logResponses(true)
                .build();

        McpTransport transport = new StdioMcpTransport.Builder()
                .command(
                        List.of(
                                "docker", "run", "-i", "--rm",
                                "--mount", "type=bind,src=/Users/louye/fun-project/langchain4j-examples/mcp-example/src/main/resources,dst=/projects",
                                "mcp/filesystem",
                                "/projects"
                        )
                )
                .logEvents(true)
                .build();

        McpClient mcpClient = new DefaultMcpClient.Builder()
                .transport(transport)
                .build();

        ToolProvider toolProvider = McpToolProvider.builder()
                .mcpClients(List.of(mcpClient))
                .build();

        Bot bot = AiServices.builder(Bot.class)
                .chatLanguageModel(model)
                .toolProvider(toolProvider)
                .build();

        try {
            String response = bot.chat("修改文件 /projects/file.txt 的内容, 将内容修改为: Hello, world!");
            System.out.println("RESPONSE: " + response);
        } finally {
            mcpClient.close();
        }
    }
}

参考文档: https://github.com/modelcontextprotocol/servers/blob/main/src/filesystem/README.md

实际上McpTransport 就是帮用户通过特定的命令进行启动MCP的server服务器

### MCP协议简介 MCP(Model Context Protocol)是一种标准化的协议,旨在简化客户端与服务器之间的交互流程,并支持复用通用外部函数[^4]。它通过提供统一的规范,显著降低了开发复杂度,同时支持多种功能调用,例如天气查询、网页爬虫和数据库访问等。此外,MCP协议还集成了多种工具,例如Cursor,能够快速接入上千个开源MCP Server,从而加速Agent的开发过程。 --- ### 协议实现核心组件概述 MCP协议的核心组件包括`Protocol类`及其相关方法[^1]。以下是协议实现的主要特性: #### 1. 类型安全和模式验证 MCP协议确保数据交换过程中类型的安全性,并通过模式验证机制防止非法数据传输。这种设计提高了系统的健壮性和可靠性。 #### 2. 请求-响应关联 MCP协议通过唯一标识符将请求与响应进行关联,确保每个请求都能准确地获取对应的响应结果。 #### 3. 错误处理 协议层内置了完善的错误处理机制,能够在发生异常时及时反馈错误信息并采取适当的恢复措施。 #### 4. 双向通信支持 MCP不仅支持传统的请求-响应模式,还允许双向通信,使得客户端和服务器可以实时交换数据。 --- ### 协议层与传输层的关系 MCP协议层主要负责定义数据格式、交互逻辑以及高级功能(如流式响应、取消请求等),而传输层则专注于数据的实际传输。两者协同工作,共同保障通信的高效性和稳定性。 --- ### 协议实现示例 以下是一个简单的MCP协议实现示例,展示了如何使用Python语言实现基本的请求-响应交互: ```python import json class MCPProtocol: def __init__(self): self.requests = {} self.responses = {} def send_request(self, request_id, payload): """发送请求""" self.requests[request_id] = payload print(f"Request {request_id} sent: {payload}") def receive_response(self, response_id, result): """接收响应""" if response_id in self.requests: self.responses[response_id] = result print(f"Response {response_id} received: {result}") else: print(f"Unknown response ID: {response_id}") # 示例使用 protocol = MCPProtocol() protocol.send_request(1, {"action": "weather_query", "location": "Beijing"}) protocol.receive_response(1, {"temperature": "20°C", "condition": "Sunny"}) ``` --- ### 高级功能 MCP协议还提供了多种高级功能,以满足复杂场景下的需求: #### 1. 流式响应 允许服务器逐步返回数据,而不是一次性完成响应。这对于处理大规模数据或实时更新非常有用。 #### 2. 取消请求 客户端可以主动取消尚未完成的请求,避免不必要的资源消耗。 #### 3. 批处理请求 支持将多个请求合并为一个批次发送,从而减少网络开销并提高效率。 --- ### 安全考虑 MCP协议在设计时充分考虑了安全性问题,例如数据加密、身份验证和访问控制等。这些措施确保了通信过程中数据的保密性和完整性。 --- ### 性能优化 为了提升性能,MCP协议采用了多种优化策略,包括但不限于压缩传输数据、缓存常用结果以及优化序列化/反序列化过程[^1]。 --- ###
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值