Skip to content

Commit ef5c763

Browse files
committed
Fix Prompt#validate_arguments! crash when arguments are nil
`Prompt#validate_arguments!` called `required_args` which does `arguments_value.filter_map`, crashing with `NoMethodError` when `arguments_value` is `nil` (the default for prompts without declared arguments). Additionally, passing `nil` as args caused a crash on `args.keys`. Fix by defaulting `arguments_value` to `[]` and guarding against `nil` args.
1 parent 76ab822 commit ef5c763

File tree

2 files changed

+50
-4
lines changed

2 files changed

+50
-4
lines changed

lib/mcp/prompt.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def to_h
2121
title: title_value,
2222
description: description_value,
2323
icons: icons_value&.then { |icons| icons.empty? ? nil : icons.map(&:to_h) },
24-
arguments: arguments_value&.map(&:to_h),
24+
arguments: arguments_value.empty? ? nil : arguments_value.map(&:to_h),
2525
_meta: meta_value,
2626
}.compact
2727
end
@@ -32,7 +32,7 @@ def inherited(subclass)
3232
subclass.instance_variable_set(:@title_value, nil)
3333
subclass.instance_variable_set(:@description_value, nil)
3434
subclass.instance_variable_set(:@icons_value, nil)
35-
subclass.instance_variable_set(:@arguments_value, nil)
35+
subclass.instance_variable_set(:@arguments_value, [])
3636
subclass.instance_variable_set(:@meta_value, nil)
3737
end
3838

@@ -76,7 +76,7 @@ def arguments(value = NOT_SET)
7676
if value == NOT_SET
7777
@arguments_value
7878
else
79-
@arguments_value = value
79+
@arguments_value = Array(value)
8080
end
8181
end
8282

@@ -103,6 +103,7 @@ def define(name: nil, title: nil, description: nil, icons: [], arguments: [], me
103103
end
104104

105105
def validate_arguments!(args)
106+
args ||= {}
106107
missing = required_args - args.keys
107108
return if missing.empty?
108109

test/mcp/prompt_test.rb

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ class FullPrompt < Prompt
182182
assert_equal expected, FullPrompt.to_h
183183
end
184184

185-
test "#to_h handles nil arguments value" do
185+
test "#to_h omits arguments key when arguments are not declared" do
186186
class NoArgumentsPrompt < Prompt
187187
description "No arguments prompt"
188188
end
@@ -196,6 +196,51 @@ class NoArgumentsPrompt < Prompt
196196
assert_equal expected, prompt.to_h
197197
end
198198

199+
test "#validate_arguments! does not raise when arguments are not declared" do
200+
prompt_class = Class.new(Prompt) do
201+
prompt_name "no_args_prompt"
202+
description "A prompt with no arguments"
203+
# NOTE: no `arguments` declaration at all
204+
end
205+
206+
assert_nothing_raised do
207+
prompt_class.validate_arguments!({})
208+
end
209+
end
210+
211+
test "#validate_arguments! handles nil args" do
212+
prompt_class = Class.new(Prompt) do
213+
prompt_name "no_args_prompt"
214+
description "A prompt with no arguments"
215+
end
216+
217+
assert_nothing_raised do
218+
prompt_class.validate_arguments!(nil)
219+
end
220+
end
221+
222+
test "#validate_arguments! does not raise when arguments is explicitly set to nil" do
223+
prompt_class = Class.new(Prompt) do
224+
prompt_name "nil_args_prompt"
225+
description "A prompt with nil arguments"
226+
arguments nil
227+
end
228+
229+
assert_nothing_raised do
230+
prompt_class.validate_arguments!({})
231+
end
232+
end
233+
234+
test "#to_h omits arguments key when arguments is empty" do
235+
prompt = Prompt.define(
236+
name: "no_args_prompt",
237+
description: "a prompt without arguments",
238+
arguments: [],
239+
)
240+
241+
refute prompt.to_h.key?(:arguments)
242+
end
243+
199244
test "#to_h does not have `:icons` key when icons is empty" do
200245
prompt = Prompt.define(
201246
name: "prompt_without_icons",

0 commit comments

Comments
 (0)