news 2026/8/7 19:56:59

--工具和MCP调用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
--工具和MCP调用

1. 工程结构概览

Spring AI 提供了完整的工具调用(Tool Calling)能力,让 AI 模型可以调用外部服务。同时,Spring AI 还支持 MCP(Model Context Protocol),这是一个标准化的工具协议。

spring-ai-model/

├── tool/ # 工具调用核心

│ ├── ToolCallback.java # 工具回调接口

│ ├── ToolDefinition.java # 工具定义

│ ├── method/ # 方法工具

│ │ └── MethodToolCallback.java

│ ├── function/ # 函数工具

│ │ └── FunctionToolCallback.java

│ └── resolution/ # 工具解析

│ ├── ToolCallbackResolver.java

│ └── SpringBeanToolCallbackResolver.java

└── model/tool/ # 工具调用管理

├── ToolCallingManager.java

└── DefaultToolCallingManager.java

mcp/ # MCP 协议支持

├── common/ # MCP 核心

│ ├── AsyncMcpToolCallback.java

│ ├── SyncMcpToolCallback.java

│ ├── AsyncMcpToolCallbackProvider.java

│ └── SyncMcpToolCallbackProvider.java

└── mcp-annotations-spring/ # MCP 注解支持

└── annotation/spring/

2. 技术体系与模块关系

工具调用和 MCP 的关系:

image.png

3. 关键场景示例代码

3.1 方法工具

使用 @Tool 注解定义工具:

@Service

public class WeatherService {

@Tool(name = "get_weather", description = "获取天气信息")

public String getWeather(String city) {

// 调用天气 API

return weatherApi.getWeather(city);

}

@Tool(name = "get_forecast", description = "获取天气预报")

public WeatherForecast getForecast(

String city,

int days,

ToolContext context // 可选:获取工具上下文

) {

// 可以从 context 中获取对话历史等

return weatherApi.getForecast(city, days);

}

}

3.2 函数工具

使用函数式接口定义工具:

FunctionToolCallback<String, String> weatherTool =

FunctionToolCallback.builder("get_weather",

(String city) -> weatherApi.getWeather(city))

.description("获取天气信息")

.build();

3.3 MCP 工具

MCP 工具通过 MCP 客户端自动发现:

// MCP 工具会自动从 MCP 服务器发现

// 无需手动定义,通过 AsyncMcpToolCallbackProvider 提供

ChatClient chatClient = ChatClient.builder(chatModel)

.defaultAdvisors(

// MCP 工具会自动注册

)

.build();

3.4 工具调用流程

工具调用是自动的:

// 1. 定义工具

@Tool(name = "search_docs", description = "搜索文档")

public String searchDocs(String query) {

return docService.search(query);

}

// 2. 使用 ChatClient(工具会自动发现)

ChatClient chatClient = ChatClient.builder(chatModel)

.build();

// 3. 模型会自动调用工具

String response = chatClient.prompt()

.user("帮我搜索 Spring AI 的文档")

.call()

.content();

// 模型会自动调用 search_docs 工具

4. 核心时序图

4.1 工具调用完整流程

image.png

4.2 MCP 工具发现流程

image.png

5. 入口类与关键类关系

image.png

6. 关键实现逻辑分析

6.1 工具注册机制

Spring AI 支持多种工具注册方式:

方式一:@Tool 注解(推荐)

@Service

public class MyService {

@Tool(name = "my_tool", description = "我的工具")

public String myTool(String input) {

return "处理结果: " + input;

}

}

MethodToolCallbackProvider 会自动扫描所有 @Tool 注解的方法:

public class MethodToolCallbackProvider implements ToolCallbackProvider {

@Override

public ToolCallback[] getToolCallbacks() {

return toolObjects.stream()

.flatMap(toolObject ->

Stream.of(ReflectionUtils.getDeclaredMethods(toolObject.getClass()))

.filter(this::isToolAnnotatedMethod)

.map(method -> MethodToolCallback.builder()

.toolDefinition(ToolDefinitions.from(method))

.toolMethod(method)

.toolObject(toolObject)

.build())

)

.toArray(ToolCallback[]::new);

}

}

方式二:手动注册

ToolCallback tool = FunctionToolCallback.builder("my_tool",

(String input) -> "结果: " + input)

.build();

ToolCallingChatOptions options = ToolCallingChatOptions.builder()

.withToolCallbacks(tool)

.build();

方式三:MCP 自动发现

MCP 工具通过 AsyncMcpToolCallbackProvider 自动发现:

public class AsyncMcpToolCallbackProvider implements ToolCallbackProvider {

@Override

public ToolCallback[] getToolCallbacks() {

// 从 MCP 客户端获取工具列表

List<Tool> mcpTools = mcpClient.listTools();

return mcpTools.stream()

.map(tool -> AsyncMcpToolCallback.builder()

.mcpClient(mcpClient)

.tool(tool)

.build())

.toArray(ToolCallback[]::new);

}

}

