Skip to content

Conversation

quaff
Copy link
Contributor

@quaff quaff commented Sep 24, 2025

Before this commit, McpSyncClient is initialized even if spring.ai.mcp.client.initialized is set to false.

See GH-3232

@imod
Copy link

imod commented Sep 29, 2025

Although this is helpful, it only solves a part of the problem: as soon as the connection gets lost (e.g. reboot of the MCP Server) the connection does not get reestablished again and one needs to reboot the client too.

Copy link
Contributor

@Kehrlann Kehrlann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR mention MCP specifically, but we're now wrapping ALL ToolCallbackProviders, including MethodToolCallbackProvider - but those do not have an initialization issue. Is that desired?

This is a real issue for bootstrapping MCP, and this addresses the bootstrapping part. There's another issue linked to this: remote MCP tools can change on the server, over time, and the client gets notified. In this case, the cached MCP tools are not updated. I wonder if we should have an MCP-specific abstraction rather than a ToolCallbackProvider abstraction.

If we want to delay this MCP-focused abstraction, then this PR is neat 👌

ToolCallbackProvider toolCallbackProvider = MethodToolCallbackProvider.builder()
.toolObjects(new WeatherService())
.build();
return Mockito.spy(toolCallbackProvider);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer a mock over a spy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Existing tests rely on spy.

@imod
Copy link

imod commented Oct 7, 2025

I was hoping this makes it into 1.1.0-M3 :(

…Provider eagerly

Before this commit, `McpSyncClient` is initialized even if `spring.ai.mcp.client.initialized` is set to `false`.

See spring-projectsGH-3232

Signed-off-by: Yanming Zhou <[email protected]>
@imod
Copy link

imod commented Oct 9, 2025

hmm, I tried this locally but did not succeed - the mcp tools still get initialised at startup and the server start fails if the mcp server is not available.

This is how I configure my ChatClient:

    @Bean
    fun chatClient(
        chatClientBuilder: ChatClient.Builder,
        mcpSyncClients: List<McpSyncClient>,
    ): ChatClient =
        chatClientBuilder
            .defaultSystem(systemPromptResource)
            .defaultToolCallbacks(
                SyncMcpToolCallbackProvider
                    .builder()
                    .mcpClients(mcpSyncClients)
                    .build(),
            ).defaultAdvisors(
                MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder().build()).build(),
                SimpleLoggerAdvisor(),
            ).build()

@Kehrlann
Copy link
Contributor

Kehrlann commented Oct 9, 2025

@imod doing .defaultToolCallbacks(...) explicitly will always trigger a tools/list on MCP clients.

@imod
Copy link

imod commented Oct 9, 2025

ok, so I always have to set them directly on the ChatClient when executing the prompt? e.g.

        val response =
            chatClient
                .prompt()
                .toolCallbacks(
                    SyncMcpToolCallbackProvider
                        .builder()
                        .mcpClients(mcpSyncClients)
                        .build(),
                ).toolContext(mapOf("progressToken" to "token-" + UUID.randomUUID().toString()))
                .advisors { advisor -> advisor.param(ChatMemory.CONVERSATION_ID, conversationId) }
                .user { u -> u.text(resolvedUserPrompt) }
                .call()
                .content()

@Kehrlann
Copy link
Contributor

Correct @imod

You can put your SyncMcpToolCallbackProvider in a variable, you don't have to create a new one every time, but you need to call .toolCallbacks() on the chat client every time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants