Module: FastMcp::SchemaMetadataExtractor

Included in:
SchemaCompiler
Defined in:
lib/mcp/tool.rb

Overview

Module for handling schema metadata

Instance Method Summary collapse

Instance Method Details

#extract_metadata(and_node, metadata, nested_path) ⇒ Object

Extract metadata from a node



310
311
312
313
314
315
316
317
318
# File 'lib/mcp/tool.rb', line 310

def (and_node, , nested_path)
  return unless and_node[1][1].is_a?(Array) && and_node[1][1][1].is_a?(Array)

  and_node[1][1][1].each do |meta_node|
    next unless meta_node[0] == :meta && meta_node[1].is_a?(Hash) && meta_node[1][:description]

    [nested_path] = meta_node[1][:description]
  end
end

#extract_metadata_from_ast(ast, metadata, parent_key = nil) ⇒ Object

Extract metadata from AST



229
230
231
232
233
234
235
# File 'lib/mcp/tool.rb', line 229

def (ast, , parent_key = nil)
  return unless ast.is_a?(Array)

  process_key_node(ast, , parent_key) if ast[0] == :key
  process_set_node(ast, , parent_key) if ast[0] == :set
  process_and_node(ast, , parent_key) if ast[0] == :and
end

#extract_metadata_from_schema(schema) ⇒ Object

Extract metadata from a schema



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/mcp/tool.rb', line 206

def (schema)
  # a deeply-assignable hash, the default value of a key is {}
   = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }

  # Extract descriptions from the top-level schema
  if schema.respond_to?(:schema_dsl) && schema.schema_dsl.respond_to?(:meta_data)
    schema.schema_dsl..each do |key, meta|
      [key.to_s][:description] = meta[:description] if meta[:description]
      [key.to_s][:hidden] = meta[:hidden]
    end
  end

  # Extract metadata from nested schemas using AST
  schema.rules.each_value do |rule|
    next unless rule.respond_to?(:ast)

    (rule.ast, )
  end

  
end

#process_and_node(ast, metadata, parent_key) ⇒ Object

Process an and node in the AST



258
259
260
261
262
263
264
265
266
267
268
# File 'lib/mcp/tool.rb', line 258

def process_and_node(ast, , parent_key)
  return unless ast[1].is_a?(Array)

  # Process each child node
  ast[1].each do |and_node|
    (and_node, , parent_key)
  end

  # Process nested properties
  process_nested_properties(ast, , parent_key)
end

#process_key_node(ast, metadata, parent_key) ⇒ Object

Process a key node in the AST



238
239
240
241
242
243
244
245
246
# File 'lib/mcp/tool.rb', line 238

def process_key_node(ast, , parent_key)
  return unless ast[1].is_a?(Array) && ast[1].size >= 2

  key = ast[1][0]
  full_key = parent_key ? "#{parent_key}.#{key}" : key.to_s

  # Process nested AST
  (ast[1][1], , full_key) if ast[1][1].is_a?(Array)
end

#process_nested_keys(set_node, metadata, nested_key) ⇒ Object

Process nested keys in a schema



298
299
300
301
302
303
304
305
306
307
# File 'lib/mcp/tool.rb', line 298

def process_nested_keys(set_node, , nested_key)
  set_node[1].each do |and_node|
    next unless and_node[0] == :key && and_node[1].is_a?(Array) && and_node[1].size >= 2

    nested_field = and_node[1][0]
    nested_path = "#{nested_key}.#{nested_field}"

    (and_node, , nested_path)
  end
end

#process_nested_properties(ast, metadata, parent_key) ⇒ Object

Process nested properties in an and node



271
272
273
274
275
276
277
278
279
280
# File 'lib/mcp/tool.rb', line 271

def process_nested_properties(ast, , parent_key)
  ast[1].each do |node|
    next unless node[0] == :key && node[1].is_a?(Array) && node[1][1].is_a?(Array) && node[1][1][0] == :and

    key_name = node[1][0]
    nested_key = parent_key ? "#{parent_key}.#{key_name}" : key_name.to_s

    process_nested_schema_ast(node[1][1], , nested_key)
  end
end

#process_nested_schema_ast(ast, metadata, nested_key) ⇒ Object

Process a nested schema



283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/mcp/tool.rb', line 283

def process_nested_schema_ast(ast, , nested_key)
  return unless ast[1].is_a?(Array)

  ast[1].each do |subnode|
    next unless subnode[0] == :set && subnode[1].is_a?(Array)

    subnode[1].each do |set_node|
      next unless set_node[0] == :and && set_node[1].is_a?(Array)

      process_nested_keys(set_node, , nested_key)
    end
  end
end

#process_set_node(ast, metadata, parent_key) ⇒ Object

Process a set node in the AST



249
250
251
252
253
254
255
# File 'lib/mcp/tool.rb', line 249

def process_set_node(ast, , parent_key)
  return unless ast[1].is_a?(Array)

  ast[1].each do |set_node|
    (set_node, , parent_key)
  end
end