You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Depending on the MCP client, only certain categories of tools provided by the MCP server may be required.
Exposing the entire tool list to the client can confuse the LLM and make it difficult to achieve the intended behavior.
I have implemented a mechanism that allows the MCP client to select the desired set of tools, such as https://localhost/mcp?group=image.
Of course, it’s possible to create separate MCP servers for image, video, or audio, but splitting them solely for client convenience would be highly inefficient in terms of resource usage.
To implement this feature, it is necessary to modify the toolsListRequestHandler in McpAsyncServer.
However, in version 1.1.0, the access modifier is private, making it impossible to modify directly.
As a workaround, I had to use reflection to manually modify the requestHandlers as shown below.
@Component
class McpAsyncServerHandlerPatcher : BeanPostProcessor {
override fun postProcessAfterInitialization(bean: Any, beanName: String): Any {
if (bean is McpAsyncServer) {
try {
val serverClass = McpAsyncServer::class.java
// 1.Get mcpTransportProvider
val providerField: Field = serverClass.getDeclaredField("mcpTransportProvider")
providerField.isAccessible = true
val transportProvider = providerField.get(bean)
// 2. Get sessionFactory
val factoryField: Field = transportProvider.javaClass.getDeclaredField("sessionFactory")
factoryField.isAccessible = true
val sessionFactory = factoryField.get(transportProvider)
// 3. Get requestHandlers
val handlersField: Field = sessionFactory.javaClass.getDeclaredField("requestHandlers")
handlersField.isAccessible = true
@Suppress("UNCHECKED_CAST")
val handlers = handlersField.get(sessionFactory) as MutableMap<String, McpRequestHandler<*>>
// 4. Get "tools/list" handler
val originalHandler =
handlers["tools/list"] as McpRequestHandler<McpSchema.ListToolsResult>
// 5. New Handler
val customHandler = McpRequestHandler<McpSchema.ListToolsResult> { exchange, params ->
val result = originalHandler.handle(exchange, params).block()!!
val group = (exchange.transportContext() as WebTransportContext).queryParams.getFirst("group")
if(group == null) {
Mono.just(McpSchema.ListToolsResult(result.tools, null))
} else {
// Service Policy for filtering of tools
val toolGroup = ToolGroup[group] ?: return@McpRequestHandler Mono.just(McpSchema.ListToolsResult(emptyList(), null))
val filteredTools = result.tools.filter {
extractFirstBracket(it.description) in toolGroup
}
Mono.just(McpSchema.ListToolsResult(filteredTools, null))
}
}
// 6. Relace handler
handlers["tools/list"] = customHandler
} catch (e: Exception) {
e.printStackTrace()
}
}
return bean
}
// ...
Unlike McpAsyncServer, classes such as McpSyncServer or McpStatelessSyncServer return a fixed set of tools.
I propose introducing an McpServer interface that accepts the request context (exchange) as a parameter and returns tools dynamically.
Classes such as Mcp***Server would then implement this interface.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Depending on the MCP client, only certain categories of tools provided by the MCP server may be required.
Exposing the entire tool list to the client can confuse the LLM and make it difficult to achieve the intended behavior.
I have implemented a mechanism that allows the MCP client to select the desired set of tools, such as https://localhost/mcp?group=image.
Of course, it’s possible to create separate MCP servers for image, video, or audio, but splitting them solely for client convenience would be highly inefficient in terms of resource usage.
To implement this feature, it is necessary to modify the toolsListRequestHandler in McpAsyncServer.
However, in version 1.1.0, the access modifier is private, making it impossible to modify directly.
As a workaround, I had to use reflection to manually modify the requestHandlers as shown below.
Unlike McpAsyncServer, classes such as McpSyncServer or McpStatelessSyncServer return a fixed set of tools.
I propose introducing an McpServer interface that accepts the request context (exchange) as a parameter and returns tools dynamically.
Classes such as Mcp***Server would then implement this interface.
Beta Was this translation helpful? Give feedback.
All reactions