@@ -12,13 +12,16 @@ This project is a Ruby client for the [Model Context Protocol (MCP)](https://mod
1212- 🛠️ ** Tool Integration** : Automatically converts MCP tools into RubyLLM-compatible tools
1313- 📄 ** Resource Management** : Access and include MCP resources (files, data) and resource templates in conversations
1414- 🎯 ** Prompt Integration** : Use predefined MCP prompts with arguments for consistent interactions
15- - 🔄 ** Real-time Communication** : Efficient bidirectional communication with MCP servers
1615- 🎨 ** Enhanced Chat Interface** : Extended RubyLLM chat methods for seamless MCP integration
1716- 📚 ** Simple API** : Easy-to-use interface that integrates seamlessly with RubyLLM
1817
1918## Installation
2019
21- Add this line to your application's Gemfile:
20+ ``` bash
21+ bundle add ruby_llm-mcp
22+ ```
23+
24+ or add this line to your application's Gemfile:
2225
2326``` ruby
2427gem ' ruby_llm-mcp'
@@ -152,12 +155,12 @@ MCP servers can provide access to resources - structured data that can be includ
152155# Get available resources from the MCP server
153156resources = client.resources
154157puts " Available resources:"
155- resources.each do |name , resource |
156- puts " - #{ name } : #{ resource.description } "
158+ resources.each do |resource |
159+ puts " - #{ resource. name} : #{ resource.description } "
157160end
158161
159- # Access a specific resource
160- file_resource = resources[ " project_readme" ]
162+ # Access a specific resource by name
163+ file_resource = client.resource( " project_readme" )
161164content = file_resource.content
162165puts " Resource content: #{ content } "
163166
@@ -179,11 +182,11 @@ Resource templates are parameterized resources that can be dynamically configure
179182``` ruby
180183# Get available resource templates
181184templates = client.resource_templates
182- log_template = templates[ " application_logs" ]
185+ log_template = client.resource_template( " application_logs" )
183186
184187# Use a template with parameters
185188chat = RubyLLM .chat(model: " gpt-4" )
186- chat.with_resource (log_template, arguments: {
189+ chat.with_resource_template (log_template, arguments: {
187190 date: " 2024-01-15" ,
188191 level: " error"
189192})
@@ -192,7 +195,7 @@ response = chat.ask("What errors occurred on this date?")
192195puts response
193196
194197# You can also get templated content directly
195- content = log_template.content (arguments: {
198+ content = log_template.to_content (arguments: {
196199 date: " 2024-01-15" ,
197200 level: " error"
198201})
@@ -204,12 +207,12 @@ puts content
204207For resource templates, you can get suggested values for arguments:
205208
206209``` ruby
207- template = client.resource_templates[ " user_profile" ]
210+ template = client.resource_template( " user_profile" )
208211
209212# Search for possible values for a specific argument
210- suggestions = template.arguments_search (" username" , " john" )
213+ suggestions = template.complete (" username" , " john" )
211214puts " Suggested usernames:"
212- suggestions.arg_values .each do |value |
215+ suggestions.values .each do |value |
213216 puts " - #{ value } "
214217end
215218puts " Total matches: #{ suggestions.total } "
@@ -224,15 +227,15 @@ MCP servers can provide predefined prompts that can be used in conversations:
224227# Get available prompts from the MCP server
225228prompts = client.prompts
226229puts " Available prompts:"
227- prompts.each do |name , prompt |
228- puts " - #{ name } : #{ prompt.description } "
230+ prompts.each do |prompt |
231+ puts " - #{ prompt. name} : #{ prompt.description } "
229232 prompt.arguments.each do |arg |
230233 puts " - #{ arg.name } : #{ arg.description } (required: #{ arg.required } )"
231234 end
232235end
233236
234237# Use a prompt in a conversation
235- greeting_prompt = prompts[ " daily_greeting" ]
238+ greeting_prompt = client.prompt( " daily_greeting" )
236239chat = RubyLLM .chat(model: " gpt-4" )
237240
238241# Method 1: Ask prompt directly
@@ -261,15 +264,15 @@ chat = RubyLLM.chat(model: "gpt-4")
261264chat.with_tools(* client.tools)
262265
263266# Add resources for context
264- chat.with_resource(client.resources[ " project_structure" ] )
267+ chat.with_resource(client.resource( " project_structure" ) )
265268chat.with_resource(
266- client.resource_templates[ " recent_commits" ] ,
269+ client.resource_template( " recent_commits" ) ,
267270 arguments: { days: 7 }
268271)
269272
270273# Add prompts for guidance
271274chat.with_prompt(
272- client.prompts[ " code_review_checklist" ] ,
275+ client.prompt( " code_review_checklist" ) ,
273276 arguments: { focus: " security" }
274277)
275278
@@ -278,6 +281,88 @@ response = chat.ask("Please review the recent commits using the checklist and su
278281puts response
279282```
280283
284+ ## Argument Completion
285+
286+ Some MCP servers support argument completion for prompts and resource templates:
287+
288+ ``` ruby
289+ # For prompts
290+ prompt = client.prompt(" user_search" )
291+ suggestions = prompt.complete(" username" , " jo" )
292+ puts " Suggestions: #{ suggestions.values } " # ["john", "joanna", "joseph"]
293+
294+ # For resource templates
295+ template = client.resource_template(" user_logs" )
296+ suggestions = template.complete(" user_id" , " 123" )
297+ puts " Total matches: #{ suggestions.total } "
298+ puts " Has more results: #{ suggestions.has_more } "
299+ ```
300+
301+ ## Additional Chat Methods
302+
303+ The gem extends RubyLLM's chat interface with convenient methods for MCP integration:
304+
305+ ``` ruby
306+ chat = RubyLLM .chat(model: " gpt-4" )
307+
308+ # Add a single resource
309+ chat.with_resource(resource)
310+
311+ # Add multiple resources
312+ chat.with_resources(resource1, resource2, resource3)
313+
314+ # Add a resource template with arguments
315+ chat.with_resource_template(resource_template, arguments: { key: " value" })
316+
317+ # Add a prompt with arguments
318+ chat.with_prompt(prompt, arguments: { name: " Alice" })
319+
320+ # Ask using a prompt directly
321+ response = chat.ask_prompt(prompt, arguments: { name: " Alice" })
322+ ```
323+
324+ ## Client Lifecycle Management
325+
326+ You can manage the MCP client connection lifecycle:
327+
328+ ``` ruby
329+ client = RubyLLM ::MCP .client(name: " my-server" , transport_type: :stdio , start: false , config: {...})
330+
331+ # Manually start the connection
332+ client.start
333+
334+ # Check if connection is alive
335+ puts client.alive?
336+
337+ # Restart the connection
338+ client.restart!
339+
340+ # Stop the connection
341+ client.stop
342+ ```
343+
344+ ## Refreshing Cached Data
345+
346+ The client caches tools, resources, prompts, and resource templates list calls are cached to reduce round trips back to the MCP server. You can refresh this cache:
347+
348+ ``` ruby
349+ # Refresh all cached tools
350+ tools = client.tools(refresh: true )
351+
352+ # Refresh a specific tool
353+ tool = client.tool(" search_files" , refresh: true )
354+
355+ # Same pattern works for resources, prompts, and resource templates
356+ resources = client.resources(refresh: true )
357+ prompts = client.prompts(refresh: true )
358+ templates = client.resource_templates(refresh: true )
359+
360+ # Or refresh specific items
361+ resource = client.resource(" project_readme" , refresh: true )
362+ prompt = client.prompt(" daily_greeting" , refresh: true )
363+ template = client.resource_template(" user_logs" , refresh: true )
364+ ```
365+
281366## Transport Types
282367
283368### SSE (Server-Sent Events)
@@ -289,7 +374,8 @@ client = RubyLLM::MCP.client(
289374 name: " web-mcp-server" ,
290375 transport_type: :sse ,
291376 config: {
292- url: " https://your-mcp-server.com/mcp/sse"
377+ url: " https://your-mcp-server.com/mcp/sse" ,
378+ headers: { " Authorization" => " Bearer your-token" }
293379 }
294380)
295381```
@@ -329,23 +415,27 @@ client = RubyLLM::MCP.client(
329415
330416- ` name ` : A unique identifier for your MCP client
331417- ` transport_type ` : Either ` :sse ` , ` :streamable ` , or ` :stdio `
418+ - ` start ` : Whether to automatically start the connection (default: true)
332419- ` request_timeout ` : Timeout for requests in milliseconds (default: 8000)
333420- ` config ` : Transport-specific configuration
334- - For SSE: ` { url: "http://..." } `
421+ - For SSE: ` { url: "http://...", headers: {...} } `
335422 - For Streamable: ` { url: "http://...", headers: {...} } `
336423 - For stdio: ` { command: "...", args: [...], env: {...} } `
337424
338425## Development
339426
340427After checking out the repo, run ` bin/setup ` to install dependencies. Then, run ` rake spec ` to run the tests. You can also run ` bin/console ` for an interactive prompt that will allow you to experiment.
341428
342- To install this gem onto your local machine, run ` bundle exec rake install ` . To release a new version, update the version number in ` version.rb ` , and then run ` bundle exec rake release ` , which will create a git tag for the version, push git commits and the created tag, and push the ` .gem ` file to [ rubygems.org] ( https://rubygems.org ) .
429+ To install this gem onto your local machine, run ` bundle exec rake install ` . Run ` bundle exec rake ` to test specs and run linters. To release a new version, update the version number in ` version.rb ` , and then run ` bundle exec rake release ` , which will create a git tag for the version, push git commits and the created tag, and push the ` .gem ` file to [ rubygems.org] ( https://rubygems.org ) .
343430
344431## Examples
345432
346433Check out the ` examples/ ` directory for more detailed usage examples:
347434
348- - ` examples/test_local_mcp.rb ` - Complete example with SSE transport
435+ - ` examples/tools/local_mcp.rb ` - Complete example with stdio transport
436+ - ` examples/tools/sse_mcp_with_gpt.rb ` - Example using SSE transport with GPT
437+ - ` examples/resources/list_resources.rb ` - Example of listing and using resources
438+ - ` examples/prompts/streamable_prompt_call.rb ` - Example of using prompts with streamable transport
349439
350440## Contributing
351441
0 commit comments