@smartbear/mcp 0.7.0 → 0.8.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.
@@ -71,17 +71,17 @@ export const TOOLS = [
71
71
  clients: ["pactflow", "pact_broker"],
72
72
  },
73
73
  {
74
- title: "PactFlow AI Status",
75
- summary: "Check PactFlow AI usage status, remaining credits, and eligibility",
76
- purpose: "Retrieve the AI feature status for the PactFlow account, including whether AI is enabled, the number of remaining and consumed AI credits, and entitlement or permission issues preventing usage.",
74
+ title: "Check PactFlow AI Entitlements",
75
+ summary: "Check your PactFlow AI entitlements and credit balance if you encounter 401 Unauthorized errors or permission/credit issues when using PactFlow AI features.",
76
+ purpose: "Retrieve AI entitlement information when PactFlow AI operations fail with 401 unauthorized errors. Use this to diagnose permission issues, check remaining credits, and verify account eligibility for AI features.",
77
77
  useCases: [
78
- "Verify if AI functionality is enabled for the account before attempting to use AI-powered features",
79
- "Monitor remaining and consumed AI credits to manage usage and avoid unexpected disruptions",
80
- "Detect entitlement or permission issues when a user tries to access AI features and guide corrective actions",
81
- "Integrate into deployment pipelines to ensure the environment is correctly configured with necessary entitlements and sufficient credits before executing AI-driven tasks",
82
- "Fetches usage and entitlement reports for auditing, budgeting, and compliance purposes",
78
+ "Diagnose 401 unauthorized errors when attempting to use PactFlow AI features",
79
+ "Check remaining AI credits when PactFlow AI operations are rejected due to insufficient credits",
80
+ "Verify account entitlements when users receive permission denied errors for PactFlow AI functionality",
81
+ "Troubleshoot PactFlow AI access issues by retrieving current entitlement status and credit balance",
82
+ "Provide detailed error context when PactFlow AI features are unavailable due to account limitations",
83
83
  ],
84
- handler: "getAIStatus",
84
+ handler: "checkAIEntitlements",
85
85
  clients: ["pactflow"],
86
86
  },
87
87
  ];
@@ -99,14 +99,15 @@ export class PactflowClient {
99
99
  return await this.pollForCompletion(status_response, "Review Pacts");
100
100
  }
101
101
  /**
102
- * Retrieves AI status information for the current user
103
- * and organization.
102
+ * Retrieve PactFlow AI entitlement information for the current user
103
+ * and organization when encountering 401 unauthorized errors.
104
+ * Use this to check AI entitlements and credits when AI operations fail.
104
105
  *
105
- * @returns Entitlement containing AI status information, organization
106
+ * @returns Entitlement containing permissions, organization
106
107
  * entitlements, and user entitlements.
107
108
  * @throws Error if the request fails or returns a non-OK response.
108
109
  */
