@browserstack/mcp-server 1.1.9 → 1.2.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.
Files changed (124) hide show
  1. package/README.md +4 -1
  2. package/dist/config.d.ts +13 -0
  3. package/dist/config.js +4 -6
  4. package/dist/index.d.ts +4 -0
  5. package/dist/index.js +21 -31
  6. package/dist/lib/api.d.ts +2 -0
  7. package/dist/lib/api.js +10 -5
  8. package/dist/lib/apiClient.d.ts +31 -0
  9. package/dist/lib/apiClient.js +108 -0
  10. package/dist/lib/constants.d.ts +17 -0
  11. package/dist/lib/device-cache.d.ts +9 -0
  12. package/dist/lib/device-cache.js +3 -3
  13. package/dist/lib/error.d.ts +7 -0
  14. package/dist/lib/fuzzy.d.ts +1 -0
  15. package/dist/lib/get-auth.d.ts +2 -0
  16. package/dist/lib/get-auth.js +8 -0
  17. package/dist/lib/inmemory-store.d.ts +1 -0
  18. package/dist/lib/instrumentation.d.ts +4 -0
  19. package/dist/lib/instrumentation.js +8 -7
  20. package/dist/lib/local.d.ts +3 -0
  21. package/dist/lib/local.js +3 -3
  22. package/dist/lib/types.d.ts +4 -0
  23. package/dist/lib/types.js +1 -0
  24. package/dist/lib/utils.d.ts +4 -0
  25. package/dist/lib/version-resolver.d.ts +6 -0
  26. package/dist/logger.d.ts +3 -0
  27. package/dist/logger.js +20 -4
  28. package/dist/oninitialized.d.ts +2 -0
  29. package/dist/oninitialized.js +2 -7
  30. package/dist/server-factory.d.ts +25 -0
  31. package/dist/server-factory.js +70 -0
  32. package/dist/tools/accessibility.d.ts +3 -0
  33. package/dist/tools/accessibility.js +21 -12
  34. package/dist/tools/accessiblity-utils/accessibility-rag.d.ts +12 -0
  35. package/dist/tools/accessiblity-utils/accessibility-rag.js +22 -12
  36. package/dist/tools/accessiblity-utils/report-fetcher.d.ts +8 -0
  37. package/dist/tools/accessiblity-utils/report-fetcher.js +26 -16
  38. package/dist/tools/accessiblity-utils/report-parser.d.ts +23 -0
  39. package/dist/tools/accessiblity-utils/report-parser.js +3 -3
  40. package/dist/tools/accessiblity-utils/scanner.d.ts +25 -0
  41. package/dist/tools/accessiblity-utils/scanner.js +43 -24
  42. package/dist/tools/appautomate-utils/appautomate.d.ts +42 -0
  43. package/dist/tools/appautomate-utils/appautomate.js +63 -38
  44. package/dist/tools/appautomate-utils/types.d.ts +5 -0
  45. package/dist/tools/appautomate.d.ts +3 -0
  46. package/dist/tools/appautomate.js +24 -21
  47. package/dist/tools/applive-utils/device-search.d.ts +6 -0
  48. package/dist/tools/applive-utils/start-session.d.ts +15 -0
  49. package/dist/tools/applive-utils/start-session.js +11 -4
  50. package/dist/tools/applive-utils/types.d.ts +7 -0
  51. package/dist/tools/applive-utils/upload-app.d.ts +5 -0
  52. package/dist/tools/applive-utils/upload-app.js +8 -12
  53. package/dist/tools/applive-utils/version-utils.d.ts +4 -0
  54. package/dist/tools/applive.d.ts +13 -0
  55. package/dist/tools/applive.js +9 -7
  56. package/dist/tools/automate-utils/fetch-screenshots.d.ts +6 -0
  57. package/dist/tools/automate-utils/fetch-screenshots.js +16 -12
  58. package/dist/tools/automate.d.ts +9 -0
  59. package/dist/tools/automate.js +9 -7
  60. package/dist/tools/bstack-sdk.d.ts +17 -0
  61. package/dist/tools/bstack-sdk.js +15 -8
  62. package/dist/tools/failurelogs-utils/app-automate.d.ts +7 -0
  63. package/dist/tools/failurelogs-utils/app-automate.js +29 -11
  64. package/dist/tools/failurelogs-utils/automate.d.ts +6 -0
  65. package/dist/tools/failurelogs-utils/automate.js +27 -12
  66. package/dist/tools/failurelogs-utils/utils.d.ts +30 -0
  67. package/dist/tools/getFailureLogs.d.ts +14 -0
  68. package/dist/tools/getFailureLogs.js +15 -16
  69. package/dist/tools/live-utils/desktop-filter.d.ts +2 -0
  70. package/dist/tools/live-utils/mobile-filter.d.ts +2 -0
  71. package/dist/tools/live-utils/start-session.d.ts +6 -0
  72. package/dist/tools/live-utils/start-session.js +18 -5
  73. package/dist/tools/live-utils/types.d.ts +33 -0
  74. package/dist/tools/live.d.ts +3 -0
  75. package/dist/tools/live.js +28 -16
  76. package/dist/tools/observability.d.ts +5 -0
  77. package/dist/tools/observability.js +14 -11
  78. package/dist/tools/sdk-utils/commands.d.ts +3 -0
  79. package/dist/tools/sdk-utils/commands.js +5 -4
  80. package/dist/tools/sdk-utils/constants.d.ts +2 -0
  81. package/dist/tools/sdk-utils/constants.js +82 -21
  82. package/dist/tools/sdk-utils/instructions.d.ts +6 -0
  83. package/dist/tools/sdk-utils/instructions.js +8 -6
  84. package/dist/tools/sdk-utils/percy/constants.d.ts +3 -0
  85. package/dist/tools/sdk-utils/percy/constants.js +1 -0
  86. package/dist/tools/sdk-utils/percy/instructions.d.ts +10 -0
  87. package/dist/tools/sdk-utils/percy/types.d.ts +5 -0
  88. package/dist/tools/sdk-utils/types.d.ts +39 -0
  89. package/dist/tools/sdk-utils/types.js +1 -0
  90. package/dist/tools/selfheal-utils/selfheal.d.ts +11 -0
  91. package/dist/tools/selfheal-utils/selfheal.js +10 -6
  92. package/dist/tools/selfheal.d.ts +7 -0
  93. package/dist/tools/selfheal.js +9 -7
  94. package/dist/tools/testmanagement-utils/TCG-utils/api.d.ts +34 -0
  95. package/dist/tools/testmanagement-utils/TCG-utils/api.js +57 -44
  96. package/dist/tools/testmanagement-utils/TCG-utils/config.d.ts +5 -0
  97. package/dist/tools/testmanagement-utils/TCG-utils/helpers.d.ts +13 -0
  98. package/dist/tools/testmanagement-utils/TCG-utils/helpers.js +2 -1
  99. package/dist/tools/testmanagement-utils/TCG-utils/types.d.ts +26 -0
  100. package/dist/tools/testmanagement-utils/add-test-result.d.ts +42 -0
  101. package/dist/tools/testmanagement-utils/add-test-result.js +23 -10
  102. package/dist/tools/testmanagement-utils/create-lca-steps.d.ts +100 -0
  103. package/dist/tools/testmanagement-utils/create-lca-steps.js +64 -55
  104. package/dist/tools/testmanagement-utils/create-project-folder.d.ts +31 -0
  105. package/dist/tools/testmanagement-utils/create-project-folder.js +31 -21
  106. package/dist/tools/testmanagement-utils/create-testcase.d.ts +122 -0
  107. package/dist/tools/testmanagement-utils/create-testcase.js +13 -10
  108. package/dist/tools/testmanagement-utils/create-testrun.d.ts +82 -0
  109. package/dist/tools/testmanagement-utils/create-testrun.js +11 -8
  110. package/dist/tools/testmanagement-utils/list-testcases.d.ts +30 -0
  111. package/dist/tools/testmanagement-utils/list-testcases.js +9 -7
  112. package/dist/tools/testmanagement-utils/list-testruns.d.ts +22 -0
  113. package/dist/tools/testmanagement-utils/list-testruns.js +9 -7
  114. package/dist/tools/testmanagement-utils/poll-lca-status.d.ts +11 -0
  115. package/dist/tools/testmanagement-utils/poll-lca-status.js +12 -8
  116. package/dist/tools/testmanagement-utils/testcase-from-file.d.ts +4 -0
  117. package/dist/tools/testmanagement-utils/testcase-from-file.js +6 -6
  118. package/dist/tools/testmanagement-utils/update-testrun.d.ts +40 -0
  119. package/dist/tools/testmanagement-utils/update-testrun.js +11 -7
  120. package/dist/tools/testmanagement-utils/upload-file.d.ts +20 -0
  121. package/dist/tools/testmanagement-utils/upload-file.js +8 -6
  122. package/dist/tools/testmanagement.d.ts +60 -0
  123. package/dist/tools/testmanagement.js +53 -53
  124. package/package.json +1 -1
