airbrake_mcp 1.0.5 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e285107444c59dad9e1bf190b5533358d3b31d2d87555ab5b95e1973dce12bd9
4
- data.tar.gz: d292168104b253d786fd1a735da199b77debbcfcbf8bb147f730d09daff28ff1
3
+ metadata.gz: a19b6eada1254e2024d78f400cd92fd0836cb121361408a1d32707920e390a05
4
+ data.tar.gz: 88ef08bbb49921cd1d37dd361301dbf57187633a24df20f99d3a526b521f53d6
5
5
  SHA512:
6
- metadata.gz: fe0f6286ba31d60bd4db9d2597b9f30bed32cb9b4e1a113d9fcb46c906b51e8e3b8e9eab93ce7edfcd39486b8c5171724f8d1079e94a4d20d6e486b1db76ffc9
7
- data.tar.gz: 43264b5a7a02d0d033fa3b25a97e59c3273ed473133107431639747a33be0922290911a29abd07b1d9050915c3df46b3f9dff54019cabe57f342844b75d382c2
6
+ metadata.gz: 8558072266fbed0f6ee9ca8a0933a0da9d48f5b59821f9e86c17903f6cf47751246924f9f90721c47d88eb88592178fbb26235688048b3d277dbbbf021cc113c
7
+ data.tar.gz: 6586486fa58bb74767308759c3b3bcc4dea0021be4fb19b0cad88f516677319bbc19d2bf4348b6e8e300d5156024ef2deac57112c229b6611c5dd4ec83fd30dd
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.1.0] - 2026-02-08
4
+
5
+ ### Fixed
6
+ - Fixed `put` method silently swallowing HTTP errors (now raises exceptions like `get`)
7
+ - Fixed `handle_response` to handle 204 No Content responses from resolve/mute endpoints
8
+ - Fixed `list_errors` client-side filtering — now passes `resolved` filter to API server-side
9
+
10
+ ### Added
11
+ - New `resolve_all` tool for bulk-resolving all open error groups in a project (with `dry_run` option)
12
+ - `order` parameter for `list_errors` (supports: `last_notice`, `notice_count`, `weight`, `created`)
13
+ - Server-side filter passthrough for `groups` client method
14
+
3
15
  ## [1.0.4] - 2026-01-06
4
16
 
5
17
  ### Fixed
data/README.md CHANGED
@@ -99,8 +99,9 @@ List error groups with filtering options.
99
99
  Parameters:
100
100
  - `project_id` (optional) - Project ID, uses default if not specified
101
101
  - `page` (optional) - Page number, default: 1
102
- - `limit` (optional) - Results per page, default: 20
102
+ - `limit` (optional) - Results per page, default: 20, max: 100
103
103
  - `resolved` (optional) - Filter by resolved status (true/false)
104
+ - `order` (optional) - Sort order: `last_notice`, `notice_count`, `weight`, `created`
104
105
 
105
106
  ### get_error
106
107
  Get detailed information about a specific error group including backtrace.
@@ -118,6 +119,13 @@ Parameters:
118
119
  - `page` (optional) - Page number, default: 1
119
120
  - `limit` (optional) - Results per page, default: 10
120
121
 
122
+ ### resolve_all
123
+ Resolve all open error groups in a project. Iterates through all pages.
124
+
125
+ Parameters:
126
+ - `project_id` (optional) - Project ID, uses default if not specified
127
+ - `dry_run` (optional) - If true, only count groups without resolving (default: false)
128
+
121
129
  ### resolve_error
122
130
  Mark an error group as resolved or unresolve it.
123
131
 
data/bin/airbrake_mcp CHANGED
@@ -26,6 +26,7 @@ server = MCP::Server.new(
26
26
  AirbrakeMcp::Tools::GetError,
27
27
  AirbrakeMcp::Tools::ListNotices,
28
28
  AirbrakeMcp::Tools::ResolveError,
29
+ AirbrakeMcp::Tools::ResolveAll,
29
30
  AirbrakeMcp::Tools::MuteError
30
31
  ],
31
32
  server_context: { client: client }
@@ -18,8 +18,9 @@ module AirbrakeMcp
18
18
  get('projects')['projects']
19
19
  end
20
20
 
21
- def groups(project_id: @project_id, page: 1, limit: 20)
22
- get("projects/#{project_id}/groups", { page: page, limit: limit })
21
+ def groups(project_id: @project_id, page: 1, limit: 20, **filters)
22
+ params = { page: page, limit: limit }.merge(filters.compact)
23
+ get("projects/#{project_id}/groups", params)
23
24
  end
24
25
 
25
26
  def group(group_id, project_id: @project_id)
@@ -56,12 +57,13 @@ module AirbrakeMcp
56
57
 
57
58
  def put(path)
58
59
  response = connection.put("#{path}?key=#{@user_key}")
59
- response.success?
60
+ handle_response(response)
60
61
  end
61
62
 
62
63
  def handle_response(response)
63
64
  case response.status
64
65
  when 200..299
66
+ return true if response.body.nil? || response.body.empty?
65
67
  JSON.parse(response.body)
66
68
  when 401
67
69
  raise AuthenticationError, 'Invalid API key'
