rubygems_mcp 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/rubygems_mcp/client.rb +99 -34
- data/lib/rubygems_mcp/server.rb +39 -23
- data/lib/rubygems_mcp/version.rb +1 -1
- data/sig/rubygems_mcp.rbs +1 -1
- metadata +9 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1a2188f3290de5f410a66437e48bacda1dfd194b7c8446ce6f7db4b6dbb5d644
|
|
4
|
+
data.tar.gz: 1d6604125b76ed9493535466306d64d0f948b921d437b86faaa95016df2314b5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: be31aff229ddfd131b59e52fe42db7af5d9787e0833bf066baa90c7155f0973e5e2f17e7dd42e443650098464212b9c832671e5b7e01b22e3f9aa185eb13682f
|
|
7
|
+
data.tar.gz: 38237f1b2c2f1ead4ebf0e72c0587bd005eec054a153db2081c5211ab86f7e00b0b4ad2d0b4c349d4828850a457b748b9f2a4fee5cb2507522f11368cb62ab02
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 0.1.1 (2025-11-21)
|
|
4
|
+
|
|
5
|
+
- Update fast-mcp dependency version constraints to allow versions >= 0.1 and < 2.0
|
|
6
|
+
- Fix Resource class references to use FastMcp::Resource instead of MCP::Resource
|
|
7
|
+
- Update resource methods from `default_content` to `content` to match fast-mcp 1.0.0+ API
|
|
8
|
+
- Fix test expectations to match fast-mcp API (tool names without `::` separators, resources as Array)
|
|
9
|
+
- Add explicit `tool_name` definitions to all tools for user-friendly snake_case names (e.g., `get_latest_versions` instead of long class names)
|
|
10
|
+
- Fix array argument definitions: Change from `filled(:array)` to `array(:string)` to fix JSON schema conversion errors with dry-schema 1.14.1+ (fixes "Could not find an equivalent conversion for type :array" error)
|
|
11
|
+
|
|
3
12
|
## 0.1.0 (2025-01-15)
|
|
4
13
|
|
|
5
14
|
- Initial release
|
data/lib/rubygems_mcp/client.rb
CHANGED
|
@@ -349,18 +349,18 @@ module RubygemsMcp
|
|
|
349
349
|
end
|
|
350
350
|
end
|
|
351
351
|
|
|
352
|
-
# Get changelog
|
|
352
|
+
# Get full changelog content for a Ruby version from release notes
|
|
353
353
|
#
|
|
354
354
|
# @param version [String] Ruby version (e.g., "3.4.7")
|
|
355
|
-
# @return [Hash] Hash with :version, :release_notes_url, and :
|
|
355
|
+
# @return [Hash] Hash with :version, :release_notes_url, and :content (full content)
|
|
356
356
|
def get_ruby_version_changelog(version)
|
|
357
357
|
# First get the release notes URL for this version
|
|
358
358
|
versions = get_ruby_versions
|
|
359
359
|
version_data = versions.find { |v| v[:version] == version }
|
|
360
|
-
return {version: version, release_notes_url: nil,
|
|
360
|
+
return {version: version, release_notes_url: nil, content: nil, error: "Version not found"} unless version_data
|
|
361
361
|
|
|
362
362
|
release_notes_url = version_data[:release_notes_url]
|
|
363
|
-
return {version: version, release_notes_url: nil,
|
|
363
|
+
return {version: version, release_notes_url: nil, content: nil, error: "No release notes available"} unless release_notes_url
|
|
364
364
|
|
|
365
365
|
cache_key = "ruby_changelog:#{version}"
|
|
366
366
|
|
|
@@ -371,29 +371,32 @@ module RubygemsMcp
|
|
|
371
371
|
|
|
372
372
|
uri = URI(release_notes_url)
|
|
373
373
|
response = make_request(uri, parse_html: true)
|
|
374
|
-
return {version: version, release_notes_url: release_notes_url,
|
|
374
|
+
return {version: version, release_notes_url: release_notes_url, content: nil, error: "Failed to fetch release notes"} unless response
|
|
375
375
|
|
|
376
|
-
# Extract the main content -
|
|
377
|
-
|
|
378
|
-
content = response.css("div.content, div.entry-content, article, main").first || response.css("body").first
|
|
376
|
+
# Extract the main content - Ruby release notes use div#content
|
|
377
|
+
content = response.css("div#content").first || response.css("div.content, div.entry-content, article, main").first
|
|
379
378
|
|
|
380
379
|
if content
|
|
381
|
-
#
|
|
380
|
+
# Remove navigation and metadata elements
|
|
381
|
+
content.css("p.post-info, .post-info, nav, .navigation, header, footer, .sidebar").remove
|
|
382
|
+
|
|
383
|
+
# Get the full text content, preserving structure
|
|
382
384
|
text = content.text.strip
|
|
383
|
-
# Split into paragraphs and take first 3-5 meaningful ones
|
|
384
|
-
paragraphs = text.split(/\n\n+/).reject { |p| p.strip.length < 50 }
|
|
385
|
-
summary = paragraphs.first(5).join("\n\n").strip
|
|
386
385
|
|
|
387
|
-
#
|
|
388
|
-
|
|
386
|
+
# Clean up excessive whitespace but preserve paragraph structure
|
|
387
|
+
text = text.gsub(/\n{3,}/, "\n\n")
|
|
388
|
+
text = text.gsub(/[ \t]+/, " ")
|
|
389
|
+
|
|
390
|
+
# Remove empty lines at start/end
|
|
391
|
+
text = text.strip
|
|
389
392
|
else
|
|
390
|
-
|
|
393
|
+
text = nil
|
|
391
394
|
end
|
|
392
395
|
|
|
393
396
|
result = {
|
|
394
397
|
version: version,
|
|
395
398
|
release_notes_url: release_notes_url,
|
|
396
|
-
|
|
399
|
+
content: text
|
|
397
400
|
}
|
|
398
401
|
|
|
399
402
|
# Cache for 24 hours
|
|
@@ -562,9 +565,10 @@ module RubygemsMcp
|
|
|
562
565
|
|
|
563
566
|
# Extract the main content - try GitHub release page first, then generic selectors
|
|
564
567
|
content = if changelog_uri.include?("github.com") && changelog_uri.include?("/releases/")
|
|
565
|
-
# GitHub release page - look for release notes in markdown-body
|
|
566
|
-
response.css(".markdown-body
|
|
567
|
-
response.css("
|
|
568
|
+
# GitHub release page - look for release notes in markdown-body
|
|
569
|
+
response.css(".markdown-body").first ||
|
|
570
|
+
response.css("[data-testid='release-body'], .release-body").first ||
|
|
571
|
+
response.css("div.repository-content article").first
|
|
568
572
|
else
|
|
569
573
|
# Generic changelog page
|
|
570
574
|
response.css("div.content, div.entry-content, article, main, .markdown-body").first
|
|
@@ -573,29 +577,90 @@ module RubygemsMcp
|
|
|
573
577
|
content ||= response.css("body").first
|
|
574
578
|
|
|
575
579
|
summary = if content
|
|
580
|
+
# Remove UI elements, navigation, and error messages
|
|
581
|
+
content.css("nav, header, footer, .navigation, .sidebar, .blankslate, details, summary, .Box-footer, .Counter, [data-view-component], script, style").remove
|
|
582
|
+
|
|
583
|
+
# Remove elements with common UI classes
|
|
584
|
+
content.css("[class*='blankslate'], [class*='Box-footer'], [class*='Counter'], [class*='details-toggle']").remove
|
|
585
|
+
|
|
586
|
+
# Get text content
|
|
576
587
|
text = content.text.strip
|
|
577
|
-
|
|
588
|
+
|
|
589
|
+
# Remove common GitHub UI text patterns
|
|
578
590
|
text = text.gsub(/Notifications.*?signed in.*?reload/im, "")
|
|
579
591
|
text = text.gsub(/You must be signed in.*?reload/im, "")
|
|
580
592
|
text = text.gsub(/There was an error.*?reload/im, "")
|
|
593
|
+
text = text.gsub(/Please reload this page.*?/im, "")
|
|
594
|
+
text = text.gsub(/Loading.*?/im, "")
|
|
595
|
+
text = text.gsub(/Uh oh!.*?/im, "")
|
|
596
|
+
text = text.gsub(/Assets.*?\d+.*?/im, "")
|
|
597
|
+
|
|
598
|
+
# Remove commit hashes and issue references that are just links without context
|
|
599
|
+
text = text.gsub(/\b[a-f0-9]{7,40}\b/, "") # Remove commit hashes
|
|
600
|
+
text = text.gsub(/#\d+\s*$/, "") # Remove trailing issue numbers without context
|
|
601
|
+
|
|
602
|
+
# Clean up whitespace
|
|
603
|
+
text = text.gsub(/\n{3,}/, "\n\n")
|
|
604
|
+
text = text.gsub(/[ \t]{2,}/, " ")
|
|
605
|
+
|
|
606
|
+
# Split into lines and filter out irrelevant content
|
|
607
|
+
lines = text.split(/\n+/)
|
|
608
|
+
|
|
609
|
+
# Filter out lines that are likely UI elements or irrelevant
|
|
610
|
+
filtered_lines = []
|
|
611
|
+
prev_line_was_meaningful = false
|
|
612
|
+
|
|
613
|
+
lines.each_with_index do |line, idx|
|
|
614
|
+
stripped = line.strip
|
|
615
|
+
next if stripped.empty?
|
|
616
|
+
|
|
617
|
+
# Skip UI elements
|
|
618
|
+
next if stripped.match?(/^(Notifications|You must|There was|Please reload|Loading|Uh oh|Assets|\d+\s*$)/i)
|
|
619
|
+
next if stripped.match?(/^\/\s*$/)
|
|
620
|
+
next if stripped.match?(/^[a-f0-9]{7,40}$/) # Standalone commit hashes
|
|
621
|
+
next if stripped.match?(/^\s*#\d+\s*$/) # Standalone issue numbers
|
|
622
|
+
|
|
623
|
+
# Skip author names that appear alone (pattern: First Last or First Middle Last)
|
|
624
|
+
# Author names typically appear after a change description ends with punctuation
|
|
625
|
+
if stripped.match?(/^[A-Z][a-z]+(?:\s+[A-Z][a-z]+){1,2}$/) && stripped.length < 50 && !stripped.match?(/^[A-Z][a-z]+ [A-Z]\./) # Not initials like "J. Smith"
|
|
626
|
+
# Check if previous line ends with punctuation (end of sentence = author attribution follows)
|
|
627
|
+
if idx > 0 && filtered_lines.any?
|
|
628
|
+
prev = filtered_lines.last.to_s.strip
|
|
629
|
+
# If previous line ends with punctuation, this standalone name is likely an author
|
|
630
|
+
if prev.match?(/[.!]$/)
|
|
631
|
+
next
|
|
632
|
+
end
|
|
633
|
+
elsif idx == 0
|
|
634
|
+
# First line that's just a name, skip it
|
|
635
|
+
next
|
|
636
|
+
end
|
|
637
|
+
end
|
|
581
638
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
text.split(/\n+/)
|
|
639
|
+
# Keep meaningful lines
|
|
640
|
+
if stripped.length >= 10
|
|
641
|
+
filtered_lines << line
|
|
642
|
+
prev_line_was_meaningful = true
|
|
643
|
+
end
|
|
588
644
|
end
|
|
589
645
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
646
|
+
# Remove trailing "No changes." and similar repetitive endings
|
|
647
|
+
while filtered_lines.last&.strip&.match?(/^(No changes\.?|Guides)$/i)
|
|
648
|
+
filtered_lines.pop
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
# Join back and clean up
|
|
652
|
+
summary_text = filtered_lines.join("\n").strip
|
|
653
|
+
|
|
654
|
+
# Remove excessive blank lines
|
|
655
|
+
summary_text = summary_text.gsub(/\n{3,}/, "\n\n")
|
|
656
|
+
|
|
657
|
+
# Limit length but keep it reasonable for changelogs
|
|
658
|
+
if summary_text.length > 10000
|
|
659
|
+
# Try to cut at a reasonable point (end of a section)
|
|
660
|
+
cut_point = summary_text[0..10000].rindex(/\n\n/)
|
|
661
|
+
summary_text = summary_text[0..(cut_point || 10000)].strip + "\n\n..."
|
|
662
|
+
end
|
|
596
663
|
|
|
597
|
-
# Limit summary length
|
|
598
|
-
summary_text = summary_text[0..3000] + "..." if summary_text.length > 3000
|
|
599
664
|
summary_text.empty? ? nil : summary_text
|
|
600
665
|
end
|
|
601
666
|
|
data/lib/rubygems_mcp/server.rb
CHANGED
|
@@ -16,6 +16,21 @@ FastMcp = MCP unless defined?(FastMcp)
|
|
|
16
16
|
module MCP
|
|
17
17
|
module Transports
|
|
18
18
|
class StdioTransport
|
|
19
|
+
if method_defined?(:send_error)
|
|
20
|
+
alias_method :original_send_error, :send_error
|
|
21
|
+
|
|
22
|
+
def send_error(code, message, id = nil)
|
|
23
|
+
# Use placeholder id if nil to satisfy strict MCP client validation
|
|
24
|
+
# JSON-RPC 2.0 allows null for notifications, but MCP clients require valid id
|
|
25
|
+
id = "error_#{SecureRandom.hex(8)}" if id.nil?
|
|
26
|
+
original_send_error(code, message, id)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class Server
|
|
33
|
+
if method_defined?(:send_error)
|
|
19
34
|
alias_method :original_send_error, :send_error
|
|
20
35
|
|
|
21
36
|
def send_error(code, message, id = nil)
|
|
@@ -26,17 +41,6 @@ module MCP
|
|
|
26
41
|
end
|
|
27
42
|
end
|
|
28
43
|
end
|
|
29
|
-
|
|
30
|
-
class Server
|
|
31
|
-
alias_method :original_send_error, :send_error
|
|
32
|
-
|
|
33
|
-
def send_error(code, message, id = nil)
|
|
34
|
-
# Use placeholder id if nil to satisfy strict MCP client validation
|
|
35
|
-
# JSON-RPC 2.0 allows null for notifications, but MCP clients require valid id
|
|
36
|
-
id = "error_#{SecureRandom.hex(8)}" if id.nil?
|
|
37
|
-
original_send_error(code, message, id)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
44
|
end
|
|
41
45
|
|
|
42
46
|
module RubygemsMcp
|
|
@@ -151,11 +155,12 @@ module RubygemsMcp
|
|
|
151
155
|
|
|
152
156
|
# Get latest versions for a list of gems with release dates
|
|
153
157
|
class GetLatestVersionsTool < BaseTool
|
|
158
|
+
tool_name "get_latest_versions"
|
|
154
159
|
description "Get latest versions for a list of gems with release dates and licenses. Supports GraphQL-like field selection."
|
|
155
160
|
|
|
156
161
|
arguments do
|
|
157
|
-
required(:gem_names).
|
|
158
|
-
optional(:fields).
|
|
162
|
+
required(:gem_names).array(:string, min_size?: 1).description("Array of gem names (e.g., ['rails', 'nokogiri', 'rack'])")
|
|
163
|
+
optional(:fields).array(:string).description("GraphQL-like field selection. Available: name, version, release_date, license, built_at, prerelease, platform, ruby_version, rubygems_version, downloads_count, sha, spec_sha, requirements, metadata")
|
|
159
164
|
end
|
|
160
165
|
|
|
161
166
|
def call(gem_names:, fields: nil)
|
|
@@ -165,6 +170,7 @@ module RubygemsMcp
|
|
|
165
170
|
|
|
166
171
|
# Get all versions for a single gem
|
|
167
172
|
class GetGemVersionsTool < BaseTool
|
|
173
|
+
tool_name "get_gem_versions"
|
|
168
174
|
description "Get all versions for a single gem with release dates and licenses, sorted by version descending. Supports GraphQL-like field selection."
|
|
169
175
|
|
|
170
176
|
arguments do
|
|
@@ -172,7 +178,7 @@ module RubygemsMcp
|
|
|
172
178
|
optional(:limit).filled(:integer).description("Maximum number of versions to return (for pagination)")
|
|
173
179
|
optional(:offset).filled(:integer).description("Number of versions to skip (for pagination)")
|
|
174
180
|
optional(:sort).filled(:string).description("Sort order: version_desc, version_asc, date_desc, or date_asc (default: version_desc)")
|
|
175
|
-
optional(:fields).
|
|
181
|
+
optional(:fields).array(:string).description("GraphQL-like field selection. Available: version, release_date, license, built_at, prerelease, platform, ruby_version, rubygems_version, downloads_count, sha, spec_sha, requirements, metadata")
|
|
176
182
|
end
|
|
177
183
|
|
|
178
184
|
def call(gem_name:, limit: nil, offset: 0, sort: "version_desc", fields: nil)
|
|
@@ -189,6 +195,7 @@ module RubygemsMcp
|
|
|
189
195
|
|
|
190
196
|
# Get latest Ruby version with release date
|
|
191
197
|
class GetLatestRubyVersionTool < BaseTool
|
|
198
|
+
tool_name "get_latest_ruby_version"
|
|
192
199
|
description "Get latest Ruby version with release date"
|
|
193
200
|
|
|
194
201
|
arguments do
|
|
@@ -202,6 +209,7 @@ module RubygemsMcp
|
|
|
202
209
|
|
|
203
210
|
# Get all Ruby versions with release dates
|
|
204
211
|
class GetRubyVersionsTool < BaseTool
|
|
212
|
+
tool_name "get_ruby_versions"
|
|
205
213
|
description "Get all Ruby versions with release dates, download URLs, and release notes URLs, sorted by version descending"
|
|
206
214
|
|
|
207
215
|
arguments do
|
|
@@ -224,6 +232,7 @@ module RubygemsMcp
|
|
|
224
232
|
|
|
225
233
|
# Get changelog summary for a Ruby version
|
|
226
234
|
class GetRubyVersionChangelogTool < BaseTool
|
|
235
|
+
tool_name "get_ruby_version_changelog"
|
|
227
236
|
description "Get changelog summary for a specific Ruby version by fetching and parsing the release notes"
|
|
228
237
|
|
|
229
238
|
arguments do
|
|
@@ -237,11 +246,12 @@ module RubygemsMcp
|
|
|
237
246
|
|
|
238
247
|
# Get gem information (summary, homepage, etc.)
|
|
239
248
|
class GetGemInfoTool < BaseTool
|
|
249
|
+
tool_name "get_gem_info"
|
|
240
250
|
description "Get detailed information about a gem (summary, homepage, source code, documentation, licenses, authors, dependencies, downloads). Supports GraphQL-like field selection."
|
|
241
251
|
|
|
242
252
|
arguments do
|
|
243
253
|
required(:gem_name).filled(:string).description("Gem name (e.g., 'rails')")
|
|
244
|
-
optional(:fields).
|
|
254
|
+
optional(:fields).array(:string).description("GraphQL-like field selection. Available: name, version, summary, description, homepage, source_code, documentation, licenses, authors, info, downloads, version_downloads, yanked, dependencies, changelog_uri, funding_uri, platform, sha, spec_sha, metadata")
|
|
245
255
|
end
|
|
246
256
|
|
|
247
257
|
def call(gem_name:, fields: nil)
|
|
@@ -251,6 +261,7 @@ module RubygemsMcp
|
|
|
251
261
|
|
|
252
262
|
# Get reverse dependencies (gems that depend on this gem)
|
|
253
263
|
class GetGemReverseDependenciesTool < BaseTool
|
|
264
|
+
tool_name "get_gem_reverse_dependencies"
|
|
254
265
|
description "Get reverse dependencies - list of gems that depend on the specified gem"
|
|
255
266
|
|
|
256
267
|
arguments do
|
|
@@ -264,6 +275,7 @@ module RubygemsMcp
|
|
|
264
275
|
|
|
265
276
|
# Get download statistics for a gem version
|
|
266
277
|
class GetGemVersionDownloadsTool < BaseTool
|
|
278
|
+
tool_name "get_gem_version_downloads"
|
|
267
279
|
description "Get download statistics for a specific gem version"
|
|
268
280
|
|
|
269
281
|
arguments do
|
|
@@ -278,6 +290,7 @@ module RubygemsMcp
|
|
|
278
290
|
|
|
279
291
|
# Get latest gems (most recently added)
|
|
280
292
|
class GetLatestGemsTool < BaseTool
|
|
293
|
+
tool_name "get_latest_gems"
|
|
281
294
|
description "Get latest gems - most recently added gems to RubyGems.org"
|
|
282
295
|
|
|
283
296
|
arguments do
|
|
@@ -291,6 +304,7 @@ module RubygemsMcp
|
|
|
291
304
|
|
|
292
305
|
# Get recently updated gems
|
|
293
306
|
class GetRecentlyUpdatedGemsTool < BaseTool
|
|
307
|
+
tool_name "get_recently_updated_gems"
|
|
294
308
|
description "Get recently updated gems - most recently updated gem versions"
|
|
295
309
|
|
|
296
310
|
arguments do
|
|
@@ -304,6 +318,7 @@ module RubygemsMcp
|
|
|
304
318
|
|
|
305
319
|
# Get changelog summary for a gem
|
|
306
320
|
class GetGemChangelogTool < BaseTool
|
|
321
|
+
tool_name "get_gem_changelog"
|
|
307
322
|
description "Get changelog summary for a gem by fetching and parsing the changelog from its changelog_uri"
|
|
308
323
|
|
|
309
324
|
arguments do
|
|
@@ -318,6 +333,7 @@ module RubygemsMcp
|
|
|
318
333
|
|
|
319
334
|
# Search for gems by name
|
|
320
335
|
class SearchGemsTool < BaseTool
|
|
336
|
+
tool_name "search_gems"
|
|
321
337
|
description "Search for gems by name on RubyGems"
|
|
322
338
|
|
|
323
339
|
arguments do
|
|
@@ -330,13 +346,13 @@ module RubygemsMcp
|
|
|
330
346
|
end
|
|
331
347
|
|
|
332
348
|
# Resource: Popular Ruby gems list
|
|
333
|
-
class PopularGemsResource <
|
|
349
|
+
class PopularGemsResource < FastMcp::Resource
|
|
334
350
|
uri "rubygems://popular"
|
|
335
351
|
resource_name "Popular Ruby Gems"
|
|
336
352
|
description "A curated list of popular Ruby gems with their latest versions"
|
|
337
353
|
mime_type "application/json"
|
|
338
354
|
|
|
339
|
-
def
|
|
355
|
+
def content
|
|
340
356
|
client = Client.new
|
|
341
357
|
popular_gems = %w[
|
|
342
358
|
rails nokogiri bundler rake rspec devise puma sidekiq
|
|
@@ -366,13 +382,13 @@ module RubygemsMcp
|
|
|
366
382
|
end
|
|
367
383
|
|
|
368
384
|
# Resource: Ruby version compatibility information
|
|
369
|
-
class RubyVersionCompatibilityResource <
|
|
385
|
+
class RubyVersionCompatibilityResource < FastMcp::Resource
|
|
370
386
|
uri "rubygems://ruby/compatibility"
|
|
371
387
|
resource_name "Ruby Version Compatibility"
|
|
372
388
|
description "Information about Ruby version compatibility and release dates"
|
|
373
389
|
mime_type "application/json"
|
|
374
390
|
|
|
375
|
-
def
|
|
391
|
+
def content
|
|
376
392
|
client = Client.new
|
|
377
393
|
ruby_versions = client.get_ruby_versions(limit: 20, sort: :version_desc)
|
|
378
394
|
latest = client.get_latest_ruby_version
|
|
@@ -402,13 +418,13 @@ module RubygemsMcp
|
|
|
402
418
|
end
|
|
403
419
|
|
|
404
420
|
# Resource: Ruby maintenance status for all versions
|
|
405
|
-
class RubyMaintenanceStatusResource <
|
|
421
|
+
class RubyMaintenanceStatusResource < FastMcp::Resource
|
|
406
422
|
uri "rubygems://ruby/maintenance"
|
|
407
423
|
resource_name "Ruby Maintenance Status"
|
|
408
424
|
description "Detailed maintenance status for all Ruby versions including EOL dates and maintenance phases"
|
|
409
425
|
mime_type "application/json"
|
|
410
426
|
|
|
411
|
-
def
|
|
427
|
+
def content
|
|
412
428
|
client = Client.new
|
|
413
429
|
maintenance_status = client.get_ruby_maintenance_status
|
|
414
430
|
|
|
@@ -428,13 +444,13 @@ module RubygemsMcp
|
|
|
428
444
|
end
|
|
429
445
|
|
|
430
446
|
# Resource: Latest Ruby version
|
|
431
|
-
class LatestRubyVersionResource <
|
|
447
|
+
class LatestRubyVersionResource < FastMcp::Resource
|
|
432
448
|
uri "rubygems://ruby/latest"
|
|
433
449
|
resource_name "Latest Ruby Version"
|
|
434
450
|
description "The latest stable Ruby version with release date"
|
|
435
451
|
mime_type "application/json"
|
|
436
452
|
|
|
437
|
-
def
|
|
453
|
+
def content
|
|
438
454
|
client = Client.new
|
|
439
455
|
latest = client.get_latest_ruby_version
|
|
440
456
|
JSON.pretty_generate(latest)
|
data/lib/rubygems_mcp/version.rb
CHANGED
data/sig/rubygems_mcp.rbs
CHANGED
|
@@ -59,7 +59,7 @@ module RubygemsMcp
|
|
|
59
59
|
) -> Array[Hash[Symbol, (String | nil)]]
|
|
60
60
|
|
|
61
61
|
# Get changelog for a Ruby version
|
|
62
|
-
def get_ruby_version_changelog: (String version) -> Hash[Symbol, (String | nil)]
|
|
62
|
+
def get_ruby_version_changelog: (String version) -> Hash[Symbol, (String | nil)] # Returns :version, :release_notes_url, :content
|
|
63
63
|
|
|
64
64
|
# Get reverse dependencies (gems that depend on this gem)
|
|
65
65
|
def get_gem_reverse_dependencies: (String gem_name) -> Array[String]
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubygems_mcp
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrei Makarov
|
|
@@ -13,16 +13,22 @@ dependencies:
|
|
|
13
13
|
name: fast-mcp
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
|
-
- - "
|
|
16
|
+
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
18
|
version: '0.1'
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '2.0'
|
|
19
22
|
type: :runtime
|
|
20
23
|
prerelease: false
|
|
21
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
25
|
requirements:
|
|
23
|
-
- - "
|
|
26
|
+
- - ">="
|
|
24
27
|
- !ruby/object:Gem::Version
|
|
25
28
|
version: '0.1'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '2.0'
|
|
26
32
|
- !ruby/object:Gem::Dependency
|
|
27
33
|
name: nokogiri
|
|
28
34
|
requirement: !ruby/object:Gem::Requirement
|