109
- async getAIStatus() {
110
+ async checkAIEntitlements() {
110
111
  const url = `${this.aiBaseUrl}/entitlement`;
111
112
  try {
112
113
  const response = await fetch(url, {
@@ -115,12 +116,12 @@ export class PactflowClient {
115
116
  });
116
117
  if (!response.ok) {
117
118
  const errorText = await response.text().catch(() => "");
118
- throw new Error(`PactFlow AI Status Request Failed - status: ${response.status} ${response.statusText}${errorText ? ` - ${errorText}` : ""}`);
119
+ throw new Error(`PactFlow AI Entitlements Request Failed - status: ${response.status} ${response.statusText}${errorText ? ` - ${errorText}` : ""}`);
119
120
  }
120
121
  return (await response.json());
121
122
  }
122
123
  catch (error) {
123
- process.stderr.write(`[GetAICredits] Unexpected error: ${error}\n`);
124
+ process.stderr.write(`[CheckAIEntitlements] Unexpected error: ${error}\n`);
124
125
  throw error;
125
126
  }
126
127
  }
@@ -0,0 +1,16 @@
1
+ import { ApiClient } from "./common/api-client.js";
2
+ import { GetProjects } from "./tool/project/get-projects.js";
3
+ export class ZephyrClient {
4
+ apiClient;
5
+ name = "Zephyr";
6
+ prefix = "zephyr";
7
+ constructor(bearerToken, baseUrl = "https://api.zephyrscale.smartbear.com/v2") {
8
+ this.apiClient = new ApiClient(bearerToken, baseUrl);
9
+ }
10
+ registerTools(register, _getInput) {
11
+ const tools = [new GetProjects(this.apiClient)];
12
+ tools.forEach((tool) => {
13
+ register(tool.specification, tool.handle);
14
+ });
15
+ }
16
+ }
@@ -0,0 +1,27 @@
1
+ import { AuthService } from "./auth-service.js";
2
+ export class ApiClient {
3
+ baseUrl;
4
+ defaultHeaders;
5
+ constructor(bearerToken, baseUrl) {
6
+ this.baseUrl = baseUrl.trim().replace(/\/$/, "");
7
+ this.defaultHeaders = new AuthService(bearerToken).getAuthHeaders();
8
+ }
9
+ getUrl(endpoint, params) {
10
+ const url = new URL(this.baseUrl + endpoint);
11
+ if (params) {
12
+ Object.entries(params).forEach(([key, value]) => {
13
+ if (value !== undefined) {
14
+ url.searchParams.append(key, String(value));
15
+ }
16
+ });
17
+ }
18
+ return url.toString();
19
+ }
20
+ async get(endpoint, params) {
21
+ const response = await fetch(this.getUrl(endpoint, params), {
22
+ method: "GET",
23
+ headers: this.defaultHeaders,
24
+ });
25
+ return response.json();
26
+ }
27
+ }
@@ -0,0 +1,14 @@
1
+ import { MCP_SERVER_NAME, MCP_SERVER_VERSION } from "../../common/info.js";
2
+ export class AuthService {
3
+ bearerToken;
4
+ constructor(accessToken) {
5
+ this.bearerToken = accessToken.trim();
6
+ }
7
+ getAuthHeaders() {
8
+ return {
9
+ Authorization: `Bearer ${this.bearerToken}`,
10
+ "Content-Type": "application/json",
11
+ "User-Agent": `${MCP_SERVER_NAME}/${MCP_SERVER_VERSION}`,
12
+ };
13
+ }
14
+ }
@@ -0,0 +1,35 @@
1
+ import { z } from "zod";
2
+ export const MaxResultsSchema = z
3
+ .number()
4
+ .min(1)
5
+ .max(1000)
6
+ .describe(`
7
+ Specifies the maximum number of results to return in a single call. The default value is 10, and the maximum value that can be requested is 1000.
8
+
9
+ Note that the server may enforce a lower limit than requested, depending on resource availability or other internal constraints.
10
+ If this happens, the result set may be truncated. Always check the maxResults value in the response to confirm how many results were actually returned.
11
+ `);
12
+ export const StartAtSchema = z
13
+ .number()
14
+ .min(0)
15
+ .max(1000000)
16
+ .describe(`
17
+ Zero-indexed starting position used to paginate through results. Defaults to 0.
18
+ `);
19
+ export const ZephyrProjectSchema = z.object({
20
+ id: z.number(),
21
+ jiraProjectId: z.number(),
22
+ key: z.string(),
23
+ enabled: z.boolean(),
24
+ });
25
+ export function createListSchema(itemSchema) {
26
+ return z.object({
27
+ next: z.string().nullable(),
28
+ startAt: StartAtSchema,
29
+ maxResults: MaxResultsSchema,
30
+ total: z.number(),
31
+ isLast: z.boolean(),
32
+ values: z.array(itemSchema),
33
+ });
34
+ }
35
+ export const ZephyrProjectListSchema = createListSchema(ZephyrProjectSchema);
@@ -0,0 +1,54 @@
1
+ import { z } from "zod";
2
+ import { MaxResultsSchema, StartAtSchema } from "../../common/types.js";
3
+ export const GetProjectsInputSchema = z.object({
4
+ startAt: StartAtSchema.optional(),
5
+ maxResults: MaxResultsSchema.optional(),
6
+ });
7
+ export class GetProjects {
8
+ apiClient;
9
+ constructor(apiClient) {
10
+ this.apiClient = apiClient;
11
+ }
12
+ specification = {
13
+ title: "Get Projects",
14
+ summary: "Get details of projects in Zephyr",
15
+ readOnly: true,
16
+ idempotent: true,
17
+ zodSchema: GetProjectsInputSchema,
18
+ examples: [
19
+ {
20
+ description: "Get the first 10 projects",
21
+ parameters: {
22
+ maxResults: 10,
23
+ startAt: 0,
24
+ },
25
+ expectedOutput: "The first 10 projects with their details",
26
+ },
27
+ {
28
+ description: "Get any project",
29
+ parameters: {
30
+ maxResults: 1,
31
+ },
32
+ expectedOutput: "One project with its details",
33
+ },
34
+ {
35
+ description: "Get five projects starting from the 7th project of the list",
36
+ parameters: {
37
+ maxResults: 5,
38
+ startAt: 6,
39
+ },
40
+ expectedOutput: "The 7th to the 11th projects with their details",
41
+ },
42
+ ],
43
+ };
44
+ handle = async (args) => {
45
+ const { maxResults, startAt } = args;
46
+ const response = await this.apiClient.get("/projects", {
47
+ maxResults,
48
+ startAt,
49
+ });
50
+ return {
51
+ content: [{ type: "text", text: JSON.stringify(response) }],
52
+ };
53
+ };
54
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartbear/mcp",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "MCP server for interacting SmartBear Products",
5
5
  "keywords": [
6
6
  "smartbear",
@@ -8,7 +8,8 @@
8
8
  "bugsnag",
9
9
  "reflect",
10
10
  "api-hub",
11
- "pactflow"
11
+ "pactflow",
12
+ "zephyr"
12
13
  ],
13
14
  "homepage": "https://developer.smartbear.com/smartbear-mcp",
14
15
  "mcpName": "com.smartbear/smartbear-mcp",