Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 25 additions & 60 deletions lib/mcp/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -146,21 +146,7 @@ def list_tools(cursor: nil)
# end
def tools
# TODO: consider renaming to `list_all_tools`.
all_tools = []
seen = Set.new
cursor = nil

loop do
page = list_tools(cursor: cursor)
all_tools.concat(page.tools)
next_cursor = page.next_cursor
break if next_cursor.nil? || seen.include?(next_cursor)

seen << next_cursor
cursor = next_cursor
end

all_tools
fetch_all_pages { |cursor| list_tools(cursor: cursor) }.flat_map(&:tools)
end

# Returns a single page of resources from the server.
Expand Down Expand Up @@ -189,21 +175,7 @@ def list_resources(cursor: nil)
# @return [Array<Hash>] An array of available resources.
def resources
# TODO: consider renaming to `list_all_resources`.
all_resources = []
seen = Set.new
cursor = nil

loop do
page = list_resources(cursor: cursor)
all_resources.concat(page.resources)
next_cursor = page.next_cursor
break if next_cursor.nil? || seen.include?(next_cursor)

seen << next_cursor
cursor = next_cursor
end

all_resources
fetch_all_pages { |cursor| list_resources(cursor: cursor) }.flat_map(&:resources)
end

# Returns a single page of resource templates from the server.
Expand Down Expand Up @@ -232,21 +204,7 @@ def list_resource_templates(cursor: nil)
# @return [Array<Hash>] An array of available resource templates.
def resource_templates
# TODO: consider renaming to `list_all_resource_templates`.
all_templates = []
seen = Set.new
cursor = nil

loop do
page = list_resource_templates(cursor: cursor)
all_templates.concat(page.resource_templates)
next_cursor = page.next_cursor
break if next_cursor.nil? || seen.include?(next_cursor)

seen << next_cursor
cursor = next_cursor
end

all_templates
fetch_all_pages { |cursor| list_resource_templates(cursor: cursor) }.flat_map(&:resource_templates)
end

# Returns a single page of prompts from the server.
Expand Down Expand Up @@ -275,21 +233,7 @@ def list_prompts(cursor: nil)
# @return [Array<Hash>] An array of available prompts.
def prompts
# TODO: consider renaming to `list_all_prompts`.
all_prompts = []
seen = Set.new
cursor = nil

loop do
page = list_prompts(cursor: cursor)
all_prompts.concat(page.prompts)
next_cursor = page.next_cursor
break if next_cursor.nil? || seen.include?(next_cursor)

seen << next_cursor
cursor = next_cursor
end

all_prompts
fetch_all_pages { |cursor| list_prompts(cursor: cursor) }.flat_map(&:prompts)
end

# Calls a tool via the transport layer and returns the full response from the server.
Expand Down Expand Up @@ -380,6 +324,27 @@ def ping

private

# Walks every page of a list endpoint, following `next_cursor`, and returns
# the page results. The `seen` set guards against a server that repeats or
# cycles cursors, so the loop always terminates.
def fetch_all_pages
pages = []
seen = Set.new
cursor = nil

loop do
page = yield(cursor)
pages << page
next_cursor = page.next_cursor
break if next_cursor.nil? || seen.include?(next_cursor)

seen << next_cursor
cursor = next_cursor
end

pages
end

def request(method:, params: nil)
request_body = {
jsonrpc: JsonRpcHandler::Version::V2_0,
Expand Down