跳到主要内容

MCP调用链路源码解密

前面几篇我们已经把 MCP Server 和 Client 跑起来了,但上一篇对“源码调用链路”的描述还是偏通用,容易把 Spring AI 的公共机制和本项目的真实实现混在一起。

这一篇就不只讲一些概念了,以之前的项目里的这两个模块为准,把链路重新梳理一遍:

  • ai-example-spring-ai-office-mcp-client
  • ai-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.checkAttendance
  • AttendanceTools.clockIn
  • MeetingRoomTools.queryRoomSchedule
  • MeetingRoomTools.bookMeetingRoom
  • MeetingRoomTools.cancelBooking

付费内容提示

该文档的全部内容仅对「JavaUp项目实战&技术讲解」知识星球用户开放

加入星球后,你可以获得:

  • 超级八股文:100万+字的全栈技术知识库,涵盖技术核心、数据库、中间件、分布式等深度剖析的讲解
  • 讲解文档:超级AI智能体、黑马点评Plus、大麦、大麦pro、大麦AI、流量切换、数据中台的从0到1的详细文档
  • 讲解视频:超级AI智能体、黑马点评Plus、大麦、大麦pro、大麦AI、流量切换、数据中台的核心业务详细讲解
  • 1 对 1 解答:可以对我进行1对1的问题提问,而不仅仅只限于项目
  • 针对性服务:有没理解的地方,文档或者视频还没有讲到可以提出,本人会补充
  • 面试与简历指导:提供面试回答技巧,项目怎样写才能在简历中具有独特的亮点
  • 中间件环境:对于项目中需要使用的中间件,可直接替换成我提供的云环境
  • 面试后复盘:小伙伴去面试后,如果哪里被面试官问住了,可以再找我解答
  • 远程的解决:如果在启动项目遇到问题,本人可以帮你远程解决
进入星球后,即可享受上述所有服务,保证不会再有其他隐藏费用。
知识星球二维码

1. 打开微信 -> 扫描左侧二维码 -> 加入「JavaUp项目实战&技术讲解」知识星球

2. 查看星球使用指导,获取完整项目讲解资料索引

👉 点击解锁全部付费内容
🎁优惠