把 MCP 理解成「AI 世界的 USB-C」之后,一切都清晰了
-
先说说我踩的坑 -
MCP 核心概念 -
直接用 HTTP 不香吗? -
使用Spring AI接入MCP -
1. 加依赖 -
2. 找个 MCP 服务接入 -
3. 写个客户端测试 -
自己写了个 MCP 服务 -
我的感受
把 MCP 理解成「AI 世界的 USB-C」之后,一切都清晰
说实话,很早之前看到模型上下文协议这个词,我是懵的。不就是让 AI 调个工具吗,搞这么复杂干嘛?
MCP这个概念很早就发布了,当时也没有怎么去用过,后来踩了几个坑,才发现这东西确实有点场景
先说说我踩的坑
让 AI 查个天气、调个文件,每次都得写一套对接代码。后端服务要写一套,IDE 插件开发又要写一套。问题是——这些代码本质上做的是同一件事:把请求发出去,把结果拿回来。
有人会说:封个 SDK 不就好了吗?
是啊,我以前也这么想。直到我发现了一个蛋疼的事实:JAVA SDK 写好了,Node.js 的同事用不了。Go 团队想调?再写一套吧。
SDK 的问题就在这儿:语言强绑定。
MCP 就不一样了。你用 Python 写一个天气服务,Node.js、Rust、Go 都能直接调。为啥?因为 MCP 规定了一套统一的对话标准——不管你用什么语言写的,只要按这个标准来,大家都能聊。
说到这里,我突然想到了一个类比:
MCP = AI 世界的 USB-C。
以前各家电脑的充电口都不一样,苹果用 Lightning,安卓用 Micro-USB。现在 Type-C 一统江湖,一个充电器走天下。MCP 就是想让 AI 工具生态也有这么一个统一接口。

MCP 核心概念
先说几个关键词,混个脸熟:
-
MCP 主机:需要调用外部资源的 AI 应用,比如 Claude Desktop、IDE 插件 -
MCP 客户端:内置在主机里,负责和服务器一对一连接 -
MCP 服务器:暴露具体能力的程序,比如能读文件、能查 GitHub、能操作数据库
这里容易搞混的是主机和客户端的关系。主机 ≠ 客户端,但主机里跑着客户端。
打个比方:
❝
主机 = 电脑 客户端 = 电脑里的浏览器
电脑是一台完整的设备,浏览器是装在电脑里的一个软件。MCP 也是这个逻辑。
直接用 HTTP 不香吗?
说实话,也能用。调个天气接口,HTTP 请求一发,完事。
但问题是:你真的只需要调一次吗?
如果你同时在用 Claude Desktop、自己的聊天机器人、终端工具,每个都想查天气——用 HTTP 的话,你得为每个地方单独写代码。但用 MCP,你写一次,到处都能调。
所以我的理解是:
-
直接用 HTTP:一次性脚本,不需要复用,就是图个快 -
用 MCP:想复用、想分享、想构建工具生态
一句大白话总结:HTTP 天气接口是原材料,MCP 天气服务是预制菜。原材料可以自己炒(但每次都要切菜调味),预制菜直接加热就能吃(但你得有个微波炉——MCP 客户端)。
使用Spring AI接入MCP
下面是我的实操记录,不保证最优解,但保证是真实踩过的坑。
1. 加依赖
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-mcp-client-webflux-spring-boot-starter</artifactId></dependency>
2. 找个 MCP 服务接入
这里插一句,我找公共 MCP 服务的几个地方:
-
魔搭社区:https://www.modelscope.cn/mcp -
阿里云百炼:https://bailian.console.aliyun.com -
mcp.so:https://mcp.so
配置其实不复杂,就是一个 JSON 文件,告诉系统「去哪找这个服务」。

引入MCP服务 mcp-servers-config.json
{"mcpServers": {"filesystem": {"command": "npx","args": ["-y","@modelcontextprotocol/server-filesystem@2025.3.28","/Users/yanglingcong/Desktop/IdeaProjects/my-ai-rag-knowledge /test","/Users/yanglingcong/Desktop/IdeaProjects/my-ai-rag-knowledge /test" ] },"weather": {"command": "npx","args": ["-y","@h1deya/mcp-server-weather" ],"env": {"OPENWEATHERMAP_API_KEY": "xxx" } },"amap-maps": {"args": ["-y","@amap/amap-maps-mcp-server" ],"command": "npx","env": {"AMAP_MAPS_API_KEY": "xxx" } } }}
-
别人写好了 MCP 天气服务,发布到 npm(JavaScript 的包仓库)。 -
这里安装命令是npx, npx会自动下载并运行这个服务,不用关心它装在哪里,免安装运行
3. 写个客户端测试
@Beanpublic ChatClient.Builder chatClientBuilder(OpenAiChatModel openAiChatModel){returnnew DefaultChatClientBuilder(openAiChatModel, ObservationRegistry.NOOP, (ChatClientObservationConvention) null);}
然后写个测试方法:
import com.alibaba.fastjson.JSON;import jakarta.annotation.Resource;import lombok.extern.slf4j.Slf4j;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.ai.chat.client.ChatClient;import org.springframework.ai.openai.OpenAiChatOptions;import org.springframework.ai.reader.tika.TikaDocumentReader;import org.springframework.ai.tool.ToolCallbackProvider;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;@Slf4j@RunWith(SpringRunner.class)@SpringBootTestpublicclassMCPTest{@Resourceprivate ChatClient.Builder chatClientBuilder;@Autowiredprivate ToolCallbackProvider tools;@Testpublicvoidtest_tool(){ String userInput = "有哪些工具可以使用";var chatClient = chatClientBuilder .defaultTools(tools) .defaultOptions(OpenAiChatOptions.builder() .model("qwen-plus") .build()) .build(); System.out.println("\n>>> QUESTION: " + userInput); System.out.println("\n>>> ASSISTANT: " + chatClient.prompt(userInput).call().content()); }}
跑起来之后,模型能自动发现并调用 MCP 服务里的工具。这个过程挺神奇的——我只需要说「帮我查下佛山的天气」,剩下的模型自己搞定。

