Raise an error when duplicate tool names are registered
This raises an exception when duplicate tool names are registered, instead of silently overwriting tools. Tool names are required to be unique within a server, so this behavior aligns with the MCP specification. > Tool names SHOULD be unique within a server. https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool-names Validation for tool names could be made more strictly spec-compliant in a separate effort. Fixes #197
This commit is contained in:
parent
171baa876e
commit
dee80d20ae
1 changed files with 74 additions and 1 deletions
|
|
@ -5,6 +5,15 @@ require_relative "instrumentation"
|
|||
require_relative "methods"
|
||||
|
||||
module MCP
|
||||
class ToolNotUnique < StandardError
|
||||
def initialize(duplicated_tool_names)
|
||||
super(<<~MESSAGE)
|
||||
Tool names should be unique. Use `tool_name` to assign unique names to:
|
||||
#{duplicated_tool_names.join(", ")}
|
||||
MESSAGE
|
||||
end
|
||||
end
|
||||
|
||||
class Server
|
||||
DEFAULT_VERSION = "0.1.0"
|
||||
|
||||
|
|
@ -53,6 +62,7 @@ module MCP
|
|||
@title = title
|
||||
@version = version
|
||||
@instructions = instructions
|
||||
@tool_names = tools.map(&:name_value)
|
||||
@tools = tools.to_h { |t| [t.name_value, t] }
|
||||
@prompts = prompts.to_h { |p| [p.name_value, p] }
|
||||
@resources = resources
|
||||
|
|
@ -101,7 +111,10 @@ module MCP
|
|||
|
||||
def define_tool(name: nil, title: nil, description: nil, input_schema: nil, annotations: nil, meta: nil, &block)
|
||||
tool = Tool.define(name:, title:, description:, input_schema:, annotations:, meta:, &block)
|
||||
@tools[tool.name_value] = tool
|
||||
tool_name = tool.name_value
|
||||
|
||||
@tool_names << tool_name
|
||||
@tools[tool_name] = tool
|
||||
|
||||
validate!
|
||||
end
|
||||
|
|
@ -176,6 +189,8 @@ module MCP
|
|||
private
|
||||
|
||||
def validate!
|
||||
validate_tool_name!
|
||||
|
||||
# NOTE: The draft protocol version is the next version after 2025-11-25.
|
||||
if @configuration.protocol_version <= "2025-06-18"
|
||||
if server_info.key?(:description)
|
||||
|
|
@ -216,6 +231,12 @@ module MCP
|
|||
end
|
||||
end
|
||||
|
||||
def validate_tool_name!
|
||||
duplicated_tool_names = @tool_names.tally.filter_map { |name, count| name if count >= 2 }
|
||||
|
||||
raise ToolNotUnique, duplicated_tool_names unless duplicated_tool_names.empty?
|
||||
end
|
||||
|
||||
def handle_request(request, method)
|
||||
handler = @handlers[method]
|
||||
unless handler
|
||||
|
|
|
|||
Loading…
Reference in a new issue