Class: Tools::FindCallRecordingsTool

Inherits:
ApplicationTool show all
Defined in:
app/mcp/tools/find_call_recordings_tool.rb

Overview

MCP Tool for searching call recording transcripts.
Access is permission-gated:

  • call_recordings: Search own call recordings only (employee's calls)
  • call_recordings_all: Search all call recordings (managers/admins)

Without either permission, this tool is not visible to the client.

Examples:

Search own call recordings

{ query: "customer asking about heated driveway pricing", limit: 5 }

Class Method Summary collapse

Class Method Details

.call(query:, limit: 10, server_context: nil) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'app/mcp/tools/find_call_recordings_tool.rb', line 36

def call(query:, limit: 10, server_context: nil)
  auth = Thread.current[:mcp_auth_result]
  return error_response('Authentication required') unless auth

  # Determine access level from token permissions
  has_all_access = auth.can_access_service?('call_recordings_all')
  has_own_access = auth.can_access_service?('call_recordings')

  unless has_all_access || has_own_access
    return error_response('You do not have permission to search call recordings')
  end

  limit = [[limit.to_i, 1].max, 30].min

  # Search call record embeddings (bypassing the mcp_safe filter)
  results = ContentEmbedding.hybrid_search(
    query,
    limit: limit,
    types: ['CallRecord'],
    exclude_sensitive: false # We're explicitly searching sensitive content
  )

  # Scope to own calls only unless manager access
  unless has_all_access
    employee_party_id = auth..party_id
    results = results.select do |embedding|
      record = embedding.embeddable
      next false unless record

      record.origin_party_id == employee_party_id ||
        record.destination_party_id == employee_party_id
    end
  end

  results = results.first(limit)

  json_response(
    query: query,
    access_level: has_all_access ? 'all' : 'own',
    total_results: results.size,
    call_recordings: results.filter_map { |emb| format_call_record(emb.embeddable) }
  )
end