spring-projects / spring-projects/spring-ai

Can't register AsyncToolSpecification directly

Open
#4,491 0 comments 0 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

Bug description

A bean of type AsyncToolSpecification will not be added as a tool.

Environment
Spring AI 1.1.0-M2, spring boot 3.5.6, using the async server starter

Steps to reproduce

  1. Use the async server starter (and configure an async server)
  2. Register AsyncToolSpecification bean

Expected behavior

The bean is used as a tool.

Minimal Complete Reproducible example

@SpringBootApplication
class Application {
    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            runApplication<Application>(*args)
        }

        val emptySchema = McpSchema.JsonSchema("object", emptyMap(), emptyList(), false, emptyMap(), emptyMap())
    }

    @Bean
    fun missingTool(): McpServerFeatures.AsyncToolSpecification = McpServerFeatures.AsyncToolSpecification
        .builder()
        .tool(McpSchema.Tool.builder().name("missing").inputSchema(emptySchema).build())
        .callHandler { _, _ -> error("Test!") }
        .build()

    @Bean
    fun presentTool(): List<McpServerFeatures.AsyncToolSpecification> = listOf(
        McpServerFeatures.AsyncToolSpecification
            .builder()
            .tool(McpSchema.Tool.builder().name("present").inputSchema(emptySchema).build())
            .callHandler { _, _ -> error("Test!") }
            .build()
    )

    @McpTool(name = "present2")
    fun presentTool2(): Mono<String> = mono { error("Test!") }
}
spring:
  ai:
    mcp:
      server:
        type: ASYNC  # Recommended for reactive applications
        annotation-scanner:
          enabled: true
        capabilities:
          tool: true
          resource: true
          prompt: true
          completion: true
        stdio: false

Additional information

The issue seems to be with McpServerAutoConfiguration. If I debug mcpAsyncServer, calling tools.getIfAvailable returns a list containing only my bean (and not ones derived from @McpTool annotated methods) while tools.stream().flatMap(List::stream).toList() returns only the @McpTool tools. I'm not familiar enough with the internals of Spring to know why.

Note that registering my tool as a List<AsyncToolSpecification> bean makes it work fine.

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 with McpServerAutoConfiguration and the mcpAsyncServer setup described in the report. Reproduce the case using the provided Kotlin example, comparing a direct AsyncToolSpecification bean with a List bean and the @McpTool result. Done means a directly registered AsyncToolSpecification is included alongside the annotated tools.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, kotlin, spring-boot
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.