airbrake_mcp 1.0.2 → 1.0.4
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 +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +6 -11
- data/bin/airbrake_mcp +6 -2
- data/lib/airbrake_mcp/client.rb +8 -8
- data/lib/airbrake_mcp/response_helper.rb +11 -0
- data/lib/airbrake_mcp/tools/get_error.rb +4 -12
- data/lib/airbrake_mcp/tools/list_errors.rb +3 -9
- data/lib/airbrake_mcp/tools/list_notices.rb +4 -12
- data/lib/airbrake_mcp/tools/list_projects.rb +2 -6
- data/lib/airbrake_mcp/tools/mute_error.rb +4 -12
- data/lib/airbrake_mcp/tools/resolve_error.rb +4 -12
- data/lib/airbrake_mcp/version.rb +1 -1
- data/lib/airbrake_mcp.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7ed4e827382daeb7329a9b383855ae55ab2c26e337585c753d80aaddeebf5179
|
|
4
|
+
data.tar.gz: 4b96efeffd6206d6cee8f5459f32e8a61cdba1b2ba03985a2b1767c51ef6c689
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 21e39e8a19ba4f93d450cb6029cc42075ae270ed86bedae141ca59bd62c7ca34aa7ab4e051e2d86a19e7f0342440a4e389481657aa733ff49ae8e789a12e0775
|
|
7
|
+
data.tar.gz: 795083e21d0151602d6bbefc6a28c3b33659594370497e574e3c2f8c66721312d069c4824828ebf4c63c863ac05532793ccb8ac277020b8c42c4f20a019d2899
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.4] - 2026-01-06
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- Fixed API URL path construction (removed leading slashes causing requests to bypass /api/v4 path)
|
|
7
|
+
- Fixed MCP response serialization (workaround for MCP gem bug where Content objects aren't converted to hashes)
|
|
8
|
+
|
|
9
|
+
## [1.0.3] - 2026-01-06
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- Removed `require 'bundler/setup'` from bin script to fix Bundler conflicts when running from project directories with their own Gemfile
|
|
13
|
+
- Made dotenv loading optional (development dependency only)
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- Simplified README installation instructions
|
|
17
|
+
|
|
3
18
|
## [1.0.2] - 2025-01-06
|
|
4
19
|
|
|
5
20
|
### Added
|
data/README.md
CHANGED
|
@@ -48,41 +48,36 @@ bundle install
|
|
|
48
48
|
### Quick Setup
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
|
-
claude mcp add airbrake
|
|
51
|
+
claude mcp add airbrake airbrake_mcp \
|
|
52
52
|
-e AIRBRAKE_USER_KEY=your_user_key \
|
|
53
53
|
-e AIRBRAKE_PROJECT_ID=123456
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
### Using rbenv/asdf/chruby
|
|
57
57
|
|
|
58
|
-
If you use a Ruby version manager, Claude Code runs in a non-interactive shell without access to your
|
|
58
|
+
If you use a Ruby version manager, Claude Code runs in a non-interactive shell without access to your shell profile. Provide the full path to the shim:
|
|
59
59
|
|
|
60
60
|
```bash
|
|
61
|
-
#
|
|
61
|
+
# rbenv
|
|
62
62
|
claude mcp add airbrake ~/.rbenv/shims/airbrake_mcp \
|
|
63
63
|
-e AIRBRAKE_USER_KEY=your_user_key \
|
|
64
64
|
-e AIRBRAKE_PROJECT_ID=123456
|
|
65
65
|
|
|
66
|
-
#
|
|
66
|
+
# asdf
|
|
67
67
|
claude mcp add airbrake ~/.asdf/shims/airbrake_mcp \
|
|
68
68
|
-e AIRBRAKE_USER_KEY=your_user_key \
|
|
69
69
|
-e AIRBRAKE_PROJECT_ID=123456
|
|
70
|
-
|
|
71
|
-
# For chruby (use full gem path)
|
|
72
|
-
claude mcp add airbrake $(gem environment gemdir)/bin/airbrake_mcp \
|
|
73
|
-
-e AIRBRAKE_USER_KEY=your_user_key \
|
|
74
|
-
-e AIRBRAKE_PROJECT_ID=123456
|
|
75
70
|
```
|
|
76
71
|
|
|
77
72
|
### Manual Configuration
|
|
78
73
|
|
|
79
|
-
Add to `~/.claude/settings.json
|
|
74
|
+
Add to `~/.claude/settings.json`:
|
|
80
75
|
|
|
81
76
|
```json
|
|
82
77
|
{
|
|
83
78
|
"mcpServers": {
|
|
84
79
|
"airbrake": {
|
|
85
|
-
"command": "
|
|
80
|
+
"command": "airbrake_mcp",
|
|
86
81
|
"args": [],
|
|
87
82
|
"env": {
|
|
88
83
|
"AIRBRAKE_USER_KEY": "your_user_key",
|
data/bin/airbrake_mcp
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
# Load dotenv for development (optional)
|
|
5
|
+
begin
|
|
6
|
+
require 'dotenv/load'
|
|
7
|
+
rescue LoadError
|
|
8
|
+
# dotenv is optional, used only for local development
|
|
9
|
+
end
|
|
6
10
|
|
|
7
11
|
require 'airbrake_mcp'
|
|
8
12
|
|
data/lib/airbrake_mcp/client.rb
CHANGED
|
@@ -15,36 +15,36 @@ module AirbrakeMcp
|
|
|
15
15
|
attr_reader :project_id
|
|
16
16
|
|
|
17
17
|
def projects
|
|
18
|
-
get('
|
|
18
|
+
get('projects')['projects']
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def groups(project_id: @project_id, page: 1, limit: 20)
|
|
22
|
-
get("
|
|
22
|
+
get("projects/#{project_id}/groups", { page: page, limit: limit })
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def group(group_id, project_id: @project_id)
|
|
26
|
-
get("
|
|
26
|
+
get("projects/#{project_id}/groups/#{group_id}")
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def notices(group_id, project_id: @project_id, page: 1, limit: 10)
|
|
30
|
-
get("
|
|
30
|
+
get("projects/#{project_id}/groups/#{group_id}/notices", { page: page, limit: limit })
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
# Write operations
|
|
34
34
|
def resolve_group(group_id, project_id: @project_id)
|
|
35
|
-
put("
|
|
35
|
+
put("projects/#{project_id}/groups/#{group_id}/resolved")
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def unresolve_group(group_id, project_id: @project_id)
|
|
39
|
-
put("
|
|
39
|
+
put("projects/#{project_id}/groups/#{group_id}/unresolved")
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def mute_group(group_id, project_id: @project_id)
|
|
43
|
-
put("
|
|
43
|
+
put("projects/#{project_id}/groups/#{group_id}/muted")
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def unmute_group(group_id, project_id: @project_id)
|
|
47
|
-
put("
|
|
47
|
+
put("projects/#{project_id}/groups/#{group_id}/unmuted")
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
private
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AirbrakeMcp
|
|
4
|
+
module ResponseHelper
|
|
5
|
+
# Workaround for MCP gem bug where Content objects aren't converted to hashes
|
|
6
|
+
# in Response#to_h. This creates responses with pre-converted content.
|
|
7
|
+
def self.text_response(text, error: false)
|
|
8
|
+
MCP::Tool::Response.new([{ type: "text", text: text }], error: error)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -19,24 +19,16 @@ module AirbrakeMcp
|
|
|
19
19
|
pid = project_id || client.project_id
|
|
20
20
|
|
|
21
21
|
unless pid
|
|
22
|
-
return
|
|
23
|
-
MCP::Content::Text.new("Error: No project_id specified and no default configured")
|
|
24
|
-
], error: true)
|
|
22
|
+
return ResponseHelper.text_response("Error: No project_id specified and no default configured", error: true)
|
|
25
23
|
end
|
|
26
24
|
|
|
27
25
|
group = client.group(group_id, project_id: pid)
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
MCP::Content::Text.new(Formatters.format_group_detail(group))
|
|
31
|
-
])
|
|
27
|
+
ResponseHelper.text_response(Formatters.format_group_detail(group))
|
|
32
28
|
rescue Client::NotFoundError
|
|
33
|
-
|
|
34
|
-
MCP::Content::Text.new("Error: Error group #{group_id} not found")
|
|
35
|
-
], error: true)
|
|
29
|
+
ResponseHelper.text_response("Error: Error group #{group_id} not found", error: true)
|
|
36
30
|
rescue Client::ApiError => e
|
|
37
|
-
|
|
38
|
-
MCP::Content::Text.new("Error: #{e.message}")
|
|
39
|
-
], error: true)
|
|
31
|
+
ResponseHelper.text_response("Error: #{e.message}", error: true)
|
|
40
32
|
end
|
|
41
33
|
end
|
|
42
34
|
end
|
|
@@ -21,9 +21,7 @@ module AirbrakeMcp
|
|
|
21
21
|
pid = project_id || client.project_id
|
|
22
22
|
|
|
23
23
|
unless pid
|
|
24
|
-
return
|
|
25
|
-
MCP::Content::Text.new("Error: No project_id specified and no default configured")
|
|
26
|
-
], error: true)
|
|
24
|
+
return ResponseHelper.text_response("Error: No project_id specified and no default configured", error: true)
|
|
27
25
|
end
|
|
28
26
|
|
|
29
27
|
result = client.groups(project_id: pid, page: page, limit: limit)
|
|
@@ -33,13 +31,9 @@ module AirbrakeMcp
|
|
|
33
31
|
result['groups'] = result['groups'].select { |g| g['resolved'] == resolved }
|
|
34
32
|
end
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
MCP::Content::Text.new(Formatters.format_groups(result))
|
|
38
|
-
])
|
|
34
|
+
ResponseHelper.text_response(Formatters.format_groups(result))
|
|
39
35
|
rescue Client::ApiError => e
|
|
40
|
-
|
|
41
|
-
MCP::Content::Text.new("Error: #{e.message}")
|
|
42
|
-
], error: true)
|
|
36
|
+
ResponseHelper.text_response("Error: #{e.message}", error: true)
|
|
43
37
|
end
|
|
44
38
|
end
|
|
45
39
|
end
|
|
@@ -21,24 +21,16 @@ module AirbrakeMcp
|
|
|
21
21
|
pid = project_id || client.project_id
|
|
22
22
|
|
|
23
23
|
unless pid
|
|
24
|
-
return
|
|
25
|
-
MCP::Content::Text.new("Error: No project_id specified and no default configured")
|
|
26
|
-
], error: true)
|
|
24
|
+
return ResponseHelper.text_response("Error: No project_id specified and no default configured", error: true)
|
|
27
25
|
end
|
|
28
26
|
|
|
29
27
|
result = client.notices(group_id, project_id: pid, page: page, limit: limit)
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
MCP::Content::Text.new(Formatters.format_notices(result))
|
|
33
|
-
])
|
|
29
|
+
ResponseHelper.text_response(Formatters.format_notices(result))
|
|
34
30
|
rescue Client::NotFoundError
|
|
35
|
-
|
|
36
|
-
MCP::Content::Text.new("Error: Error group #{group_id} not found")
|
|
37
|
-
], error: true)
|
|
31
|
+
ResponseHelper.text_response("Error: Error group #{group_id} not found", error: true)
|
|
38
32
|
rescue Client::ApiError => e
|
|
39
|
-
|
|
40
|
-
MCP::Content::Text.new("Error: #{e.message}")
|
|
41
|
-
], error: true)
|
|
33
|
+
ResponseHelper.text_response("Error: #{e.message}", error: true)
|
|
42
34
|
end
|
|
43
35
|
end
|
|
44
36
|
end
|
|
@@ -10,13 +10,9 @@ module AirbrakeMcp
|
|
|
10
10
|
client = server_context[:client]
|
|
11
11
|
projects = client.projects
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
MCP::Content::Text.new(Formatters.format_projects(projects))
|
|
15
|
-
])
|
|
13
|
+
ResponseHelper.text_response(Formatters.format_projects(projects))
|
|
16
14
|
rescue Client::ApiError => e
|
|
17
|
-
|
|
18
|
-
MCP::Content::Text.new("Error: #{e.message}")
|
|
19
|
-
], error: true)
|
|
15
|
+
ResponseHelper.text_response("Error: #{e.message}", error: true)
|
|
20
16
|
end
|
|
21
17
|
end
|
|
22
18
|
end
|
|
@@ -20,9 +20,7 @@ module AirbrakeMcp
|
|
|
20
20
|
pid = project_id || client.project_id
|
|
21
21
|
|
|
22
22
|
unless pid
|
|
23
|
-
return
|
|
24
|
-
MCP::Content::Text.new("Error: No project_id specified and no default configured")
|
|
25
|
-
], error: true)
|
|
23
|
+
return ResponseHelper.text_response("Error: No project_id specified and no default configured", error: true)
|
|
26
24
|
end
|
|
27
25
|
|
|
28
26
|
if mute
|
|
@@ -33,17 +31,11 @@ module AirbrakeMcp
|
|
|
33
31
|
action = "unmuted"
|
|
34
32
|
end
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
MCP::Content::Text.new("Error group ##{group_id} #{action}")
|
|
38
|
-
])
|
|
34
|
+
ResponseHelper.text_response("Error group ##{group_id} #{action}")
|
|
39
35
|
rescue Client::NotFoundError
|
|
40
|
-
|
|
41
|
-
MCP::Content::Text.new("Error: Error group #{group_id} not found")
|
|
42
|
-
], error: true)
|
|
36
|
+
ResponseHelper.text_response("Error: Error group #{group_id} not found", error: true)
|
|
43
37
|
rescue Client::ApiError => e
|
|
44
|
-
|
|
45
|
-
MCP::Content::Text.new("Error: #{e.message}")
|
|
46
|
-
], error: true)
|
|
38
|
+
ResponseHelper.text_response("Error: #{e.message}", error: true)
|
|
47
39
|
end
|
|
48
40
|
end
|
|
49
41
|
end
|
|
@@ -20,9 +20,7 @@ module AirbrakeMcp
|
|
|
20
20
|
pid = project_id || client.project_id
|
|
21
21
|
|
|
22
22
|
unless pid
|
|
23
|
-
return
|
|
24
|
-
MCP::Content::Text.new("Error: No project_id specified and no default configured")
|
|
25
|
-
], error: true)
|
|
23
|
+
return ResponseHelper.text_response("Error: No project_id specified and no default configured", error: true)
|
|
26
24
|
end
|
|
27
25
|
|
|
28
26
|
if resolved
|
|
@@ -33,17 +31,11 @@ module AirbrakeMcp
|
|
|
33
31
|
action = "unresolved"
|
|
34
32
|
end
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
MCP::Content::Text.new("Error group ##{group_id} marked as #{action}")
|
|
38
|
-
])
|
|
34
|
+
ResponseHelper.text_response("Error group ##{group_id} marked as #{action}")
|
|
39
35
|
rescue Client::NotFoundError
|
|
40
|
-
|
|
41
|
-
MCP::Content::Text.new("Error: Error group #{group_id} not found")
|
|
42
|
-
], error: true)
|
|
36
|
+
ResponseHelper.text_response("Error: Error group #{group_id} not found", error: true)
|
|
43
37
|
rescue Client::ApiError => e
|
|
44
|
-
|
|
45
|
-
MCP::Content::Text.new("Error: #{e.message}")
|
|
46
|
-
], error: true)
|
|
38
|
+
ResponseHelper.text_response("Error: #{e.message}", error: true)
|
|
47
39
|
end
|
|
48
40
|
end
|
|
49
41
|
end
|
data/lib/airbrake_mcp/version.rb
CHANGED
data/lib/airbrake_mcp.rb
CHANGED
|
@@ -5,6 +5,7 @@ require 'mcp'
|
|
|
5
5
|
require_relative 'airbrake_mcp/version'
|
|
6
6
|
require_relative 'airbrake_mcp/client'
|
|
7
7
|
require_relative 'airbrake_mcp/formatters'
|
|
8
|
+
require_relative 'airbrake_mcp/response_helper'
|
|
8
9
|
require_relative 'airbrake_mcp/tools/list_projects'
|
|
9
10
|
require_relative 'airbrake_mcp/tools/list_errors'
|
|
10
11
|
require_relative 'airbrake_mcp/tools/get_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.
|
|
4
|
+
version: 1.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- httplab
|
|
@@ -95,6 +95,7 @@ files:
|
|
|
95
95
|
- lib/airbrake_mcp.rb
|
|
96
96
|
- lib/airbrake_mcp/client.rb
|
|
97
97
|
- lib/airbrake_mcp/formatters.rb
|
|
98
|
+
- lib/airbrake_mcp/response_helper.rb
|
|
98
99
|
- lib/airbrake_mcp/tools/get_error.rb
|
|
99
100
|
- lib/airbrake_mcp/tools/list_errors.rb
|
|
100
101
|
- lib/airbrake_mcp/tools/list_notices.rb
|