apache/shenyu · error · IllegalArgumentException
ToolContext is required
Error message
ToolContext is required
What it means
IllegalArgumentException from McpSessionHelper.getMcpSyncServerExchange when the ToolContext argument is null. Spring AI passes a ToolContext to tool callbacks during MCP tool execution; the helper needs it to retrieve the McpSyncServerExchange under the 'exchange' key. A null context means the tool was invoked without the MCP-provided context.
Solutions
- Invoke the tool through the MCP server path (or pass a ToolContext built with the 'exchange' key) rather than calling call(args) directly
- Upgrade Spring AI to the tested version (1.1.2) so ToolContext is populated automatically for MCP tool calls
- In custom wrappers, always forward the ToolContext argument to the underlying callback
- Guard in your code: reject tool invocations where ToolContext is null before reaching the plugin
Example fix
// before
toolCallback.call(toolArgs);
// after
toolCallback.call(toolArgs, new ToolContext(Map.of("exchange", mcpSyncServerExchange))); Defensive patterns
Strategy: type-guard
Validate before calling
if (toolContext == null) {
throw new IllegalArgumentException("tool call requires a ToolContext from the MCP pipeline");
} Type guard
boolean hasToolContext(Object ctx) { return ctx instanceof ToolContext; } Try / catch
try {
result = toolCallback.call(args, toolContext);
} catch (IllegalArgumentException e) {
if ("ToolContext is required".equals(e.getMessage())) {
LOG.error("Tool invoked without MCP ToolContext; use the MCP execution path", e);
} else throw e;
} Prevention
- Never call ShenyuToolCallback.call(args) without a ToolContext in custom code
- Upgrade Spring AI to 1.1.2 so ToolContext is auto-propagated
- Unit-test tool callbacks with a populated ToolContext
When it happens
Trigger: getMcpSyncServerExchange(null) is called — i.e. a ShenyuToolCallback is executed with a null ToolContext (e.g. calling call()/apply() directly without context, or a Spring AI version not passing context).
Common situations: Directly invoking ShenyuToolCallback in tests or custom code without a ToolContext; an older Spring AI runtime that doesn't propagate ToolContext into tool calls; a custom tool-execution wrapper dropping the context argument.
Related errors
- McpAsyncServerExchange is required in McpSyncServerExchange
- Import mcp server config failed:
- OpenAPI document is missing the top-level 'servers' field…
- OpenAPI pathKey cannot be null or empty
- OpenAPI methodType cannot be null or empty
AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12).
Data as JSON: /api/errors/4c5c11ff867548f7.
Report an issue: GitHub.
Appendix: source
Thrown at shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/session/McpSessionHelper.java:132
+ "(tested: {}). Error: {}", SUPPORTED_SDK_VERSION, e.getMessage(), e);
}
}
private static void clearReflectionFieldCache() {
asyncExchangeFieldCache = null;
sessionFieldCache = null;
fieldsResolved = false;
}
/**
* Get McpSyncServerExchange from ToolContext.
*
* @param toolContext the tool context
* @return the McpSyncServerExchange instance
*/
public static McpSyncServerExchange getMcpSyncServerExchange(final ToolContext toolContext) {
if (Objects.isNull(toolContext)) {
throw new IllegalArgumentException("ToolContext is required");
}
Map<String, Object> contextMap = toolContext.getContext();
if (Objects.isNull(contextMap) || contextMap.isEmpty()) {
throw new IllegalArgumentException("ToolContext is required");
}
McpSyncServerExchange mcpSyncServerExchange = (McpSyncServerExchange) contextMap.get("exchange");
if (Objects.isNull(mcpSyncServerExchange)) {
throw new IllegalArgumentException("McpSyncServerExchange is required in ToolContext");
}
return mcpSyncServerExchange;
}
/**
* Get sessionId from McpSyncServerExchange.
*
* <p>Uses reflection to access internal SDK fields. If reflection fails,
* an IllegalStateException is thrown with SDK compatibility information.
*View on GitHub (pinned to 567142e072)