Module: ActionMCP::Server::Resources

Included in:
TransportHandler
Defined in:
lib/action_mcp/server/resources.rb

Instance Method Summary collapse

Instance Method Details

#send_resource_read(id, params) ⇒ Object

Read and return the contents of a resource

Examples:

Input:

id = "req-789"
params = { uri: "file:///example.txt" }

Output:

# Sends: {"jsonrpc":"2.0","id":"req-789","result":{"contents":[{"uri":"file:///example.txt","text":"Example content"}]}}

Parameters:

  • id (String, Integer)

    The ID of the request to respond to

  • params (Hash)

    Parameters specifying which resource to read



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
79
80
81
82
83
84
85
86
# File 'lib/action_mcp/server/resources.rb', line 47

def send_resource_read(id, params)
  uri = params["uri"]
  template = ResourceTemplatesRegistry.find_template_for_uri(uri)

  unless template
    send_jsonrpc_error(id, :method_not_found, "No resource template found for URI: '#{uri}'")
    return
  end

  # Check if resource requires consent and if consent is granted
  if template.respond_to?(:requires_consent?) && template.requires_consent? && !session.consent_granted_for?("resource:#{template.name}")
    # Use custom error response for consent required (-32002)
    error = {
      code: -32_002,
      message: "Consent required for resource template '#{template.name}'"
    }
    send_jsonrpc_response(id, error: error)
    return
  end

  begin
    # Create template instance and set execution context
    record = template.process(uri)
    record.with_context({ session: session })

    response = record.call

    if response.error?
      # response.to_h works properly when error? is true:
      send_jsonrpc_response(id, error: response.to_h)
    else
      # Handle successful response - ResourceResponse.contents is already an array
      send_jsonrpc_response(id, result: { contents: response.contents.map(&:to_h) })
    end
  rescue StandardError => e
    # Should rather `ErrorHandling` module be included here? Then we could use `log_error(e)` directly.
    Rails.logger.error "[MCP Error] #{e.class}: #{e.message}"
    send_jsonrpc_error(id, :internal_error, "Failed to read resource: #{e.message}")
  end
end

#send_resource_templates_list(request_id) ⇒ Object

Send list of resource templates to the client

Examples:

Input:

request_id = "req-456"

Output:

# Sends: {"jsonrpc":"2.0","id":"req-456","result":{"resourceTemplates":[{"uriTemplate":"db://{table}","name":"Database Table"}]}}

Parameters:

  • request_id (String, Integer)

    The ID of the request to respond to



28
29
30
31
32
33
34
# File 'lib/action_mcp/server/resources.rb', line 28

def send_resource_templates_list(request_id)
  templates = ActionMCP::ResourceTemplatesRegistry.resource_templates.values.map(&:to_h)
  # TODO: add pagination support
  # TODO add autocomplete
  log_resource_templates
  send_jsonrpc_response(request_id, result: { resourceTemplates: templates })
end

#send_resources_list(request_id) ⇒ Object

Send list of available resources to the client

Examples:

Input:

request_id = "req-123"

Output:

# Sends: {"jsonrpc":"2.0","id":"req-123","result":{"resources":[]}}

Parameters:

  • request_id (String, Integer)

    The ID of the request to respond to



15
16
17
# File 'lib/action_mcp/server/resources.rb', line 15

def send_resources_list(request_id)
  send_jsonrpc_response(request_id, result: { resources: [] })
end