Class: GroqRuby::MCP::Bridge
- Inherits:
-
Object
- Object
- GroqRuby::MCP::Bridge
- Defined in:
- lib/groq_ruby/mcp/bridge.rb
Overview
Glues one or more MCP servers into a Groq chat completion. Connects to each server, builds the OpenAI-style ‘tools:` array the model expects, and routes each `tool_calls` from the model back to the owning MCP server.
Bridge surfaces three MCP capabilities:
-
Tools — every server-advertised tool becomes a Groq function tool, namespaced as ‘<server>__<tool>`. The LLM calls these exactly like any other function tool; #call routes the call to the owning server.
-
Resources — for every server that advertises resources, Bridge injects a synthetic ‘<server>__read_resource(uri)` tool into #tools so the LLM can fetch resource content on demand. #resources returns the full inventory if you want to surface it (e.g. in a system-prompt catalogue).
-
Prompts — #prompts returns the list of prompt templates advertised by each server. Prompts are typically surfaced to a user (a picker in your UI), not the LLM directly. #get_prompt renders one with arguments.
Optional capabilities are probed gracefully — a server that responds with ‘-32601 method not found` to `resources/list` simply contributes no resources.
Constant Summary collapse
- NAME_SEPARATOR =
"__".freeze
- READ_RESOURCE_SUFFIX =
"read_resource".freeze
Instance Method Summary collapse
-
#call(namespaced_name, arguments) ⇒ Hash
Dispatch a tool call from a Groq response to the owning MCP server.
-
#get_prompt(namespaced_name, arguments = {}) ⇒ Hash
Render a prompt template.
-
#initialize(configs, request_timeout: Client::DEFAULT_REQUEST_TIMEOUT) ⇒ Bridge
constructor
A new instance of Bridge.
-
#prompts ⇒ Array<Hash>
Flat inventory of every prompt template discovered across all servers.
-
#read_resource(uri, server: nil) ⇒ Hash
Read a resource by URI.
-
#resources ⇒ Array<Hash>
Flat inventory of every resource discovered across all servers.
-
#stop ⇒ Object
Stop every underlying MCP server.
-
#tool_names ⇒ Array<String>
Every namespaced tool name #tools surfaces.
-
#tools ⇒ Array<Hash>
Tool definitions for ‘chat.completions.create(tools:)`.
Constructor Details
#initialize(configs, request_timeout: Client::DEFAULT_REQUEST_TIMEOUT) ⇒ Bridge
Returns a new instance of Bridge.
50 51 52 53 54 55 |
# File 'lib/groq_ruby/mcp/bridge.rb', line 50 def initialize(configs, request_timeout: Client::DEFAULT_REQUEST_TIMEOUT) @clients = configs.map { |c| Client.connect(c, request_timeout: request_timeout) } @tool_index = build_tool_index @resource_index = build_resource_index @prompt_index = build_prompt_index end |
Instance Method Details
#call(namespaced_name, arguments) ⇒ Hash
Dispatch a tool call from a Groq response to the owning MCP server. Recognises the synthetic ‘<server>__read_resource` tool and routes to #read_resource instead.
96 97 98 99 100 101 102 103 104 |
# File 'lib/groq_ruby/mcp/bridge.rb', line 96 def call(namespaced_name, arguments) parsed_args = parse_args(arguments) if (server_name = match_synthetic_resource_tool(namespaced_name)) uri = parsed_args["uri"] || parsed_args[:uri] read_resource(uri, server: server_name) else dispatch_tool_call(namespaced_name, parsed_args) end end |
#get_prompt(namespaced_name, arguments = {}) ⇒ Hash
Render a prompt template. The name is the namespaced ‘<server>__<prompt>` form returned by #prompts.
127 128 129 130 |
# File 'lib/groq_ruby/mcp/bridge.rb', line 127 def get_prompt(namespaced_name, arguments = {}) entry = @prompt_index[namespaced_name] or raise UnknownToolError, "no MCP prompt named #{namespaced_name.inspect}" entry[:client].prompts_get(entry[:prompt].name, arguments) end |
#prompts ⇒ Array<Hash>
Flat inventory of every prompt template discovered across all servers.
82 83 84 85 86 |
# File 'lib/groq_ruby/mcp/bridge.rb', line 82 def prompts @prompt_index.map do |namespaced, entry| {server: entry[:server_name], namespaced_name: namespaced, prompt: entry[:prompt]} end end |
#read_resource(uri, server: nil) ⇒ Hash
Read a resource by URI. When more than one server advertises the same URI, pass ‘server:` to disambiguate.
113 114 115 116 117 118 |
# File 'lib/groq_ruby/mcp/bridge.rb', line 113 def read_resource(uri, server: nil) candidates = @resource_index.values.select { |e| e[:resource].uri == uri } candidates = candidates.select { |e| e[:server_name] == server } if server entry = candidates.first or raise UnknownToolError, "no MCP resource for uri #{uri.inspect}" entry[:client].resources_read(uri) end |
#resources ⇒ Array<Hash>
Flat inventory of every resource discovered across all servers.
75 76 77 |
# File 'lib/groq_ruby/mcp/bridge.rb', line 75 def resources @resource_index.values.map { |entry| {server: entry[:server_name], resource: entry[:resource]} } end |
#stop ⇒ Object
Stop every underlying MCP server. Idempotent.
133 134 135 |
# File 'lib/groq_ruby/mcp/bridge.rb', line 133 def stop @clients.each(&:stop) end |
#tool_names ⇒ Array<String>
Returns every namespaced tool name #tools surfaces.
68 69 70 |
# File 'lib/groq_ruby/mcp/bridge.rb', line 68 def tool_names tools.map { |t| t[:function][:name] } end |
#tools ⇒ Array<Hash>
Tool definitions for ‘chat.completions.create(tools:)`. Includes every advertised MCP tool plus, for each server with resources, a synthetic `<server>__read_resource(uri)` tool so the LLM can fetch resource content on demand.
63 64 65 |
# File 'lib/groq_ruby/mcp/bridge.rb', line 63 def tools @tool_index.values.map { |entry| as_groq_tool(entry) } + synthetic_resource_tools end |