yardmcp 0.1.0 → 0.2.0
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/lib/yardmcp/version.rb +1 -1
- data/lib/yardmcp.rb +57 -21
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88e4b95aa833c7d4beb6cf789d921410f3ff5d0112a1a10456dff4943ec3561c
|
4
|
+
data.tar.gz: 751d12f0deedd21838b34ddf5cc1b4e36585888be3b5a899547d6bc4684462c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9fbd30f73eaac7a36457ed89ffce04b87c6537641910c71c0f01aeac3bcfe700a8cb3c249c8c1f03f76d365028aec4e51fa355d1360ffaee18d1d0e404ee038
|
7
|
+
data.tar.gz: dea12928f18006a12bd44473f55f0e849b65530e9ee7b5dc0a79fab5a321e06368b20222958491080930857beb98e205bd90adee601a77140d9ea2a22571684c
|
data/lib/yardmcp/version.rb
CHANGED
data/lib/yardmcp.rb
CHANGED
@@ -11,6 +11,7 @@ require_relative 'yardmcp/version'
|
|
11
11
|
# Utility class for YARD operations
|
12
12
|
class YardUtils
|
13
13
|
include Singleton
|
14
|
+
|
14
15
|
attr_reader :libraries, :logger, :object_to_gem
|
15
16
|
|
16
17
|
def initialize
|
@@ -43,7 +44,7 @@ class YardUtils
|
|
43
44
|
# Ensures the correct .yardoc is loaded for the given object path
|
44
45
|
def ensure_yardoc_loaded_for_object!(object_path)
|
45
46
|
# TODO: Handle multiple gems for the same object path, use some heuristic to determine the correct gem
|
46
|
-
gem_name = @object_to_gem[object_path]
|
47
|
+
gem_name = @object_to_gem[object_path]&.first
|
47
48
|
raise "No documentation found for #{object_path}" unless gem_name
|
48
49
|
|
49
50
|
load_yardoc_for_gem(gem_name)
|
@@ -275,22 +276,50 @@ class YardUtils
|
|
275
276
|
(libraries[spec.name] ||= []) << YARD::Server::LibraryVersion.new(spec.name, spec.version.to_s, nil, :gem)
|
276
277
|
end
|
277
278
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
279
|
+
begin
|
280
|
+
require 'parallel'
|
281
|
+
logger.info 'Using parallel gem for index building'
|
282
|
+
|
283
|
+
# Use processes to avoid YARD thread-safety issues
|
284
|
+
# Each process returns a hash of object_path => [gem_names]
|
285
|
+
results = Parallel.map(list_gems, in_processes: 8) { |gem| process_gem_for_index(gem) }
|
286
|
+
merge_gem_results(results)
|
287
|
+
rescue LoadError
|
288
|
+
logger.warn 'parallel gem not found, falling back to single-threaded processing'
|
289
|
+
results = list_gems.map { |gem| process_gem_for_index(gem) }
|
290
|
+
merge_gem_results(results)
|
290
291
|
end
|
291
292
|
logger.info "Index built: #{libraries.size} gems, #{@object_to_gem.size} objects"
|
292
293
|
end
|
293
294
|
|
295
|
+
# Merge gem processing results into @object_to_gem
|
296
|
+
def merge_gem_results(results)
|
297
|
+
results.each do |gem_objects|
|
298
|
+
gem_objects.each do |obj_path, gem_names|
|
299
|
+
(@object_to_gem[obj_path] ||= []).concat(gem_names)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
# Process a single gem and return its objects as a hash
|
305
|
+
def process_gem_for_index(gem_name)
|
306
|
+
logger.debug "Loading #{gem_name}..."
|
307
|
+
begin
|
308
|
+
load_yardoc_for_gem(gem_name)
|
309
|
+
rescue StandardError => e
|
310
|
+
logger.error "Error loading #{gem_name}: #{e.message}"
|
311
|
+
return {}
|
312
|
+
end
|
313
|
+
|
314
|
+
# Collect all objects for this gem
|
315
|
+
gem_objects = {}
|
316
|
+
YARD::Registry.all.each do |obj|
|
317
|
+
logger.debug "Adding #{obj.path} to #{gem_name}"
|
318
|
+
gem_objects[obj.path.to_s] = [gem_name]
|
319
|
+
end
|
320
|
+
gem_objects
|
321
|
+
end
|
322
|
+
|
294
323
|
def build_docs(gem_name)
|
295
324
|
logger.info "Building docs for #{gem_name}..."
|
296
325
|
YARD::CLI::Gems.new.run(gem_name)
|
@@ -302,7 +331,8 @@ class ListGemsTool < FastMcp::Tool
|
|
302
331
|
description 'List all installed gems that have a .yardoc file'
|
303
332
|
|
304
333
|
def call
|
305
|
-
|
334
|
+
gems = YardUtils.instance.list_gems
|
335
|
+
{ content: gems.map { |gem| { text: gem, type: 'gem' } } }
|
306
336
|
end
|
307
337
|
end
|
308
338
|
|
@@ -314,7 +344,8 @@ class ListClassesTool < FastMcp::Tool
|
|
314
344
|
end
|
315
345
|
|
316
346
|
def call(gem_name:)
|
317
|
-
|
347
|
+
classes = YardUtils.instance.list_classes(gem_name)
|
348
|
+
{ content: classes.map { |cls| { text: cls, type: 'class' } } }
|
318
349
|
end
|
319
350
|
end
|
320
351
|
|
@@ -339,7 +370,8 @@ class ChildrenTool < FastMcp::Tool
|
|
339
370
|
end
|
340
371
|
|
341
372
|
def call(path:)
|
342
|
-
|
373
|
+
children = YardUtils.instance.children(path)
|
374
|
+
{ content: children.map { |child| { text: child, type: 'child' } } }
|
343
375
|
end
|
344
376
|
end
|
345
377
|
|
@@ -351,7 +383,8 @@ class MethodsListTool < FastMcp::Tool
|
|
351
383
|
end
|
352
384
|
|
353
385
|
def call(path:)
|
354
|
-
|
386
|
+
methods = YardUtils.instance.methods_list(path)
|
387
|
+
{ content: methods.map { |method| { text: method, type: 'method' } } }
|
355
388
|
end
|
356
389
|
end
|
357
390
|
|
@@ -376,7 +409,8 @@ class SearchTool < FastMcp::Tool
|
|
376
409
|
|
377
410
|
def call(query:)
|
378
411
|
# Enhanced search: ranked, fuzzy, and full-text
|
379
|
-
|
412
|
+
results = YardUtils.instance.search(query)
|
413
|
+
{ content: results.map { |result| { text: result[:path], score: result[:score], type: 'search_result' } } }
|
380
414
|
end
|
381
415
|
end
|
382
416
|
|
@@ -400,7 +434,8 @@ class CodeSnippetTool < FastMcp::Tool
|
|
400
434
|
end
|
401
435
|
|
402
436
|
def call(path:)
|
403
|
-
YardUtils.instance.code_snippet(path)
|
437
|
+
snippet = YardUtils.instance.code_snippet(path)
|
438
|
+
{ content: { text: snippet, type: 'code_snippet' } }
|
404
439
|
end
|
405
440
|
end
|
406
441
|
|
@@ -412,7 +447,8 @@ class AncestorsTool < FastMcp::Tool
|
|
412
447
|
end
|
413
448
|
|
414
449
|
def call(path:)
|
415
|
-
|
450
|
+
ancestors = YardUtils.instance.ancestors(path)
|
451
|
+
{ content: ancestors.map { |ancestor| { text: ancestor, type: 'ancestor' } } }
|
416
452
|
end
|
417
453
|
end
|
418
454
|
|
@@ -429,7 +465,7 @@ class RelatedObjectsTool < FastMcp::Tool
|
|
429
465
|
end
|
430
466
|
|
431
467
|
module YardMCP
|
432
|
-
def self.start_server(preload:
|
468
|
+
def self.start_server(preload: true)
|
433
469
|
YardUtils.instance if preload
|
434
470
|
server = FastMcp::Server.new(name: 'yard-mcp-server', version: YardMCP::VERSION)
|
435
471
|
server.register_tool(ListGemsTool)
|