Bug description Now it can be called successfully. But it will not call the tools in mcp。 What I can confirm is that there are tools in sse, and sse can be linked normally。 openAiClientManager is my custom built OpenAiChatModel and it works fine. I have tried many methods and asked cursor. I have also read the relevant documents of springai, but I still can't find the reason for this problem. I have been troubled for 3 days. I would be very grateful if anyone could help me。
maven
ai:
mcp:
client:
enabled: true
name: mcp-test-client
version: 1.0.0
request-timeout: 30s
type: SYNC # 同步客户端类型
sse:
connections:
mcp-server: # MCP服务器连接名称
url: http://0.0.0.0:3000
sse-endpoint: /sse # SSE端点
<spring-ai.version>1.1.0-SNAPSHOT </spring-ai.version>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
<version>${spring-ai.version}</version>
</dependency>
@Autowired
List<McpSyncClient> mcpSyncClients;
@Test
public void predefinedQuestions() {
HashSet<String> names = new HashSet<>();
OpenAiChatModel client = openAiClientManager.getClient(OpenAiProvider.xxxx);
for (McpSyncClient mcpClient : mcpSyncClients) {
for (McpSchema.Tool tool : mcpClient.listTools().tools()) {
String name = tool.name();
String description = tool.description();
//System.err.println("name:" + name);
//System.err.println("description:" + description);
names.add("mcp_test_client_mcp_server_" + name);
}
}
var mcpToolProvider = new SyncMcpToolCallbackProvider(mcpSyncClients);
ToolCallback[] toolCallbacks = mcpToolProvider.getToolCallbacks();
ChatClient chatClient = ChatClient.builder(client).defaultToolCallbacks(mcpToolProvider).build();
String userQuestion = """
What tools are available?
""";
Prompt prompt = new Prompt(userQuestion, OpenAiChatOptions.builder()
.model("gpt-4o")
.build());
System.out.println("> USER: " + userQuestion);
System.out.println("> ASSISTANT: " + chatClient.prompt(prompt).call().content());
}
private OpenAiChatModel buildModel(OpenAiProvider provider) {
OpenAiApi openAiApi = OpenAiApi.builder().apiKey(cfg.getApiKey()).baseUrl(cfg.getBaseUrl()).build();
OpenAiChatModel chatModel = OpenAiChatModel.builder().openAiApi(openAiApi).build();
return chatModel;
}
Comment From: sunyuhan1998
I tried to reproduce your scenario using the Qwen model combined with the Amap MCP server, but couldn't replicate the issue. In my tests, the model successfully called the tools in MCP. The only difference from your code is that I used HttpClientSseClientTransport
to construct the NamedClientMcpTransport
. Maybe you could give it a try as well?
like this:
@Configuration
public class McpConfig {
@Bean
public List<NamedClientMcpTransport> mcpClientTransport() {
McpClientTransport transport = HttpClientSseClientTransport
.builder("https://mcp.amap.com")
.sseEndpoint("/sse?key=<your key>")
.objectMapper(new ObjectMapper())
.build();
return Collections.singletonList(new NamedClientMcpTransport("amap", transport));
}
}
Comment From: qiuyueovo
I tried to reproduce your scenario using the Qwen model combined with the Amap MCP server, but couldn't replicate the issue. In my tests, the model successfully called the tools in MCP. The only difference from your code is that I used
HttpClientSseClientTransport
to construct theNamedClientMcpTransport
. Maybe you could give it a try as well?like this:
``` @Configuration public class McpConfig {
@Bean public List<NamedClientMcpTransport> mcpClientTransport() { McpClientTransport transport = HttpClientSseClientTransport .builder("https://mcp.amap.com") .sseEndpoint("/sse?key=<your key>") .objectMapper(new ObjectMapper()) .build(); return Collections.singletonList(new NamedClientMcpTransport("amap", transport)); }
} ```
But I don't know how to integrate the above code into my code. Can you modify it based on the code I provided? There is no configuration about mcpClientTransport in my code. The reference document of the code is: https://docs.spring.io/spring-ai/reference/1.1-SNAPSHOT/api/mcp/mcp-client-boot-starter-docs.html.
I would be grateful if you could help me
Comment From: jingsewu
I think what he means is inteading of these configurations by using code:
But I doubt it will work. I’ve encountered an issue where using English input triggers the tool, but it doesn’t work with Chinese input.
Comment From: qiuyueovo
I think what he means is inteading of these configurations by using code:我认为他的意思是使用代码来实现这些配置:
But I doubt it will work. I’ve encountered an issue where using English input triggers the tool, but it doesn’t work with Chinese input.但我怀疑它能否正常工作。我遇到过一个问题,使用英文输入可以触发该工具,但使用中文输入却不行。
After I commented out the content in your screenshot, I added the above configuration file to the code, but the mcp tool was still not called correctly. This problem has troubled me for 3 days, and I still have no idea. And the prompt words of my question are in English. I can make sure that the sse port of mcp is working properly. I can call it normally using Cherry Studio tool. But it doesn't work in the code.
Comment From: jingbio
bug 描述现在可以成功调用。但它不会调用 mcp 中的工具。我可以确认 sse 中有工具,并且 sse 可以正常链接。openAiClientManager 是我自定义构建的 OpenAiChatModel,它运行正常。我尝试了很多方法并咨询了光标,还阅读了 springai 的相关文档,但仍然找不到这个问题的原因。我已经困扰了 3 天。如果有人能帮助我,我将不胜感激。
maven
ai: mcp: client: enabled: true name: mcp-test-client version: 1.0.0 request-timeout: 30s type: SYNC # 同步客户端类型 sse: connections: mcp-server: # MCP服务器连接名称 url: http://0.0.0.0:3000 sse-endpoint: /sse # SSE端点 ```
1.1.0-SNAPSHOT org.springframework.ai spring-ai-starter-mcp-client ${spring-ai.version} <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-openai</artifactId> <version>${spring-ai.version}</version> </dependency>
```
@Autowired List<McpSyncClient> mcpSyncClients; @Test public void predefinedQuestions() { HashSet<String> names = new HashSet<>(); OpenAiChatModel client = openAiClientManager.getClient(OpenAiProvider.xxxx); for (McpSyncClient mcpClient : mcpSyncClients) { for (McpSchema.Tool tool : mcpClient.listTools().tools()) { String name = tool.name(); String description = tool.description(); //System.err.println("name:" + name); //System.err.println("description:" + description); names.add("mcp_test_client_mcp_server_" + name); } } var mcpToolProvider = new SyncMcpToolCallbackProvider(mcpSyncClients); ToolCallback[] toolCallbacks = mcpToolProvider.getToolCallbacks(); ChatClient chatClient = ChatClient.builder(client).defaultToolCallbacks(mcpToolProvider).build(); String userQuestion = """ What tools are available? """; Prompt prompt = new Prompt(userQuestion, OpenAiChatOptions.builder() .model("gpt-4o") .build()); System.out.println("> USER: " + userQuestion); System.out.println("> ASSISTANT: " + chatClient.prompt(prompt).call().content()); } private OpenAiChatModel buildModel(OpenAiProvider provider) { OpenAiApi openAiApi = OpenAiApi.builder().apiKey(cfg.getApiKey()).baseUrl(cfg.getBaseUrl()).build(); OpenAiChatModel chatModel = OpenAiChatModel.builder().openAiApi(openAiApi).build(); return chatModel; }
Do these two lines of comments print any content? ‘‘‘ //System.err.println("name:" + name); //System.err.println("description:" + description); ’’’
Comment From: qiuyueovo
They can print out the complete tool in the mcp, including name and description. Like this: name:create description: create something name: update description: some updates
And the above results are consistent with the tools I viewed in Cherry Studio. They are all the tools in my mcp
But unfortunately, my mcp tool is not printed out in ASSISTANT.
Comment From: jingbio
Bug description Now it can be called successfully. But it will not call the tools in mcp。 What I can confirm is that there are tools in sse, and sse can be linked normally。 openAiClientManager is my custom built OpenAiChatModel and it works fine. I have tried many methods and asked cursor. I have also read the relevant documents of springai, but I still can't find the reason for this problem. I have been troubled for 3 days. I would be very grateful if anyone could help me。
maven
ai: mcp: client: enabled: true name: mcp-test-client version: 1.0.0 request-timeout: 30s type: SYNC # 同步客户端类型 sse: connections: mcp-server: # MCP服务器连接名称 url: http://0.0.0.0:3000 sse-endpoint: /sse # SSE端点 ```
1.1.0-SNAPSHOT org.springframework.ai spring-ai-starter-mcp-client ${spring-ai.version} <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-openai</artifactId> <version>${spring-ai.version}</version> </dependency>
```
@Autowired List<McpSyncClient> mcpSyncClients; @Test public void predefinedQuestions() { HashSet<String> names = new HashSet<>(); OpenAiChatModel client = openAiClientManager.getClient(OpenAiProvider.xxxx); for (McpSyncClient mcpClient : mcpSyncClients) { for (McpSchema.Tool tool : mcpClient.listTools().tools()) { String name = tool.name(); String description = tool.description(); //System.err.println("name:" + name); //System.err.println("description:" + description); names.add("mcp_test_client_mcp_server_" + name); } } var mcpToolProvider = new SyncMcpToolCallbackProvider(mcpSyncClients); ToolCallback[] toolCallbacks = mcpToolProvider.getToolCallbacks(); ChatClient chatClient = ChatClient.builder(client).defaultToolCallbacks(mcpToolProvider).build(); String userQuestion = """ What tools are available? """; Prompt prompt = new Prompt(userQuestion, OpenAiChatOptions.builder() .model("gpt-4o") .build()); System.out.println("> USER: " + userQuestion); System.out.println("> ASSISTANT: " + chatClient.prompt(prompt).call().content()); } private OpenAiChatModel buildModel(OpenAiProvider provider) { OpenAiApi openAiApi = OpenAiApi.builder().apiKey(cfg.getApiKey()).baseUrl(cfg.getBaseUrl()).build(); OpenAiChatModel chatModel = OpenAiChatModel.builder().openAiApi(openAiApi).build(); return chatModel; }
try it: ''' var mcpToolProvider = new SyncMcpToolCallbackProvider(mcpSyncClients); ChatClient chatClient = ChatClient.builder(client).defaultToolCallbacks(mcpToolProvider).build(); String userQuestion = """ What tools are available? """; System.out.println("> USER: " + userQuestion); System.out.println("> ASSISTANT: " + chatClient.prompt().user(userQuestion).call().content()); '''
Comment From: qiuyueovo
Unfortunately, it still doesn't work.
System.out.println("> ASSISTANT: " + chatClient.prompt(prompt).call().content());
System.out.println("> ASSISTANT: " + chatClient.prompt().user(userQuestion).call().content());
There is no difference between these two calling methods. The result is the same. There is no output of mcp tool And I need to pass prompt in chatClient because I set the model and conversation memory and other related information in prompt.
Comment From: jingbio
Unfortunately, it still doesn't work.
System.out.println("> ASSISTANT: " + chatClient.prompt(prompt).call().content()); System.out.println("> ASSISTANT: " + chatClient.prompt().user(userQuestion).call().content()); There is no difference between these two calling methods. The result is the same. There is no output of mcp tool And I need to pass prompt in chatClient because I set the model and conversation memory and other related information in prompt.
I almost replicated your code. The line missing is: OpenAiChatModel client = openAiClientManager.getClient(OpenAiProvider.xxxx);
Comment From: sunyuhan1998
Hi @qiuyueovo , it seems your issue hasn't been resolved yet. I suggest you organize the code that can reproduce the problem into a minimal project and share it. This might make it easier for others to help you identify the issue.
Comment From: qiuyueovo
OpenAiClientManager
private final Map<OpenAiProvider, OpenAiChatModel> clientMap = new EnumMap<>(OpenAiProvider.class);
@Resource(name = "aClient")
private OpenAiChatModel aClient;
@Resource(name = "bClient")
private OpenAiChatModel bClient;
@PostConstruct
public void init() {
clientMap.put(OpenAiProvider.a, aClient);
clientMap.put(OpenAiProvider.b, bClient);
}
public OpenAiChatModel getClient(OpenAiProvider provider) {
return clientMap.get(provider);
}
@Configuration
public class OpenAiClientConfig {
@Autowired
private AiProperties aiProperties;
@Bean("aClient")
public OpenAiChatModel aClient() {
return buildModel(OpenAiProvider.a);
}
@Bean("bClient")
public OpenAiChatModel bClient() {
return buildModel(OpenAiProvider.b);
}
private OpenAiChatModel buildModel(OpenAiProvider provider) {
AiProperties.AiProviderConfig cfg = aiProperties.getProviders().get(key);
if (cfg == null) throw new IllegalArgumentException("没有配置:" + provider);
//return new OpenAiChatModel(new OpenAiApi(cfg.getApiKey(), cfg.getBaseUrl()));
OpenAiApi openAiApi = OpenAiApi.builder().apiKey(cfg.getApiKey()).baseUrl(cfg.getBaseUrl()).build();
OpenAiChatModel chatModel = OpenAiChatModel.builder().openAiApi(openAiApi).build();
return chatModel;
}
}
The role of OpenAiClientManager is that I can freely choose and switch when I have multiple service providers.
Comment From: qiuyueovo
I only set the base url and api key. Nothing else changed.
Comment From: qiuyueovo
Hi @qiuyueovo , it seems your issue hasn't been resolved yet. I suggest you organize the code that can reproduce the problem into a minimal project and share it. This might make it easier for others to help you identify the issue.
The core code related to springai in the project has been pasted in the issues. There is almost no configuration. I also followed the official website documentation step by step. But it didn't work, which made me crazy. If it still doesn't work, I will streamline my project and share it
Comment From: jingbio
Hi @qiuyueovo , 你的问题似乎还没有解决。我建议你将能够重现问题的代码整理成一个最小的项目并分享出来。这可能有助于其他人更容易地帮你找出问题。
该项目中与 springai 相关的核心代码已在 issues 中粘贴。几乎没有任何配置。我也按照官方网站文档一步步操作了。但还是不行,这让我很抓狂。如果还是不行,我会精简我的项目并分享。
There is a fatal bug in your code: two @Bean methods have the same name, both are "aClient".
Comment From: qiuyueovo
Sorry. I made a typo when mosaicking part of my code. The actual code is correct
Comment From: jingbio
Sorry. I made a typo when mosaicking part of my code. The actual code is correct
I think you should minimize your code. This is more helpful for analysis.
Comment From: qiuyueovo
Thank you. My question may be complicated. I sent you an email
Comment From: hbsjz-swl
一群中国人在这用英文交流看起来很怪异, chatClient.defaultToolCallBack(ToolCallBackProvider).build(); 然后直接chatclient.prompt(YourQuestion).call().content(); 就可以了, toolcallbackprovider直接从容器中获取 不要自己配置, 这样就可以了, 在使用指定的mcpclient的时候 ,直接在容器中获取 mcpclients 然后过滤出你想使用的指定mcpclient 就能使用指定mcpclient 了,如果不单独获取 它,chatclient会自动根据所有mcpserver中工具的描述自己选择使用哪个工具来回答问题了