@smartbear/mcp 0.14.1 → 0.16.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.
- package/README.md +1 -1
- package/dist/bugsnag/client.js +47 -1340
- package/dist/bugsnag/input-schemas.js +18 -18
- package/dist/bugsnag/tool/error/get-error.js +98 -0
- package/dist/bugsnag/tool/error/list-project-errors.js +102 -0
- package/dist/bugsnag/tool/error/update-error.js +256 -0
- package/dist/bugsnag/tool/event/get-event-details-from-dashboard-url.js +55 -0
- package/dist/bugsnag/tool/event/get-event.js +38 -0
- package/dist/bugsnag/tool/performance/get-network-endpoint-groupings.js +46 -0
- package/dist/bugsnag/tool/performance/get-span-group.js +73 -0
- package/dist/bugsnag/tool/performance/get-trace.js +83 -0
- package/dist/bugsnag/tool/performance/list-span-groups.js +111 -0
- package/dist/bugsnag/tool/performance/list-spans.js +97 -0
- package/dist/bugsnag/tool/performance/list-trace-fields.js +41 -0
- package/dist/bugsnag/tool/performance/set-network-endpoint-groupings.js +90 -0
- package/dist/bugsnag/tool/project/get-current-project.js +31 -0
- package/dist/bugsnag/tool/project/list-project-event-filters.js +42 -0
- package/dist/bugsnag/tool/project/list-projects.js +43 -0
- package/dist/bugsnag/tool/release/get-build.js +50 -0
- package/dist/bugsnag/tool/release/get-release.js +68 -0
- package/dist/bugsnag/tool/release/list-releases.js +88 -0
- package/dist/common/prompts.js +9 -0
- package/dist/common/server.js +16 -0
- package/dist/common/transport-http.js +2 -0
- package/dist/package.json.js +1 -1
- package/dist/qmetry/client/api/client-api.js +2 -1
- package/dist/qmetry/client/automation.js +2 -1
- package/dist/qmetry/client/tools/testcase-tools.js +269 -1
- package/dist/qmetry/client/tools/testsuite-tools.js +1 -1
- package/dist/reflect/client.js +82 -255
- package/dist/reflect/config/constants.js +8 -0
- package/dist/reflect/prompt/sap-test.js +29 -0
- package/dist/reflect/tool/recording/add-prompt-step.js +60 -0
- package/dist/reflect/tool/recording/add-segment.js +56 -0
- package/dist/reflect/tool/recording/connect-to-session.js +89 -0
- package/dist/reflect/tool/recording/delete-previous-step.js +47 -0
- package/dist/reflect/tool/recording/get-screenshot.js +55 -0
- package/dist/reflect/tool/suites/cancel-suite-execution.js +50 -0
- package/dist/reflect/tool/suites/execute-suite.js +40 -0
- package/dist/reflect/tool/suites/get-suite-execution-status.js +50 -0
- package/dist/reflect/tool/suites/list-suite-executions.js +40 -0
- package/dist/reflect/tool/suites/list-suites.js +27 -0
- package/dist/reflect/tool/tests/get-test-status.js +42 -0
- package/dist/reflect/tool/tests/list-segments.js +68 -0
- package/dist/reflect/tool/tests/list-tests.js +27 -0
- package/dist/reflect/tool/tests/run-test.js +40 -0
- package/dist/reflect/websocket-manager.js +92 -0
- package/dist/zephyr/client.js +35 -1
- package/dist/zephyr/common/rest-api-schemas.js +463 -477
- package/dist/zephyr/tool/folder/create-folder.js +55 -0
- package/dist/zephyr/tool/issue-link/get-test-cases.js +33 -0
- package/dist/zephyr/tool/issue-link/get-test-cycles.js +32 -0
- package/dist/zephyr/tool/issue-link/get-test-executions.js +32 -0
- package/dist/zephyr/tool/test-case/create-issue-link.js +38 -0
- package/dist/zephyr/tool/test-case/create-test-script.js +57 -0
- package/dist/zephyr/tool/test-case/create-test-steps.js +91 -0
- package/dist/zephyr/tool/test-case/create-web-link.js +5 -2
- package/dist/zephyr/tool/test-case/get-links.js +32 -0
- package/dist/zephyr/tool/test-case/get-test-script.js +46 -0
- package/dist/zephyr/tool/test-case/get-test-steps.js +56 -0
- package/dist/zephyr/tool/test-cycle/create-issue-link.js +45 -0
- package/dist/zephyr/tool/test-cycle/create-web-link.js +56 -0
- package/dist/zephyr/tool/test-cycle/get-links.js +39 -0
- package/dist/zephyr/tool/test-execution/create-issue-link.js +45 -0
- package/dist/zephyr/tool/test-execution/get-test-execution-links.js +39 -0
- package/dist/zephyr/tool/test-execution/get-test-steps.js +75 -0
- package/dist/zephyr/tool/test-execution/update-test-execution.js +73 -0
- package/package.json +11 -9
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
const filterValueSchema =
|
|
3
|
-
type:
|
|
4
|
-
value:
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const filterValueSchema = z.object({
|
|
3
|
+
type: z.enum(["eq", "ne", "empty"]),
|
|
4
|
+
value: z.union([z.string(), z.boolean(), z.number()])
|
|
5
5
|
});
|
|
6
|
-
const filtersSchema =
|
|
6
|
+
const filtersSchema = z.record(z.string(), z.array(filterValueSchema));
|
|
7
7
|
const toolInputParameters = {
|
|
8
|
-
empty:
|
|
9
|
-
buildId:
|
|
10
|
-
errorId:
|
|
11
|
-
eventId:
|
|
12
|
-
projectId:
|
|
8
|
+
empty: z.object({}).describe("No parameters are required for this tool"),
|
|
9
|
+
buildId: z.string().describe("Unique identifier of the app build"),
|
|
10
|
+
errorId: z.string().describe("Unique identifier of the error"),
|
|
11
|
+
eventId: z.string().describe("Unique identifier of the event"),
|
|
12
|
+
projectId: z.string().optional().describe(
|
|
13
13
|
"Unique identifier of the project. This is optional if a current project is set and is used to set the current project for BugSnag tools."
|
|
14
14
|
),
|
|
15
|
-
releaseId:
|
|
16
|
-
direction:
|
|
15
|
+
releaseId: z.string().describe("Unique identifier of the app release"),
|
|
16
|
+
direction: z.enum(["asc", "desc"]).describe("Sort direction for ordering results").default("desc"),
|
|
17
17
|
performanceFilters: filtersSchema.describe(
|
|
18
18
|
"Apply filters to narrow down the span group list. Use the List Trace Fields tool to discover available filter fields. Time filters support extended ISO 8601 format (e.g. 2018-05-20T00:00:00Z) or relative format (e.g. 7d, 24h)."
|
|
19
19
|
).default({
|
|
@@ -25,16 +25,16 @@ const toolInputParameters = {
|
|
|
25
25
|
"event.since": [{ type: "eq", value: "30d" }],
|
|
26
26
|
"error.status": [{ type: "eq", value: "open" }]
|
|
27
27
|
}),
|
|
28
|
-
nextUrl:
|
|
28
|
+
nextUrl: z.string().describe(
|
|
29
29
|
"URL for retrieving the next page of results. Use the value in the previous response to get the next page when more results are available. Only values provided in the output from this tool can be used. Do not attempt to construct it manually."
|
|
30
30
|
).optional(),
|
|
31
|
-
page:
|
|
32
|
-
perPage:
|
|
33
|
-
releaseStage:
|
|
31
|
+
page: z.number().describe("Page number to return (starts from 1)").default(1),
|
|
32
|
+
perPage: z.number().describe("How many results to return per page.").min(1).max(100).default(30),
|
|
33
|
+
releaseStage: z.string().describe(
|
|
34
34
|
"Filter releases by this stage (e.g. production, staging), defaults to 'production'"
|
|
35
35
|
).default("production"),
|
|
36
|
-
sort:
|
|
37
|
-
spanGroupId:
|
|
36
|
+
sort: z.enum(["first_seen", "last_seen", "events", "users", "unsorted"]).describe("Field to sort the errors by").default("last_seen"),
|
|
37
|
+
spanGroupId: z.string().describe("ID of the span group")
|
|
38
38
|
};
|
|
39
39
|
export {
|
|
40
40
|
toolInputParameters
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Tool, ToolError } from "../../../common/tools.js";
|
|
3
|
+
import { toUrlSearchParams } from "../../client/filters.js";
|
|
4
|
+
import { toolInputParameters } from "../../input-schemas.js";
|
|
5
|
+
const inputSchema = z.object({
|
|
6
|
+
projectId: toolInputParameters.projectId,
|
|
7
|
+
errorId: toolInputParameters.errorId.describe(
|
|
8
|
+
"Unique identifier of the error to retrieve"
|
|
9
|
+
),
|
|
10
|
+
filters: toolInputParameters.filters.describe(
|
|
11
|
+
"Apply filters to narrow down the error list. Use the List Project Event Filters tool to discover available filter fields. Time filters support extended ISO 8601 format (e.g. 2018-05-20T00:00:00Z) or relative format (e.g. 7d, 24h)."
|
|
12
|
+
)
|
|
13
|
+
});
|
|
14
|
+
class GetError extends Tool {
|
|
15
|
+
specification = {
|
|
16
|
+
title: "Get Error",
|
|
17
|
+
summary: "Get full details on an error, including aggregated and summarized data across all events (occurrences) and details of the latest event (occurrence), such as breadcrumbs, metadata and the stacktrace. Use the filters parameter to narrow down the summaries further.",
|
|
18
|
+
purpose: "Retrieve all the information required on a specified error to understand who it is affecting and why.",
|
|
19
|
+
useCases: [
|
|
20
|
+
"Investigate a specific error found through the List Project Errors tool",
|
|
21
|
+
"Understand which types of user are affected by the error using summarized event data",
|
|
22
|
+
"Get error details for debugging and root cause analysis",
|
|
23
|
+
"Retrieve error metadata for incident reports and documentation"
|
|
24
|
+
],
|
|
25
|
+
inputSchema,
|
|
26
|
+
outputDescription: "JSON object containing: - error_details: Aggregated data about the error, including first and last seen occurrence - latest_event: Detailed information about the most recent occurrence of the error, including stacktrace, breadcrumbs, user and context - pivots: List of pivots (summaries) for the error, which can be used to analyze patterns in occurrences - url: A link to the error in the dashboard - this should be shown to the user for them to perform further analysis",
|
|
27
|
+
examples: [
|
|
28
|
+
{
|
|
29
|
+
description: "Get details for a specific error",
|
|
30
|
+
parameters: {
|
|
31
|
+
errorId: "6863e2af8c857c0a5023b411"
|
|
32
|
+
},
|
|
33
|
+
expectedOutput: "JSON object with error details including message, stack trace, occurrence count, and metadata"
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
hints: [
|
|
37
|
+
"Error IDs can be found using the List Project Errors tool",
|
|
38
|
+
"Use this after filtering errors to get detailed information about specific errors",
|
|
39
|
+
"Use Get Event Details tool if you need detailed information about a specific event (occurrence) rather than the aggregated error",
|
|
40
|
+
"If you used a filter to get this error, you can pass the same filters here to restrict the results or apply further filters",
|
|
41
|
+
"The URL provided in the response points should be shown to the user in all cases as it allows them to view the error in the dashboard and perform further analysis"
|
|
42
|
+
]
|
|
43
|
+
};
|
|
44
|
+
handle = async (args, _extra) => {
|
|
45
|
+
const params = inputSchema.parse(args);
|
|
46
|
+
const project = await this.client.getInputProject(params.projectId);
|
|
47
|
+
const errorDetails = (await this.client.errorsApi.viewErrorOnProject(project.id, params.errorId)).body;
|
|
48
|
+
if (!errorDetails) {
|
|
49
|
+
throw new ToolError(
|
|
50
|
+
`Error with ID ${params.errorId} not found in project ${project.id}.`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
const filters = {
|
|
54
|
+
error: [{ type: "eq", value: params.errorId }],
|
|
55
|
+
...params.filters
|
|
56
|
+
};
|
|
57
|
+
await this.client.validateEventFields(project, filters);
|
|
58
|
+
let latestEvent = null;
|
|
59
|
+
try {
|
|
60
|
+
const latestEvents = (await this.client.errorsApi.listEventsOnProject(
|
|
61
|
+
project.id,
|
|
62
|
+
null,
|
|
63
|
+
"timestamp",
|
|
64
|
+
"desc",
|
|
65
|
+
1,
|
|
66
|
+
filters,
|
|
67
|
+
true
|
|
68
|
+
)).body;
|
|
69
|
+
if (latestEvents && latestEvents.length > 0) {
|
|
70
|
+
latestEvent = latestEvents[0];
|
|
71
|
+
latestEvent.threads = void 0;
|
|
72
|
+
}
|
|
73
|
+
} catch (e) {
|
|
74
|
+
console.warn("Failed to fetch latest event:", e);
|
|
75
|
+
}
|
|
76
|
+
const content = {
|
|
77
|
+
error_details: errorDetails,
|
|
78
|
+
latest_event: latestEvent,
|
|
79
|
+
pivots: (await this.client.errorsApi.getPivotValuesOnAnError(
|
|
80
|
+
project.id,
|
|
81
|
+
params.errorId,
|
|
82
|
+
filters,
|
|
83
|
+
5
|
|
84
|
+
)).body || [],
|
|
85
|
+
url: await this.client.getErrorUrl(
|
|
86
|
+
project,
|
|
87
|
+
params.errorId,
|
|
88
|
+
toUrlSearchParams(filters).toString()
|
|
89
|
+
)
|
|
90
|
+
};
|
|
91
|
+
return {
|
|
92
|
+
content: [{ type: "text", text: JSON.stringify(content) }]
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export {
|
|
97
|
+
GetError
|
|
98
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Tool } from "../../../common/tools.js";
|
|
3
|
+
import { toolInputParameters } from "../../input-schemas.js";
|
|
4
|
+
const inputSchema = z.object({
|
|
5
|
+
projectId: toolInputParameters.projectId,
|
|
6
|
+
filters: toolInputParameters.filters.describe(
|
|
7
|
+
"Apply filters to narrow down the error list. Use the List Project Event Filters tool to discover available filter fields. Time filters support extended ISO 8601 format (e.g. 2018-05-20T00:00:00Z) or relative format (e.g. 7d, 24h)."
|
|
8
|
+
),
|
|
9
|
+
sort: toolInputParameters.sort,
|
|
10
|
+
direction: toolInputParameters.direction,
|
|
11
|
+
perPage: toolInputParameters.perPage,
|
|
12
|
+
nextUrl: toolInputParameters.nextUrl
|
|
13
|
+
});
|
|
14
|
+
class ListProjectErrors extends Tool {
|
|
15
|
+
specification = {
|
|
16
|
+
title: "List Project Errors",
|
|
17
|
+
summary: "List and search errors in a project using customizable filters and pagination",
|
|
18
|
+
purpose: "Retrieve filtered list of errors from a project for analysis, debugging, and reporting",
|
|
19
|
+
useCases: [
|
|
20
|
+
"Debug recent application errors by filtering for open errors in the last 7 days",
|
|
21
|
+
"Generate error reports for stakeholders by filtering specific error types or severity levels",
|
|
22
|
+
"Monitor error trends over time using date range filters",
|
|
23
|
+
"Find errors affecting specific users or environments using metadata filters"
|
|
24
|
+
],
|
|
25
|
+
inputSchema,
|
|
26
|
+
examples: [
|
|
27
|
+
{
|
|
28
|
+
description: "Find errors affecting a specific user in the last 24 hours",
|
|
29
|
+
parameters: {
|
|
30
|
+
filters: {
|
|
31
|
+
"user.email": [{ type: "eq", value: "user@example.com" }],
|
|
32
|
+
"event.since": [{ type: "eq", value: "24h" }]
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
expectedOutput: "JSON object with a list of errors in the 'data' field, a count of the current page of results in the 'count' field, and a total count of all results in the 'total' field"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
description: "Get the 10 open errors with the most users affected in the last 30 days",
|
|
39
|
+
parameters: {
|
|
40
|
+
filters: {
|
|
41
|
+
"event.since": [{ type: "eq", value: "30d" }],
|
|
42
|
+
"error.status": [{ type: "eq", value: "open" }]
|
|
43
|
+
},
|
|
44
|
+
sort: "users",
|
|
45
|
+
direction: "desc",
|
|
46
|
+
perPage: 10
|
|
47
|
+
},
|
|
48
|
+
expectedOutput: "JSON object with a list of errors in the 'data' field, a count of the current page of results in the 'count' field, and a total count of all results in the 'total' field"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
description: "Get the next 50 results",
|
|
52
|
+
parameters: {
|
|
53
|
+
nextUrl: "https://api.bugsnag.com/projects/515fb9337c1074f6fd000003/errors?base=2025-08-29T13%3A11%3A37Z&direction=desc&filters%5Berror.status%5D%5B%5D%5Btype%5D=eq&filters%5Berror.status%5D%5B%5D%5Bvalue%5D=open&offset=10&per_page=10&sort=users",
|
|
54
|
+
perPage: 50
|
|
55
|
+
},
|
|
56
|
+
expectedOutput: "JSON object with a list of errors, with a URL to the next page if more results are available and a total count of all errors matched"
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
hints: [
|
|
60
|
+
"Use List Project Event Filters tool first to discover valid filter field names for your project",
|
|
61
|
+
"Combine multiple filters to narrow results - filters are applied with AND logic",
|
|
62
|
+
"For time filters: use relative format (7d, 24h) for recent periods or ISO 8601 UTC format (2018-05-20T00:00:00Z) for specific dates",
|
|
63
|
+
"Common time filters: event.since (from this time), event.before (until this time)",
|
|
64
|
+
"The 'event.since' filter and 'error.status' filters are always applied and if not specified are set to '30d' and 'open' respectively",
|
|
65
|
+
"There may not be any errors matching the filters - this is not a problem with the tool, in fact it might be a good thing that the user's application had no errors",
|
|
66
|
+
"This tool returns paged results. The 'page_error_count' field indicates the number of results returned in the current page, and the 'total_error_count' field indicates the total number of results across all pages.",
|
|
67
|
+
"If the output contains a 'next_url' value, there are more results available - call this tool again supplying the next URL as a parameter to retrieve the next page.",
|
|
68
|
+
"Do not modify the next URL as this can cause incorrect results. The only other parameter that can be used with 'next' is 'per_page' to control the page size."
|
|
69
|
+
]
|
|
70
|
+
};
|
|
71
|
+
handle = async (args, _extra) => {
|
|
72
|
+
const params = inputSchema.parse(args);
|
|
73
|
+
const project = await this.client.getInputProject(params.projectId);
|
|
74
|
+
const filters = {
|
|
75
|
+
"event.since": [{ type: "eq", value: "30d" }],
|
|
76
|
+
"error.status": [{ type: "eq", value: "open" }],
|
|
77
|
+
...params.filters
|
|
78
|
+
};
|
|
79
|
+
await this.client.validateEventFields(project, filters);
|
|
80
|
+
const response = await this.client.errorsApi.listProjectErrors(
|
|
81
|
+
project.id,
|
|
82
|
+
null,
|
|
83
|
+
params.sort,
|
|
84
|
+
params.direction,
|
|
85
|
+
params.perPage,
|
|
86
|
+
filters,
|
|
87
|
+
params.nextUrl
|
|
88
|
+
);
|
|
89
|
+
const result = {
|
|
90
|
+
data: response.body,
|
|
91
|
+
next_url: response.nextUrl ?? void 0,
|
|
92
|
+
data_count: response.body?.length,
|
|
93
|
+
total_count: response.totalCount ?? void 0
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
content: [{ type: "text", text: JSON.stringify(result) }]
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
export {
|
|
101
|
+
ListProjectErrors
|
|
102
|
+
};
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Tool, ToolError } from "../../../common/tools.js";
|
|
3
|
+
import { ErrorUpdateRequest } from "../../client/api/api.js";
|
|
4
|
+
import { toolInputParameters } from "../../input-schemas.js";
|
|
5
|
+
const PERMITTED_UPDATE_OPERATIONS = [
|
|
6
|
+
"override_severity",
|
|
7
|
+
"open",
|
|
8
|
+
"fix",
|
|
9
|
+
"ignore",
|
|
10
|
+
"discard",
|
|
11
|
+
"undiscard",
|
|
12
|
+
"snooze",
|
|
13
|
+
"link_issue",
|
|
14
|
+
"unlink_issue"
|
|
15
|
+
];
|
|
16
|
+
const PERMITTED_REOPEN_CONDITIONS = [
|
|
17
|
+
"occurs_after",
|
|
18
|
+
"n_occurrences_in_m_hours",
|
|
19
|
+
"n_additional_occurrences",
|
|
20
|
+
"n_additional_users"
|
|
21
|
+
];
|
|
22
|
+
const inputSchema = z.object({
|
|
23
|
+
projectId: toolInputParameters.projectId,
|
|
24
|
+
errorId: toolInputParameters.errorId,
|
|
25
|
+
operation: z.enum(PERMITTED_UPDATE_OPERATIONS).describe("The operation to apply to the error"),
|
|
26
|
+
issue_url: z.string().optional().describe(
|
|
27
|
+
"The URL of the issue to link to the error - required when operation is 'link_issue'"
|
|
28
|
+
),
|
|
29
|
+
reopenRules: z.object({
|
|
30
|
+
reopenIf: z.enum(PERMITTED_REOPEN_CONDITIONS).describe("Condition for when the error should be reopened"),
|
|
31
|
+
additionalUsers: z.number().min(1).max(1e5).optional().describe(
|
|
32
|
+
"for n_additional_users reopen rules, the number of additional users to be affected by an Error before the Error is automatically reopened."
|
|
33
|
+
),
|
|
34
|
+
seconds: z.number().min(1).optional().describe(
|
|
35
|
+
"for occurs_after reopen rules, the number of seconds that the Error should be snoozed for."
|
|
36
|
+
),
|
|
37
|
+
occurrences: z.number().min(1).optional().describe(
|
|
38
|
+
"for n_occurrences_in_m_hours reopen rules, the number of occurrences to allow in the number of hours indicated by the hours field, before the Error is automatically reopened."
|
|
39
|
+
),
|
|
40
|
+
hours: z.number().min(1).optional().describe(
|
|
41
|
+
"for n_occurrences_in_m_hours reopen rules, the number of hours."
|
|
42
|
+
),
|
|
43
|
+
additionalOccurrences: z.number().min(1).optional().describe(
|
|
44
|
+
"or n_additional_occurrences reopen rules, the number of additional occurrences allowed before reopening."
|
|
45
|
+
)
|
|
46
|
+
}).optional().describe(
|
|
47
|
+
"Reopen rules for snooze operation - required when operation is 'snooze'"
|
|
48
|
+
)
|
|
49
|
+
});
|
|
50
|
+
class UpdateError extends Tool {
|
|
51
|
+
getInput;
|
|
52
|
+
specification = {
|
|
53
|
+
title: "Update Error",
|
|
54
|
+
summary: "Update the status of an error",
|
|
55
|
+
purpose: "Change an error's workflow state, such as marking it as resolved or ignored",
|
|
56
|
+
useCases: [
|
|
57
|
+
"Mark an error as open, fixed or ignored",
|
|
58
|
+
"Discard or un-discard an error",
|
|
59
|
+
"Update the severity of an error",
|
|
60
|
+
"Snooze an error with defined conditions for when it should be reopened"
|
|
61
|
+
],
|
|
62
|
+
inputSchema,
|
|
63
|
+
examples: [
|
|
64
|
+
{
|
|
65
|
+
description: "Mark an error as fixed",
|
|
66
|
+
parameters: {
|
|
67
|
+
errorId: "6863e2af8c857c0a5023b411",
|
|
68
|
+
operation: "fix"
|
|
69
|
+
},
|
|
70
|
+
expectedOutput: "Success response indicating the error was marked as fixed"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
description: "Snooze an error for 1 hour",
|
|
74
|
+
parameters: {
|
|
75
|
+
errorId: "6863e2af8c857c0a5023b411",
|
|
76
|
+
operation: "snooze",
|
|
77
|
+
reopenRules: {
|
|
78
|
+
reopenIf: "occurs_after",
|
|
79
|
+
seconds: 3600
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
expectedOutput: "Success response indicating the error was snoozed for 1 hour"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
description: "Snooze an error until 5 additional users are affected",
|
|
86
|
+
parameters: {
|
|
87
|
+
errorId: "6863e2af8c857c0a5023b411",
|
|
88
|
+
operation: "snooze",
|
|
89
|
+
reopenRules: {
|
|
90
|
+
reopenIf: "n_additional_users",
|
|
91
|
+
additionalUsers: 5
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
expectedOutput: "Success response indicating the error was snoozed until 5 additional users are affected"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
description: "Snooze an error until 10 occurrences in 24 hours",
|
|
98
|
+
parameters: {
|
|
99
|
+
errorId: "6863e2af8c857c0a5023b411",
|
|
100
|
+
operation: "snooze",
|
|
101
|
+
reopenRules: {
|
|
102
|
+
reopenIf: "n_occurrences_in_m_hours",
|
|
103
|
+
occurrences: 10,
|
|
104
|
+
hours: 24
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
expectedOutput: "Success response indicating the error was snoozed until 10 occurrences in 24 hours"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
description: "Link a Jira issue to an error",
|
|
111
|
+
parameters: {
|
|
112
|
+
errorId: "6863e2af8c857c0a5023b411",
|
|
113
|
+
operation: "link_issue",
|
|
114
|
+
issue_url: "https://smartbear.atlassian.net/browse/PIPE-9547"
|
|
115
|
+
},
|
|
116
|
+
expectedOutput: "Success response indicating the Jira issue was linked to the error"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
description: "Unlink a Jira issue from an error",
|
|
120
|
+
parameters: {
|
|
121
|
+
errorId: "6863e2af8c857c0a5023b411",
|
|
122
|
+
operation: "unlink_issue"
|
|
123
|
+
},
|
|
124
|
+
expectedOutput: "Success response indicating the Jira issue was unlinked from the error"
|
|
125
|
+
}
|
|
126
|
+
],
|
|
127
|
+
hints: [
|
|
128
|
+
"Only use valid operations - BugSnag may reject invalid values",
|
|
129
|
+
"When using 'snooze' operation, reopenRules parameter is required",
|
|
130
|
+
"When using 'link_issue' operation, issue_url parameter is required",
|
|
131
|
+
"Use 'unlink_issue' to remove the link between an error and its issue",
|
|
132
|
+
"For 'occurs_after' reopen rules, specify 'seconds' parameter",
|
|
133
|
+
"For 'n_additional_users' reopen rules, specify 'additionalUsers' parameter (max 100,000)",
|
|
134
|
+
"For 'n_occurrences_in_m_hours' reopen rules, specify both 'occurrences' and 'hours' parameters",
|
|
135
|
+
"For 'n_additional_occurrences' reopen rules, specify 'additionalOccurrences' parameter",
|
|
136
|
+
"Snoozing temporarily silences an error until the specified reopen condition is met"
|
|
137
|
+
],
|
|
138
|
+
readOnly: false,
|
|
139
|
+
idempotent: false
|
|
140
|
+
};
|
|
141
|
+
constructor(client, getInput) {
|
|
142
|
+
super(client);
|
|
143
|
+
this.getInput = getInput;
|
|
144
|
+
}
|
|
145
|
+
handle = async (args, _extra) => {
|
|
146
|
+
const params = inputSchema.parse(args);
|
|
147
|
+
const project = await this.client.getInputProject(params.projectId);
|
|
148
|
+
if (params.operation === "snooze" && !params.reopenRules) {
|
|
149
|
+
throw new ToolError(
|
|
150
|
+
"reopenRules parameter is required when using 'snooze' operation"
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
if (params.operation === "link_issue" && !params.issue_url) {
|
|
154
|
+
throw new ToolError(
|
|
155
|
+
"'issue_url' parameter is required for 'link_issue' operation"
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
if (params.reopenRules) {
|
|
159
|
+
const { reopenIf } = params.reopenRules;
|
|
160
|
+
if (reopenIf === "occurs_after" && !params.reopenRules.seconds) {
|
|
161
|
+
throw new ToolError(
|
|
162
|
+
"'seconds' parameter is required for 'occurs_after' reopen rules"
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
if (reopenIf === "n_additional_users" && !params.reopenRules.additionalUsers) {
|
|
166
|
+
throw new ToolError(
|
|
167
|
+
"'additionalUsers' parameter is required for 'n_additional_users' reopen rules"
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
if (reopenIf === "n_occurrences_in_m_hours" && (!params.reopenRules.occurrences || !params.reopenRules.hours)) {
|
|
171
|
+
throw new ToolError(
|
|
172
|
+
"Both 'occurrences' and 'hours' parameters are required for 'n_occurrences_in_m_hours' reopen rules"
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
if (reopenIf === "n_additional_occurrences" && !params.reopenRules.additionalOccurrences) {
|
|
176
|
+
throw new ToolError(
|
|
177
|
+
"'additionalOccurrences' parameter is required for 'n_additional_occurrences' reopen rules"
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
let severity;
|
|
182
|
+
if (params.operation === "override_severity") {
|
|
183
|
+
const result2 = await this.getInput({
|
|
184
|
+
message: "Please provide the new severity for the error (e.g. 'info', 'warning', 'error', 'critical')",
|
|
185
|
+
requestedSchema: {
|
|
186
|
+
type: "object",
|
|
187
|
+
properties: {
|
|
188
|
+
severity: {
|
|
189
|
+
type: "string",
|
|
190
|
+
enum: ["info", "warning", "error"],
|
|
191
|
+
description: "The new severity level for the error"
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
required: ["severity"]
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
if (result2.action === "accept" && result2.content?.severity) {
|
|
198
|
+
severity = result2.content.severity;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
let reopenRules;
|
|
202
|
+
if (params.reopenRules) {
|
|
203
|
+
reopenRules = {
|
|
204
|
+
reopen_if: params.reopenRules.reopenIf
|
|
205
|
+
};
|
|
206
|
+
if (params.reopenRules.additionalUsers !== void 0) {
|
|
207
|
+
reopenRules.additional_users = params.reopenRules.additionalUsers;
|
|
208
|
+
}
|
|
209
|
+
if (params.reopenRules.seconds !== void 0) {
|
|
210
|
+
reopenRules.seconds = params.reopenRules.seconds;
|
|
211
|
+
}
|
|
212
|
+
if (params.reopenRules.occurrences !== void 0) {
|
|
213
|
+
reopenRules.occurrences = params.reopenRules.occurrences;
|
|
214
|
+
}
|
|
215
|
+
if (params.reopenRules.hours !== void 0) {
|
|
216
|
+
reopenRules.hours = params.reopenRules.hours;
|
|
217
|
+
}
|
|
218
|
+
if (params.reopenRules.additionalOccurrences !== void 0) {
|
|
219
|
+
reopenRules.additional_occurrences = params.reopenRules.additionalOccurrences;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const errorUpdateRequestBody = {
|
|
223
|
+
operation: Object.values(ErrorUpdateRequest.OperationEnum).find(
|
|
224
|
+
(value) => value === params.operation
|
|
225
|
+
)
|
|
226
|
+
};
|
|
227
|
+
if (severity !== void 0) {
|
|
228
|
+
errorUpdateRequestBody.severity = severity;
|
|
229
|
+
}
|
|
230
|
+
if (reopenRules !== void 0) {
|
|
231
|
+
errorUpdateRequestBody.reopen_rules = reopenRules;
|
|
232
|
+
}
|
|
233
|
+
if (params.operation === "link_issue" && params.issue_url) {
|
|
234
|
+
errorUpdateRequestBody.issue_url = params.issue_url;
|
|
235
|
+
errorUpdateRequestBody.verify_issue_url = true;
|
|
236
|
+
}
|
|
237
|
+
const result = await this.client.errorsApi.updateErrorOnProject(
|
|
238
|
+
project.id,
|
|
239
|
+
params.errorId,
|
|
240
|
+
errorUpdateRequestBody
|
|
241
|
+
);
|
|
242
|
+
return {
|
|
243
|
+
content: [
|
|
244
|
+
{
|
|
245
|
+
type: "text",
|
|
246
|
+
text: JSON.stringify({
|
|
247
|
+
success: result.status === 200 || result.status === 204
|
|
248
|
+
})
|
|
249
|
+
}
|
|
250
|
+
]
|
|
251
|
+
};
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
export {
|
|
255
|
+
UpdateError
|
|
256
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Tool, ToolError } from "../../../common/tools.js";
|
|
3
|
+
const inputSchema = z.object({
|
|
4
|
+
link: z.string().describe(
|
|
5
|
+
"Full URL to the event details page in the BugSnag dashboard (web interface), containing project slug and event_id parameter."
|
|
6
|
+
)
|
|
7
|
+
});
|
|
8
|
+
class GetEventDetailsFromDashboardUrl extends Tool {
|
|
9
|
+
specification = {
|
|
10
|
+
title: "Get Event Details From Dashboard URL",
|
|
11
|
+
summary: "Get detailed information about a specific event using its dashboard URL",
|
|
12
|
+
purpose: "Retrieve event details directly from a dashboard URL for quick debugging",
|
|
13
|
+
useCases: [
|
|
14
|
+
"Get event details when given a dashboard URL from a user or notification",
|
|
15
|
+
"Extract event information from shared links or browser URLs",
|
|
16
|
+
"Quick lookup of event details without needing separate project and event IDs"
|
|
17
|
+
],
|
|
18
|
+
inputSchema,
|
|
19
|
+
examples: [
|
|
20
|
+
{
|
|
21
|
+
description: "Get event details from a dashboard URL",
|
|
22
|
+
parameters: {
|
|
23
|
+
link: "https://app.bugsnag.com/my-org/my-project/errors/6863e2af8c857c0a5023b411?event_id=6863e2af012caf1d5c320000"
|
|
24
|
+
},
|
|
25
|
+
expectedOutput: "JSON object with complete event details including stack trace, metadata, and context"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
hints: [
|
|
29
|
+
"The URL must contain both project slug in the path and event_id in query parameters",
|
|
30
|
+
"This is useful when users share BugSnag dashboard URLs and you need to extract the event data"
|
|
31
|
+
]
|
|
32
|
+
};
|
|
33
|
+
handle = async (args, _extra) => {
|
|
34
|
+
const params = inputSchema.parse(args);
|
|
35
|
+
const url = new URL(params.link);
|
|
36
|
+
const eventId = url.searchParams.get("event_id");
|
|
37
|
+
const projectSlug = url.pathname.split("/")[2];
|
|
38
|
+
if (!projectSlug || !eventId)
|
|
39
|
+
throw new ToolError(
|
|
40
|
+
"Both projectSlug and eventId must be present in the link"
|
|
41
|
+
);
|
|
42
|
+
const projects = await this.client.getProjects();
|
|
43
|
+
const projectId = projects.find((p) => p.slug === projectSlug)?.id;
|
|
44
|
+
if (!projectId) {
|
|
45
|
+
throw new ToolError("Project with the specified slug not found.");
|
|
46
|
+
}
|
|
47
|
+
const response = await this.client.getEvent(eventId, projectId);
|
|
48
|
+
return {
|
|
49
|
+
content: [{ type: "text", text: JSON.stringify(response) }]
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
GetEventDetailsFromDashboardUrl
|
|
55
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Tool } from "../../../common/tools.js";
|
|
3
|
+
import { toolInputParameters } from "../../input-schemas.js";
|
|
4
|
+
const inputSchema = z.object({
|
|
5
|
+
projectId: toolInputParameters.projectId,
|
|
6
|
+
eventId: toolInputParameters.eventId
|
|
7
|
+
});
|
|
8
|
+
class GetEvent extends Tool {
|
|
9
|
+
specification = {
|
|
10
|
+
title: "Get Event",
|
|
11
|
+
summary: "Get detailed information about a specific event",
|
|
12
|
+
purpose: "Retrieve event details directly from its ID",
|
|
13
|
+
useCases: [
|
|
14
|
+
"Get the full details of an event, including any thread stack traces"
|
|
15
|
+
],
|
|
16
|
+
inputSchema,
|
|
17
|
+
examples: [
|
|
18
|
+
{
|
|
19
|
+
description: "Get event details of an event",
|
|
20
|
+
parameters: {
|
|
21
|
+
eventId: "6863e2af012caf1d5c320000"
|
|
22
|
+
},
|
|
23
|
+
expectedOutput: "JSON object with complete event details including stack trace (error trace and other threads, if present), metadata, and context"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
};
|
|
27
|
+
handle = async (args, _extra) => {
|
|
28
|
+
const params = inputSchema.parse(args);
|
|
29
|
+
const project = await this.client.getInputProject(params.projectId);
|
|
30
|
+
const response = await this.client.getEvent(params.eventId, project.id);
|
|
31
|
+
return {
|
|
32
|
+
content: [{ type: "text", text: JSON.stringify(response) }]
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
GetEvent
|
|
38
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Tool } from "../../../common/tools.js";
|
|
3
|
+
import { toolInputParameters } from "../../input-schemas.js";
|
|
4
|
+
const inputSchema = z.object({
|
|
5
|
+
projectId: toolInputParameters.projectId
|
|
6
|
+
});
|
|
7
|
+
class GetNetworkEndpointGroupings extends Tool {
|
|
8
|
+
specification = {
|
|
9
|
+
title: "Get Network Endpoint Groupings",
|
|
10
|
+
summary: "Get the network endpoint grouping rules for a project",
|
|
11
|
+
purpose: "Retrieve the URL patterns used to group network spans for performance monitoring",
|
|
12
|
+
useCases: [
|
|
13
|
+
"View current network endpoint grouping configuration",
|
|
14
|
+
"Understand how network requests are being grouped in performance monitoring",
|
|
15
|
+
"Check grouping patterns before making updates"
|
|
16
|
+
],
|
|
17
|
+
inputSchema,
|
|
18
|
+
examples: [
|
|
19
|
+
{
|
|
20
|
+
description: "Get network grouping rules for a project",
|
|
21
|
+
parameters: {},
|
|
22
|
+
expectedOutput: "Array of endpoint URL patterns"
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
hints: [
|
|
26
|
+
"Network grouping patterns help consolidate similar requests into single span groups",
|
|
27
|
+
"Patterns use OpenAPI path templating syntax with curly braces for path parameters (e.g., /users/{userId})",
|
|
28
|
+
"Wildcards (*) can be used in domains to match multiple subdomains (e.g., https://*.example.com)"
|
|
29
|
+
],
|
|
30
|
+
readOnly: true,
|
|
31
|
+
idempotent: true
|
|
32
|
+
};
|
|
33
|
+
handle = async (args, _extra) => {
|
|
34
|
+
const params = inputSchema.parse(args);
|
|
35
|
+
const project = await this.client.getInputProject(params.projectId);
|
|
36
|
+
const result = await this.client.projectApi.getProjectNetworkGroupingRuleset(project.id);
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{ type: "text", text: JSON.stringify(result.body.endpoints || []) }
|
|
40
|
+
]
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
GetNetworkEndpointGroupings
|
|
46
|
+
};
|