@@ -0,0 +1,31 @@
1
+ import { z } from "zod";
2
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
+ import { BrowserStackConfig } from "../../lib/types.js";
4
+ export declare const CreateProjFoldSchema: z.ZodObject<{
5
+ project_name: z.ZodOptional<z.ZodString>;
6
+ project_description: z.ZodOptional<z.ZodString>;
7
+ project_identifier: z.ZodOptional<z.ZodString>;
8
+ folder_name: z.ZodOptional<z.ZodString>;
9
+ folder_description: z.ZodOptional<z.ZodString>;
10
+ parent_id: z.ZodOptional<z.ZodNumber>;
11
+ }, "strip", z.ZodTypeAny, {
12
+ project_name?: string | undefined;
13
+ project_description?: string | undefined;
14
+ project_identifier?: string | undefined;
15
+ folder_name?: string | undefined;
16
+ folder_description?: string | undefined;
17
+ parent_id?: number | undefined;
18
+ }, {
19
+ project_name?: string | undefined;
20
+ project_description?: string | undefined;
21
+ project_identifier?: string | undefined;
22
+ folder_name?: string | undefined;
23
+ folder_description?: string | undefined;
24
+ parent_id?: number | undefined;
25
+ }>;
26
+ type CreateProjFoldArgs = z.infer<typeof CreateProjFoldSchema>;
27
+ /**
28
+ * Creates a project and/or folder in BrowserStack Test Management.
29
+ */
30
+ export declare function createProjectOrFolder(args: CreateProjFoldArgs, config: BrowserStackConfig): Promise<CallToolResult>;
31
+ export {};
@@ -1,8 +1,8 @@
1
- import axios from "axios";
2
- import config from "../../config.js";
1
+ import { apiClient } from "../../lib/apiClient.js";
3
2
  import { z } from "zod";