6.2 工具发现机制

ToolCallbackResolver 负责解析工具:

public class DelegatingToolCallbackResolver implements ToolCallbackResolver {

private final List<ToolCallbackResolver> resolvers;

@Override

public ToolCallback resolve(String toolName) {

// 按顺序尝试每个解析器

for (ToolCallbackResolver resolver : resolvers) {

ToolCallback tool = resolver.resolve(toolName);

if (tool != null) {

return tool;

}

}

return null;

}

}

SpringBeanToolCallbackResolver 从 Spring 容器中查找:

public class SpringBeanToolCallbackResolver implements ToolCallbackResolver {

@Override

public ToolCallback resolve(String toolName) {

// 1. 检查缓存

ToolCallback cached = cache.get(toolName);

if (cached != null) {

return cached;

}

// 2. 从 Spring 容器中查找 Bean

try {

Object bean = applicationContext.getBean(toolName);

ResolvableType toolType = resolveBeanType(bean);

// 3. 构建 ToolCallback

ToolCallback tool = buildToolCallback(toolName, toolType, bean);

// 4. 缓存

cache.put(toolName, tool);

return tool;

} catch (Exception e) {

return null;

}

}

}

6.3 工具调用执行

DefaultToolCallingManager 负责执行工具调用:

public class DefaultToolCallingManager implements ToolCallingManager {

@Override

public ToolExecutionResult executeToolCalls(Prompt prompt, ChatResponse response) {

// 1. 提取工具调用请求

AssistantMessage assistantMessage = extractToolCalls(response);

// 2. 构建工具上下文

ToolContext toolContext = buildToolContext(prompt, assistantMessage);

// 3. 执行每个工具调用

List<ToolResponse> toolResponses = new ArrayList<>();

for (ToolCall toolCall : assistantMessage.getToolCalls()) {

// 3.1 解析工具回调

ToolCallback callback = resolveToolCallback(toolCall.getName());

// 3.2 执行工具

String result = callback.call(toolCall.getArguments(), toolContext);

// 3.3 构建响应

toolResponses.add(new ToolResponse(toolCall.getId(), result));

}

// 4. 构建工具响应消息

ToolResponseMessage toolResponseMessage =

new ToolResponseMessage(toolResponses);

// 5. 构建对话历史

List<Message> conversationHistory = buildConversationHistory(

prompt.getInstructions(),

assistantMessage,

toolResponseMessage

);

return ToolExecutionResult.builder()

.conversationHistory(conversationHistory)

.returnDirect(shouldReturnDirect())

.build();

}

}

6.4 MCP 工具适配

MCP 工具通过 AsyncMcpToolCallback 适配到 Spring AI:

public class AsyncMcpToolCallback implements ToolCallback {

@Override

public String call(String toolInput, ToolContext toolContext) {

// 1. 解析工具输入

Map<String, Object> arguments = jsonToMap(toolInput);

// 2. 转换工具上下文

McpMeta mcpMeta = toolContextToMcpMetaConverter.convert(toolContext);

// 3. 构建 MCP 请求

CallToolRequest request = CallToolRequest.builder()

.name(tool.name()) // 使用原始工具名

.arguments(arguments)

.meta(mcpMeta)

.build();

// 4. 调用 MCP 客户端

CallToolResult response = mcpClient.callTool(request)

.onErrorMap(exception ->

new ToolExecutionException(getToolDefinition(), exception))

.block();

// 5. 处理错误

if (response.isError()) {

throw new ToolExecutionException(getToolDefinition(),

new IllegalStateException("Error: " + response.content()));

}

// 6. 返回结果

return toJsonString(response.content());

}

}

7. MCP 协议集成

7.1 MCP 是什么

MCP(Model Context Protocol)是一个标准化的协议,用于让 AI 模型访问外部工具和数据源。它定义了:

工具发现:服务器可以暴露可用的工具

工具调用:客户端可以调用工具

资源访问:客户端可以访问服务器资源

7.2 MCP 工具提供者

AsyncMcpToolCallbackProvider 负责从 MCP 服务器发现工具:

public class AsyncMcpToolCallbackProvider implements ToolCallbackProvider {

@Override

public ToolCallback[] getToolCallbacks() {

// 1. 从 MCP 客户端获取工具列表

List<Tool> tools = mcpClient.listTools();

// 2. 转换为 Spring AI ToolCallback

return tools.stream()

.map(tool -> AsyncMcpToolCallback.builder()

.mcpClient(mcpClient)

.tool(tool)

.toolNamePrefixGenerator(prefixGenerator)

.build())

.toArray(ToolCallback[]::new);

}

}

