最近半年技术圈最火的概念,MCP绝对算一个。
但说实话,我一开始是没搞明白的。看了几篇介绍文章,满屏的"JSON-RPC 2.0"、"stdio transport"、"SSE transport"------每个字都认识,连起来就是不知道在说啥。
后来我发现,绝大多数讲MCP的文章都有个问题:要么太底层,一上来就讲协议规范;要么太概念,满篇比喻但没一行能跑的代码。
这篇文章我换个方式------不讲虚的,直接说我周末做了什么:用Java接了5个MCP Server,跑通了完整的调用链路。过程写下来,你跟着做一遍就懂了。
先用最土的话说清楚MCP是啥
你用Claude或者Cursor的时候,有没有想过一个问题:AI怎么知道你本地有哪些文件?怎么知道你的GitHub仓库长啥样?怎么连上你的数据库的?
答案就是MCP------Model Context Protocol。
你可以把它理解成"AI的USB接口"。以前你想让AI连一个新工具(比如GitHub),得写专门的集成代码。换一个AI工具,又得重写一遍。N个AI乘以M个工具,就是N×M份集成代码。
MCP干的事就是把这变成N+M:每个工具写一个MCP Server,每个AI实现一个MCP Client,大家用同一套协议通信。写一次,到处用。
打个更直白的比方------你手机以前充电,每个品牌一个接口。现在全是Type-C了。MCP就是AI工具界的Type-C。
截至2026年中,社区已经有5800多个公开的MCP Server了,覆盖数据库、GitHub、Slack、文件系统等等。基本上你能想到的常见工具都有现成的Server。
我接了哪5个MCP Server
周末挑了5个比较实用的:
- filesystem --- 让AI能读写本地文件
- github --- 让AI能看你的仓库、提Issue
- postgres --- 让AI能查PostgreSQL数据库
- fetch --- 让AI能抓取网页内容
- memory --- 让AI有长期记忆
目标是什么?搭一个本地AI助手,能帮我读代码、查数据库、看GitHub Issue、搜网页,还能记住之前的对话上下文。
环境准备
MCP Server目前大多是Node.js写的(Python的也有),但Client端------也就是调用方------Java完全没问题。Spring AI 1.0已经原生支持MCP了。
先建项目:
xml
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
</dependencies>
然后是MCP Server的安装。大部分MCP Server通过npx就能跑,不需要全局安装:
bash
# 这些不需要手动安装,MCP Client会通过npx自动拉起
# filesystem server
npx -y @modelcontextprotocol/server-filesystem /path/to/your/project
# github server(需要GITHUB_TOKEN环境变量)
npx -y @modelcontextprotocol/server-github
# postgres server
npx -y @modelcontextprotocol/server-postgres postgresql://user:pass@localhost:5432/mydb
# fetch server
npx -y @modelcontextprotocol/server-fetch
# memory server
npx -y @modelcontextprotocol/server-memory
配置Spring AI连接MCP Server
Spring AI 1.0对MCP的支持是通过配置文件管理的,这点很方便。在application.yml里:
yaml
spring:
ai:
mcp:
client:
stdio:
servers-configuration: classpath:mcp-servers.json
然后建一个mcp-servers.json:
json
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/juanmao/projects"],
"env": {}
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
},
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://user:pass@localhost:5432/mydb"],
"env": {}
},
"fetch": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-fetch"],
"env": {}
},
"memory": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-memory"],
"env": {}
}
}
}
Spring AI启动时会自动拉起这些Server进程,通过stdio和它们通信。你不需要手动管理这些进程的生命周期。
写一个能调用所有MCP工具的AI助手
配置好之后,代码其实很简单。Spring AI会自动把MCP Server暴露的工具注册为Function:
java
@Service
public class McpAssistantService {
private final ChatClient chatClient;
public McpAssistantService(ChatClient.Builder builder,
ToolCallbackProvider mcpToolProvider) {
// 把所有MCP工具都注册到ChatClient
this.chatClient = builder
.defaultTools(mcpToolProvider)
.defaultSystem("""
你是一个开发助手,可以使用以下工具:
- 文件读写:读取和搜索本地文件
- GitHub:查看仓库、Issue、PR
- 数据库:查询PostgreSQL
- 网页抓取:获取网页内容
- 记忆:记住和回忆信息
回答时要简洁,使用工具时说明你在做什么。
""")
.build();
}
public String ask(String question) {
return chatClient.prompt()
.user(question)
.call()
.content();
}
}
就这样,没有一行手动写工具调用的代码。Spring AI + MCP帮你把工具发现、参数构造、结果解析全搞定了。
实际效果
举几个真实场景:
场景1:让AI读你的项目代码
css
我问:"看一下我projects目录下的order-service项目,main方法在哪?入口做了什么?"
AI的执行过程:
1. 调用filesystem的list_directory工具,浏览目录结构
2. 调用filesystem的read_file工具,读取主类
3. 分析代码内容,总结入口逻辑
AI回答:"你的order-service入口在src/main/java/.../OrderServiceApplication.java,
主要做了三件事:1. 初始化Spring Boot上下文 2. 加载配置文件 3. 启动定时任务..."
场景2:让AI查数据库
sql
我问:"查一下users表最近7天注册的用户有多少,列出他们的用户名"
AI的执行过程:
1. 调用postgres的query工具,执行 SHOW TABLES 确认表结构
2. 执行 SELECT username, created_at FROM users WHERE created_at > NOW() - INTERVAL '7 days'
3. 格式化返回结果
AI回答:"最近7天注册的用户共23人,包括:zhang_san, li_si, wang_wu..."
场景3:让AI看GitHub Issue
ini
我问:"我的仓库juanmao/order-service有哪些open的issue?帮我总结一下"
AI的执行过程:
1. 调用github的list_issues工具
2. 遍历每个issue的内容
3. 总结归纳
AI回答:"你有3个open issue:
#12 - 订单创建接口偶发超时(3天前)
#15 - 批量导出时内存溢出(1天前,标记为bug)
#18 - 希望增加订单导出Excel功能(2小时前,标记为feature)"
这个体验说实话挺震撼的。以前这些事情你要开三四个工具来回切,现在一句话AI全给你搞定了。
踩的坑
坑1:MCP Server启动失败不会有明显的错误提示。 我一开始配github server的时候,Token写错了,Server进程直接退出了,Spring AI那边只是报了个"connection closed"的错。后来发现可以加--debug参数看Server的日志:
json
{
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github", "--debug"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "your_token"
}
}
}
坑2:stdio transport不支持多Client同时连接。 Spring AI的MCP Client通过stdio和Server通信,一个Server进程只能被一个Client连接。如果你同时跑了两个Spring Boot实例,第二个会连不上。解决方案是改用SSE transport(HTTP方式),但需要额外配Server端。
坑3:工具太多会让大模型"选择困难"。 5个MCP Server加起来可能有二三十个工具(每个Server暴露多个工具)。工具描述全塞进context,token消耗不小,而且模型有时候会选错工具。解决方案是按场景分组,只注册当前任务需要的工具:
java
// 只用filesystem和github
public String analyzeCode(String question) {
return chatClient.prompt()
.user(question)
.tools(mcpToolProvider, "filesystem", "github") // 按名称过滤
.call()
.content();
}
不过Spring AI 1.0目前这个按名称过滤的API还不太稳定,有时会报错。我目前的做法是给不同场景的ChatClient配不同的工具集。
一些思考
MCP这个东西,说大不大说小不小。从技术上看,它就是个标准化的工具调用协议,JSON-RPC那一套,没什么花哨的。但从生态上看,它解决了一个真实的痛点------AI工具集成的碎片化问题。
我的判断是:MCP会像REST API一样成为基础设施。以后你写一个新工具,默认会提供一个MCP Server,就像现在默认提供REST接口一样。
对Java开发者来说,好消息是Spring AI已经原生支持MCP了。你不需要学Node.js,不需要理解JSON-RPC的底层细节,配个JSON文件就能用。这大概就是框架层的价值------把复杂的东西封装好,让你专注业务逻辑。
如果你也在折腾MCP,或者对Spring AI的AI Agent方向感兴趣,留言聊聊。这个领域迭代速度太快了,一个人折腾不如一群人折腾。
《卷毛的技术笔记》,一个9年Java开发的真实技术笔记。