Class: RailsAiBridge::ToolResultCache

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_ai_bridge/tool_result_cache.rb

Overview

Caches MCP tool call results keyed by a stable fingerprint of the arguments.

The cache is in-memory, per-process, and TTL-based. It ignores server_context when fingerprinting so identical client requests share the same cached response.

Enable by setting config.mcp.tool_result_cache_ttl to a positive number of seconds.

Defined Under Namespace

Classes: CachedTool

Constant Summary collapse

NON_CACHEABLE =

Tool names that must never be cached because their results may change between calls (external provider data) or represent live network state.

Returns:

  • (Set<String>)
Set[
  'rails_get_provider_context'
].freeze

Class Method Summary collapse

Class Method Details

.enabled?Boolean

Returns whether tool result caching is enabled.

Returns:

  • (Boolean)

    whether tool result caching is enabled



123
124
125
# File 'lib/rails_ai_bridge/tool_result_cache.rb', line 123

def enabled?
  RailsAiBridge.configuration.mcp.tool_result_cache_ttl.to_i.positive?
end

.fetch_response(tool_name, arguments) ⇒ MCP::Tool::Response

Fetches a cached response or yields to compute it.

Parameters:

  • tool_name (String)
  • arguments (Hash)

Yield Returns:

  • (MCP::Tool::Response)

Returns:

  • (MCP::Tool::Response)


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/rails_ai_bridge/tool_result_cache.rb', line 94

def fetch_response(tool_name, arguments)
  return yield unless enabled?

  key = cache_key(tool_name, arguments)
  fingerprint = key.split(':', 2).last

  mutex.synchronize do
    entry = cache[key]
    if entry && ttl_valid?(entry)
      Instrumentation.instrument('tool.result_cache_hit', tool_name: tool_name, fingerprint: fingerprint)
      return entry[:response]
    end
  end

  Instrumentation.instrument('tool.result_cache_miss', tool_name: tool_name, fingerprint: fingerprint) do
    response = yield
    mutex.synchronize { cache[key] = { response: response, fetched_at: monotonic_now } }
    response
  end
end

.maybe_wrap(tool_class) ⇒ Class, CachedTool

Wraps a tool class if caching is enabled; otherwise returns the class unchanged.

Parameters:

  • tool_class (Class)

    an MCP::Tool subclass

Returns:



73
74
75
76
77
78
# File 'lib/rails_ai_bridge/tool_result_cache.rb', line 73

def maybe_wrap(tool_class)
  return tool_class unless enabled?
  return tool_class if NON_CACHEABLE.include?(tool_class.tool_name)

  wrap(tool_class)
end

.reset!void

This method returns an undefined value.

Clears all cached tool results.



118
119
120
# File 'lib/rails_ai_bridge/tool_result_cache.rb', line 118

def reset!
  mutex.synchronize { @cache = {} }
end

.wrap(tool_class) ⇒ CachedTool

Wraps a tool class so every call goes through the cache.

Parameters:

  • tool_class (Class)

Returns:



84
85
86
# File 'lib/rails_ai_bridge/tool_result_cache.rb', line 84

def wrap(tool_class)
  CachedTool.new(tool_class)
end