Spring AI MCP客户端连接成功却看不到工具?从初始化、传输、过滤到ChatClient完整排查
文章摘要
Spring AI项目接入MCP时,最常见的问题之一是:应用启动没有报错,MCP Server日志也显示连接成功,但ChatClient始终不调用工具,甚至工具列表为空。问题可能发生在初始化、传输配置、工具回调开关、客户端类型、工具过滤、名称冲突、Schema生成、权限或ChatClient注册等多个环节。本文给出一条从MCP连接到模型工具调用的完整排查链路。
一、先区分三种不同故障
“工具不可用”至少分三类:
1. MCP客户端没有连接成功
表现:
连接超时
初始化失败
协议版本不匹配
认证失败
2. 客户端连接成功,但没有发现工具
表现:
tools/list为空
工具被过滤
服务器没有注册工具
缓存仍是旧列表
3. 工具已经发现,但模型不调用
表现:
ChatClient中可以看到ToolCallback
模型始终直接回答
工具Description不清楚
用户问题不需要工具
模型不支持工具调用
排查时必须先判断属于哪一类。
二、第一步:确认客户端是否完成初始化
Spring AI MCP客户端默认可以自动初始化。
配置:
spring:
ai:
mcp:
client:
enabled: true
initialized: true
request-timeout: 20s
如果配置为:
initialized: false
客户端创建后可能尚未完成协议初始化和能力发现。
检查启动日志:
客户端名称
服务端地址
传输类型
初始化状态
协议版本
工具数量
不要只看“Application started”。
三、第二步:确认传输配置匹配
服务端:
spring:
ai:
mcp:
server:
protocol: STREAMABLE
客户端必须使用对应的Streamable HTTP连接配置。
如果服务端是:
STDIO
客户端却按HTTP连接,当然无法发现工具。
常见不匹配:
服务端STATELESS
客户端仍按旧SSE端点连接
服务端WebMVC
客户端URL指向错误上下文路径
服务端STDIO
客户端命令或参数错误
四、第三步:确认连接地址不是普通业务接口
MCP端点通常不是你的:
/api/chat
/api/tools
而是MCP Starter配置或默认暴露的协议端点。
如果服务部署在反向代理后:
外部:https://api.example.com/ai/mcp
内部:http://mcp-service:8080/mcp
需要检查:
- 网关Path Rewrite;
- Context Path;
- HTTPS终止;
- Content-Type;
- 请求头转发;
- 流式响应缓冲;
- 超时。
五、第四步:确认服务端真的注册了工具
使用注解:
@Component
public class OrderTools {
@McpTool(
name = "query_order",
description = "根据订单号查询订单当前状态"
)
public OrderResult queryOrder(
String orderId
) {
return orderService.query(orderId);
}
}
检查:
类是否是Spring Bean
注解扫描是否启用
包是否在扫描路径下
方法是否为public
参数是否能生成JSON Schema
返回类型是否可序列化
工具名称是否合法
如果类是自己new出来的,不属于Spring容器,自动扫描不会注册。
六、第五步:检查工具回调集成是否关闭
Spring AI MCP客户端可以把远程MCP Tool转换为Spring AI ToolCallback。
关键配置:
spring:
ai:
mcp:
client:
toolcallback:
enabled: true
如果设为:
enabled: false
MCP客户端仍可能连接成功,但工具不会自动进入Spring AI工具执行体系。
这是一类非常隐蔽的问题。
七、第六步:检查是否配置了工具过滤
生产项目通常不会把所有MCP工具暴露给模型。
可能配置:
允许列表
拒绝列表
按Server过滤
按工具名过滤
按租户过滤
如果过滤规则写错:
query_*
而实际工具名是:
order.query
最终列表可能为空。
建议启动时输出:
原始工具数
过滤后工具数
每个被排除工具的原因
不要只输出最终结果。
八、第七步:检查工具名称冲突
多个MCP Server可能都暴露:
search
query
get_status
Spring AI支持工具名前缀,用于避免冲突。
最终工具可能变成:
crm_search
knowledge_search
order_get_status
如果Prompt仍要求模型调用:
search
模型可能找不到准确工具。
工具名称建议:
领域_动作
例如:
order_query_status
customer_search_profile
knowledge_search_policy
九、第八步:检查工具Description是否足够明确
工具已注册但模型不调用,最常见原因之一是描述不清楚。
错误:
@McpTool(description = "查询数据")
模型不知道查询什么、何时调用。
推荐:
@McpTool(
name = "order_query_status",
description = "当用户询问某个具体订单的当前状态、物流节点或是否已签收时调用。必须提供orderId。不能用于查询商品库存。"
)
Description应说明:
- 解决什么问题;
- 什么时候调用;
- 必填参数;
- 不能做什么;
- 是否有副作用。
十、检查参数Schema是否生成成功
模型选择工具后,还需要生成合法参数。
复杂参数类:
public record OrderQuery(
@NotBlank String orderId,
boolean includeLogistics
) {
}
检查生成Schema:
{
"type": "object",
"properties": {
"orderId": {
"type": "string"
},
"includeLogistics": {
"type": "boolean"
}
},
"required": ["orderId"]
}
常见问题:
- 参数类型无法反射;
- Jackson无法序列化;
- 泛型过于复杂;
- 参数名丢失;
- 必填字段未标记;
- Schema过大。
十一、确认MCP Tool已经加入ChatClient
如果使用自动配置,MCP ToolCallback通常会由框架接入。
但自定义ChatClient时可能遗漏。
例如业务代码重新构建:
this.chatClient = builder.build();
而不是注入已经完成MCP工具集成的Bean。
建议检查:
当前ChatClient工具数量
工具名称列表
工具来源Server
不要假设所有ChatClient.Builder都具有相同工具集合。
十二、确认模型支持Tool Calling
不是所有兼容OpenAI接口的模型都完整支持工具调用。
检查:
- Provider是否支持;
- 模型版本是否支持;
- 是否关闭Tool Calling;
- JSON Schema支持程度;
- 最大工具数量;
- 流式工具调用支持;
- 并行工具调用支持。
固定测试:
请查询订单A1001的实时状态。
你必须调用订单查询工具,不得猜测。
如果仍然不产生Tool Call,应查看模型原始响应。
十三、不要用模型常识能够回答的问题测试
测试问题:
北京是中国首都吗?
即使存在知识工具,模型也可能直接回答。
更好的测试:
查询订单A1001当前状态。
或:
查询公司内部制度V4.2的差旅住宿标准。
问题必须依赖外部实时数据。
十四、权限失败可能被误判为没有工具
服务端可能按用户Scope过滤工具列表。
例如:
当前Token只有order:read
工具要求order:refund
服务端可以:
- 不返回该工具;
- 返回工具但调用时拒绝;
- 触发增量授权。
检查:
Access Token是否存在
Scope是否正确
Token是否过期
Audience是否匹配
租户信息是否进入请求
十五、工具列表缓存可能仍是旧数据
新规范允许工具列表带TTL。
如果服务端刚增加工具,而客户端仍使用缓存:
连接成功
但新工具不可见
处理:
- 等待TTL;
- 主动刷新;
- 发送listChanged;
- 重建客户端;
- 检查缓存键。
十六、建议增加启动自检
应用启动后执行:
连接每个MCP Server
→ 完成初始化
→ 拉取工具列表
→ 校验必需工具
→ 输出兼容报告
例如:
public record McpServerHealth(
String serverName,
boolean connected,
String protocolVersion,
int toolCount,
List missingRequiredTools
) {
}
必需工具缺失时,可以阻止生产实例接收流量。
十七、完整排查顺序
1. 客户端是否创建
2. 是否完成初始化
3. 传输与端点是否匹配
4. 鉴权是否成功
5. 服务端是否注册工具
6. tools/list是否有结果
7. 工具是否被过滤
8. 工具名称是否冲突
9. ToolCallback集成是否开启
10. ChatClient是否获得工具
11. 模型是否支持Tool Calling
12. 测试问题是否必须调用工具
13. 工具Schema是否有效
14. 缓存是否过期
十八、最小诊断日志
建议记录:
mcp.server.name
mcp.transport
mcp.protocol.version
mcp.initialized
mcp.tools.raw_count
mcp.tools.filtered_count
mcp.tool.names
chatclient.tool_count
model.name
model.tool_call_count
注意不要把Token、密码和完整敏感参数写入日志。
总结
MCP客户端“连接成功却没有工具”,通常不是一个问题,而是链路中某一层没有完成:
连接
→ 初始化
→ tools/list
→ 工具过滤
→ ToolCallback适配
→ ChatClient注册
→ 模型选择
按照这条链路逐层检查,比反复修改Prompt或重启服务更有效。
延伸阅读
如果你正在关注企业级 AI 应用、Spring AI、RAG、Agent 与 MCP 工程化落地,欢迎访问 智元界:
https://www.zyentor.com/
智元界将持续分享可运行的技术实战、架构设计、问题排查与企业应用案例。