Skip to content

MCP Server @Tool throws "Multiple tools with the same name" #2771

Open
@finyuq

Description

@finyuq

Bug description
When a method annotated with @tool inherits from a parent class which is a generic class, and the method's input parameter is modified by the subclass. In this situation, when retrieving the declaredMethod, we get both a method with an Object type input parameter and a method with the actual subclass type input parameter (i.e., the bridge method). Currently, since there is no filtering of the bridge method, both of these methods are judged to have the @tool annotation, which will then throw an exception: java.lang.IllegalStateException: Multiple tools with the same name.

Steps to reproduce

  1. Create a generic parent class with a method that can be overridden by a subclass.
  2. Create a subclass that inherits from the generic parent class and modifies the input parameter of the overridden method.
  3. Annotate the overridden method in the subclass with @tool.
  4. Try to retrieve the declaredMethod for the method in the subclass.
  5. Observe that both the method with Object type input parameter and the bridge method (with the actual subclass type input parameter) are considered to have the @tool annotation, and the java.lang.IllegalStateException: Multiple tools with the same name exception is thrown.

Expected behavior
Only the actual method in the subclass with the correct input parameter type (the one that should be considered the valid implementation with the @tool annotation) should be recognized as having the @tool annotation, and the bridge method should be filtered out to avoid the situation where multiple methods with the same annotation lead to the IllegalStateException.

Minimal Complete Reproducible example

class MethodToolCallbackProviderTest {

	abstract class TestObjectClass<T> {

		public abstract String test(T input);
	}

	class TestObjectSuperClass extends TestObjectClass<String> {

		@Tool
		public String test(String input) {
			return input;
		}
	}

	@Test
	public void buildToolsWithBridgeMethodReturnOnlyUserDeclaredMethods() {
		MethodToolCallbackProvider provider = MethodToolCallbackProvider.builder().toolObjects(new TestObjectSuperClass()).build();
		ToolCallback[] toolCallbacks = provider.getToolCallbacks();

	}

}
`

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions