前置声明: windows系统
一、MCP Client通过mcp.json方式使用MCP Server(Claude Desktop 格式的 JSON 文件,目前仅支持 stdio 连接方式)
1. 引入pom依赖
java
<!-- 添加Spring AI MCP Client starter依赖 -->
<!-- Source: https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-mcp-client-spring-boot-starter -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
<version>1.0.0-M6</version>
<scope>compile</scope>
</dependency>
2. 添加application.yml配置:
java
spring:
ai:
# mcp client 客户端配置
mcp:
client:
stdio:
servers-configuration: classpath:mcp-servers.json
注意:
1. 指定MCP服务器配置文件路径(推荐)为项目resources目录下的json文件。 2. 流程: classpath:mcp-servers.json → 读取资源目录里打包进 jar 的文件,打包部署后依然 正常生效(推荐配置文件写法)→ Spring Boot 应用启动时读取(放在 resources 下,打进 jar) 2. 项目根目录的 .mcp.json → 不属于 classpath 资源,Spring 默认不会读取,仅给 Claude Code IDE 使用 4. classpath:mcp-servers.json对应文件位置:src/main/resources/mcp-servers.json 5. 编译后会自动复制mcp-servers.json到 target/classes/mcp-servers.json,Spring 就能读到。
3. 在resources目录下添加mcp-servers.json文件:(推荐②)
① 配置文件如下:(开发上传到git不推荐 这种形式,包含api_key敏感信息)
踩坑点: windows系统加.cmd才能找到npx命令
java
{
"mcpServers": {
"amap-maps": {
"command": "npx.cmd",
"args": [
"-y",
"@amap/amap-maps-mcp-server"
],
"env": {
"AMAP_MAPS_API_KEY": "your_key_here"
}
}
}
}
② 我更推荐这种形式,将api_key放到我们电脑的系统环境变量中,避免git提交上去,json配置如下:
java
{
"mcpServers": {
"amap-maps": {
"command": "npx.cmd",
"args": [
"-y",
"@amap/amap-maps-mcp-server"
]
}
}
}
配置系统环境变量:

检验系统环境变量是否能正确读取到,打开cmd输入命令:
bash
echo %AMAP_MAPS_API_KEY%
输出密钥就说明能正确读取到。
接下来重点踩坑点 ,必须关闭idea再重新打开,这样才能将修改的环境变量刷新到idea中!
如此,json文件就配置好了!
踩坑点总结:
mcp-servers.json文件放在resources目录下,而不是项目根目录
json文件中windows系统使用npx.cmd而不是npx,否则找不到命令
将高德地图api_key写入系统环境变量后,一定关闭idea再打开进行刷新
4. 编写MCP Client调用MCP Server与大模型对话进行工具调用的代码:
java
/**
* 注入MCP服务后与AI进行对话
* @param userMessage 用户提问
* @param chatId 会话id
* @return AI回复
*/
public String doChatWithMcp(String userMessage,String chatId){
ChatResponse chatResponse = chatClient
.prompt()
.user(userMessage)
.advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
.tools(toolCallbackProvider)
.call()
.chatResponse();
String content = chatResponse.getResult().getOutput().getText();
log.info("MCP invoke result - content: {}",content);
return content;
}
5. 编写测试代码进行真实调用的集成测试
java
@SpringBootTest
@DisplayName("调用MCP服务中的工具与AI交互")
public class DoChatWithMcpTest {
@Resource
private LoveApp loveApp;
@Test
@DisplayName("测试高德地图MCP Server是否能正确调用")
void loveAppDoChatWithMcp(){
String chatId = UUID.randomUUID().toString();
String userMessage = "我想搜索下北京市海淀区五道口附近5km内适合约会的咖啡厅,推荐三个即可";
String result = loveApp.doChatWithMcp(userMessage, chatId);
Assert.notNull(result,"大模型应该回复有内容的信息");
}
}
6. 观察控制台日志,查看启动测试方法后,用户向大模型发送的两次请求内容
可以看到用户携带MCP信息向模型发送第一次请求后,返回的要调用的工具名是maps_around_search,AI回复的消息类型是ASSISTANT。

可以看到模型返回的信息中包含TOOL和高德的工具名maps_around_search,调用完工具拿到结果返回给大模型的消息类型是TOOL。

所以,我们成功调用了高德地图MCP Server且仅调用了一个工具maps_around_search。
高德开放平台控制台也可以看到只调用了一个工具。调用MCP Server的工具成功!

7. 一些疑问
① 为什么mcp-servers.json中没有设置env中的AMAP_MAPS_API_KEY,我们启动程序仍然可以读取到呢?
🔧 env 字段的作用
在 mcp-servers.json 中的 env 字段不是读取环境变量,而是设置/覆盖该 MCP Server 进程的环境变量。
✅ 正确的理解
{
"mcpServers": {
"amap-maps": {
"command": "npx.cmd",
"args": "-y", "@amap/amap-maps-mcp-server",
"env": {
"AMAP_MAPS_API_KEY": "abc123" // ← 这是设置,不是读取!
}
}
}
}
env 字段:为这个 MCP Server 子进程设置环境变量
如果设置了,会覆盖系统环境变量中同名的值
- 优先级:JSON 中的 env > 系统环境变量
📊 环境变量优先级(从高到低)
1️⃣ mcp-servers.json 中的 "env" 配置
↓
2️⃣ 系统/用户环境变量(Windows 环境变量)
↓
3️⃣ ~/.amap/config.json(如果有)
我们env中没有设置api_key,所以当前流程是:
mcp-servers.json 中没有 env 配置
npx 启动 MCP Server 时继承父进程的环境变量
你的系统环境变量中设置了 AMAP_MAPS_API_KEY
MCP Server 成功读取到该环境变量