@@ -11,12 +11,13 @@ module AirbrakeMcp
11
11
  project_id: { type: "integer", description: "Project ID (uses default if not specified)" },
12
12
  page: { type: "integer", description: "Page number (default: 1)" },
13
13
  limit: { type: "integer", description: "Results per page (default: 20, max: 100)" },
14
- resolved: { type: "boolean", description: "Filter by resolved status (true/false)" }
14
+ resolved: { type: "boolean", description: "Filter by resolved status (true/false)" },
15
+ order: { type: "string", description: "Sort order: last_notice, notice_count, weight, created (default: last_notice)" }
15
16
  },
16
17
  required: []
17
18
  )
18
19
 
19
- def self.call(project_id: nil, page: 1, limit: 20, resolved: nil, server_context:)
20
+ def self.call(project_id: nil, page: 1, limit: 20, resolved: nil, order: nil, server_context:)
20
21
  client = server_context[:client]
21
22
  pid = project_id || client.project_id
22
23
 
@@ -24,12 +25,11 @@ module AirbrakeMcp
24
25
  return ResponseHelper.text_response("Error: No project_id specified and no default configured", error: true)
25
26
  end
26
27
 
27
- result = client.groups(project_id: pid, page: page, limit: limit)
28
+ filters = {}
29
+ filters[:resolved] = resolved unless resolved.nil?
30
+ filters[:order] = order if order
28
31
 
29
- # Client-side filtering for resolved status if specified
30
- if !resolved.nil? && result['groups']
31
- result['groups'] = result['groups'].select { |g| g['resolved'] == resolved }
32
- end
32
+ result = client.groups(project_id: pid, page: page, limit: limit, **filters)
33
33
 
34
34
  ResponseHelper.text_response(Formatters.format_groups(result))
35
35
  rescue Client::ApiError => e
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AirbrakeMcp
4
+ module Tools
5
+ class ResolveAll < MCP::Tool
6
+ tool_name "resolve_all"
7
+ description "Resolve all open error groups in a project. Iterates through all pages and resolves each group."
8
+
9
+ input_schema(
10
+ properties: {
11
+ project_id: { type: "integer", description: "Project ID (uses default if not specified)" },
12
+ dry_run: { type: "boolean", description: "If true, only count groups without resolving (default: false)" }
13
+ },
14
+ required: []
15
+ )
16
+
17
+ def self.call(project_id: nil, dry_run: false, server_context:)
18
+ client = server_context[:client]
19
+ pid = project_id || client.project_id
20
+
21
+ unless pid
22
+ return ResponseHelper.text_response("Error: No project_id specified and no default configured", error: true)
23
+ end
24
+
25
+ resolved_count = 0
26
+ failed_count = 0
27
+ page = 1
28
+ limit = 100
29
+
30
+ loop do
31
+ result = client.groups(project_id: pid, page: page, limit: limit)
32
+ groups = result['groups'] || []
33
+ break if groups.empty?
34
+
35
+ unresolved = groups.reject { |g| g['resolved'] }
36
+
37
+ unresolved.each do |group|
38
+ if dry_run
39
+ resolved_count += 1
40
+ else
41
+ begin
42
+ client.resolve_group(group['id'].to_s, project_id: pid)
43
+ resolved_count += 1
44
+ rescue Client::ApiError => e
45
+ failed_count += 1
46
+ end
47
+ end
48
+ end
49
+
50
+ # If all groups on this page were resolved, there may be more
51
+ break if groups.length < limit
52
+
53
+ page += 1
54
+ end
55
+
56
+ if dry_run
57
+ ResponseHelper.text_response("Dry run: found #{resolved_count} unresolved error groups in project #{pid}")
58
+ else
59
+ msg = "Resolved #{resolved_count} error groups in project #{pid}"
60
+ msg += " (#{failed_count} failed)" if failed_count > 0
61
+ ResponseHelper.text_response(msg)
62
+ end
63
+ rescue Client::ApiError => e
64
+ ResponseHelper.text_response("Error: #{e.message}", error: true)
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AirbrakeMcp
4
- VERSION = '1.0.5'
4
+ VERSION = '1.1.0'
5
5
  end
data/lib/airbrake_mcp.rb CHANGED
@@ -11,4 +11,5 @@ require_relative 'airbrake_mcp/tools/list_errors'
11
11
  require_relative 'airbrake_mcp/tools/get_error'
12
12
  require_relative 'airbrake_mcp/tools/list_notices'
13
13
  require_relative 'airbrake_mcp/tools/resolve_error'
14
+ require_relative 'airbrake_mcp/tools/resolve_all'
14
15
  require_relative 'airbrake_mcp/tools/mute_error'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: airbrake_mcp
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - httplab
@@ -101,6 +101,7 @@ files:
101
101
  - lib/airbrake_mcp/tools/list_notices.rb
102
102
  - lib/airbrake_mcp/tools/list_projects.rb
103
103
  - lib/airbrake_mcp/tools/mute_error.rb
104
+ - lib/airbrake_mcp/tools/resolve_all.rb
104
105
  - lib/airbrake_mcp/tools/resolve_error.rb
105
106
  - lib/airbrake_mcp/version.rb
106
107
  homepage: https://github.com/httplab/airbrake_mcp