airbrake_mcp 1.0.3 → 1.0.5
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 +6 -0
- data/README.md +71 -1
- data/lib/airbrake_mcp/client.rb +8 -8
- data/lib/airbrake_mcp/formatters.rb +1 -1
- data/lib/airbrake_mcp/response_helper.rb +11 -0
- data/lib/airbrake_mcp/tools/get_error.rb +5 -13
- data/lib/airbrake_mcp/tools/list_errors.rb +3 -9
- data/lib/airbrake_mcp/tools/list_notices.rb +5 -13
- data/lib/airbrake_mcp/tools/list_projects.rb +2 -6
- data/lib/airbrake_mcp/tools/mute_error.rb +5 -13
- data/lib/airbrake_mcp/tools/resolve_error.rb +5 -13
- 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: e285107444c59dad9e1bf190b5533358d3b31d2d87555ab5b95e1973dce12bd9
|
|
4
|
+
data.tar.gz: d292168104b253d786fd1a735da199b77debbcfcbf8bb147f730d09daff28ff1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fe0f6286ba31d60bd4db9d2597b9f30bed32cb9b4e1a113d9fcb46c906b51e8e3b8e9eab93ce7edfcd39486b8c5171724f8d1079e94a4d20d6e486b1db76ffc9
|
|
7
|
+
data.tar.gz: 43264b5a7a02d0d033fa3b25a97e59c3273ed473133107431639747a33be0922290911a29abd07b1d9050915c3df46b3f9dff54019cabe57f342844b75d382c2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
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
|
+
|
|
3
9
|
## [1.0.3] - 2026-01-06
|
|
4
10
|
|
|
5
11
|
### Fixed
|
data/README.md
CHANGED
|
@@ -142,12 +142,82 @@ Parameters:
|
|
|
142
142
|
bundle exec rspec
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
-
### Building
|
|
145
|
+
### Building and Installing from Source
|
|
146
146
|
|
|
147
147
|
```bash
|
|
148
|
+
# Build the gem
|
|
148
149
|
gem build airbrake_mcp.gemspec
|
|
150
|
+
|
|
151
|
+
# Install locally
|
|
152
|
+
gem install ./airbrake_mcp-*.gem --no-document
|
|
153
|
+
|
|
154
|
+
# If using rbenv, rehash to update shims
|
|
155
|
+
rbenv rehash
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Updating an Installed Gem
|
|
159
|
+
|
|
160
|
+
When updating the gem after code changes:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# 1. Remove ALL old versions
|
|
164
|
+
gem uninstall airbrake_mcp --all --executables --ignore-dependencies
|
|
165
|
+
|
|
166
|
+
# 2. Remove old gem files
|
|
167
|
+
rm -f *.gem
|
|
168
|
+
|
|
169
|
+
# 3. Build fresh gem
|
|
170
|
+
gem build airbrake_mcp.gemspec
|
|
171
|
+
|
|
172
|
+
# 4. Install with force flag
|
|
173
|
+
gem install ./airbrake_mcp-*.gem --no-document --force
|
|
174
|
+
|
|
175
|
+
# 5. Rehash rbenv shims
|
|
176
|
+
rbenv rehash
|
|
177
|
+
|
|
178
|
+
# 6. Verify installation
|
|
179
|
+
gem which airbrake_mcp
|
|
149
180
|
```
|
|
150
181
|
|
|
182
|
+
## Troubleshooting
|
|
183
|
+
|
|
184
|
+
### "command not found" after installation
|
|
185
|
+
|
|
186
|
+
If you see `rbenv: airbrake_mcp: command not found`, the gem was installed for a different Ruby version.
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# Check which Ruby versions have the gem
|
|
190
|
+
rbenv versions # shows available versions
|
|
191
|
+
gem list airbrake_mcp # shows if installed for current Ruby
|
|
192
|
+
|
|
193
|
+
# Install for the correct Ruby version
|
|
194
|
+
RBENV_VERSION=3.4.4 gem install ./airbrake_mcp-*.gem --no-document
|
|
195
|
+
rbenv rehash
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### MCP fails to connect after gem update
|
|
199
|
+
|
|
200
|
+
1. Ensure the gem is completely uninstalled before reinstalling:
|
|
201
|
+
```bash
|
|
202
|
+
gem uninstall airbrake_mcp --all --executables --ignore-dependencies
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
2. Verify the new code is in the built gem:
|
|
206
|
+
```bash
|
|
207
|
+
gem unpack airbrake_mcp-*.gem --target=/tmp/check
|
|
208
|
+
cat /tmp/check/airbrake_mcp-*/lib/airbrake_mcp/client.rb
|
|
209
|
+
rm -rf /tmp/check
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
3. After installation, verify the installed code:
|
|
213
|
+
```bash
|
|
214
|
+
cat $(dirname $(gem which airbrake_mcp))/airbrake_mcp/client.rb
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Large Error Group IDs
|
|
218
|
+
|
|
219
|
+
Airbrake uses very large integers for error group IDs (e.g., `4235892606830408977`). These IDs are passed as strings to avoid JavaScript precision loss issues. When using tools like `get_error` or `list_notices`, provide the `group_id` exactly as shown in `list_errors` output.
|
|
220
|
+
|
|
151
221
|
## License
|
|
152
222
|
|
|
153
223
|
MIT
|
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}")['group']
|
|
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
|
|
@@ -29,7 +29,7 @@ module AirbrakeMcp
|
|
|
29
29
|
muted = group['muted'] ? ' (muted)' : ''
|
|
30
30
|
error = group['errors']&.first || {}
|
|
31
31
|
|
|
32
|
-
output += "#{status}#{muted}
|
|
32
|
+
output += "#{status}#{muted} id:#{group['id']}\n"
|
|
33
33
|
output += " Type: #{error['type']}\n"
|
|
34
34
|
output += " Message: #{truncate(error['message'], 100)}\n"
|
|
35
35
|
output += " Count: #{group['noticeCount']} occurrences\n"
|
|
@@ -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
|
|
@@ -8,7 +8,7 @@ module AirbrakeMcp
|
|
|
8
8
|
|
|
9
9
|
input_schema(
|
|
10
10
|
properties: {
|
|
11
|
-
group_id: { type: "
|
|
11
|
+
group_id: { type: "string", description: "Error group ID" },
|
|
12
12
|
project_id: { type: "integer", description: "Project ID (uses default if not specified)" }
|
|
13
13
|
},
|
|
14
14
|
required: ["group_id"]
|
|
@@ -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
|
|
@@ -8,7 +8,7 @@ module AirbrakeMcp
|
|
|
8
8
|
|
|
9
9
|
input_schema(
|
|
10
10
|
properties: {
|
|
11
|
-
group_id: { type: "
|
|
11
|
+
group_id: { type: "string", description: "Error group ID" },
|
|
12
12
|
project_id: { type: "integer", description: "Project ID (uses default if not specified)" },
|
|
13
13
|
page: { type: "integer", description: "Page number (default: 1)" },
|
|
14
14
|
limit: { type: "integer", description: "Results per page (default: 10)" }
|
|
@@ -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
|
|
@@ -8,7 +8,7 @@ module AirbrakeMcp
|
|
|
8
8
|
|
|
9
9
|
input_schema(
|
|
10
10
|
properties: {
|
|
11
|
-
group_id: { type: "
|
|
11
|
+
group_id: { type: "string", description: "Error group ID" },
|
|
12
12
|
project_id: { type: "integer", description: "Project ID (uses default if not specified)" },
|
|
13
13
|
mute: { type: "boolean", description: "true to mute, false to unmute (default: true)" }
|
|
14
14
|
},
|
|
@@ -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
|
|
@@ -8,7 +8,7 @@ module AirbrakeMcp
|
|
|
8
8
|
|
|
9
9
|
input_schema(
|
|
10
10
|
properties: {
|
|
11
|
-
group_id: { type: "
|
|
11
|
+
group_id: { type: "string", description: "Error group ID" },
|
|
12
12
|
project_id: { type: "integer", description: "Project ID (uses default if not specified)" },
|
|
13
13
|
resolved: { type: "boolean", description: "true to resolve, false to unresolve (default: true)" }
|
|
14
14
|
},
|
|
@@ -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.5
|
|
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
|