4
- import { formatAxiosError } from "../../lib/error.js"; // or correct path
3
+ import { formatAxiosError } from "../../lib/error.js";
5
4
  import { projectIdentifierToId } from "../testmanagement-utils/TCG-utils/api.js";
5
+ import { getBrowserStackAuth } from "../../lib/get-auth.js";
6
6
  // Schema for combined project/folder creation
7
7
  export const CreateProjFoldSchema = z.object({
8
8
  project_name: z
@@ -30,21 +30,29 @@ export const CreateProjFoldSchema = z.object({
30
30
  /**
31
31
  * Creates a project and/or folder in BrowserStack Test Management.
32
32
  */
33
- export async function createProjectOrFolder(args) {
33
+ export async function createProjectOrFolder(args, config) {
34
34
  const { project_name, project_description, project_identifier, folder_name, folder_description, parent_id, } = CreateProjFoldSchema.parse(args);
35
35
  if (!project_name && !project_identifier && !folder_name) {
36
36
  throw new Error("Provide project_name (to create project), or project_identifier and folder_name (to create folder).");
37
37
  }
38
+ const authString = getBrowserStackAuth(config);
39
+ const [username, password] = authString.split(":");
38
40
  let projId = project_identifier;
39
41
  // Step 1: Create project if project_name provided
40
42
  if (project_name) {
41
43
  try {
42
- const res = await axios.post("https://test-management.browserstack.com/api/v2/projects", { project: { name: project_name, description: project_description } }, {
43
- auth: {
44
- username: config.browserstackUsername,
45
- password: config.browserstackAccessKey,
44
+ const authString = getBrowserStackAuth(config);
45
+ const [username, password] = authString.split(":");
46
+ const res = await apiClient.post({
47
+ url: "https://test-management.browserstack.com/api/v2/projects",
48
+ headers: {
49
+ "Content-Type": "application/json",
50
+ Authorization: "Basic " +
51
+ Buffer.from(`${username}:${password}`).toString("base64"),
52
+ },
53
+ body: {
54
+ project: { name: project_name, description: project_description },
46
55
  },
47
- headers: { "Content-Type": "application/json" },
48
56
  });
49
57
  if (!res.data.success) {
50
58
  throw new Error(`Failed to create project: ${JSON.stringify(res.data)}`);
@@ -53,7 +61,7 @@ export async function createProjectOrFolder(args) {
53
61
  projId = res.data.project.identifier;
54
62
  }
55
63
  catch (err) {
56
- return formatAxiosError(err, "Failed to create project..");
64
+ return formatAxiosError(err, "Failed to create project.");
57
65
  }
58
66
  }
59
67
  // Step 2: Create folder if folder_name provided
@@ -61,25 +69,27 @@ export async function createProjectOrFolder(args) {
61
69
  if (!projId)
62
70
  throw new Error("Cannot create folder without project_identifier.");
63
71
  try {
64
- const res = await axios.post(`https://test-management.browserstack.com/api/v2/projects/${encodeURIComponent(projId)}/folders`, {
65
- folder: {
66
- name: folder_name,
67
- description: folder_description,
68
- parent_id,
72
+ const res = await apiClient.post({
73
+ url: `https://test-management.browserstack.com/api/v2/projects/${encodeURIComponent(projId)}/folders`,
74
+ headers: {
75
+ "Content-Type": "application/json",
76
+ Authorization: "Basic " +
77
+ Buffer.from(`${username}:${password}`).toString("base64"),
69
78
  },
70
- }, {
71
- auth: {
72
- username: config.browserstackUsername,
73
- password: config.browserstackAccessKey,
79
+ body: {
80
+ folder: {
81
+ name: folder_name,
82
+ description: folder_description,
83
+ parent_id,
84
+ },
74
85
  },
75
- headers: { "Content-Type": "application/json" },
76
86
  });
77
87
  if (!res.data.success) {
78
88
  throw new Error(`Failed to create folder: ${JSON.stringify(res.data)}`);
79
89
  }
80
90
  // Folder created successfully
81
91
  const folder = res.data.folder;
82
- const projectId = await projectIdentifierToId(projId);
92
+ const projectId = await projectIdentifierToId(projId, config);
83
93
  return {
84
94
  content: [
85
95
  {
@@ -0,0 +1,122 @@
1
+ import { z } from "zod";
2
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
+ import { BrowserStackConfig } from "../../lib/types.js";
4
+ interface TestCaseStep {
5
+ step: string;
6
+ result: string;
7
+ }
8
+ interface IssueTracker {
9
+ name: string;
10
+ host: string;
11
+ }
12
+ export interface TestCaseCreateRequest {
13
+ project_identifier: string;
14
+ folder_id: string;
15
+ name: string;
16
+ description?: string;
17
+ owner?: string;
18
+ preconditions?: string;
19
+ test_case_steps: TestCaseStep[];
20
+ issues?: string[];
21
+ issue_tracker?: IssueTracker;
22
+ tags?: string[];
23
+ custom_fields?: Record<string, string>;
24
+ }
25
+ export interface TestCaseResponse {
26
+ data: {
27
+ success: boolean;
28
+ test_case: {
29
+ case_type: string;
30
+ priority: string;
31
+ status: string;
32
+ folder_id: number;
33
+ issues: Array<{
34
+ jira_id: string;
35
+ issue_type: string;
36
+ }>;
37
+ tags: string[];
38
+ template: string;
39
+ description: string;
40
+ preconditions: string;
41
+ title: string;
42
+ identifier: string;
43
+ automation_status: string;
44
+ owner: string;
45
+ steps: TestCaseStep[];
46
+ custom_fields: Array<{
47
+ name: string;
48
+ value: string;
49
+ }>;
50
+ };
51
+ };
52
+ }
53
+ export declare const CreateTestCaseSchema: z.ZodObject<{
54
+ project_identifier: z.ZodString;
55
+ folder_id: z.ZodString;
56
+ name: z.ZodString;
57
+ description: z.ZodOptional<z.ZodString>;
58
+ owner: z.ZodOptional<z.ZodString>;
59
+ preconditions: z.ZodOptional<z.ZodString>;
60
+ test_case_steps: z.ZodArray<z.ZodObject<{
61
+ step: z.ZodString;
62
+ result: z.ZodString;
63
+ }, "strip", z.ZodTypeAny, {
64
+ step: string;
65
+ result: string;
66
+ }, {
67
+ step: string;
68
+ result: string;
69
+ }>, "many">;
70
+ issues: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
71
+ issue_tracker: z.ZodOptional<z.ZodObject<{
72
+ name: z.ZodString;
73
+ host: z.ZodString;
74
+ }, "strip", z.ZodTypeAny, {
75
+ name: string;
76
+ host: string;
77
+ }, {
78
+ name: string;
79
+ host: string;
80
+ }>>;
81
+ tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
82
+ custom_fields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
83
+ }, "strip", z.ZodTypeAny, {
84
+ name: string;
85
+ test_case_steps: {
86
+ step: string;
87
+ result: string;
88
+ }[];
89
+ project_identifier: string;
90
+ folder_id: string;
91
+ issues?: string[] | undefined;
92
+ description?: string | undefined;
93
+ tags?: string[] | undefined;
94
+ custom_fields?: Record<string, string> | undefined;
95
+ preconditions?: string | undefined;
96
+ owner?: string | undefined;
97
+ issue_tracker?: {
98
+ name: string;
99
+ host: string;
100
+ } | undefined;
101
+ }, {
102
+ name: string;
103
+ test_case_steps: {
104
+ step: string;
105
+ result: string;
106
+ }[];
107
+ project_identifier: string;
108
+ folder_id: string;
109
+ issues?: string[] | undefined;
110
+ description?: string | undefined;
111
+ tags?: string[] | undefined;
112
+ custom_fields?: Record<string, string> | undefined;
113
+ preconditions?: string | undefined;
114
+ owner?: string | undefined;
115
+ issue_tracker?: {
116
+ name: string;
117
+ host: string;
118
+ } | undefined;
119
+ }>;
120
+ export declare function sanitizeArgs(args: any): any;
121
+ export declare function createTestCase(params: TestCaseCreateRequest, config: BrowserStackConfig): Promise<CallToolResult>;
122
+ export {};
@@ -1,7 +1,6 @@
1
- import axios from "axios";
2
- import config from "../../config.js";
1
+ import { apiClient } from "../../lib/apiClient.js";
3
2
  import { z } from "zod";
4
- import { formatAxiosError } from "../../lib/error.js"; // or correct
3
+ import { formatAxiosError } from "../../lib/error.js";
5
4
  import { projectIdentifierToId } from "./TCG-utils/api.js";
6
5
  export const CreateTestCaseSchema = z.object({
7
6
  project_identifier: z
@@ -67,15 +66,19 @@ export function sanitizeArgs(args) {
67
66
  }
68
67
  return cleaned;
69
68
  }
70
- export async function createTestCase(params) {
69
+ import { getBrowserStackAuth } from "../../lib/get-auth.js";
70
+ export async function createTestCase(params, config) {
71
71
  const body = { test_case: params };
72
+ const authString = getBrowserStackAuth(config);
73
+ const [username, password] = authString.split(":");
72
74
  try {
73
- const response = await axios.post(`https://test-management.browserstack.com/api/v2/projects/${encodeURIComponent(params.project_identifier)}/folders/${encodeURIComponent(params.folder_id)}/test-cases`, body, {
74
- auth: {
75
- username: config.browserstackUsername,
76
- password: config.browserstackAccessKey,
75
+ const response = await apiClient.post({
76
+ url: `https://test-management.browserstack.com/api/v2/projects/${encodeURIComponent(params.project_identifier)}/folders/${encodeURIComponent(params.folder_id)}/test-cases`,
77
+ headers: {
78
+ "Content-Type": "application/json",
79
+ Authorization: "Basic " + Buffer.from(`${username}:${password}`).toString("base64"),
77
80
  },
78
- headers: { "Content-Type": "application/json" },
81
+ body,
79
82
  });
80
83
  const { data } = response.data;
81
84
  if (!data.success) {
@@ -91,7 +94,7 @@ export async function createTestCase(params) {
91
94
  };
92
95
  }
93
96
  const tc = data.test_case;
94
- const projectId = await projectIdentifierToId(params.project_identifier);
97
+ const projectId = await projectIdentifierToId(params.project_identifier, config);
95
98
  return {
96
99
  content: [
97
100
  {
@@ -0,0 +1,82 @@
1
+ import { z } from "zod";
2
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
+ import { BrowserStackConfig } from "../../lib/types.js";
4
+ /**
5
+ * Schema for creating a test run.
6
+ */
7
+ export declare const CreateTestRunSchema: z.ZodObject<{
8
+ project_identifier: z.ZodString;
9
+ test_run: z.ZodObject<{
10
+ name: z.ZodString;
11
+ description: z.ZodOptional<z.ZodString>;
12
+ run_state: z.ZodOptional<z.ZodEnum<["new_run", "in_progress", "under_review", "rejected", "done", "closed"]>>;
13
+ issues: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
14
+ issue_tracker: z.ZodOptional<z.ZodObject<{
15
+ name: z.ZodString;
16
+ host: z.ZodString;
17
+ }, "strip", z.ZodTypeAny, {
18
+ name: string;
19
+ host: string;
20
+ }, {
21
+ name: string;
22
+ host: string;
23
+ }>>;
24
+ test_cases: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
25
+ folder_ids: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
26
+ }, "strip", z.ZodTypeAny, {
27
+ name: string;
28
+ issues?: string[] | undefined;
29
+ description?: string | undefined;
30
+ issue_tracker?: {
31
+ name: string;
32
+ host: string;
33
+ } | undefined;
34
+ test_cases?: string[] | undefined;
35
+ run_state?: "new_run" | "in_progress" | "under_review" | "rejected" | "done" | "closed" | undefined;
36
+ folder_ids?: number[] | undefined;
37
+ }, {
38
+ name: string;
39
+ issues?: string[] | undefined;
40
+ description?: string | undefined;
41
+ issue_tracker?: {
42
+ name: string;
43
+ host: string;
44
+ } | undefined;
45
+ test_cases?: string[] | undefined;
46
+ run_state?: "new_run" | "in_progress" | "under_review" | "rejected" | "done" | "closed" | undefined;
47
+ folder_ids?: number[] | undefined;
48
+ }>;
49
+ }, "strip", z.ZodTypeAny, {
50
+ project_identifier: string;
51
+ test_run: {
52
+ name: string;
53
+ issues?: string[] | undefined;
54
+ description?: string | undefined;
55
+ issue_tracker?: {
56
+ name: string;
57
+ host: string;
58
+ } | undefined;
59
+ test_cases?: string[] | undefined;
60
+ run_state?: "new_run" | "in_progress" | "under_review" | "rejected" | "done" | "closed" | undefined;
61
+ folder_ids?: number[] | undefined;
62
+ };
63
+ }, {
64
+ project_identifier: string;
65
+ test_run: {
66
+ name: string;
67
+ issues?: string[] | undefined;
68
+ description?: string | undefined;
69
+ issue_tracker?: {
70
+ name: string;
71
+ host: string;
72
+ } | undefined;
73
+ test_cases?: string[] | undefined;
74
+ run_state?: "new_run" | "in_progress" | "under_review" | "rejected" | "done" | "closed" | undefined;
75
+ folder_ids?: number[] | undefined;
76
+ };
77
+ }>;
78
+ export type CreateTestRunArgs = z.infer<typeof CreateTestRunSchema>;
79
+ /**
80
+ * Creates a test run via BrowserStack Test Management API.
81
+ */
82
+ export declare function createTestRun(rawArgs: CreateTestRunArgs, config: BrowserStackConfig): Promise<CallToolResult>;
@@ -1,7 +1,7 @@
1
- import axios from "axios";
2
- import config from "../../config.js";
1
+ import { apiClient } from "../../lib/apiClient.js";
3
2
  import { z } from "zod";
4
3
  import { formatAxiosError } from "../../lib/error.js";
4
+ import { getBrowserStackAuth } from "../../lib/get-auth.js";
5
5
  /**
6
6
  * Schema for creating a test run.
7
7
  */
@@ -44,7 +44,7 @@ export const CreateTestRunSchema = z.object({
44
44
  /**
45
45
  * Creates a test run via BrowserStack Test Management API.
46
46
  */
47
- export async function createTestRun(rawArgs) {
47
+ export async function createTestRun(rawArgs, config) {
48
48
  try {
49
49
  const inputArgs = {
50
50
  ...rawArgs,
@@ -55,12 +55,15 @@ export async function createTestRun(rawArgs) {
55
55
  };
56
56
  const args = CreateTestRunSchema.parse(inputArgs);
57
57
  const url = `https://test-management.browserstack.com/api/v2/projects/${encodeURIComponent(args.project_identifier)}/test-runs`;
58
- const response = await axios.post(url, { test_run: args.test_run }, {
59
- auth: {
60
- username: config.browserstackUsername,
61
- password: config.browserstackAccessKey,
58
+ const authString = getBrowserStackAuth(config);
59
+ const [username, password] = authString.split(":");
60
+ const response = await apiClient.post({
61
+ url,
62
+ headers: {
63
+ "Content-Type": "application/json",
64
+ Authorization: "Basic " + Buffer.from(`${username}:${password}`).toString("base64"),
62
65
  },
63
- headers: { "Content-Type": "application/json" },
66
+ body: { test_run: args.test_run },
64
67
  });
65
68
  const data = response.data;
66
69
  if (!data.success) {
@@ -0,0 +1,30 @@
1
+ import { z } from "zod";
2
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
+ import { BrowserStackConfig } from "../../lib/types.js";
4
+ /**
5
+ * Schema for listing test cases with optional filters.
6
+ */
7
+ export declare const ListTestCasesSchema: z.ZodObject<{
8
+ project_identifier: z.ZodString;
9
+ folder_id: z.ZodOptional<z.ZodString>;
10
+ case_type: z.ZodOptional<z.ZodString>;
11
+ priority: z.ZodOptional<z.ZodString>;
12
+ p: z.ZodOptional<z.ZodNumber>;
13
+ }, "strip", z.ZodTypeAny, {
14
+ project_identifier: string;
15
+ priority?: string | undefined;
16
+ case_type?: string | undefined;
17
+ folder_id?: string | undefined;
18
+ p?: number | undefined;
19
+ }, {
20
+ project_identifier: string;
21
+ priority?: string | undefined;
22
+ case_type?: string | undefined;
23
+ folder_id?: string | undefined;
24
+ p?: number | undefined;
25
+ }>;
26
+ export type ListTestCasesArgs = z.infer<typeof ListTestCasesSchema>;
27
+ /**
28
+ * Calls BrowserStack Test Management to list test cases with filters.
29
+ */
30
+ export declare function listTestCases(args: ListTestCasesArgs, config: BrowserStackConfig): Promise<CallToolResult>;
@@ -1,7 +1,7 @@
1
- import axios from "axios";
2
- import config from "../../config.js";
1
+ import { apiClient } from "../../lib/apiClient.js";
3
2
  import { z } from "zod";
4
3
  import { formatAxiosError } from "../../lib/error.js";
4
+ import { getBrowserStackAuth } from "../../lib/get-auth.js";
5
5
  /**
6
6
  * Schema for listing test cases with optional filters.
7
7
  */
@@ -26,7 +26,7 @@ export const ListTestCasesSchema = z.object({
26
26
  /**
27
27
  * Calls BrowserStack Test Management to list test cases with filters.
28
28
  */
29
- export async function listTestCases(args) {
29
+ export async function listTestCases(args, config) {
30
30
  try {
31
31
  // Build query string
32
32
  const params = new URLSearchParams();
@@ -39,10 +39,12 @@ export async function listTestCases(args) {
39
39
  if (args.p !== undefined)
40
40
  params.append("p", args.p.toString());
41
41
  const url = `https://test-management.browserstack.com/api/v2/projects/${encodeURIComponent(args.project_identifier)}/test-cases?${params.toString()}`;
42
- const resp = await axios.get(url, {
43
- auth: {
44
- username: config.browserstackUsername,
45
- password: config.browserstackAccessKey,
42
+ const authString = getBrowserStackAuth(config);
43
+ const [username, password] = authString.split(":");
44
+ const resp = await apiClient.get({
45
+ url,
46
+ headers: {
47
+ Authorization: "Basic " + Buffer.from(`${username}:${password}`).toString("base64"),
46
48
  },
47
49
  });
48
50
  const resp_data = resp.data;
@@ -0,0 +1,22 @@
1
+ import { z } from "zod";
2
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
+ import { BrowserStackConfig } from "../../lib/types.js";
4
+ /**
5
+ * Schema for listing test runs with optional filters.
6
+ */
7
+ export declare const ListTestRunsSchema: z.ZodObject<{
8
+ project_identifier: z.ZodString;
9
+ run_state: z.ZodOptional<z.ZodString>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ project_identifier: string;
12
+ run_state?: string | undefined;
13
+ }, {
14
+ project_identifier: string;
15
+ run_state?: string | undefined;
16
+ }>;
17
+ type ListTestRunsArgs = z.infer<typeof ListTestRunsSchema>;
18
+ /**
19
+ * Fetches and formats the list of test runs for a project.
20
+ */
21
+ export declare function listTestRuns(args: ListTestRunsArgs, config: BrowserStackConfig): Promise<CallToolResult>;
22
+ export {};
@@ -1,7 +1,7 @@
1
- import axios from "axios";
2
- import config from "../../config.js";
1
+ import { apiClient } from "../../lib/apiClient.js";
3
2
  import { z } from "zod";
4
3
  import { formatAxiosError } from "../../lib/error.js";
4
+ import { getBrowserStackAuth } from "../../lib/get-auth.js";
5
5
  /**
6
6
  * Schema for listing test runs with optional filters.
7
7
  */
@@ -17,17 +17,19 @@ export const ListTestRunsSchema = z.object({
17
17
  /**
18
18
  * Fetches and formats the list of test runs for a project.
19
19
  */
20
- export async function listTestRuns(args) {
20
+ export async function listTestRuns(args, config) {
21
21
  try {
22
22
  const params = new URLSearchParams();
23
23
  if (args.run_state) {
24
24
  params.set("run_state", args.run_state);
25
25
  }
26
26
  const url = `https://test-management.browserstack.com/api/v2/projects/${encodeURIComponent(args.project_identifier)}/test-runs?` + params.toString();
27
- const resp = await axios.get(url, {
28
- auth: {
29
- username: config.browserstackUsername,
30
- password: config.browserstackAccessKey,
27
+ const authString = getBrowserStackAuth(config);
28
+ const [username, password] = authString.split(":");
29
+ const resp = await apiClient.get({
30
+ url,
31
+ headers: {
32
+ Authorization: "Basic " + Buffer.from(`${username}:${password}`).toString("base64"),
31
33
  },
32
34
  });
33
35
  const data = resp.data;
@@ -0,0 +1,11 @@
1
+ import { BrowserStackConfig } from "../../lib/types.js";
2
+ /**
3
+ * Poll test case details to check LCA build status
4
+ */
5
+ export declare function pollLCAStatus(projectId: string, folderId: string, testCaseId: string, context: any, maxWaitTimeMs: number | undefined, // 10 minutes default
6
+ initialWaitMs: number | undefined, // 2 minutes initial wait
7
+ pollIntervalMs: number | undefined, // 10 seconds interval
8
+ config: BrowserStackConfig): Promise<{
9
+ resource_path: string;
10
+ status: string;
11
+ } | null>;
@@ -1,11 +1,12 @@
1
- import axios from "axios";
2
- import config from "../../config.js";
1
+ import { apiClient } from "../../lib/apiClient.js";
2
+ import { getBrowserStackAuth } from "../../lib/get-auth.js";
3
3
  /**
4
4
  * Poll test case details to check LCA build status
5
5
  */
6
6
  export async function pollLCAStatus(projectId, folderId, testCaseId, context, maxWaitTimeMs = 10 * 60 * 1000, // 10 minutes default
7
7
  initialWaitMs = 2 * 60 * 1000, // 2 minutes initial wait
8
- pollIntervalMs = 10 * 1000) {
8
+ pollIntervalMs = 10 * 1000, // 10 seconds interval
9
+ config) {
9
10
  const url = `https://test-management.browserstack.com/api/v1/projects/${projectId}/folder/${folderId}/test-cases/${testCaseId}`;
10
11
  const startTime = Date.now();
11
12
  // Send initial notification that polling is starting
@@ -49,17 +50,20 @@ pollIntervalMs = 10 * 1000) {
49
50
  // Set up polling interval
50
51
  const intervalId = setInterval(async () => {
51
52
  try {
52
- const response = await axios.get(url, {
53
+ const authString = getBrowserStackAuth(config);
54
+ const response = await apiClient.get({
55
+ url,
53
56
  headers: {
54
- "API-TOKEN": `${config.browserstackUsername}:${config.browserstackAccessKey}`,
57
+ "API-TOKEN": authString,
55
58
  accept: "application/json, text/plain, */*",
56
59
  },
57
60
  });
58
- if (response.data.data.success && response.data.data.test_case) {
59
- const testCase = response.data.data.test_case;
61
+ const responseData = response.data;
62
+ if (responseData.data.success && responseData.data.test_case) {
63
+ const testCase = responseData.data.test_case;
60
64
  // Check lcnc_build_map in both possible locations
61
65
  const lcncBuildMap = testCase.lcnc_build_map ||
62
- response.data.data.metadata?.lcnc_build_map;
66
+ responseData.data.metadata?.lcnc_build_map;
63
67
  if (lcncBuildMap) {
64
68
  if (lcncBuildMap.status === "done") {
65
69
  // Clean up timers
@@ -0,0 +1,4 @@
1
+ import { CreateTestCasesFromFileArgs } from "./TCG-utils/types.js";
2
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
+ import { BrowserStackConfig } from "../../lib/types.js";
4
+ export declare function createTestCasesFromFile(args: CreateTestCasesFromFileArgs, context: any, config: BrowserStackConfig): Promise<CallToolResult>;
@@ -3,12 +3,12 @@ import { buildDefaultFieldMaps, findBooleanFieldId, } from "./TCG-utils/helpers.
3
3
  import { signedUrlMap } from "../../lib/inmemory-store.js";
4
4
  import logger from "../../logger.js";
5
5
  import { projectIdentifierToId } from "./TCG-utils/api.js";
6
- export async function createTestCasesFromFile(args, context) {
6
+ export async function createTestCasesFromFile(args, context, config) {
7
7
  logger.info(`createTestCasesFromFile called with projectId: ${args.projectReferenceId}, folderId: ${args.folderId}`);
8
8
  if (args.projectReferenceId.startsWith("PR-")) {
9
- args.projectReferenceId = await projectIdentifierToId(args.projectReferenceId);
9
+ args.projectReferenceId = await projectIdentifierToId(args.projectReferenceId, config);
10
10
  }
11
- const { default_fields, custom_fields } = await fetchFormFields(args.projectReferenceId);
11
+ const { default_fields, custom_fields } = await fetchFormFields(args.projectReferenceId, config);
12
12
  const fieldMaps = buildDefaultFieldMaps(default_fields);
13
13
  const booleanFieldId = findBooleanFieldId(custom_fields);
14
14
  const documentObj = signedUrlMap.get(args.documentId);
@@ -27,9 +27,9 @@ export async function createTestCasesFromFile(args, context) {
27
27
  const documentId = documentObj.fileId;
28
28
  const document = documentObj.downloadUrl;
29
29
  const source = "jira-on-prem";
30
- const traceId = await triggerTestCaseGeneration(document, documentId, args.folderId, args.projectReferenceId, source);
31
- const scenariosMap = await pollScenariosTestDetails(args, traceId, context, documentId, source);
32
- const resultString = await bulkCreateTestCases(scenariosMap, args.projectReferenceId, args.folderId, fieldMaps, booleanFieldId, traceId, context, documentId);
30
+ const traceId = await triggerTestCaseGeneration(document, documentId, args.folderId, args.projectReferenceId, source, config);
31
+ const scenariosMap = await pollScenariosTestDetails(args, traceId, context, documentId, source, config);
32
+ const resultString = await bulkCreateTestCases(scenariosMap, args.projectReferenceId, args.folderId, fieldMaps, booleanFieldId, traceId, context, documentId, config);
33
33
  signedUrlMap.delete(args.documentId);
34
34
  const dashboardURL = `https://test-management.browserstack.com/projects/${args.projectReferenceId}/folder/${args.folderId}/test-cases`;
35
35
  return {