7.3 MCP 工具动态更新

MCP 支持工具的动态添加和删除:

// MCP 客户端监听工具变更事件

mcpClient.onToolsChanged(event -> {

// 重新获取工具列表

List<Tool> newTools = mcpClient.listTools();

// 更新工具提供者

toolCallbackProvider.updateTools(newTools);

});

8. 外部依赖

8.1 工具调用

Spring Framework:IoC 容器和反射

Jackson:JSON 处理(工具 Schema 生成)

Swagger Annotations:Schema 生成

8.2 MCP

MCP Java SDK:MCP 协议实现

Reactor Core:响应式支持(AsyncMcpToolCallback)

9. 工程总结

Spring AI 的工具调用和 MCP 能力设计有几个亮点:

统一的工具抽象。所有工具(方法、函数、MCP)都实现 ToolCallback 接口,这让工具调用变得统一和透明。不管工具来自哪里,调用方式都一样。

灵活的注册机制。支持注解、手动注册、MCP 自动发现等多种方式,适应不同的使用场景。想用注解?加个 @Tool 就行。想手动注册?创建 ToolCallback 就行。

智能的工具发现。通过 ToolCallbackResolver 链,可以按顺序尝试多个解析器,支持 Spring Bean、静态工具、MCP 工具等多种来源。找不到工具?换个解析器试试。

MCP 协议集成。通过 MCP 适配器,Spring AI 可以无缝集成 MCP 服务器提供的工具,支持工具的动态发现和更新。MCP 服务器添加了新工具?Spring AI 会自动同步。

工具上下文传递。工具可以接收 ToolContext,获取对话历史、用户信息等上下文,这让工具可以做出更智能的决策。比如根据用户历史记录,提供个性化服务。

总的来说,Spring AI 的工具调用和 MCP 能力既强大又灵活。统一的抽象让工具调用变得简单,灵活的机制让系统可以适应各种场景。这种设计让 Spring AI 既能支持简单的本地工具,也能支持复杂的 MCP 服务器工具。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/7 6:09:12

【信创】中间件对比

定位说明&#xff1a;本文面向企业架构师、后端研发负责人、信创项目技术选型人员&#xff0c;系统梳理中间件的分类体系、国外主流产品格局&#xff0c;以及国产信创中间件的对标与落地实践建议&#xff0c;适合作为技术博客或内部技术白皮书使用。一、中间件的核心定位与价值…

作者头像 李华
网站建设 2026/8/7 20:00:39

傅里叶变换小波变换

在信号分析领域&#xff0c;我们经常面对这样的问题&#xff1a;信号中有哪些频率成分&#xff1f;这些频率在什么时候出现&#xff1f;是否发生了突变&#xff1f;围绕这个问题&#xff0c;形成了三种非常经典、也是工程中最常用的分析工具&#xff1a; 傅里叶变换&#xff08…

作者头像 李华
网站建设 2026/8/7 19:59:31

智能桑拿房首选:水管家集成系统如何提升体验?

2025水质综合处理器桑拿智能水管家行业权威榜单极致体验与降本增效如何平衡&#xff1f;看头部品牌如何重塑行业标准引言随着浴室行业竞争白热化&#xff0c;消费者对水质体验的敏感度持续攀升——女性用户吐槽漂浮药味、年轻客群对水质浑浊率杀评、家庭客群则因孩子皮肤不适直…

作者头像 李华
网站建设 2026/8/7 15:26:44

最简单的LangChain和RAG

ollama的API&#xff1a;https://docs.ollama.com/api/ps ollama的API&#xff1a;https://github.com/ollama/ollama/blob/main/docs/api.md?utm_sourcechatgpt.com Ollama API ├── 推理类&#xff08;最常用&#xff09; │ ├── /api/generate ← 单轮生成 │ …

作者头像 李华
网站建设 2026/8/8 1:25:04

空压机监控运维管理系统方案

行业背景 我国制造业近年来经历了迅猛的发展&#xff0c;这一进程离不开各式各样动力设备的支持与推动。其中&#xff0c;空压机作为大型通用机械设备&#xff0c;在钢铁、电力、冶金、造船、纺织、电子、装备制造等多个关键领域发挥着不可或缺的作用。其长期稳定运行不仅是高…

作者头像 李华
网站建设 2026/8/8 5:00:21

实习面试题-Rust 面试题

1.Rust 有哪些特点?它和 C、C++ 有什么区别? 回答重点 Rust 是一门系统编程语言,最大的特点就是在保证高性能的同时,通过编译器在编译期就能保证内存安全。简单来说,Rust 既有 C/C++ 那样的性能,又不会出现 C/C++ 那些令人头疼的内存问题。 Rust 的核心特点包括所有权…

作者头像 李华