MCP服务器开发流程
mcp开发的三层架构
客户端(mcp client,mcp session, mcp transport) <-- stdio/ see--> 服务端(mcp server, mcp session, mcp transport)
客户端负责客户端操作,使用mcp session进行通信,mcp session 使用defaultMcpSession进行通信和状态管理,传输层支持 json-rpc的序列化和反序列化(基于stdio的标准io流,http see远程传输)
mcp提供的功能
提供资源,提示词(向客户端提供提示词模板,以及工作流),tools(工具调用能力),sampling(采样允许服务端向发模型发送生成内容的请求),roots(根目录,mcp的安全协议) transport是(传输)定义客户端和服务器件的通信方式
mcp接入
本地软件:从mcp软件市场下载之后,本地config里要写好其对应的mcp.json 以及申请的api key 在cursor或者codex里有mcp 直接选择后软件会自动扫描
程序客户端mcp:
- 引入spring ai mcp sdk开发依赖,在resource目录下新建mcp-server.json配置,定义需要用到的mcp服务
2)主程序的yaml里写上对应的mcp服务器配置,保证mcp客户端启动后会使用子进程启动mcp服务
3)创建ToolCallBackProvider类,内部注册了mcp创建的工具类,在app调用chatmodel时向tool方法传入ToolCallBackProvider实例
mcp程序开发
1)引入spring ai 依赖,spring ai-starter-mcp-client(支持stdio以及http的see支持);spring ai-starter-mcp-client-webFlux 基于webFlux的响应式的see传输实现
2)配置连接: 第一种直接写入配置文件
spring:
ai:
mcp:
client:
enabled: true
name: my-mcp-client
version: 1.0.0
request-timeout: 30s
type: SYNC
sse:
connections:
server1:
url: http://localhost:8080
stdio:
connections:
server1:
command: /path/to/server
args:
- --port=8080
env:
API_KEY: your-api-key
使用基于claude desktop格式的json文件(仅支持stdio连接方式)
spring:
ai:
mcp:
client:
stdio:
servers-configuration: classpath:mcp-servers.json
配置文件(放到mcp客户端):
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/Desktop",
"/Users/username/Downloads"
]
}
}
}
想要完全控制mcp客户端的行为:使用mcpClient bean,其中提供了很多方法进行交互,想要使用mcp的工具增强ai能力,使用ToolCallbackProvider进行注入
mcp服务端开发
1 引入依赖
spring ai-starter-mcp-server:提供stdio传输支持,不额外需要web依赖
spring ai-starter-mcp-server-webmvc:提供基于spring mvc的see传输和可选的stdio传(建议)
spring-ai-starter-mcp-server-webflux:基于spring webflux的响应式see传输以及可选stdio输出
2 yaml配置:stdio配置和see配置
# 使用 spring-ai-starter-mcp-server
spring:
ai:
mcp:
server:
name: stdio-mcp-server
version: 1.0.0
stdio: true
type: SYNC # 同步
# see服务
# 使用 spring-ai-starter-mcp-server-webmvc
spring:
ai:
mcp:
server:
name: webmvc-mcp-server
version: 1.0.0
type: SYNC # 同步
sse-message-endpoint: /mcp/message # SSE 消息端点路径
sse-endpoint: /sse # SSE 端点路径
3 服务开发
创建对应的服务功能类,功能类中创建对应的工具函数,工具函数使用tool注解修饰,函数参数用toolparameter参数进行修饰
在mcp的spring application主启动类中,注册toolcallbackprovider bean即可
@Service
public class ImageSearchTool {
// 替换为你的 Pexels API 密钥(需从官网申请)
private static final String API_KEY = "改为你的 API Key";
// Pexels 常规搜索接口(请以文档为准)
private static final String API_URL = "https://api.pexels.com/v1/search";
@Tool(description = "search image from web")
public String searchImage(@ToolParam(description = "Search query keyword") String query) {
try {
return String.join(",", searchMediumImages(query));
} catch (Exception e) {
return "Error search image: " + e.getMessage();
}
}
/**
* 搜索中等尺寸的图片列表
*
* @param query
* @return
*/
public List<String> searchMediumImages(String query) {
// 设置请求头(包含API密钥)
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", API_KEY);
// 设置请求参数(仅包含query,可根据文档补充page、per_page等参数)
Map<String, Object> params = new HashMap<>();
params.put("query", query);
// 发送 GET 请求
String response = HttpUtil.createGet(API_URL)
.addHeaders(headers)
.form(params)
.execute()
.body();
// 解析响应JSON(假设响应结构包含"photos"数组,每个元素包含"medium"字段)
return JSONUtil.parseObj(response)
.getJSONArray("photos")
.stream()
.map(photoObj -> (JSONObject) photoObj)
.map(photoObj -> photoObj.getJSONObject("src"))
.map(photo -> photo.getStr("medium"))
.filter(StrUtil::isNotBlank)
.collect(Collectors.toList());
}
}
启动类注入bean实例对象
@SpringBootApplication
public class YuImageSearchMcpServerApplication {
public static void main(String[] args) {
SpringApplication.run(YuImageSearchMcpServerApplication.class, args);
}
@Bean
public ToolCallbackProvider imageSearchTools(ImageSearchTool imageSearchTool) {
return MethodToolCallbackProvider.builder()
.toolObjects(imageSearchTool)
.build();
}
}
拓展问题:
mcp安全:mcp内部的信息处理过程对于模型来说是一个黑箱,模型通过程序调用mcp服务,mcp服务传输数据到用户程序,这个过程客户端程序无法进行安全检查只能做输入输出检查,大模型接收到的也是mcp的输出,因此不具备完备的安全性,要慎用
Stdio通信:适用于本地,单客户端,命令行工具,ide插件等,客户端启动mcp服务作为其子进程,通信通过管道进行,可u护短向服务器写入请求,服务器读取并处理,将响应写入到标准输出后客户端读取响应
优点:性能高,安全性好,不对外暴露端口,部署极简
局限:仅适用于与客户端在同一台机器上运行的服务器,无法远程访问;严格的进行间1:1关系,无法直接响应多客户端
SEE:适用于远程访问,多客户端,跨网络,公共服务等场景,客户端通过get请求连接到服务器的see端点,简历一条持久化的http长连接,服务器可以随时向客户端单向推送事件
客户端如果需发送请求,需要向服务器的另一个post端口发送http请求
优点:支持跨网络的远程服务,可服务多个客户端,兼容标准http认证和安全机制
局限:性能开销比stdio大,需要处理网络波动和重建逻辑
大模型与MCP的完整交互流程是动态发现和调用的标准化过程:
初始化阶段:MCP客户端启动或检测到有服务器加入时,向服务器发送 initialize 请求完成握手。
工具发现:客户端发送 tools/list JSON-RPC请求,服务器返回所有可用工具的列表,包含名称、描述、参数模式(JSON Schema)等元数据。
模型决策:大模型根据用户请求、历史对话和工具列表中的描述,决定调用哪个工具以及如何传参。
工具调用:客户端发送 tools/call 请求,服务器执行后返回结果。
动态更新:若服务器工具列表变化,发送 notifications/tools/list_changed 通知客户端刷新,大模型可即时感知新能力
浙公网安备 33010602011771号