Skip to content

Commit 2195272

Browse files
committed
ClientMcp*HandlersRegistry: support beans with unresolvable types
- Fixes gh-4917 Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
1 parent 7f30987 commit 2195272

File tree

3 files changed

+30
-2
lines changed

3 files changed

+30
-2
lines changed

mcp/mcp-annotations-spring/src/main/java/org/springframework/ai/mcp/annotation/spring/AbstractClientMcpHandlerRegistry.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,14 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
7474
// Only process singleton beans, not scoped beans
7575
continue;
7676
}
77-
var foundAnnotations = this.scan(AutoProxyUtils.determineTargetClass(beanFactory, beanName));
77+
Class<?> beanClass = AutoProxyUtils.determineTargetClass(beanFactory, beanName);
78+
if (beanClass == null) {
79+
// If we cannot determine the bean class, we cannot scan it before
80+
// it is really resolved. This is very likely an infrastructure-level
81+
// bean, not a "service" type, skip it entirely.
82+
continue;
83+
}
84+
var foundAnnotations = this.scan(beanClass);
7885
if (!foundAnnotations.isEmpty()) {
7986
this.allAnnotatedBeans.add(beanName);
8087
}

mcp/mcp-annotations-spring/src/test/java/org/springframework/ai/mcp/annotation/spring/ClientMcpAsyncHandlersRegistryTests.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
3939

4040
import static org.assertj.core.api.Assertions.assertThat;
41+
import static org.assertj.core.api.Assertions.assertThatNoException;
4142
import static org.assertj.core.api.Assertions.assertThatThrownBy;
4243
import static org.assertj.core.api.InstanceOfAssertFactories.type;
4344

@@ -340,6 +341,16 @@ void supportsProxiedClass() {
340341
assertThat(registry.getCapabilities("client-1").elicitation()).isNotNull();
341342
}
342343

344+
@Test
345+
void skipsUnknownBeanClass() {
346+
var registry = new ClientMcpAsyncHandlersRegistry();
347+
var beanFactory = new DefaultListableBeanFactory();
348+
beanFactory.registerBeanDefinition("myConfig",
349+
BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition());
350+
351+
assertThatNoException().isThrownBy(() -> registry.postProcessBeanFactory(beanFactory));
352+
}
353+
343354
static class ClientCapabilitiesConfiguration {
344355

345356
@McpElicitation(clients = { "client-1", "client-2" })

mcp/mcp-annotations-spring/src/test/java/org/springframework/ai/mcp/annotation/spring/ClientMcpSyncHandlersRegistryTests.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
import org.springframework.aop.framework.autoproxy.AutoProxyUtils;
3636
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
3737
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
38-
3938
import static org.assertj.core.api.Assertions.assertThat;
39+
import static org.assertj.core.api.Assertions.assertThatNoException;
4040
import static org.assertj.core.api.Assertions.assertThatThrownBy;
4141
import static org.assertj.core.api.InstanceOfAssertFactories.type;
4242

@@ -332,6 +332,16 @@ void supportsProxiedClass() {
332332
assertThat(registry.getCapabilities("client-1").elicitation()).isNotNull();
333333
}
334334

335+
@Test
336+
void skipsUnknownBeanClass() {
337+
var registry = new ClientMcpAsyncHandlersRegistry();
338+
var beanFactory = new DefaultListableBeanFactory();
339+
beanFactory.registerBeanDefinition("myConfig",
340+
BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition());
341+
342+
assertThatNoException().isThrownBy(() -> registry.postProcessBeanFactory(beanFactory));
343+
}
344+
335345
static class ClientCapabilitiesConfiguration {
336346

337347
@McpElicitation(clients = { "client-1", "client-2" })

0 commit comments

Comments
 (0)