Class: FastMcp::Tool

Inherits:
Object
  • Object
show all
Defined in:
lib/mcp/tool.rb

Overview

Main Tool class that represents an MCP Tool

Defined Under Namespace

Classes: InvalidArgumentsError

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(headers: {}) ⇒ Tool

Returns a new instance of Tool.



338
339
340
341
# File 'lib/mcp/tool.rb', line 338

def initialize(headers: {})
  @_meta = {}
  @headers = headers
end

Class Attribute Details

.serverObject

Returns the value of attribute server.



266
267
268
# File 'lib/mcp/tool.rb', line 266

def server
  @server
end

Instance Attribute Details

#_metaObject

Returns the value of attribute _meta.



363
364
365
# File 'lib/mcp/tool.rb', line 363

def _meta
  @_meta
end

#headersObject (readonly)

Returns the value of attribute headers.



364
365
366
# File 'lib/mcp/tool.rb', line 364

def headers
  @headers
end

Class Method Details

.annotations(annotations_hash = nil) ⇒ Object



318
319
320
321
322
# File 'lib/mcp/tool.rb', line 318

def annotations(annotations_hash = nil)
  return @annotations || {} if annotations_hash.nil?

  @annotations = annotations_hash
end

.arguments(&block) ⇒ Object



289
290
291
292
293
294
295
296
297
# File 'lib/mcp/tool.rb', line 289

def arguments(&block)
  @metadata_context = MetadataContext.new

  @input_schema = MetadataContext.with_context(@metadata_context) do
    Dry::Schema.JSON(&block)
  end

  @collected_metadata = @metadata_context.
end

.authorize(&block) ⇒ Object



324
325
326
327
# File 'lib/mcp/tool.rb', line 324

def authorize(&block)
  @authorization_blocks ||= []
  @authorization_blocks.push block
end

.call(**args) ⇒ Object

Raises:

  • (NotImplementedError)


329
330
331
# File 'lib/mcp/tool.rb', line 329

def call(**args)
  raise NotImplementedError, 'Subclasses must implement the call method'
end

.description(description = nil) ⇒ Object



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

def description(description = nil)
  return @description if description.nil?

  @description = description
end

.input_schemaObject



299
300
301
# File 'lib/mcp/tool.rb', line 299

def input_schema
  @input_schema ||= Dry::Schema.JSON
end

.input_schema_to_jsonObject



333
334
335
# File 'lib/mcp/tool.rb', line 333

def input_schema_to_json
  SchemaMetadataProcessor.process(@input_schema, @collected_metadata || {})
end

.metadata(key = nil, value = nil) ⇒ Object

Add metadata support for tools



278
279
280
281
282
283
284
285
286
287
# File 'lib/mcp/tool.rb', line 278

def (key = nil, value = nil)
  @metadata ||= {}
  if key.nil?
    @metadata
  elsif value.nil?
    @metadata[key]
  else
    @metadata[key] = value
  end
end

.tags(*tag_list) ⇒ Object

Add tagging support for tools



269
270
271
272
273
274
275
# File 'lib/mcp/tool.rb', line 269

def tags(*tag_list)
  if tag_list.empty?
    @tags || []
  else
    @tags = tag_list.flatten.map(&:to_sym)
  end
end

.tool_name(name = nil) ⇒ Object



303
304
305
306
307
308
309
310
# File 'lib/mcp/tool.rb', line 303

def tool_name(name = nil)
  name = @name || self.name if name.nil?
  return if name.nil?

  name = name.gsub(/[^a-zA-Z0-9_-]/, '')[0, 64]

  @name = name
end

Instance Method Details

#authorized?(**args) ⇒ Boolean

Returns:

  • (Boolean)

Raises:



343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# File 'lib/mcp/tool.rb', line 343

def authorized?(**args)
  auth_checks = self.class.ancestors.filter_map do |ancestor|
    ancestor.ancestors.include?(FastMcp::Tool) &&
      ancestor.instance_variable_get(:@authorization_blocks)
  end.flatten

  return true if auth_checks.empty?

  arg_validation = self.class.input_schema.call(args)
  raise InvalidArgumentsError, arg_validation.errors.to_h.to_json if arg_validation.errors.any?

  auth_checks.all? do |auth_check|
    if auth_check.parameters.empty?
      instance_exec(&auth_check)
    else
      instance_exec(**args, &auth_check)
    end
  end
end

#call_with_schema_validation!(**args) ⇒ Object



370
371
372
373
374
375
376
377
# File 'lib/mcp/tool.rb', line 370

def call_with_schema_validation!(**args)
  arg_validation = self.class.input_schema.call(args)
  raise InvalidArgumentsError, arg_validation.errors.to_h.to_json if arg_validation.errors.any?

  # When calling the tool, its metadata can be altered to be returned in response.
  # We return the altered metadata with the tool's result
  [call(**args), _meta]
end

#notify_resource_updated(uri) ⇒ Object



366
367
368
# File 'lib/mcp/tool.rb', line 366

def notify_resource_updated(uri)
  self.class.server.notify_resource_updated(uri)
end