@smartbear/mcp 0.24.0 → 0.25.1
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/dist/bearq/tool/tasks/chat-with-qa-lead.js +1 -0
- package/dist/bearq/tool/tasks/expand-application-model.js +1 -0
- package/dist/bearq/tool/tasks/get-task-status.js +1 -0
- package/dist/bearq/tool/tasks/get-task.js +1 -0
- package/dist/bearq/tool/tasks/refine-all-draft-tests.js +1 -0
- package/dist/bearq/tool/tasks/refine-test-cases.js +1 -0
- package/dist/bearq/tool/tasks/refine-tests-in-functional-areas.js +1 -0
- package/dist/bearq/tool/tasks/run-regression-tests.js +1 -0
- package/dist/bearq/tool/tasks/run-test-cases.js +1 -0
- package/dist/bearq/tool/tasks/run-tests-in-functional-areas.js +1 -0
- package/dist/bearq/tool/tasks/stop-task.js +1 -0
- package/dist/bearq/tool/tasks/wait-for-task.js +1 -0
- package/dist/bugsnag/client.js +1 -0
- package/dist/bugsnag/tool/error/get-error.js +1 -0
- package/dist/bugsnag/tool/error/list-project-errors.js +1 -0
- package/dist/bugsnag/tool/error/update-error.js +1 -0
- package/dist/bugsnag/tool/event/get-event-details-from-dashboard-url.js +1 -0
- package/dist/bugsnag/tool/event/get-event.js +1 -0
- package/dist/bugsnag/tool/event/list-error-events.js +1 -0
- package/dist/bugsnag/tool/performance/get-network-endpoint-groupings.js +1 -0
- package/dist/bugsnag/tool/performance/get-span-group.js +1 -0
- package/dist/bugsnag/tool/performance/get-trace.js +1 -0
- package/dist/bugsnag/tool/performance/list-span-groups.js +1 -0
- package/dist/bugsnag/tool/performance/list-spans.js +1 -0
- package/dist/bugsnag/tool/performance/list-trace-fields.js +1 -0
- package/dist/bugsnag/tool/performance/set-network-endpoint-groupings.js +1 -0
- package/dist/bugsnag/tool/project/get-current-project.js +1 -0
- package/dist/bugsnag/tool/project/list-project-event-filters.js +1 -0
- package/dist/bugsnag/tool/project/list-projects.js +1 -0
- package/dist/bugsnag/tool/release/get-build.js +1 -0
- package/dist/bugsnag/tool/release/get-release.js +1 -0
- package/dist/bugsnag/tool/release/list-releases.js +1 -0
- package/dist/collaborator/client.js +10 -0
- package/dist/common/client-registry.js +17 -9
- package/dist/common/server.js +44 -1
- package/dist/common/transport-http.js +24 -20
- package/dist/common/transport-stdio.js +7 -5
- package/dist/package.json.js +1 -1
- package/dist/pactflow/client/tools.js +102 -0
- package/dist/qmetry/client/tools/automation-tools.js +2 -0
- package/dist/qmetry/client/tools/issue-tools.js +6 -0
- package/dist/qmetry/client/tools/project-tools.js +9 -0
- package/dist/qmetry/client/tools/requirement-tools.js +5 -0
- package/dist/qmetry/client/tools/testcase-tools.js +7 -0
- package/dist/qmetry/client/tools/testsuite-tools.js +11 -0
- package/dist/qtm4j/client.js +25 -1
- package/dist/qtm4j/config/constants.js +101 -1
- package/dist/qtm4j/config/field-resolution.types.js +3 -1
- package/dist/qtm4j/http/api-client.js +20 -2
- package/dist/qtm4j/resolver/resolver-registry.js +7 -1
- package/dist/qtm4j/resolver/resolvers/requirement-id-resolver.js +28 -0
- package/dist/qtm4j/resolver/resolvers/test-cycle-uid-resolver.js +28 -0
- package/dist/qtm4j/schema/linked-items.schema.js +95 -0
- package/dist/qtm4j/schema/requirements.schema.js +109 -0
- package/dist/qtm4j/schema/test-cycle.link.schema.js +260 -0
- package/dist/qtm4j/tool/project/get-projects.js +2 -1
- package/dist/qtm4j/tool/project/set-project-context.js +2 -1
- package/dist/qtm4j/tool/requirement/get-linked-testcases.js +93 -0
- package/dist/qtm4j/tool/requirement/link-testcases.js +107 -0
- package/dist/qtm4j/tool/requirement/unlink-testcases.js +97 -0
- package/dist/qtm4j/tool/test-automation/get-automation-history.js +2 -1
- package/dist/qtm4j/tool/test-automation/upload-automation-result.js +2 -1
- package/dist/qtm4j/tool/test-case/create-test-case.js +2 -1
- package/dist/qtm4j/tool/test-case/get-linked-requirements.js +67 -0
- package/dist/qtm4j/tool/test-case/get-test-cases.js +2 -1
- package/dist/qtm4j/tool/test-case/get-test-steps.js +2 -1
- package/dist/qtm4j/tool/test-case/link-requirements.js +124 -0
- package/dist/qtm4j/tool/test-case/unlink-requirements.js +116 -0
- package/dist/qtm4j/tool/test-case/update-test-case.js +2 -1
- package/dist/qtm4j/tool/test-cycle/create-test-cycle.js +2 -1
- package/dist/qtm4j/tool/test-cycle/get-linked-requirements.js +71 -0
- package/dist/qtm4j/tool/test-cycle/link-requirements.js +91 -0
- package/dist/qtm4j/tool/test-cycle/link-testcases.js +118 -0
- package/dist/qtm4j/tool/test-cycle/search-linked-testcases.js +114 -0
- package/dist/qtm4j/tool/test-cycle/search-test-cycle.js +2 -1
- package/dist/qtm4j/tool/test-cycle/unlink-requirements.js +87 -0
- package/dist/qtm4j/tool/test-cycle/unlink-testcases.js +103 -0
- package/dist/qtm4j/tool/test-cycle/update-test-cycle.js +2 -1
- package/dist/reflect/tool/recording/add-prompt-step.js +1 -0
- package/dist/reflect/tool/recording/add-segment.js +1 -0
- package/dist/reflect/tool/recording/connect-to-session.js +1 -0
- package/dist/reflect/tool/recording/delete-previous-step.js +1 -0
- package/dist/reflect/tool/recording/get-screenshot.js +1 -0
- package/dist/reflect/tool/suites/cancel-suite-execution.js +1 -0
- package/dist/reflect/tool/suites/execute-suite.js +1 -0
- package/dist/reflect/tool/suites/get-suite-execution-status.js +1 -0
- package/dist/reflect/tool/suites/list-suite-executions.js +1 -0
- package/dist/reflect/tool/suites/list-suites.js +1 -0
- package/dist/reflect/tool/tests/get-test-status.js +1 -0
- package/dist/reflect/tool/tests/list-segments.js +1 -0
- package/dist/reflect/tool/tests/list-tests.js +1 -0
- package/dist/reflect/tool/tests/run-test.js +1 -0
- package/dist/swagger/client/tools.js +23 -0
- package/dist/zephyr/tool/environment/get-environments.js +1 -0
- package/dist/zephyr/tool/folder/create-folder.js +1 -0
- package/dist/zephyr/tool/issue-link/get-test-cases.js +1 -0
- package/dist/zephyr/tool/issue-link/get-test-cycles.js +1 -0
- package/dist/zephyr/tool/issue-link/get-test-executions.js +1 -0
- package/dist/zephyr/tool/priority/get-priorities.js +1 -0
- package/dist/zephyr/tool/project/get-project.js +1 -0
- package/dist/zephyr/tool/project/get-projects.js +1 -0
- package/dist/zephyr/tool/status/get-statuses.js +1 -0
- package/dist/zephyr/tool/test-case/create-issue-link.js +1 -0
- package/dist/zephyr/tool/test-case/create-test-case.js +1 -0
- package/dist/zephyr/tool/test-case/create-test-script.js +1 -0
- package/dist/zephyr/tool/test-case/create-test-steps.js +1 -0
- package/dist/zephyr/tool/test-case/create-web-link.js +1 -0
- package/dist/zephyr/tool/test-case/get-links.js +1 -0
- package/dist/zephyr/tool/test-case/get-test-case.js +1 -0
- package/dist/zephyr/tool/test-case/get-test-cases.js +1 -0
- package/dist/zephyr/tool/test-case/get-test-script.js +1 -0
- package/dist/zephyr/tool/test-case/get-test-steps.js +1 -0
- package/dist/zephyr/tool/test-case/update-test-case.js +1 -0
- package/dist/zephyr/tool/test-cycle/create-issue-link.js +1 -0
- package/dist/zephyr/tool/test-cycle/create-test-cycle.js +1 -0
- package/dist/zephyr/tool/test-cycle/create-web-link.js +1 -0
- package/dist/zephyr/tool/test-cycle/get-links.js +1 -0
- package/dist/zephyr/tool/test-cycle/get-test-cycle.js +1 -0
- package/dist/zephyr/tool/test-cycle/get-test-cycles.js +1 -0
- package/dist/zephyr/tool/test-cycle/update-test-cycle.js +1 -0
- package/dist/zephyr/tool/test-execution/create-issue-link.js +1 -0
- package/dist/zephyr/tool/test-execution/create-test-execution.js +1 -0
- package/dist/zephyr/tool/test-execution/get-test-execution-links.js +1 -0
- package/dist/zephyr/tool/test-execution/get-test-execution.js +1 -0
- package/dist/zephyr/tool/test-execution/get-test-executions.js +1 -0
- package/dist/zephyr/tool/test-execution/get-test-steps.js +1 -0
- package/dist/zephyr/tool/test-execution/update-test-execution.js +1 -0
- package/dist/zephyr/tool/test-execution/update-test-steps.js +1 -0
- package/package.json +1 -1
|
@@ -8,6 +8,7 @@ const inputSchema = z.object({
|
|
|
8
8
|
class ChatWithQaLead extends Tool {
|
|
9
9
|
specification = {
|
|
10
10
|
title: "Chat with QA Lead",
|
|
11
|
+
toolset: "Tasks",
|
|
11
12
|
summary: "Sends an open-ended instruction to BearQ's QA lead agent. Use this when no other BearQ tool fits — the QA lead can list, create, and update test cases, manage functional areas, and read the application model, and acts as a general-purpose escape hatch.",
|
|
12
13
|
inputSchema
|
|
13
14
|
};
|
|
@@ -8,6 +8,7 @@ const inputSchema = z.object({
|
|
|
8
8
|
class ExpandApplicationModel extends Tool {
|
|
9
9
|
specification = {
|
|
10
10
|
title: "Expand Application Model",
|
|
11
|
+
toolset: "Tasks",
|
|
11
12
|
summary: "Explores the live application to discover or update its pages and elements in BearQ's application model. Optionally scope to a single functional area.",
|
|
12
13
|
inputSchema
|
|
13
14
|
};
|
|
@@ -6,6 +6,7 @@ const inputSchema = z.object({
|
|
|
6
6
|
class GetTaskStatus extends Tool {
|
|
7
7
|
specification = {
|
|
8
8
|
title: "Get Task Status",
|
|
9
|
+
toolset: "Tasks",
|
|
9
10
|
summary: "Retrieves the status of a task (running / complete / error / cancelled). Cheaper than fetching full task details.",
|
|
10
11
|
inputSchema
|
|
11
12
|
};
|
|
@@ -6,6 +6,7 @@ const inputSchema = z.object({
|
|
|
6
6
|
class GetTask extends Tool {
|
|
7
7
|
specification = {
|
|
8
8
|
title: "Get Task",
|
|
9
|
+
toolset: "Tasks",
|
|
9
10
|
summary: "Retrieves a task's current state, metadata, and activity log. Returns immediately with whatever's available — does not block on the task completing.",
|
|
10
11
|
inputSchema
|
|
11
12
|
};
|
|
@@ -4,6 +4,7 @@ const inputSchema = z.object({});
|
|
|
4
4
|
class RefineAllDraftTests extends Tool {
|
|
5
5
|
specification = {
|
|
6
6
|
title: "Refine All Draft Tests",
|
|
7
|
+
toolset: "Tasks",
|
|
7
8
|
summary: "Refines every draft test case in the workspace. Use to push an entire draft backlog forward; may take multiple passes before all drafts are ready to be promoted to regression tests.",
|
|
8
9
|
inputSchema
|
|
9
10
|
};
|
|
@@ -6,6 +6,7 @@ const inputSchema = z.object({
|
|
|
6
6
|
class RefineTestCases extends Tool {
|
|
7
7
|
specification = {
|
|
8
8
|
title: "Refine Test Cases",
|
|
9
|
+
toolset: "Tasks",
|
|
9
10
|
summary: "Refines specific BearQ draft test cases — improves their steps so they can eventually be promoted to regression tests. Use when a draft is incomplete or has drifted from its intent.",
|
|
10
11
|
inputSchema
|
|
11
12
|
};
|
|
@@ -6,6 +6,7 @@ const inputSchema = z.object({
|
|
|
6
6
|
class RefineTestsInFunctionalAreas extends Tool {
|
|
7
7
|
specification = {
|
|
8
8
|
title: "Refine Tests in Functional Areas",
|
|
9
|
+
toolset: "Tasks",
|
|
9
10
|
summary: "Refines every draft test case tagged with one or more functional areas. Functional areas can be given by ID or name. May take multiple passes before drafts are ready to be promoted to regression tests.",
|
|
10
11
|
inputSchema
|
|
11
12
|
};
|
|
@@ -4,6 +4,7 @@ const inputSchema = z.object({});
|
|
|
4
4
|
class RunRegressionTests extends Tool {
|
|
5
5
|
specification = {
|
|
6
6
|
title: "Run Regression Tests",
|
|
7
|
+
toolset: "Tasks",
|
|
7
8
|
summary: "Runs the full BearQ regression suite — every regression-ready test case in the workspace. Use for CI/CD or pre-release smoke.",
|
|
8
9
|
inputSchema
|
|
9
10
|
};
|
|
@@ -6,6 +6,7 @@ const inputSchema = z.object({
|
|
|
6
6
|
class RunTestCases extends Tool {
|
|
7
7
|
specification = {
|
|
8
8
|
title: "Run Test Cases",
|
|
9
|
+
toolset: "Tasks",
|
|
9
10
|
summary: "Runs specific BearQ regression test cases by ID. Targets only regression-ready cases — drafts will be rejected.",
|
|
10
11
|
inputSchema
|
|
11
12
|
};
|
|
@@ -6,6 +6,7 @@ const inputSchema = z.object({
|
|
|
6
6
|
class RunTestsInFunctionalAreas extends Tool {
|
|
7
7
|
specification = {
|
|
8
8
|
title: "Run Tests in Functional Areas",
|
|
9
|
+
toolset: "Tasks",
|
|
9
10
|
summary: "Runs every regression test case tagged with one or more functional areas. Functional areas can be given by ID or name.",
|
|
10
11
|
inputSchema
|
|
11
12
|
};
|
|
@@ -17,6 +17,7 @@ function parseFrame(frame) {
|
|
|
17
17
|
class WaitForTask extends Tool {
|
|
18
18
|
specification = {
|
|
19
19
|
title: "Wait For Task",
|
|
20
|
+
toolset: "Tasks",
|
|
20
21
|
summary: "Blocks until a BearQ task reaches a terminal state (completed / failed / cancelled) or the stream times out, then returns the full ordered sequence of SSE events from the public API (metadata, activityLogEntries, and a terminal done or timeout event) verbatim. Blocks for the lifetime of the task — for a quick check use bearq_get_task_status instead.",
|
|
21
22
|
inputSchema
|
|
22
23
|
};
|
package/dist/bugsnag/client.js
CHANGED
|
@@ -73,6 +73,7 @@ class BugsnagClient {
|
|
|
73
73
|
capabilityPrefix = "bugsnag";
|
|
74
74
|
configPrefix = "Bugsnag";
|
|
75
75
|
config = ConfigurationSchema;
|
|
76
|
+
defaultToolsets = ["Projects"];
|
|
76
77
|
async configure(server, config) {
|
|
77
78
|
this.cache = server.getCache();
|
|
78
79
|
this._appEndpoint = this.getEndpoint(
|
|
@@ -14,6 +14,7 @@ const inputSchema = z.object({
|
|
|
14
14
|
class GetError extends Tool {
|
|
15
15
|
specification = {
|
|
16
16
|
title: "Get Error",
|
|
17
|
+
toolset: "Errors",
|
|
17
18
|
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
19
|
purpose: "Retrieve all the information required on a specified error to understand who it is affecting and why.",
|
|
19
20
|
useCases: [
|
|
@@ -14,6 +14,7 @@ const inputSchema = z.object({
|
|
|
14
14
|
class ListProjectErrors extends Tool {
|
|
15
15
|
specification = {
|
|
16
16
|
title: "List Project Errors",
|
|
17
|
+
toolset: "Errors",
|
|
17
18
|
summary: "List and search errors in a project using customizable filters and pagination",
|
|
18
19
|
purpose: "Retrieve filtered list of errors from a project for analysis, debugging, and reporting",
|
|
19
20
|
useCases: [
|
|
@@ -51,6 +51,7 @@ class UpdateError extends Tool {
|
|
|
51
51
|
getInput;
|
|
52
52
|
specification = {
|
|
53
53
|
title: "Update Error",
|
|
54
|
+
toolset: "Errors",
|
|
54
55
|
summary: "Update the status of an error",
|
|
55
56
|
purpose: "Change an error's workflow state, such as marking it as resolved or ignored",
|
|
56
57
|
useCases: [
|
|
@@ -8,6 +8,7 @@ const inputSchema = z.object({
|
|
|
8
8
|
class GetEventDetailsFromDashboardUrl extends Tool {
|
|
9
9
|
specification = {
|
|
10
10
|
title: "Get Event Details From Dashboard URL",
|
|
11
|
+
toolset: "Events",
|
|
11
12
|
summary: "Get detailed information about a specific event using its dashboard URL",
|
|
12
13
|
purpose: "Retrieve event details directly from a dashboard URL for quick debugging",
|
|
13
14
|
useCases: [
|
|
@@ -14,6 +14,7 @@ const inputSchema = z.object({
|
|
|
14
14
|
class ListErrorEvents extends Tool {
|
|
15
15
|
specification = {
|
|
16
16
|
title: "Get Events on an Error",
|
|
17
|
+
toolset: "Events",
|
|
17
18
|
summary: "Gets a list of events that have grouped into the specified error",
|
|
18
19
|
purpose: "Show the events that make up an error to see individual occurrences of the error for detailed analysis",
|
|
19
20
|
useCases: [
|
|
@@ -7,6 +7,7 @@ const inputSchema = z.object({
|
|
|
7
7
|
class GetNetworkEndpointGroupings extends Tool {
|
|
8
8
|
specification = {
|
|
9
9
|
title: "Get Network Endpoint Groupings",
|
|
10
|
+
toolset: "Performance",
|
|
10
11
|
summary: "Get the network endpoint grouping rules for a project",
|
|
11
12
|
purpose: "Retrieve the URL patterns used to group network spans for performance monitoring",
|
|
12
13
|
useCases: [
|
|
@@ -9,6 +9,7 @@ const inputSchema = z.object({
|
|
|
9
9
|
class GetSpanGroup extends Tool {
|
|
10
10
|
specification = {
|
|
11
11
|
title: "Get Span Group",
|
|
12
|
+
toolset: "Performance",
|
|
12
13
|
summary: "Get detailed performance metrics for a specific span group",
|
|
13
14
|
purpose: "Analyze performance characteristics of a specific operation",
|
|
14
15
|
useCases: [
|
|
@@ -13,6 +13,7 @@ const inputSchema = z.object({
|
|
|
13
13
|
class GetTrace extends Tool {
|
|
14
14
|
specification = {
|
|
15
15
|
title: "Get Trace",
|
|
16
|
+
toolset: "Performance",
|
|
16
17
|
summary: "Get all spans within a specific trace",
|
|
17
18
|
purpose: "View the complete trace of operations for a request/transaction",
|
|
18
19
|
useCases: [
|
|
@@ -43,6 +43,7 @@ const inputSchema = z.object({
|
|
|
43
43
|
class ListSpanGroups extends Tool {
|
|
44
44
|
specification = {
|
|
45
45
|
title: "List Span Groups",
|
|
46
|
+
toolset: "Performance",
|
|
46
47
|
summary: "List span groups (operations) tracked for performance monitoring",
|
|
47
48
|
purpose: "Discover and analyze different operations being monitored",
|
|
48
49
|
useCases: [
|
|
@@ -29,6 +29,7 @@ const inputSchema = z.object({
|
|
|
29
29
|
class ListSpans extends Tool {
|
|
30
30
|
specification = {
|
|
31
31
|
title: "List Spans",
|
|
32
|
+
toolset: "Performance",
|
|
32
33
|
summary: "Get individual spans belonging to a span group",
|
|
33
34
|
purpose: "Examine individual operation instances within a span group",
|
|
34
35
|
useCases: [
|
|
@@ -7,6 +7,7 @@ const inputSchema = z.object({
|
|
|
7
7
|
class ListTraceFields extends Tool {
|
|
8
8
|
specification = {
|
|
9
9
|
title: "List Trace Fields",
|
|
10
|
+
toolset: "Performance",
|
|
10
11
|
summary: "Get available trace fields/attributes for filtering",
|
|
11
12
|
purpose: "Discover what custom attributes are available for filtering",
|
|
12
13
|
useCases: [
|
|
@@ -10,6 +10,7 @@ const inputSchema = z.object({
|
|
|
10
10
|
class SetNetworkEndpointGroupings extends Tool {
|
|
11
11
|
specification = {
|
|
12
12
|
title: "Set Network Endpoint Groupings",
|
|
13
|
+
toolset: "Performance",
|
|
13
14
|
summary: "Set the network endpoint grouping rules for a project",
|
|
14
15
|
purpose: "Configure URL patterns to control how network spans are grouped in performance monitoring",
|
|
15
16
|
useCases: [
|
|
@@ -3,6 +3,7 @@ import { toolInputParameters } from "../../input-schemas.js";
|
|
|
3
3
|
class GetCurrentProject extends Tool {
|
|
4
4
|
specification = {
|
|
5
5
|
title: "Get Current Project",
|
|
6
|
+
toolset: "Projects",
|
|
6
7
|
summary: "Retrieve the 'current' project on which tools should operate by default. This allows BugSnag tools to be called with no projectId parameter.",
|
|
7
8
|
purpose: "Gets information about the 'current' BugSnag project, including ID and API key",
|
|
8
9
|
useCases: ["Understand if a current project has been set"],
|
|
@@ -7,6 +7,7 @@ const inputSchema = z.object({
|
|
|
7
7
|
class ListProjectEventFilters extends Tool {
|
|
8
8
|
specification = {
|
|
9
9
|
title: "List Project Event Filters",
|
|
10
|
+
toolset: "Projects",
|
|
10
11
|
summary: "Get available event filter fields for a project",
|
|
11
12
|
purpose: "Discover valid filter field names and options that can be used with the List Errors or Get Error tools",
|
|
12
13
|
useCases: [
|
|
@@ -5,6 +5,7 @@ const inputSchema = z.object({
|
|
|
5
5
|
});
|
|
6
6
|
class ListProjects extends Tool {
|
|
7
7
|
specification = {
|
|
8
|
+
toolset: "Projects",
|
|
8
9
|
title: "List Projects",
|
|
9
10
|
summary: "List all projects in the organization that the current user has access to, or find a project matching an API key.",
|
|
10
11
|
purpose: "Retrieve available projects for browsing and selecting which project to analyze.",
|
|
@@ -8,6 +8,7 @@ const inputSchema = z.object({
|
|
|
8
8
|
class GetBuild extends Tool {
|
|
9
9
|
specification = {
|
|
10
10
|
title: "Get Build",
|
|
11
|
+
toolset: "Releases",
|
|
11
12
|
summary: "Get more details for a specific build by its ID",
|
|
12
13
|
purpose: "Retrieve detailed information about a build for analysis and debugging",
|
|
13
14
|
useCases: [
|
|
@@ -8,6 +8,7 @@ const inputSchema = z.object({
|
|
|
8
8
|
class GetRelease extends Tool {
|
|
9
9
|
specification = {
|
|
10
10
|
title: "Get Release",
|
|
11
|
+
toolset: "Releases",
|
|
11
12
|
summary: "Get more details for a specific release by its ID, including source control information and associated builds",
|
|
12
13
|
purpose: "Retrieve detailed information about a release for analysis and debugging",
|
|
13
14
|
useCases: [
|
|
@@ -13,6 +13,7 @@ const inputSchema = z.object({
|
|
|
13
13
|
class ListReleases extends Tool {
|
|
14
14
|
specification = {
|
|
15
15
|
title: "List Releases",
|
|
16
|
+
toolset: "Releases",
|
|
16
17
|
summary: "List releases for a project",
|
|
17
18
|
purpose: "Retrieve a list of release summaries to analyze deployment history and associated errors",
|
|
18
19
|
useCases: [
|
|
@@ -64,6 +64,7 @@ class CollaboratorClient {
|
|
|
64
64
|
register(
|
|
65
65
|
{
|
|
66
66
|
title: "Find Review By ID",
|
|
67
|
+
toolset: "Review Management",
|
|
67
68
|
summary: "Finds a review in Collaborator by its review ID.",
|
|
68
69
|
inputSchema: z.object({
|
|
69
70
|
reviewId: z.string().describe("The Collaborator review ID to find.")
|
|
@@ -86,6 +87,7 @@ class CollaboratorClient {
|
|
|
86
87
|
register(
|
|
87
88
|
{
|
|
88
89
|
title: "Create Review",
|
|
90
|
+
toolset: "Review Management",
|
|
89
91
|
summary: "Creates a new review in Collaborator. All parameters are optional.",
|
|
90
92
|
inputSchema: z.object({
|
|
91
93
|
creator: z.string().optional().describe(
|
|
@@ -123,6 +125,7 @@ class CollaboratorClient {
|
|
|
123
125
|
register(
|
|
124
126
|
{
|
|
125
127
|
title: "Reject Review",
|
|
128
|
+
toolset: "Review Management",
|
|
126
129
|
summary: "Rejects a review in Collaborator by its review ID and reason.",
|
|
127
130
|
inputSchema: z.object({
|
|
128
131
|
reviewId: z.union([z.string(), z.number()]).describe("The Collaborator review ID to reject."),
|
|
@@ -149,6 +152,7 @@ class CollaboratorClient {
|
|
|
149
152
|
register(
|
|
150
153
|
{
|
|
151
154
|
title: "ReviewService Action",
|
|
155
|
+
toolset: "Review Management",
|
|
152
156
|
summary: "Invoke any ReviewService method by name and arguments. For finishReviewPhase and waitOnPhase, provide reviewId (required) and until (optional, defaults to 'ANY').",
|
|
153
157
|
inputSchema: z.object({
|
|
154
158
|
action: z.enum([
|
|
@@ -172,6 +176,7 @@ class CollaboratorClient {
|
|
|
172
176
|
register(
|
|
173
177
|
{
|
|
174
178
|
title: "Get Reviews",
|
|
179
|
+
toolset: "Review Management",
|
|
175
180
|
summary: "Retrieves reviews from Collaborator using ReviewService.getReviews. All parameters are optional and only provided ones are sent.",
|
|
176
181
|
inputSchema: z.object({
|
|
177
182
|
login: z.string().optional().describe("Collaborator username to filter reviews."),
|
|
@@ -208,6 +213,7 @@ class CollaboratorClient {
|
|
|
208
213
|
register(
|
|
209
214
|
{
|
|
210
215
|
title: "Create Remote System Configuration",
|
|
216
|
+
toolset: "Remote System Configuration Management",
|
|
211
217
|
summary: "Creates a remote system configuration in Collaborator (e.g., Bitbucket, GitHub, etc).",
|
|
212
218
|
inputSchema: z.object({
|
|
213
219
|
token: z.string().describe("Remote system token, e.g., BITBUCKET, GITHUB, etc."),
|
|
@@ -239,6 +245,7 @@ class CollaboratorClient {
|
|
|
239
245
|
register(
|
|
240
246
|
{
|
|
241
247
|
title: "Edit Remote System Configuration",
|
|
248
|
+
toolset: "Remote System Configuration Management",
|
|
242
249
|
summary: "Edits parameters of an existing remote system configuration in Collaborator. Only title and config are editable after creation.",
|
|
243
250
|
inputSchema: z.object({
|
|
244
251
|
id: z.string().describe("ID of the remote system Configuration to edit."),
|
|
@@ -272,6 +279,7 @@ class CollaboratorClient {
|
|
|
272
279
|
register(
|
|
273
280
|
{
|
|
274
281
|
title: "Delete Remote System Configuration",
|
|
282
|
+
toolset: "Remote System Configuration Management",
|
|
275
283
|
summary: "Deletes a remote system configuration in Collaborator by its ID.",
|
|
276
284
|
inputSchema: z.object({
|
|
277
285
|
id: z.union([z.string(), z.number()]).describe("ID of the remote system Configuration to delete.")
|
|
@@ -296,6 +304,7 @@ class CollaboratorClient {
|
|
|
296
304
|
register(
|
|
297
305
|
{
|
|
298
306
|
title: "Update Remote System Configuration Webhook",
|
|
307
|
+
toolset: "Remote System Configuration Management",
|
|
299
308
|
summary: "Updates the webhook for a remote system configuration in Collaborator by its ID.",
|
|
300
309
|
inputSchema: z.object({
|
|
301
310
|
id: z.union([z.string(), z.number()]).describe(
|
|
@@ -322,6 +331,7 @@ class CollaboratorClient {
|
|
|
322
331
|
register(
|
|
323
332
|
{
|
|
324
333
|
title: "Test Remote System Configuration Connection",
|
|
334
|
+
toolset: "Remote System Configuration Management",
|
|
325
335
|
summary: "Tests the connection for a remote system configuration in Collaborator by its ID.",
|
|
326
336
|
inputSchema: z.object({
|
|
327
337
|
id: z.union([z.string(), z.number()]).describe(
|
|
@@ -2,27 +2,35 @@ import { ZodURL } from "zod";
|
|
|
2
2
|
import { fullyUnwrapZodType, isOptionalType } from "./zod-utils.js";
|
|
3
3
|
class ClientRegistry {
|
|
4
4
|
entries = [];
|
|
5
|
-
enabledClients
|
|
5
|
+
enabledClients;
|
|
6
6
|
/**
|
|
7
|
-
* Configure which clients should be enabled based on MCP_CLIENTS env var
|
|
7
|
+
* Configure which clients should be enabled based on MCP_CLIENTS env var and MCP_TOOLSETS (to enable any referenced clients)
|
|
8
8
|
* If not set or empty, all clients are enabled
|
|
9
9
|
* If set, should be comma-separated list of client names (case-insensitive)
|
|
10
10
|
*/
|
|
11
11
|
constructor() {
|
|
12
|
-
|
|
13
|
-
if (
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
let enabledClientsStr = "";
|
|
13
|
+
if (process.env.MCP_CLIENTS) {
|
|
14
|
+
enabledClientsStr = process.env.MCP_CLIENTS.trim();
|
|
15
|
+
}
|
|
16
|
+
enabledClientsStr += ",";
|
|
17
|
+
if (process.env.MCP_TOOLSETS) {
|
|
18
|
+
enabledClientsStr += process.env.MCP_TOOLSETS.trim();
|
|
16
19
|
}
|
|
17
20
|
this.enabledClients = new Set(
|
|
18
|
-
|
|
21
|
+
enabledClientsStr.trim().split(",").map((name) => {
|
|
22
|
+
if (name.includes(":")) {
|
|
23
|
+
return name.split(":")[0].trim().toLowerCase();
|
|
24
|
+
}
|
|
25
|
+
return name.trim().toLowerCase();
|
|
26
|
+
}).filter((name) => name.length > 0)
|
|
19
27
|
);
|
|
20
28
|
}
|
|
21
29
|
/**
|
|
22
|
-
* Check if a client is enabled based on
|
|
30
|
+
* Check if a client is enabled based on client filtering configuration
|
|
23
31
|
*/
|
|
24
32
|
isClientEnabled(name) {
|
|
25
|
-
if (this.enabledClients ===
|
|
33
|
+
if (this.enabledClients.size === 0) {
|
|
26
34
|
return true;
|
|
27
35
|
}
|
|
28
36
|
return this.enabledClients.has(name.toLowerCase());
|
package/dist/common/server.js
CHANGED
|
@@ -11,7 +11,8 @@ class SmartBearMcpServer extends McpServer {
|
|
|
11
11
|
samplingSupported = false;
|
|
12
12
|
elicitationSupported = false;
|
|
13
13
|
clients = [];
|
|
14
|
-
|
|
14
|
+
enabledToolsets;
|
|
15
|
+
constructor(enabledToolsets) {
|
|
15
16
|
super(
|
|
16
17
|
{
|
|
17
18
|
name: MCP_SERVER_NAME,
|
|
@@ -28,6 +29,9 @@ class SmartBearMcpServer extends McpServer {
|
|
|
28
29
|
}
|
|
29
30
|
);
|
|
30
31
|
this.cache = new CacheService();
|
|
32
|
+
if (enabledToolsets) {
|
|
33
|
+
this.enabledToolsets = enabledToolsets.split(",").map((s) => s.trim().toLowerCase());
|
|
34
|
+
}
|
|
31
35
|
}
|
|
32
36
|
getCache() {
|
|
33
37
|
return this.cache;
|
|
@@ -56,6 +60,9 @@ class SmartBearMcpServer extends McpServer {
|
|
|
56
60
|
this.clients.push(client);
|
|
57
61
|
await client.registerTools(
|
|
58
62
|
(params, cb) => {
|
|
63
|
+
if (!this.isToolEnabled(client, params.toolset)) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
59
66
|
const toolName = this.getCapabilityName(client, params.title);
|
|
60
67
|
const toolTitle = this.getCapabilityTitle(client, params.title);
|
|
61
68
|
if (toolName.length > 64) {
|
|
@@ -236,9 +243,40 @@ ${result.instructions}`
|
|
|
236
243
|
getCapabilityName(client, title) {
|
|
237
244
|
return `${client.capabilityPrefix}_${title.replace(/\s+/g, "_").toLowerCase()}`;
|
|
238
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* The tool is enabled if:
|
|
248
|
+
* - No enabled toolsets are defined on the server, or
|
|
249
|
+
* - The client is included in the enabled toolsets list, or
|
|
250
|
+
* - The toolset is included in the enabled toolsets list, or
|
|
251
|
+
* - The toolset is in the client's default list and there is at least one specific toolset enabled for the client
|
|
252
|
+
* @param client
|
|
253
|
+
* @param toolset
|
|
254
|
+
* @returns whether to register the tool based on enabled toolsets configuration
|
|
255
|
+
*/
|
|
256
|
+
isToolEnabled(client, toolset) {
|
|
257
|
+
if (!this.enabledToolsets) {
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
const clientPrefix = client.configPrefix.toLowerCase();
|
|
261
|
+
const clientIsEnabled = this.enabledToolsets.some(
|
|
262
|
+
(ts) => !ts.includes(":") && ts === clientPrefix
|
|
263
|
+
);
|
|
264
|
+
if (clientIsEnabled) {
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
const toolsetEntries = this.enabledToolsets.filter(
|
|
268
|
+
(ts) => ts.includes(":") && ts.split(":")[0] === clientPrefix
|
|
269
|
+
);
|
|
270
|
+
if (toolsetEntries.length === 0) {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
const toolsetName = `${clientPrefix}:${toolset.replace(/[\s\-_]/g, "")}`.toLowerCase();
|
|
274
|
+
return toolsetEntries.includes(toolsetName) || (client.defaultToolsets || [])?.includes(toolset);
|
|
275
|
+
}
|
|
239
276
|
getDescription(params) {
|
|
240
277
|
const {
|
|
241
278
|
summary,
|
|
279
|
+
toolset,
|
|
242
280
|
useCases,
|
|
243
281
|
examples,
|
|
244
282
|
inputSchema,
|
|
@@ -246,6 +284,11 @@ ${result.instructions}`
|
|
|
246
284
|
outputDescription
|
|
247
285
|
} = params;
|
|
248
286
|
let description = summary;
|
|
287
|
+
if (toolset) {
|
|
288
|
+
description += `
|
|
289
|
+
|
|
290
|
+
**Toolset:** ${toolset}`;
|
|
291
|
+
}
|
|
249
292
|
if (inputSchema && inputSchema instanceof ZodObject) {
|
|
250
293
|
let parameters = Object.keys(inputSchema.shape).map((key) => {
|
|
251
294
|
const field = inputSchema.shape[key];
|
|
@@ -343,27 +343,31 @@ async function handleLegacyMessageRequest(req, res, url, transports) {
|
|
|
343
343
|
}
|
|
344
344
|
});
|
|
345
345
|
}
|
|
346
|
+
function getConfigValue(clientPrefix, key, req) {
|
|
347
|
+
const queryStringName = getQueryStringName(clientPrefix, key);
|
|
348
|
+
const queryParams = querystring.parse(req.url?.split("?")[1] || "");
|
|
349
|
+
let value = queryParams[queryStringName] || queryParams[queryStringName.toLowerCase()];
|
|
350
|
+
if (typeof value === "string") {
|
|
351
|
+
return value;
|
|
352
|
+
}
|
|
353
|
+
const headerName = getHeaderName(clientPrefix, key);
|
|
354
|
+
value = req.headers[headerName] || req.headers[headerName.toLowerCase()];
|
|
355
|
+
if (typeof value === "string") {
|
|
356
|
+
return value;
|
|
357
|
+
}
|
|
358
|
+
const envVarName = getEnvVarName(clientPrefix, key);
|
|
359
|
+
return process.env[envVarName] || null;
|
|
360
|
+
}
|
|
346
361
|
async function newServer(req, res) {
|
|
347
|
-
const
|
|
362
|
+
const enabledToolsets = getConfigValue("smartbear", "toolsets", req) || void 0;
|
|
363
|
+
const server = new SmartBearMcpServer(enabledToolsets);
|
|
348
364
|
try {
|
|
349
365
|
const configuredCount = await withRequestContext(
|
|
350
366
|
req,
|
|
351
367
|
() => clientRegistry.configure(
|
|
352
368
|
server,
|
|
353
369
|
(client, key) => {
|
|
354
|
-
|
|
355
|
-
const queryParams = querystring.parse(req.url?.split("?")[1] || "");
|
|
356
|
-
let value = queryParams[queryStringName] || queryParams[queryStringName.toLowerCase()];
|
|
357
|
-
if (typeof value === "string") {
|
|
358
|
-
return value;
|
|
359
|
-
}
|
|
360
|
-
const headerName = getHeaderName(client, key);
|
|
361
|
-
value = req.headers[headerName] || req.headers[headerName.toLowerCase()];
|
|
362
|
-
if (typeof value === "string") {
|
|
363
|
-
return value;
|
|
364
|
-
}
|
|
365
|
-
const envVarName = getEnvVarName(client, key);
|
|
366
|
-
return process.env[envVarName] || null;
|
|
370
|
+
return getConfigValue(client.configPrefix, key, req);
|
|
367
371
|
},
|
|
368
372
|
true
|
|
369
373
|
// ignoreMissingRequiredConfigs
|
|
@@ -405,13 +409,13 @@ ${headerHelp.join("\n")}` : "No clients support HTTP header configuration.";
|
|
|
405
409
|
}
|
|
406
410
|
return server;
|
|
407
411
|
}
|
|
408
|
-
function getHeaderName(
|
|
409
|
-
return `${
|
|
412
|
+
function getHeaderName(clientPrefix, key) {
|
|
413
|
+
return `${clientPrefix}-${key.split("_").map(
|
|
410
414
|
(part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()
|
|
411
415
|
).join("-")}`;
|
|
412
416
|
}
|
|
413
|
-
function getQueryStringName(
|
|
414
|
-
return `${
|
|
417
|
+
function getQueryStringName(clientPrefix, key) {
|
|
418
|
+
return `${clientPrefix.toLowerCase()}${key.split("_").map(
|
|
415
419
|
(part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()
|
|
416
420
|
).join("")}`;
|
|
417
421
|
}
|
|
@@ -419,7 +423,7 @@ function getHttpHeaders() {
|
|
|
419
423
|
const headers = /* @__PURE__ */ new Set();
|
|
420
424
|
for (const entry of clientRegistry.getAll()) {
|
|
421
425
|
for (const configKey of Object.keys(entry.config.shape)) {
|
|
422
|
-
headers.add(getHeaderName(entry, configKey));
|
|
426
|
+
headers.add(getHeaderName(entry.configPrefix, configKey));
|
|
423
427
|
}
|
|
424
428
|
}
|
|
425
429
|
return Array.from(headers).sort((a, b) => a.localeCompare(b));
|
|
@@ -429,7 +433,7 @@ function getHttpHeadersHelp() {
|
|
|
429
433
|
for (const entry of clientRegistry.getAll()) {
|
|
430
434
|
messages.push(` - ${entry.name}:`);
|
|
431
435
|
for (const [configKey, requirement] of Object.entries(entry.config.shape)) {
|
|
432
|
-
const headerName = getHeaderName(entry, configKey);
|
|
436
|
+
const headerName = getHeaderName(entry.configPrefix, configKey);
|
|
433
437
|
const requiredTag = isOptionalType(requirement) ? " (optional)" : " (required)";
|
|
434
438
|
messages.push(
|
|
435
439
|
` - ${headerName}${requiredTag}: ${getTypeDescription(requirement)}`
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { enableCompileCache } from "node:module";
|
|
1
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2
3
|
import { clientRegistry } from "./client-registry.js";
|
|
3
4
|
import { MCP_SERVER_NAME, MCP_SERVER_VERSION } from "./info.js";
|
|
@@ -9,7 +10,7 @@ function getNoConfigMessage() {
|
|
|
9
10
|
for (const entry of clientRegistry.getAll()) {
|
|
10
11
|
messages.push(` - ${entry.name}:`);
|
|
11
12
|
for (const [configKey, requirement] of Object.entries(entry.config.shape)) {
|
|
12
|
-
const envVarName = getEnvVarName(entry, configKey);
|
|
13
|
+
const envVarName = getEnvVarName(entry.configPrefix, configKey);
|
|
13
14
|
const requiredTag = isOptionalType(requirement) ? " (optional)" : " (required)";
|
|
14
15
|
messages.push(
|
|
15
16
|
` - ${envVarName}${requiredTag}: ${getTypeDescription(requirement)}`
|
|
@@ -29,11 +30,12 @@ async function runStdioMode() {
|
|
|
29
30
|
console.log(getNoConfigMessage().join("\n"));
|
|
30
31
|
process.exit(0);
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
+
enableCompileCache();
|
|
34
|
+
const server = new SmartBearMcpServer(process.env.MCP_TOOLSETS);
|
|
33
35
|
const configuredCount = await clientRegistry.configure(
|
|
34
36
|
server,
|
|
35
37
|
(client, key) => {
|
|
36
|
-
const envVarName = getEnvVarName(client, key);
|
|
38
|
+
const envVarName = getEnvVarName(client.configPrefix, key);
|
|
37
39
|
return process.env[envVarName] || null;
|
|
38
40
|
}
|
|
39
41
|
);
|
|
@@ -70,8 +72,8 @@ ${message.join("\n")}` : "No clients support environment variable configuration.
|
|
|
70
72
|
};
|
|
71
73
|
await server.connect(transport);
|
|
72
74
|
}
|
|
73
|
-
function getEnvVarName(
|
|
74
|
-
return `${
|
|
75
|
+
function getEnvVarName(clientPrefix, key) {
|
|
76
|
+
return `${clientPrefix.toUpperCase().replace(/-/g, "_")}_${key.toUpperCase()}`;
|
|
75
77
|
}
|
|
76
78
|
export {
|
|
77
79
|
getEnvVarName,
|
package/dist/package.json.js
CHANGED