Skip to content

SyncMcpToolCallback call fails with UnsupportedOperationException if ToolContext is set #2378

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

Closed
henningSaulCM opened this issue Mar 3, 2025 · 8 comments · Fixed by #2432
Assignees
Labels
Milestone

Comments

@henningSaulCM
Copy link

Bug description
Integrating and calling an MCP Tool with an existing Spring AI application that uses a ToolContext will result in an UnsupportedOperationException.

Environment
Spring AI 1.0.0-M6

Steps to reproduce

  1. Integrate https://github.com/modelcontextprotocol/servers/tree/main/src/everything into a Spring AI application using https://docs.spring.io/spring-ai/reference/api/mcp/mcp-client-boot-starter-docs.html
  2. Set the ToolContext in your Spring AI application
  3. Call one of the tools provided by the everything MCP server, e.g. printEnv
  4. Observe "UnsupportedOperationException: Tool context is not supported!" for SyncMcpToolCallback

Exception is raised here:

throw new UnsupportedOperationException("Tool context is not supported!");

Expected behavior
The MCP printEnv tool is called, ignoring the ToolContext (assuming this concept is not supported in MCP).

@tzolov
Copy link
Contributor

tzolov commented Mar 7, 2025

Thanks @henningSaulCM , I believe this is a know issue and should have been resolved by
the 82d98b6
Can you test with 1.0.0-SNAPSHOT please?

@tzolov tzolov self-assigned this Mar 7, 2025
@tzolov tzolov added duplicate This issue or pull request already exists tool/function calling status: waiting-for-feedback labels Mar 7, 2025
@tzolov
Copy link
Contributor

tzolov commented Mar 7, 2025

Likely the same as #2337

@henningSaulCM
Copy link
Author

henningSaulCM commented Mar 7, 2025

Hi @tzolov, thanks for chiming in.

I just tried with 1.0.0-SNAPSHOT (spring-ai-core-1.0.0-20250307.123602-1325.jar) and it seems I'm still getting the UnsupportedOperationException.

Stacktrace (excerpt):

java.lang.UnsupportedOperationException: Tool context is not supported!
		at org.springframework.ai.tool.ToolCallback.call(ToolCallback.java:57)
		at org.springframework.ai.model.tool.DefaultToolCallingManager.executeToolCall(DefaultToolCallingManager.java:226)
		at org.springframework.ai.model.tool.DefaultToolCallingManager.executeToolCalls(DefaultToolCallingManager.java:138)
		at org.springframework.ai.openai.OpenAiChatModel.lambda$internalStream$10(OpenAiChatModel.java:442)
		at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:388)
		...

Any thoughts?

@tzolov tzolov added the MCP label Mar 8, 2025
@tzolov
Copy link
Contributor

tzolov commented Mar 9, 2025

@henningSaulCM I overlooked that AsyncMcpToolCallback and SyncMcpToolCallback don't implement String call(String toolInput, ToolContext tooContext).
I'm not sure how to map ToolContext to a general-purpose MCP Tool Call, as the context only makes sense within Spring AI Tool Calling.
Are you looking for MCP ToolContext support, or is the error happening because you're mixing MCP and Spring AI tools? If it's the latter, we could implement the method for both callback types by ignoring the toolContext. Would that work?

@henningSaulCM
Copy link
Author

Hi @tzolov,

Are you looking for MCP ToolContext support, or is the error happening because you're mixing MCP and Spring AI tools? If it's the latter, we could implement the method for both callback types by ignoring the toolContext. Would that work?

Yes, this is happening because I was trying to integrate MCP tools with an existing Spring AI application that uses custom Spring AI tools and custom (non-empty) ToolContext. If MCP does not support a ToolContext (yet), ignoring the ToolContext for MCP Tool calls would be just fine IMHO to avoid the Exception.

#2432 looks good to me.
Thanks for your work on Spring AI and the quick turnaround for this particular issue.

Cheers

abhiraj2 pushed a commit to couchbaselabs/spring-ai that referenced this issue Mar 12, 2025
- Implement the new ToolCallback.call(String, ToolContext) method in both Sync and Async MCP tool callbacks.
- Since MCP tools don't support tool context, the implementation ignores the context parameter and
  delegates to the existing call(String) method. Added test to verify the behavior.

Resolves spring-projects#2378

Signed-off-by: Christian Tzolov <[email protected]>
abhiraj2 pushed a commit to couchbaselabs/spring-ai that referenced this issue Mar 12, 2025
- Implement the new ToolCallback.call(String, ToolContext) method in both Sync and Async MCP tool callbacks.
- Since MCP tools don't support tool context, the implementation ignores the context parameter and
  delegates to the existing call(String) method. Added test to verify the behavior.

