Class: LinearToonMcp::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/linear_toon_mcp/client.rb

Overview

Minimal HTTP client for Linear’s GraphQL API.

Constant Summary collapse

ENDPOINT =
URI("https://api.linear.app/graphql").freeze

Instance Method Summary collapse

Constructor Details

#initialize(api_key: ENV["LINEAR_API_KEY"]) ⇒ Client

Returns a new instance of Client.

Parameters:

  • api_key (String) (defaults to: ENV["LINEAR_API_KEY"])

    Linear API key (defaults to LINEAR_API_KEY env var)

Raises:

  • (ArgumentError)

    when API key is nil or empty



14
15
16
17
18
# File 'lib/linear_toon_mcp/client.rb', line 14

def initialize(api_key: ENV["LINEAR_API_KEY"])
  raise ArgumentError, "LINEAR_API_KEY is required" if api_key.nil? || api_key.empty?

  @api_key = api_key
end

Instance Method Details

#query(query_string, variables: {}) ⇒ Hash

Execute a GraphQL query against Linear API.

Parameters:

  • query_string (String)

    GraphQL query

  • variables (Hash) (defaults to: {})

    query variables

Returns:

  • (Hash)

    the data key from the GraphQL response

Raises:

  • (Error)

    on HTTP errors, GraphQL errors, or empty responses



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/linear_toon_mcp/client.rb', line 25

def query(query_string, variables: {})
  response = post(query_string, variables)

  body = begin
    JSON.parse(response.body)
  rescue JSON::ParserError
    nil
  end

  unless response.is_a?(Net::HTTPSuccess)
    messages = body&.dig("errors")&.map { |e| e["message"] }&.join("; ")
    raise Error, "HTTP #{response.code}: #{messages || response.body}"
  end

  raise Error, "Empty response from Linear API" unless body

  if body["errors"]&.any?
    messages = body["errors"].map { |e| e["message"] }.join("; ")
    raise Error, "GraphQL error: #{messages}"
  end

  body["data"]
end