Class McpToolSpecificationsBootstrapWrapper

java.lang.Object
com.github._1c_syntax.bsl.languageserver.mcp.McpToolSpecificationsBootstrapWrapper
All Implemented Interfaces:
BeanPostProcessor

@Component @Profile("mcp") public class McpToolSpecificationsBootstrapWrapper extends Object implements BeanPostProcessor
Оборачивает каждый McpServerFeatures.SyncToolSpecification, собранный Spring AI MCP по @McpTool-методам, в обёртку, которая перед делегированием в исходный handler вызывает McpRootsBootstrapper. Это даёт проактивный roots/list (как требует MCP-спека) без какого-либо знания о bootstrap-логике в самих tool-методах.

Обёртка же гарантирует ответ на вызов, упавший с VirtualMachineError (например, StackOverflowError) или LinkageError: Spring AI превращает в результат-ошибку только исключения, а Reactor такие ошибки считает фатальными для JVM и пробрасывает мимо onError — запрос остаётся без ответа, и клиент ждёт его бесконечно. Вместо этого клиент получает результат с isError, а ошибка пишется в лог.

Spring AI autoconfig публикует список как @Bean public List<SyncToolSpecification> toolSpecs(...) в McpServerSpecificationFactoryAutoConfiguration; имя bean'а — "toolSpecs". Мы перехватываем post-init этого bean'а и подменяем его на список обёрток.

Зависимость на McpRootsBootstrapper ленивая через ObjectProvider, чтобы не вынуждать создание workspace-scoped бина в момент инициализации BeanPostProcessor'а.