Resolves spring-projects#2378

Signed-off-by: Christian Tzolov <[email protected]>
abhiraj2 pushed a commit to couchbaselabs/spring-ai that referenced this issue Mar 12, 2025
- Implement the new ToolCallback.call(String, ToolContext) method in both Sync and Async MCP tool callbacks.
- Since MCP tools don't support tool context, the implementation ignores the context parameter and
  delegates to the existing call(String) method. Added test to verify the behavior.

Resolves spring-projects#2378

Signed-off-by: Christian Tzolov <[email protected]>
abhiraj2 pushed a commit to couchbaselabs/spring-ai that referenced this issue Mar 12, 2025
- Implement the new ToolCallback.call(String, ToolContext) method in both Sync and Async MCP tool callbacks.
- Since MCP tools don't support tool context, the implementation ignores the context parameter and
  delegates to the existing call(String) method. Added test to verify the behavior.

Resolves spring-projects#2378

Signed-off-by: Christian Tzolov <[email protected]>
abhiraj2 pushed a commit to couchbaselabs/spring-ai that referenced this issue Mar 12, 2025
- Implement the new ToolCallback.call(String, ToolContext) method in both Sync and Async MCP tool callbacks.
- Since MCP tools don't support tool context, the implementation ignores the context parameter and
  delegates to the existing call(String) method. Added test to verify the behavior.

Resolves spring-projects#2378

Signed-off-by: Christian Tzolov <[email protected]>
leijendary pushed a commit to leijendary/spring-ai that referenced this issue Mar 28, 2025
- Implement the new ToolCallback.call(String, ToolContext) method in both Sync and Async MCP tool callbacks.
- Since MCP tools don't support tool context, the implementation ignores the context parameter and
  delegates to the existing call(String) method. Added test to verify the behavior.

Resolves spring-projects#2378

Signed-off-by: Christian Tzolov <[email protected]>
@gule002
Copy link

gule002 commented Apr 7, 2025

@tzolov when you said " as the context only makes sense within Spring AI Tool Calling." can you please elaborate. Do you mean this is supported only when the tool is not remotely hosted over sse?

I am attempting to pass a bearer token back to the MCP server using some mechanism - I thought ToolContext would be the right way, but if it is not supported, I am at a loss on how to pass a special parameter back that the AI agent is not allowed to touch.

@ligenzatomas
Copy link

@tzolov when you said " as the context only makes sense within Spring AI Tool Calling." can you please elaborate. Do you mean this is supported only when the tool is not remotely hosted over sse?

I am attempting to pass a bearer token back to the MCP server using some mechanism - I thought ToolContext would be the right way, but if it is not supported, I am at a loss on how to pass a special parameter back that the AI agent is not allowed to touch.

I am also interested in this topic.

@gule002
Copy link

gule002 commented Apr 10, 2025

I think I got to the bottom of this, currently the framework and maybe even the protocol (SSE/STDIO transport) does not support the ToolContext feature, I got it working with great success by pulling the tool into the App server's memory and process space by using org.springframework.ai.tool.method.MethodToolCallback

In order to get a reference to the MethodToolCallback objects you annotated and scanned in your App server, just autowire it:

List<ToolCallbackProvider> toolCallbackProviders;

This allows you to pass in the HttpServletRequest object and do all sorts of fancy things:

            responseSpec = chatClient.prompt(prompt)
                .toolContext(Map.of("httpRequest", httpRequest))
                .tools(selectedTools.toArray(new ToolCallback[0]))
                .call();

For example, you can have the tool return the time in the visitor's own timezone:

        @Tool(description = "Format a date string according to the specified pattern in the user's timezone")
        public String formatDate(
            @ToolParam(description = "ISO date-time string to format (e.g., '2023-01-01T12:00:00Z')") String dateString,
            @ToolParam(description = "Date format pattern (e.g., 'yyyy-MM-dd', 'MMMM d, yyyy', etc.)") String pattern,
            ToolContext context
        ) {
            try {
                HttpServletRequest request = (HttpServletRequest) context.getContext().get("httpRequest");
                ZoneId userZone = getUserTimeZone(request);
                
                // Parse the input date
                Instant instant = Instant.parse(dateString);
                ZonedDateTime dateTime = instant.atZone(userZone);
                
                // Format using the provided pattern
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
                return dateTime.format(formatter);
            } catch (Exception e) {
                logger.error("Error formatting date: {}", e.getMessage());
                return "Error formatting date: " + e.getMessage();
            }
        }

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

Successfully merging a pull request may close this issue.

4 participants