Skip to content

Commit ec4712a

Browse files
committed
Add worker queue to enable sending message from S -> C
1 parent 394bbb0 commit ec4712a

File tree

5 files changed

+83
-10
lines changed

5 files changed

+83
-10
lines changed

lib/ruby_mcp/capabilities/prompts.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module RubyMCP::Capabilities::Prompts
2+
def add_prompt(...)
3+
@prompts.add(...)
4+
5+
RubyMCP.logger.info(@transport)
6+
send_prompts_list_changed if @transport
7+
end
8+
9+
private
10+
11+
def send_prompts_list_changed
12+
@transport.enqueue(jsonrpc: "2.0", method: "notifications/prompts/list_changed")
13+
end
14+
end

lib/ruby_mcp/server.rb

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module RubyMCP
22
class Server
33
include Capabilities::Logging
4+
include Capabilities::Prompts
45

56
attr_reader :lifecycle, :prompts, :resources
67

@@ -21,17 +22,13 @@ def connect(transport)
2122
start_transport
2223
end
2324

24-
def add_prompt(...)
25-
@prompts.add(...)
26-
end
27-
2825
def add_resource(...)
2926
@resources.add(...)
3027
end
3128

3229
def send_message(message)
3330
RubyMCP.logger.debug "S -> C : #{message}"
34-
@transport.send(message)
31+
@transport.enqueue(message)
3532
end
3633

3734
def answer(request, result)

lib/ruby_mcp/transport/stdio.rb

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
module RubyMCP
22
class Transport
33
class Stdio < Transport
4+
def initialize
5+
@queue = Queue.new
6+
end
7+
48
def start
59
@running = true
10+
start_message_worker
611

712
while @running
813
begin
914
line = $stdin.gets
1015

1116
break if line.nil?
1217

13-
@on_message.call(line.strip)
18+
@queue << [ :incoming, line.strip ]
1419
rescue StandardError => e
1520
RubyMCP.logger.error("Exception: #{e}")
1621
end
@@ -19,15 +24,33 @@ def start
1924
@on_close.call
2025
end
2126

22-
def send(message)
23-
$stdout.puts(JSON.generate(message))
24-
$stdout.flush
27+
def enqueue(message)
28+
@queue << [ :outgoing, JSON.generate(message) ]
2529
end
2630

2731

2832
def on_close(&block)
2933
@on_close = block
3034
end
35+
36+
private
37+
38+
def start_message_worker
39+
sleep 0.2
40+
RubyMCP.logger.info("Starting worker thread")
41+
@worker = Thread.new do
42+
while @running
43+
type, message = @queue.pop
44+
45+
if type == :incoming
46+
@on_message.call(message)
47+
else
48+
$stdout.puts(message)
49+
$stdout.flush
50+
end
51+
end
52+
end
53+
end
3154
end
3255
end
3356
end

lib/ruby_mcp/transport/test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def start
1111
@running = true
1212
end
1313

14-
def send(message)
14+
def enqueue(message)
1515
@responses << JSON.generate(message)
1616
end
1717

test/capabilities/test_prompts_capability.rb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,4 +329,43 @@ def test_prompt_get_missing_required_argument_with_multiple_required_args
329329
}
330330
)
331331
end
332+
333+
def test_adding_prompt_sends_prompts_list_changed
334+
@server.add_prompt(
335+
name: "refactor",
336+
description: "Review this code",
337+
arguments: [
338+
{
339+
name: "code",
340+
description: "code to review",
341+
required: true,
342+
completions: ->(*) { [ "some", "completion", "value" ] }
343+
},
344+
{
345+
name: "language",
346+
description: "Programming language",
347+
required: true,
348+
completions: ->(*) { [ "some", "completion", "value" ] }
349+
}
350+
],
351+
result: ->() {
352+
{
353+
description: "demo",
354+
messages: [
355+
{
356+
role: "user",
357+
content: {
358+
type: "text",
359+
text: "demo"
360+
}
361+
}
362+
]
363+
}
364+
},
365+
)
366+
367+
assert_last_response(
368+
jsonrpc: "2.0", method: "notifications/prompts/list_changed"
369+
)
370+
end
332371
end

0 commit comments

Comments
 (0)