工具都可以操作使用,申请一个高德地图API,可以调用MCP服务
@Testpublicvoidtest_workflow(){ String userInput = "帮我查下佛山的天气";var chatClient = chatClientBuilder .defaultTools(tools) .defaultOptions(OpenAiChatOptions.builder() .model("qwen-plus") .build()) .build(); System.out.println("\n>>> QUESTION: " + userInput); System.out.println("\n>>> ASSISTANT: " + chatClient.prompt(userInput).call().content()); }

整体流程大概是:
用户说:「帮我查下佛山的天气」 ↓模型分析 → 哦,需要调 weather 工具 ↓Spring AI 自动触发高德地图 MCP server ↓高德 API 返回数据 ↓模型把数据整合成自然语言 ↓你看到:「佛山今天晴,温度 25°C...」
自己写了个 MCP 服务
光用别人的不过瘾,我试着写了一个对接 Gitee 的 MCP 服务。
核心就三步:
第一步:引入POM配置
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId></dependency>
第二步:写个 Service,用 @Tool 注解标记方法
java服务类
package knowledge.server;import lombok.extern.slf4j.Slf4j;import org.springframework.ai.tool.annotation.Tool;import org.springframework.ai.tool.annotation.ToolParam;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;import org.springframework.web.client.RestTemplate;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;@Component@Slf4jpublicclassGitService{privatefinal RestTemplate restTemplate;@Value("${gitee.access-token:}")private String accessToken;privatestaticfinal String GITEE_API_BASE = "https://gitee.com/api/v5";publicGitService(RestTemplate restTemplate){this.restTemplate = restTemplate; }/** * 获取仓库提交列表 */@Tool(name = "get_commits", description = "获取Gitee仓库的提交列表,返回最近的提交记录")public Map<String, Object> getCommits( @ToolParam(description = "仓库所有者(用户名或组织)") String owner, @ToolParam(description = "仓库名称") String repo, @ToolParam(description = "分支名称,默认为master") String branch) { log.info("获取提交列表: owner={}, repo={}, branch={}", owner, repo, branch);try { String url = GITEE_API_BASE + "/repos/{owner}/{repo}/commits?sha={branch}&per_page=20&access_token={token}";@SuppressWarnings("unchecked") List<Map<String, Object>> commits = restTemplate.getForObject(url, List.class, owner, repo, branch, accessToken); List<Map<String, Object>> result = new ArrayList<>();if (commits != null) {for (Map<String, Object> commit : commits) { Map<String, Object> item = new HashMap<>(); item.put("sha", commit.get("sha")); item.put("message", commit.get("message")); item.put("timestamp", commit.get("timestamp"));@SuppressWarnings("unchecked") Map<String, Object> author = (Map<String, Object>) commit.get("author");if (author != null) { Map<String, Object> authorMap = new HashMap<>(); authorMap.put("name", author.get("name")); authorMap.put("email", author.get("email")); authorMap.put("date", author.get("date")); item.put("author", authorMap); }@SuppressWarnings("unchecked") Map<String, Object> committer = (Map<String, Object>) commit.get("committer");if (committer != null) { Map<String, Object> committerMap = new HashMap<>(); committerMap.put("name", committer.get("name")); committerMap.put("email", committer.get("email")); committerMap.put("date", committer.get("date")); item.put("committer", committerMap); } item.put("url", "https://gitee.com/" + owner + "/" + repo + "/commits/" + commit.get("sha")); result.add(item); } } Map<String, Object> response = new HashMap<>(); response.put("success", true); response.put("commits", result); response.put("count", result.size()); response.put("owner", owner); response.put("repo", repo); response.put("branch", branch);return response; } catch (Exception e) { log.error("获取提交列表失败", e); Map<String, Object> errorResponse = new HashMap<>(); errorResponse.put("success", false); errorResponse.put("error", e.getMessage());return errorResponse; } }}
第三步:注册成工具
@Beanpublic ToolCallbackProvider gitTools(GitService gitService){return MethodToolCallbackProvider.builder() .toolObjects(gitService) .build();}
@Tool 注解的意思是「这个方法可以被大模型调用」,而 ToolCallbackProvider 负责把它注册进 Spring AI 的工具系统。
打包成 jar 之后,配到 mcp-servers-config.json 里就能用了:
"mcp-server-git": {"command": "java路径","args": ["-jar", "你的jar包路径"],"env": {"GITEE_ACCESS_TOKEN": "你的token" }}
通过 Maven install 生成 jar 包:

Gitee 的 Access Token 在平台设置里生成:

测试了一下,让 AI「帮我获取 xxx 仓库的提交记录」,模型自己拆解意图、调用工具、返回结果:

整个过程行云流水。
我的感受
以前各个 AI 工具互相割裂,一个工具一套 API,学习成本高、维护成本更高。有了 MCP,至少在工具调用这个层面,大家有了一个共同语言。
但MCP 不是银弹,如果场景是:
-
后端服务之间的直接调用,没有 AI 模型什么事 → 用 SDK 吧,MCP 反而麻烦 -
就是想快速调一个天气接口,一次性的 → 直接 HTTP 请求,三行代码搞定
MCP 的价值在于:当想让多个 AI 客户端复用同一套工具时,它才能发挥优势。 没有这个需求,强行上 MCP 就是给自己找事。
夜雨聆风