MCP调用链路源码解密
前面几篇我们已经把 MCP Server 和 Client 跑起来了,但上一篇对“源码调用链路”的描述还是偏通用,容易把 Spring AI 的公共机制和本项目的真实实现混在一起。
这一篇就不只讲一些概念了,以之前的项目里的这两个模块为准,把链路重新梳理一遍:
ai-example-spring-ai-office-mcp-clientai-example-spring-ai-office-mcp-server
我们要回答的问题也很具体:
- 用户发一句“帮我查下 E10086 2025-03 的考勤”,请求先落到哪里?
- Client 端的 MCP 工具是什么时候发现的?是在模型返回
tool_calls之后,还是更早? - Server 端的
@Tool方法,是怎样变成/mcp接口可调用工具的? - 工具执行完以后,结果是怎么回到大模型,再生成最终自然语言回答的?
从对话入口端来入手
Client 端:office-mcp-client
@RestController
@RequestMapping("/api/assistant")
public class AssistantController {
private final AssistantService assistantService;
@PostMapping("/chat")
public ChatResponse chat(@RequestBody ChatRequest request) {
String response = assistantService.chat(request.message());
return new ChatResponse(response);
}
}
@Service
public class AssistantService {
private final ChatModel chatModel;
private final SyncMcpToolCallbackProvider toolCallbackProvider;
private ChatClient chatClient;
@PostConstruct
public void init() {
ToolCallback[] toolCallbacks = toolCallbackProvider.getToolCallbacks();
this.chatClient = ChatClient.builder(chatModel)
.defaultToolCallbacks(toolCallbacks)
.build();
}
public String chat(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.call()
.content();
}
}
所以这套示例的真实入口是:
AssistantController -> AssistantService -> ChatClient
Server 端:office-mcp-server
这个模块不是手写一个 /mcp Controller,而是交给 Spring AI Starter 自动暴露。
@Configuration
public class McpServerConfig {
@Bean
public ToolCallbackProvider attendanceToolProvider(AttendanceTools attendanceTools) {
return MethodToolCallbackProvider.builder()
.toolObjects(attendanceTools)
.build();
}
@Bean
public ToolCallbackProvider meetingRoomToolProvider(MeetingRoomTools meetingRoomTools) {
return MethodToolCallbackProvider.builder()
.toolObjects(meetingRoomTools)
.build();
}
}
以及具体的 @Tool 方法:
@Service
public class AttendanceTools {
@Tool(description = "查询员工的考勤记录,包括出勤天数、迟到次数、早退次数、请假天数。")
public String checkAttendance(String employeeId, String month) {
...
}
}
@Service
public class MeetingRoomTools {
@Tool(description = "查询指定会议室在某天的预订情况和空闲时段。")
public String queryRoomSchedule(String roomId, String date) {
...
}
}
所以 Server 侧真正暴露出去的工具,来自:
AttendanceTools.checkAttendanceAttendanceTools.clockInMeetingRoomTools.queryRoomScheduleMeetingRoomTools.bookMeetingRoomMeetingRoomTools.cancelBooking
付费内容提示
该文档的全部内容仅对「JavaUp项目实战&技术讲解」知识星球用户开放
加入星球后,你可以获得:
- 超级八股文:100万+字的全栈技术知识库,涵盖技术核心、数据库、中间件、分布式等深度剖析的讲解
- 讲解文档:超级AI智能体、黑马点评Plus、大麦、大麦pro、大麦AI、流量切换、数据中台的从0到1的详细文档
- 讲解视频:超级AI智能体、黑马点评Plus、大麦、大麦pro、大麦AI、流量切换、数据中台的核心业务详细讲解
- 1 对 1 解答:可以对我进行1对1的问题提问,而不仅仅只限于项目
- 针对性服务:有没理解的地方,文档或者视频还没有讲到可以提出,本人会补充
- 面试与简历指导:提供面试回答技巧,项目怎样写才能在简历中具有独特的亮点
- 中间件环境:对于项目中需要使用的中间件,可直接替换成我提供的云环境
- 面试后复盘:小伙伴去面试后,如果哪里被面试官问住了,可以再找我解答
- 远程的解决:如果在启动项目遇到问题,本人可以帮你远程解决
进入星球后,即可享受上述所有服务,保证不会再有其他隐藏费用。
