微信扫码
添加专属顾问
 
                        我要投稿
探索MCP协议如何革新后台管理系统的数据交互方式。 核心内容: 1. MCP协议及其在AI编程中的重要性 2. 实际案例:如何通过MCP协议连接ERP系统和AI模型 3. MCP协议的架构设计与应用前景
 
                                MCP❓引用一些官方的介绍吧:
❝❞
Model Context Protocol(MCP) 是一个开放协议,它使LLM应用与外部数据源和工具之间的无缝集成成为可能。无论你是构建 AI 驱动的 IDE、改善 chat 交互,还是构建自定义的 AI 工作流,MCP 提供了一种标准化的方式,将 LLM 与它们所需的上下文连接起来。
大白话就是一个数据通信的应用协议,约定了应用和大模型之间如何传递数据进行无缝连接。
「本文主要讲的是 MCP 的 SSE+HTTP 方式的使用。」
先举个荔枝吧:)
Ollama 部署了一些乱七八糟的模型,用于提供给公司内部的朋友们使用。ERP 系统,管理着公司大量的数据信息。那我们能在这个背景下玩一些什么事情呢?
先看截图:
❝我们使用的客户端是 「CherryStudio」,左边是我们的
❞ERP系统,右边是Ollama跑的一个小 「7B」 的通义千问开源模型。
我们直接通过 「CherryStudio」 的 MCP 协议接入功能,直接和 ERP 系统进行通信,实现 ERP 系统的数据查询和操作。
如果我们把 「CherryStudio」 换成手机上的 「Siri」,身边的小爱同学呢?
❝Siri 可以通过快捷指令来完成,小爱同学可以通过小爱技能来完成,当然,体验肯定没有直接内置 MCP 来得快体验好。
❞
首先,我们先了解一下 「MCP」 的架构设计时序图:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(linesequenceDiagram    participant User as User    participant CherryStudio as CherryStudio    participant Server as Server    participant Ollama as Ollama    User->>CherryStudio: 打开软件    CherryStudio-->>Server: **SSE** 兄弟,我们聊会    Server--)CherryStudio: **SSE** 好,你有事的话 POST 这个地址(endpoint)    CherryStudio-->>Server: **POST** 兄弟,自我介绍一下(initalize)    Server--)CherryStudio: **SSE** 好,这是我的基本信息(serverInfo)    CherryStudio-->>Server: **POST** 兄弟,我收到了,我准备好了(initialized)    CherryStudio-->>Server: POST: 兄弟,你有MCP的工具吗(tools/list)    Server--)CherryStudio: **SSE** 我提供了几个工具(tools)    User->>CherryStudio: 输入: 禁用张三的账号    CherryStudio->>Ollama: POST: 带工具调用 `禁用张三的账号`    Ollama-)CherryStudio: 意图识别: {工具:禁用账号,参数:张三}    CherryStudio-->>Server: **POST** 请求发送 {工具:禁用账号,参数:张三}    Server-->>CherryStudio: 执行工具并 **SSE** 推送结果    CherryStudio->>Ollama: 整理下收到的结果    Ollama-)CherryStudio: 返回处理后的结果    CherryStudio-)User: 显示给用户看
有了架构图了,那开发起来倒是没有什么难事了:
当然,你可以使用官网提供的一些 「SDK」 来做,不过吧,很多问题,你可以先试试了来评论区讨论~。。。
我们就不考虑上 「SDK」 啦,直接在项目里生撸!
来吧,直接开始。
ounter(lineounter(lineounter(lineounter(line{  "id": 0,  "jsonrpc": "2.0"}
所有发送给 「MCP」 服务器的请求都是这个结构:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineinterface Request {  // 请求的ID  id: number  // 请求的协议 固定2.0  jsonrpc: "2.0";  // 请求的方法  method: string;  // 请求的参数  params?: { ... };}
例如 方法 initalize 的请求结构:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line{  "id": 0,  "jsonrpc": "2.0",  "method": "initalize",  "params": {    // 客户端的一些能力    "capabilities": {},    "clientInfo": {      // 一些客户端信息,比如名称、版本等    }  }}
又例如 函数调用的 请求结构
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line{  "id": 1,  "jsonrpc": "2.0",  "method": "tools/call",  "params": {    "name": "disableUserByName",    "arguments": {      "name": "张三"    }  }}
所有通过 「SSE」 推送给客户端的响应都是这个结构:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineinterface Response {  id: 0;  jsonrpc: "2.0";  result: {    // 一些数据信息  };  error: {    // 一些错误信息  };}
SpringBoot 下开启一个 「SSE」 服务简单得不要不要的:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(linepublic final static ConcurrentHashMap<String, SseEmitter> EMITTERS = new ConcurrentHashMap<>();@GetMapping(value = "sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public SseEmitter connect() throws IOException {    String uuid = UUID.randomUUID().toString();    SseEmitter emitter = new SseEmitter();    sseEmitter.send(SseEmitter.event()            .name("endpoint")            .data("/mcp/messages?sessionId=" + uuid)            .build()    );    EMITTERS.put(uuid, emitter);    // 可以加点心跳    emitter.onCompletion(() -> EMITTERS.remove(uuid));    emitter.onTimeout(() -> EMITTERS.remove(uuid));    return emitter;    return sseEmitter;}
❝这里需要注意的是,「MCP」 要求连接上后必须发送一次消息,内容是 「MCP」 服务用于接受 「POST」 请求的 URL。
❞
好,这个服务有了,客户端就可以通过这个服务来收我们要下发的消息了。
接下来,我们来实现这个复杂一点的 「POST」 请求:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line("messages")public Json messages(HttpServletRequest request,  McpRequest mcpRequest) {    String uuid = request.getParameter("sessionId");    if (Objects.isNull(uuid)) {        return Json.error("sessionId is required");    }    String method = mcpRequest.getMethod();    switch(method){      case "initalize":        // 这个请求是初始化请求,需要返回一些服务器信息给客户端        break;      case "tools/call":        // 这个请求是工具调用请求,需要返回执行结果给客户端        break;      case "tools/list":        // 这个请求是工具列表请求,需要返回一些工具列表给客户端        break;      default:    }}
❝请注意,所有请求都不是 HTTP 直接响应,而是通过刚才的 「SSE」 通道推送回去。
❞
初始化请求需要响应给客户端的是服务器的一些基本信息:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line{  id: id,  jsonrpc: "2.0",  result: {    // 一些服务能力    capabilities: {},    serverInfo: {      name: "服务器名称",      version: "1.0.0"    }  }}
这时候,客户端已经可以显示服务器的基本信息了。
「SSE」 服务器收到到请求后,需要响应给客户端的是工具列表:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line{  "id": 0,  "jsonrpc": "2.0",  "result": {    "tools": [      {        "name": "disableUserByName",        "description": "禁用一个用户的账号",        "inputSchema": {          "type": "object",          "properties": {            "nickname": {              "type": "string",              "description": "名称"            }          },          "required": ["nickname"]        }      }    ]  }}
「SSE」 服务器需要执行工具时,会得到这个结构体:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line{  "id": 1,  "jsonrpc": "2.0",  "method": "tools/call",  "params": {    "name": "disableUserByName",    "arguments": {      "name": "张三"    }  }}
你可以在执行一些代码后,返回下面的结构体:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line{  "id": 1,  "jsonrpc": "2.0",  "result": {    "content": [      {        "type": "text",        "text": "好,张三被我干掉了"      }    ]  }}
到这里,几乎完成了整个流程。
我们因为使用的 「Java」 和 「SpringBoot」, 所以我们使用了 @McpMethod 注解配合 Reflections 来实现自动注册工具。
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line@McpMethod("modifyEmailByName")@Description("modify user new email by name")public String modifyEmailByName(        @Description("the name of user, e.g. 凌小云")        String name,        @Description("the new email of user, e.g. example@domain.com")        String email) {    List<UserEntity> userList = filter(new UserEntity().setNickname(name));    DATA_NOT_FOUND.when(userList.isEmpty(), "没有叫 " + name + " 的用户");    userList.forEach(user -> {        updateToDatabase(get(user.getId()).setEmail(email));    });    return "已经将 " + userList.size() + " 个叫 " + name + " 的用户邮箱修改为 " + email;}
只要标记了 @McpMethod 注解, MCP 服务器就会自动注册这个方法。
然后你就可以通过 「CherryStudio」 等工具来调用这个方法了。
❝动动嘴的事情~
❞
我们通过上述的方式完成了一个的 「MCP」 服务, 并且也可以为我们的一些其他系统进行扩展,用大模型来改造这些系统的使用方式,美滋滋。
当然,这里还有很多问题需要我们解决,比如权限控制。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2025-10-31
OpenAI 公开 Atlas 架构:为 Agent 重新发明浏览器
2025-10-31
Palantir 本体论模式:重塑企业 AI 应用的 “语义根基” 与产业启示
2025-10-31
树莓派这种“玩具级”设备,真能跑大模型吗?
2025-10-30
Cursor 2.0的一些有趣的新特性
2025-10-30
Anthropic 发布最新研究:LLM 展现初步自省迹象
2025-10-30
让Agent系统更聪明之前,先让它能被信任
2025-10-30
Rag不行?谷歌DeepMind同款,文档阅读新助手:ReadAgent
2025-10-29
4大阶段,10个步骤,助你高效构建企业级智能体(Agent)
 
            2025-08-21
2025-08-21
2025-08-19
2025-09-16
2025-10-02
2025-09-08
2025-09-17
2025-08-19
2025-09-29
2025-08-20