-
Notifications
You must be signed in to change notification settings - Fork 2k
feat: MCP tools support ToolContext #3831
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Just an idea regarding the spring.ai.mcp.client.toolcallback.tool-call-history.enabled=trueThat way, the out-of-the-box user experience would be that the server only receives what the user explicitly writes into the ToolContext. And if the user wants to transmit additional metadata (such as On the other hand, one could argue that the default behavior of the ToolContext would then change depending on whether the tool call is executed locally or via MCP, which in turn would be an argument for including it by default. Tough decision, but I just thought I’d think out loud about it for a moment 🤔 |
| /** | ||
| * The keys that will not be sent to the MCP Server inside * the `_meta` field of | ||
| * {@link io.modelcontextprotocol.spec.McpSchema.CallToolRequest} | ||
| */ | ||
| // Remember to update META-INF/additional-spring-configuration-metadata.json if | ||
| // you change this default values. | ||
| private Set<String> excludedToolContextKeys = Set.of(TOOL_CALL_HISTORY); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That way, the out-of-the-box user experience would be that the server only receives what the user explicitly writes into the ToolContext. And if the user wants to transmit additional metadata (such as TOOL_CALL_HISTORY), they can explicitly enable that on the client side.
@msievers I did think about the scenario you mentioned.
The default value is spring.ai.mcp.client.toolcallback.excluded-tool-context-keys=TOOL_CALL_HISTORY, and users can override it. It also makes it easier for us to add more defaults in the future.
I'm not sure if we need a separate field just for handling TOOL_CALL_HISTORY.
7db214a to
9053c65
Compare
...-mcp-client-common/src/main/resources/META-INF/additional-spring-configuration-metadata.json
Show resolved
Hide resolved
...springframework/ai/mcp/client/common/autoconfigure/properties/McpClientCommonProperties.java
Show resolved
Hide resolved
| if (request.meta().containsKey(DEFAULT_MCP_META_TOOL_CONTEXT_KEY)) { | ||
| // Get the McpClient tool context from the | ||
| // `ai.springframework.org/tool_context` key in the _meta. | ||
| Map<String, Object> toolContext = OBJECT_MAPPER.convertValue( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could ModelOptionsUtils.objectToMap perhaps be used here instead of a dedicated ObjectMapper? I'm just asking because I noticed that in other parts, ModelOptionsUtils is often used when it comes to parameter conversions.
Map<String, Object> toolContext = ModelOptionsUtils.objectToMap(request.meta().get(DEFAULT_MCP_META_TOOL_CONTEXT_KEY));There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
I used to think that ModelOptionsUtils was only meant for handling Models, but apparently McpToolUtils also uses it for JSON serialization. So it makes sense to use it for _meta too.
I've updated the code accordingly and also adjusted some comments.
9053c65 to
e289c5c
Compare
- Added `excludedToolContextKeys` to `McpClientCommonProperties.ToolCallback`. This will let us control which `ToolContext` fields should not be sent to the server. By default, `excludedToolContextKeys` is set to `TOOL_CALL_HISTORY`. - Added `AbstractMcpToolCallback` to hold common code for `McpToolCallback` - Updated `AsyncMcpToolCallback` and `SyncMcpToolCallback` to pass `ToolContext` via `_meta` using key `ai.springframework.org/tool_context` - Updated `McpToolUtils` to help server tools extract `ToolContext` from MCP Client requests - Updated `AsyncMcpToolCallbackProvider` and `SyncMcpToolCallbackProvider` to use the Builder design pattern and add the `excludedToolContextKeys` field - Updated the corresponding test cases Signed-off-by: YunKui Lu <[email protected]>
e289c5c to
ad5c309
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At least in my humble opinion, this looks good. I think you can ping one the maintainers so they can take a look and ideally include it in the 1.1.0 release.
|
Hi @tzolov @markpollack, could you help review this PR? Thank you! 😊 |
|
@ilayaperumalg I wanted to ask if one of the maintainers could take a look at this merge request, which implements Support for |
|
@YunKuiLu Thanks for the PR and @msievers thanks for the review and follow up. While this PR addresses the issue, we think we can simplify this by setting the meta argument directly when invoking the MCP client callTool. I have submitted a PR #3925 for that. Could you review this and let us know what you think? Thank you |
|
@YunKuiLu Sorry, I misunderstood your implementation. I see you are using the same approach in setting the ToolContext and handling the server side. I will close my PR and let's continue review yours from here. |
|
@ilayaperumalg Thank you. If there is anything I didn't explain clearly, please point it out. By the way, could you help check this PR #3252 ? It's been merged into |
|
Any progress on this PR? |
|
Hi @markpollack , is there a chance to add this feature to the 1.1.0.M1 milestone? |
- Introduce ToolContextToMcpMetaConverter interface for converting Spring AI ToolContext to MCP call metadata - Refactor McpToolCallbackAutoConfiguration to use ObjectProvider for flexible dependency injection - Remove automatic McpToolNamePrefixGenerator bean creation in favor of ObjectProvider-based resolution - Add builder pattern for AsyncMcpToolCallback and SyncMcpToolCallback with comprehensive configuration options - Add builder pattern for AsyncMcpToolCallbackProvider and SyncMcpToolCallbackProvider - Enhance tool callback call methods to support ToolContext parameter with metadata conversion - Update MCP tool callbacks to use new CallToolRequest.builder() API - Improve error handling and logging in tool callback implementations - Add comprehensive coverage for new builder functionality - Update documentation with ToolContextToMcpMetaConverter usage examples - Maintain backward compatibility through deprecation of old constructors Breaking changes: - McpToolCallbackAutoConfiguration no longer automatically creates McpToolNamePrefixGenerator bean - Tool callback constructors are now private, use builder() method instead Resolves: spring-projects#3505 Resolves: spring-projects#2868 Resolves: spring-projects#2784 Resolves: spring-projects#2620 Replaces: spring-projects#3831 Signed-off-by: Christian Tzolov <[email protected]> Co-authored-by: YunKui Lu <[email protected]>
|
@YunKuiLu, thanks for your work on this. I've reworked the issue in PR #4328 with you as co-author, making necessary design changes. Key update: replaced exclude/include key properties with a customizable ToolContextToMcpMetaConverter. Let's continue discussion and work on #4328. |
|
Closing this as replaced by #4328. |
- Introduce ToolContextToMcpMetaConverter interface for converting Spring AI ToolContext to MCP call metadata - Refactor McpToolCallbackAutoConfiguration to use ObjectProvider for flexible dependency injection - Remove automatic McpToolNamePrefixGenerator bean creation in favor of ObjectProvider-based resolution - Add builder pattern for AsyncMcpToolCallback and SyncMcpToolCallback with comprehensive configuration options - Add builder pattern for AsyncMcpToolCallbackProvider and SyncMcpToolCallbackProvider - Enhance tool callback call methods to support ToolContext parameter with metadata conversion - Update MCP tool callbacks to use new CallToolRequest.builder() API - Improve error handling and logging in tool callback implementations - Add comprehensive coverage for new builder functionality - Update documentation with ToolContextToMcpMetaConverter usage examples - Maintain backward compatibility through deprecation of old constructors Breaking changes: - McpToolCallbackAutoConfiguration no longer automatically creates McpToolNamePrefixGenerator bean - Tool callback constructors are now private, use builder() method instead Resolves: #3505 Resolves: #2868 Resolves: #2784 Resolves: #2620 Replaces: #3831 ref docs updates Signed-off-by: Christian Tzolov <[email protected]> Co-authored-by: YunKui Lu <[email protected]>
- Introduce ToolContextToMcpMetaConverter interface for converting Spring AI ToolContext to MCP call metadata - Refactor McpToolCallbackAutoConfiguration to use ObjectProvider for flexible dependency injection - Remove automatic McpToolNamePrefixGenerator bean creation in favor of ObjectProvider-based resolution - Add builder pattern for AsyncMcpToolCallback and SyncMcpToolCallback with comprehensive configuration options - Add builder pattern for AsyncMcpToolCallbackProvider and SyncMcpToolCallbackProvider - Enhance tool callback call methods to support ToolContext parameter with metadata conversion - Update MCP tool callbacks to use new CallToolRequest.builder() API - Improve error handling and logging in tool callback implementations - Add comprehensive coverage for new builder functionality - Update documentation with ToolContextToMcpMetaConverter usage examples - Maintain backward compatibility through deprecation of old constructors Breaking changes: - McpToolCallbackAutoConfiguration no longer automatically creates McpToolNamePrefixGenerator bean - Tool callback constructors are now private, use builder() method instead Resolves: spring-projects#3505 Resolves: spring-projects#2868 Resolves: spring-projects#2784 Resolves: spring-projects#2620 Replaces: spring-projects#3831 ref docs updates Signed-off-by: Christian Tzolov <[email protected]> Co-authored-by: YunKui Lu <[email protected]>
- Introduce ToolContextToMcpMetaConverter interface for converting Spring AI ToolContext to MCP call metadata - Refactor McpToolCallbackAutoConfiguration to use ObjectProvider for flexible dependency injection - Remove automatic McpToolNamePrefixGenerator bean creation in favor of ObjectProvider-based resolution - Add builder pattern for AsyncMcpToolCallback and SyncMcpToolCallback with comprehensive configuration options - Add builder pattern for AsyncMcpToolCallbackProvider and SyncMcpToolCallbackProvider - Enhance tool callback call methods to support ToolContext parameter with metadata conversion - Update MCP tool callbacks to use new CallToolRequest.builder() API - Improve error handling and logging in tool callback implementations - Add comprehensive coverage for new builder functionality - Update documentation with ToolContextToMcpMetaConverter usage examples - Maintain backward compatibility through deprecation of old constructors Breaking changes: - McpToolCallbackAutoConfiguration no longer automatically creates McpToolNamePrefixGenerator bean - Tool callback constructors are now private, use builder() method instead Resolves: spring-projects#3505 Resolves: spring-projects#2868 Resolves: spring-projects#2784 Resolves: spring-projects#2620 Replaces: spring-projects#3831 ref docs updates Signed-off-by: Christian Tzolov <[email protected]> Co-authored-by: YunKui Lu <[email protected]>
- Introduce ToolContextToMcpMetaConverter interface for converting Spring AI ToolContext to MCP call metadata - Refactor McpToolCallbackAutoConfiguration to use ObjectProvider for flexible dependency injection - Remove automatic McpToolNamePrefixGenerator bean creation in favor of ObjectProvider-based resolution - Add builder pattern for AsyncMcpToolCallback and SyncMcpToolCallback with comprehensive configuration options - Add builder pattern for AsyncMcpToolCallbackProvider and SyncMcpToolCallbackProvider - Enhance tool callback call methods to support ToolContext parameter with metadata conversion - Update MCP tool callbacks to use new CallToolRequest.builder() API - Improve error handling and logging in tool callback implementations - Add comprehensive coverage for new builder functionality - Update documentation with ToolContextToMcpMetaConverter usage examples - Maintain backward compatibility through deprecation of old constructors Breaking changes: - McpToolCallbackAutoConfiguration no longer automatically creates McpToolNamePrefixGenerator bean - Tool callback constructors are now private, use builder() method instead Resolves: spring-projects#3505 Resolves: spring-projects#2868 Resolves: spring-projects#2784 Resolves: spring-projects#2620 Replaces: spring-projects#3831 ref docs updates Signed-off-by: Christian Tzolov <[email protected]> Co-authored-by: YunKui Lu <[email protected]> Signed-off-by: 家娃 <[email protected]>
excludedToolContextKeystoMcpClientCommonProperties.ToolCallback. This will let us control whichToolContextfields should not be sent to the server. By default,excludedToolContextKeysis set toTOOL_CALL_HISTORY.AbstractMcpToolCallbackto hold common code forMcpToolCallbackAsyncMcpToolCallbackandSyncMcpToolCallbackto passToolContextvia_metausing keyai.springframework.org/tool_contextMcpToolUtilsto help server tools extractToolContextfrom MCP Client requestsAsyncMcpToolCallbackProviderandSyncMcpToolCallbackProviderto use the Builder design pattern and add theexcludedToolContextKeysfieldPR description
The Spring AI MCP client now sends
ToolContextdata inside the_metafield ofCallToolRequest, using the keyai.springframework.org/tool_context.By default, the
TOOL_CALL_HISTORYentry inToolContextis excluded from being sent to the server. This can be customized using the configspring.ai.mcp.client.toolcallback.excluded-tool-context-keys.On the server side, Spring AI reads the
ToolContextfrom the_metafield using the same keyai.springframework.org/tool_context, and passes it into the tool method.QA
ai.springframework.org/tool_contextused as the key forToolContextin_meta?I decided to use it based on the MCP protocol's description of
_meta. https://modelcontextprotocol.io/specification/2025-06-18/basic/index#metaExample
Client
Server
Resolves #3505
Resolves #2868
Resolves #2784
Resolves #2620