spring-projects / spring-projects/spring-ai

ToolContext from MCP Client is lost in Spring AI MCP Server

Open Beginner friendly
#4,773 3 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: waiting-for-triage
Dominant language
Java
Stars
9.5k
Forks
2.9k
Avg merge
1d 7h
Merged PRs (30d)
6

Description

When using spring-ai-mcp (tested with 1.1.0-M3), the ToolContext values provided by the MCP client are not correctly propagated to the MCP server’s @Tool method.

This causes the ToolContext parameter injected into the tool method to lose the original client context, such as tokens or metadata.


Reproduction Steps
MCP Client Code
chatClient.prompt()
    .toolContext(Map.of("token", request.getToken()))
    .user(request.getMessage())
    .stream()
    .content()
    .subscribe();

The client sets a token inside toolContext, expecting the MCP server to receive it.

MCP Server Tool
@Tool(description = "Calculate financial statistics for a user")
public String calculateUserStatistics(Long createdByUserId, ToolContext toolContext) {
    // toolContext should contain "token" from client, but it’s missing
    System.out.println("Received ToolContext: " + toolContext);
    ...
}

On the server side, the toolContext received by the @Tool method does not contain the client-provided values (e.g. "token").


Root Cause Analysis

In the class

org.springframework.ai.mcp.McpToolUtils#toSharedSyncToolSpecification

the current code creates a new ToolContext as follows:

new ToolContext(Map.of(TOOL_CONTEXT_MCP_EXCHANGE_KEY, exchangeOrContext))

However, it does not include the meta field from the CallToolRequest (which contains the client’s tool context).

So the original client-provided ToolContext is completely ignored.


Expected Behavior

The ToolContext passed into the tool callback should merge both:

  1. the existing MCP exchange context (TOOL_CONTEXT_MCP_EXCHANGE_KEY), and
  2. the meta values from CallToolRequest (coming from the MCP client).

Proposed Fix

Modify McpToolUtils#toSharedSyncToolSpecification() to merge the client context:

Map<String, Object> mergedContext = new HashMap<>();
mergedContext.put(TOOL_CONTEXT_MCP_EXCHANGE_KEY, exchangeOrContext);
if (request.meta() != null) {
    mergedContext.putAll(request.meta());
}

ToolContext toolContext = new ToolContext(mergedContext);
String callResult = toolCallback.call(
    ModelOptionsUtils.toJsonString(request.arguments()), toolContext);

This will ensure that any context values set on the MCP client (via .toolContext(...)) are correctly available on the server.


Environment
  • Spring AI version: 1.1.0-M3
  • Java version: 25
  • MCP client: Spring AI MCP Client
  • MCP server: Spring AI MCP Server

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in org.springframework.ai.mcp.McpToolUtils#toSharedSyncToolSpecification and inspect how CallToolRequest, request.meta(), and the exchange context are converted into ToolContext. Reproduce the MCP client/server flow with the token example, then verify that the @Tool method receives both the exchange context and client-provided metadata.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
api, backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.