@atlassian-dc-mcp/bitbucket 0.12.2 → 0.13.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +45 -2
  3. package/build/__tests__/bitbucket-service.test.js +106 -17
  4. package/build/__tests__/bitbucket-service.test.js.map +1 -1
  5. package/build/__tests__/bitbucket-token-optimization.test.d.ts +2 -0
  6. package/build/__tests__/bitbucket-token-optimization.test.d.ts.map +1 -0
  7. package/build/__tests__/bitbucket-token-optimization.test.js +281 -0
  8. package/build/__tests__/bitbucket-token-optimization.test.js.map +1 -0
  9. package/build/__tests__/config.test.d.ts +2 -0
  10. package/build/__tests__/config.test.d.ts.map +1 -0
  11. package/build/__tests__/config.test.js +49 -0
  12. package/build/__tests__/config.test.js.map +1 -0
  13. package/build/bitbucket-response-mapper.d.ts +8 -0
  14. package/build/bitbucket-response-mapper.d.ts.map +1 -0
  15. package/build/bitbucket-response-mapper.js +95 -0
  16. package/build/bitbucket-response-mapper.js.map +1 -0
  17. package/build/bitbucket-service.d.ts +24 -22
  18. package/build/bitbucket-service.d.ts.map +1 -1
  19. package/build/bitbucket-service.js +88 -54
  20. package/build/bitbucket-service.js.map +1 -1
  21. package/build/config.d.ts +4 -0
  22. package/build/config.d.ts.map +1 -0
  23. package/build/config.js +11 -0
  24. package/build/config.js.map +1 -0
  25. package/build/index.js +15 -15
  26. package/build/index.js.map +1 -1
  27. package/package.json +3 -3
  28. package/server.json +11 -4
  29. package/src/__tests__/bitbucket-service.test.ts +109 -17
  30. package/src/__tests__/bitbucket-token-optimization.test.ts +314 -0
  31. package/src/__tests__/config.test.ts +64 -0
  32. package/src/bitbucket-response-mapper.ts +112 -0
  33. package/src/bitbucket-service.ts +117 -57
  34. package/src/config.ts +13 -0
  35. package/src/index.ts +18 -17
  36. package/tsconfig.tsbuildinfo +1 -1
@@ -2,15 +2,47 @@ import { z } from 'zod';
2
2
  import { OpenAPI, ProjectService, PullRequestsService, RepositoryService } from './bitbucket-client/index.js';
3
3
  import { request as __request } from './bitbucket-client/core/request.js';
4
4
  import { handleApiOperation } from '@atlassian-dc-mcp/common';
5
- import { simplifyBitbucketPRComments } from './pr-comment-mapper.js';
6
- import { simplifyBitbucketPRChanges } from './pr-changes-mapper.js';
7
5
  import { simplifyInboxPullRequests } from './inbox-pr-mapper.js';
6
+ import { getDefaultPageSize, getMissingConfig } from './config.js';
7
+ import {
8
+ BitbucketMutationOutputMode,
9
+ BitbucketOutputMode,
10
+ shapePullRequestAck,
11
+ shapePullRequestChangesResponse,
12
+ shapePullRequestCommentAck,
13
+ shapePullRequestCommentsResponse,
14
+ } from './bitbucket-response-mapper.js';
15
+
16
+ function resolveToken(token: string | (() => string | undefined), missingTokenMessage: string) {
17
+ return async () => {
18
+ const resolvedToken = typeof token === 'function' ? token() : token;
19
+ if (!resolvedToken) {
20
+ throw new Error(missingTokenMessage);
21
+ }
22
+ return resolvedToken;
23
+ };
24
+ }
8
25
 
9
26
  export class BitbucketService {
10
- constructor(host: string, token: string, fullBaseUrl?: string) {
11
- OpenAPI.BASE = fullBaseUrl ?? `https://${host}/rest`;
12
- OpenAPI.TOKEN = token;
27
+ private readonly getPageSize: () => number;
28
+
29
+ constructor(
30
+ host: string | undefined,
31
+ token: string | (() => string | undefined),
32
+ fullBaseUrl?: string,
33
+ getPageSize: () => number = getDefaultPageSize,
34
+ ) {
35
+ if (fullBaseUrl) {
36
+ OpenAPI.BASE = fullBaseUrl;
37
+ } else if (host) {
38
+ OpenAPI.BASE = `https://${host}/rest`;
39
+ } else {
40
+ throw new Error('Either host or fullBaseUrl must be provided');
41
+ }
42
+
43
+ OpenAPI.TOKEN = resolveToken(token, 'Missing required environment variable: BITBUCKET_API_TOKEN');
13
44
  OpenAPI.VERSION = '1.0';
45
+ this.getPageSize = getPageSize;
14
46
  }
15
47
 
16
48
  /**
@@ -24,7 +56,7 @@ export class BitbucketService {
24
56
  * @returns Promise with commits data
25
57
  */
26
58
  async getCommits(projectKey: string, repositorySlug: string, path?: string, since?: string, until?: string,
27
- limit: number = 25
59
+ limit?: number
28
60
  ) {
29
61
  return handleApiOperation(
30
62
  () => RepositoryService.getCommits(
@@ -40,7 +72,7 @@ export class BitbucketService {
40
72
  undefined, // merges
41
73
  undefined, // ignoreMissing
42
74
  0, // start
43
- limit
75
+ limit ?? this.getPageSize()
44
76
  ),
45
77
  'Error fetching commits'
46
78
  );
@@ -54,9 +86,9 @@ export class BitbucketService {
54
86
  * @param limit Optional pagination limit (default: 25)
55
87
  * @returns Promise with projects data
56
88
  */
57
- async getProjects(name?: string, permission?: string, start?: number, limit: number = 25) {
89
+ async getProjects(name?: string, permission?: string, start?: number, limit?: number) {
58
90
  return handleApiOperation(
59
- () => ProjectService.getProjects(name, permission, start, limit),
91
+ () => ProjectService.getProjects(name, permission, start, limit ?? this.getPageSize()),
60
92
  'Error fetching projects'
61
93
  );
62
94
  }
@@ -80,9 +112,9 @@ export class BitbucketService {
80
112
  * @param limit Optional pagination limit (default: 25)
81
113
  * @returns Promise with repositories data
82
114
  */
83
- async getRepositories(projectKey: string, start?: number, limit: number = 25) {
115
+ async getRepositories(projectKey: string, start?: number, limit?: number) {
84
116
  return handleApiOperation(
85
- () => ProjectService.getRepositories(projectKey, start, limit),
117
+ () => ProjectService.getRepositories(projectKey, start, limit ?? this.getPageSize()),
86
118
  'Error fetching repositories'
87
119
  );
88
120
  }
@@ -128,7 +160,7 @@ export class BitbucketService {
128
160
  order?: string,
129
161
  direction?: string,
130
162
  start?: number,
131
- limit: number = 25
163
+ limit?: number
132
164
  ) {
133
165
  return handleApiOperation(
134
166
  () => PullRequestsService.getPage(
@@ -143,7 +175,7 @@ export class BitbucketService {
143
175
  order,
144
176
  direction,
145
177
  start,
146
- limit
178
+ limit ?? this.getPageSize()
147
179
  ),
148
180
  'Error fetching pull requests'
149
181
  );
@@ -167,8 +199,13 @@ export class BitbucketService {
167
199
  );
168
200
  }
169
201
 
170
- async getPullRequestCommentsAndActions(projectKey: string, repositorySlug: string, pullRequestId: string, start?: number,
171
- limit: number = 25
202
+ async getPullRequestCommentsAndActions(
203
+ projectKey: string,
204
+ repositorySlug: string,
205
+ pullRequestId: string,
206
+ start?: number,
207
+ limit?: number,
208
+ output: BitbucketOutputMode = 'compact'
172
209
  ) {
173
210
  const result = await handleApiOperation(
174
211
  () => PullRequestsService.getActivities(
@@ -178,17 +215,15 @@ export class BitbucketService {
178
215
  undefined,
179
216
  undefined,
180
217
  start,
181
- limit
218
+ limit ?? this.getPageSize()
182
219
  ),
183
220
  'Error fetching pull request comments'
184
221
  );
185
222
 
186
- // Apply simplification if the API call was successful
187
223
  if (result.success && result.data) {
188
- const simplifiedData = simplifyBitbucketPRComments(result.data);
189
224
  return {
190
225
  success: true,
191
- data: simplifiedData
226
+ data: shapePullRequestCommentsResponse(result.data, output)
192
227
  };
193
228
  }
194
229
 
@@ -217,7 +252,8 @@ export class BitbucketService {
217
252
  untilId?: string,
218
253
  withComments?: string,
219
254
  start?: number,
220
- limit: number = 25
255
+ limit?: number,
256
+ output: BitbucketOutputMode = 'compact'
221
257
  ) {
222
258
  const result = await handleApiOperation(
223
259
  () => PullRequestsService.streamChanges1(
@@ -229,17 +265,15 @@ export class BitbucketService {
229
265
  untilId,
230
266
  withComments,
231
267
  start,
232
- limit
268
+ limit ?? this.getPageSize()
233
269
  ),
234
270
  'Error fetching pull request changes'
235
271
  );
236
272
 
237
- // Apply simplification if the API call was successful
238
273
  if (result.success && result.data) {
239
- const simplifiedData = simplifyBitbucketPRChanges(result.data);
240
274
  return {
241
275
  ...result,
242
- data: simplifiedData
276
+ data: shapePullRequestChangesResponse(result.data, output)
243
277
  };
244
278
  }
245
279
 
@@ -270,7 +304,8 @@ export class BitbucketService {
270
304
  filePath?: string,
271
305
  line?: number,
272
306
  lineType?: 'ADDED' | 'REMOVED' | 'CONTEXT',
273
- pending?: boolean
307
+ pending?: boolean,
308
+ output: BitbucketMutationOutputMode = 'ack'
274
309
  ) {
275
310
  const comment: any = {
276
311
  text
@@ -302,7 +337,7 @@ export class BitbucketService {
302
337
  }
303
338
  }
304
339
 
305
- return handleApiOperation(
340
+ const result = await handleApiOperation(
306
341
  () => PullRequestsService.createComment2(
307
342
  projectKey,
308
343
  pullRequestId,
@@ -311,6 +346,15 @@ export class BitbucketService {
311
346
  ),
312
347
  'Error posting pull request comment'
313
348
  );
349
+
350
+ if (result.success && result.data && output !== 'full') {
351
+ return {
352
+ ...result,
353
+ data: shapePullRequestCommentAck(result.data),
354
+ };
355
+ }
356
+
357
+ return result;
314
358
  }
315
359
 
316
360
  /**
@@ -452,7 +496,8 @@ export class BitbucketService {
452
496
  description: string | undefined,
453
497
  fromRefId: string,
454
498
  toRefId: string,
455
- reviewers?: string[]
499
+ reviewers?: string[],
500
+ output: BitbucketMutationOutputMode = 'ack'
456
501
  ) {
457
502
  const pullRequestData: any = {
458
503
  title,
@@ -485,10 +530,19 @@ export class BitbucketService {
485
530
  }));
486
531
  }
487
532
 
488
- return handleApiOperation(
533
+ const result = await handleApiOperation(
489
534
  () => PullRequestsService.create(projectKey, repositorySlug, pullRequestData),
490
535
  'Error creating pull request'
491
536
  );
537
+
538
+ if (result.success && result.data && output !== 'full') {
539
+ return {
540
+ ...result,
541
+ data: shapePullRequestAck(result.data),
542
+ };
543
+ }
544
+
545
+ return result;
492
546
  }
493
547
 
494
548
  /**
@@ -509,7 +563,8 @@ export class BitbucketService {
509
563
  version: number,
510
564
  title?: string,
511
565
  description?: string,
512
- reviewers?: string[]
566
+ reviewers?: string[],
567
+ output: BitbucketMutationOutputMode = 'ack'
513
568
  ) {
514
569
  const pullRequestData: any = {
515
570
  version
@@ -531,10 +586,19 @@ export class BitbucketService {
531
586
  }));
532
587
  }
533
588
 
534
- return handleApiOperation(
589
+ const result = await handleApiOperation(
535
590
  () => PullRequestsService.update(projectKey, pullRequestId, repositorySlug, pullRequestData),
536
591
  'Error updating pull request'
537
592
  );
593
+
594
+ if (result.success && result.data && output !== 'full') {
595
+ return {
596
+ ...result,
597
+ data: shapePullRequestAck(result.data),
598
+ };
599
+ }
600
+
601
+ return result;
538
602
  }
539
603
 
540
604
  /**
@@ -577,7 +641,7 @@ export class BitbucketService {
577
641
  * @param closedSince Optional timestamp (in milliseconds) to filter PRs closed after this date
578
642
  * @param order Order: NEWEST (default), OLDEST, or PARTICIPANT
579
643
  * @param start Optional pagination start
580
- * @param limit Pagination limit (default: 10)
644
+ * @param limit Pagination limit (defaults to the package page size)
581
645
  * @returns Promise with dashboard pull requests data
582
646
  */
583
647
  async getDashboardPullRequests(
@@ -586,7 +650,7 @@ export class BitbucketService {
586
650
  closedSince?: number,
587
651
  order: string = 'NEWEST',
588
652
  start?: number,
589
- limit: number = 10
653
+ limit?: number
590
654
  ) {
591
655
  return handleApiOperation(
592
656
  () => __request(OpenAPI, {
@@ -598,7 +662,7 @@ export class BitbucketService {
598
662
  'closedSince': closedSince,
599
663
  'order': order,
600
664
  'start': start,
601
- 'limit': limit,
665
+ 'limit': limit ?? this.getPageSize(),
602
666
  },
603
667
  errors: {
604
668
  401: 'The currently authenticated user is not permitted to access the dashboard.',
@@ -611,17 +675,17 @@ export class BitbucketService {
611
675
  /**
612
676
  * Get pull requests from the authenticated user's inbox (PRs awaiting review)
613
677
  * @param start Optional pagination start
614
- * @param limit Optional pagination limit (default: 25)
678
+ * @param limit Optional pagination limit (defaults to the package page size)
615
679
  * @returns Promise with inbox pull requests data
616
680
  */
617
- async getInboxPullRequests(start?: number, limit: number = 25) {
681
+ async getInboxPullRequests(start?: number, limit?: number) {
618
682
  const result = await handleApiOperation(
619
683
  () => __request(OpenAPI, {
620
684
  method: 'GET',
621
685
  url: '/api/latest/inbox/pull-requests',
622
686
  query: {
623
687
  'start': start,
624
- 'limit': limit,
688
+ 'limit': limit ?? this.getPageSize(),
625
689
  },
626
690
  errors: {
627
691
  401: 'The currently authenticated user is not permitted to access the inbox.',
@@ -641,16 +705,7 @@ export class BitbucketService {
641
705
  }
642
706
 
643
707
  static validateConfig(): string[] {
644
- // Check for BITBUCKET_HOST or its alternative BITBUCKET_API_BASE_PATH
645
- const requiredEnvVars = ['BITBUCKET_API_TOKEN'] as const;
646
- const missingVars: string[] = requiredEnvVars.filter(varName => !process.env[varName]);
647
-
648
- // Special handling for BITBUCKET_HOST with BITBUCKET_API_BASE_PATH as an alternative
649
- if (!process.env.BITBUCKET_HOST && !process.env.BITBUCKET_API_BASE_PATH) {
650
- missingVars.push('BITBUCKET_HOST or BITBUCKET_API_BASE_PATH');
651
- }
652
-
653
- return missingVars;
708
+ return getMissingConfig();
654
709
  }
655
710
  }
656
711
 
@@ -659,7 +714,7 @@ export const bitbucketToolSchemas = {
659
714
  name: z.string().optional().describe("Filter projects by name"),
660
715
  permission: z.string().optional().describe("Filter projects by permission"),
661
716
  start: z.number().optional().describe("Start number for pagination"),
662
- limit: z.number().optional().default(25).describe("Number of items to return")
717
+ limit: z.number().optional().describe("Number of items to return. If not passed, the package default page size is used.")
663
718
  },
664
719
  getPullRequests: {
665
720
  projectKey: z.string().describe("The project key"),
@@ -673,7 +728,7 @@ export const bitbucketToolSchemas = {
673
728
  order: z.string().optional().describe("(optional, defaults to NEWEST) the order to return pull requests in, either OLDEST (as in: \"oldest first\") or NEWEST"),
674
729
  direction: z.string().optional().describe("(optional, defaults to INCOMING) the direction relative to the specified repository. Either INCOMING or OUTGOING"),
675
730
  start: z.number().optional().describe("Start number for the page (inclusive). If not passed, first page is assumed"),
676
- limit: z.number().optional().default(25).describe("Number of items to return. If not passed, a page size of 25 is used")
731
+ limit: z.number().optional().describe("Number of items to return. If not passed, the package default page size is used.")
677
732
  },
678
733
  getPullRequest: {
679
734
  projectKey: z.string().describe("The project key"),
@@ -686,7 +741,7 @@ export const bitbucketToolSchemas = {
686
741
  getRepositories: {
687
742
  projectKey: z.string().describe("The project key"),
688
743
  start: z.number().optional().describe("Start number for pagination"),
689
- limit: z.number().optional().default(25).describe("Number of items to return")
744
+ limit: z.number().optional().describe("Number of items to return. If not passed, the package default page size is used.")
690
745
  },
691
746
  getRepository: {
692
747
  projectKey: z.string().describe("The project key"),
@@ -698,14 +753,15 @@ export const bitbucketToolSchemas = {
698
753
  path: z.string().optional().describe("Optional path to filter commits by"),
699
754
  since: z.string().optional().describe("The commit ID (exclusively) to retrieve commits after"),
700
755
  until: z.string().optional().describe("The commit ID (inclusively) to retrieve commits before"),
701
- limit: z.number().optional().default(25).describe("Number of items to return")
756
+ limit: z.number().optional().describe("Number of items to return. If not passed, the package default page size is used.")
702
757
  },
703
758
  getPullRequestComments: {
704
759
  projectKey: z.string().describe("The project key"),
705
760
  repositorySlug: z.string().describe("The repository slug"),
706
761
  pullRequestId: z.string().describe("The pull request ID"),
707
762
  start: z.number().optional().describe("Start number for pagination"),
708
- limit: z.number().optional().default(25).describe("Number of items to return")
763
+ limit: z.number().optional().describe("Number of items to return. If not passed, the package default page size is used."),
764
+ output: z.enum(['summary', 'compact', 'full']).optional().describe("Choose between summary lines, compact structured output, or the full API payload. Defaults to compact.")
709
765
  },
710
766
  getPullRequestChanges: {
711
767
  projectKey: z.string().describe("The project key"),
@@ -716,7 +772,8 @@ export const bitbucketToolSchemas = {
716
772
  untilId: z.string().optional().describe("The until commit hash to stream changes for a RANGE arbitrary change scope"),
717
773
  withComments: z.string().optional().describe("true to apply comment counts in the changes (default), false to stream changes without comment counts"),
718
774
  start: z.number().optional().describe("Start number for pagination"),
719
- limit: z.number().optional().default(25).describe("Number of items to return")
775
+ limit: z.number().optional().describe("Number of items to return. If not passed, the package default page size is used."),
776
+ output: z.enum(['summary', 'compact', 'full']).optional().describe("Choose between summary lines, compact structured output, or the full API payload. Defaults to compact.")
720
777
  },
721
778
  postPullRequestComment: {
722
779
  projectKey: z.string().describe("The project key"),
@@ -727,7 +784,8 @@ export const bitbucketToolSchemas = {
727
784
  filePath: z.string().optional().describe("File path for file-specific comments"),
728
785
  line: z.number().optional().describe("Line number for line-specific comments"),
729
786
  lineType: z.enum(['ADDED', 'REMOVED', 'CONTEXT']).optional().describe("Line type for line comments"),
730
- pending: z.boolean().optional().describe("If true, creates a pending (draft) comment not visible to others until the review is submitted via bitbucket_submitPullRequestReview. Only works when filePath is provided — top-level PR comments (no filePath) are always posted live.")
787
+ pending: z.boolean().optional().describe("If true, creates a pending (draft) comment not visible to others until the review is submitted via bitbucket_submitPullRequestReview. Only works when filePath is provided — top-level PR comments (no filePath) are always posted live."),
788
+ output: z.enum(['ack', 'full']).optional().describe("Return a compact acknowledgement or the full API response. Defaults to ack.")
731
789
  },
732
790
  getUser: {
733
791
  userSlug: z.string().optional().describe("Exact slug of the user to look up (e.g. 'tdepole'). Use this to confirm a known slug or fetch a user's details."),
@@ -760,7 +818,8 @@ export const bitbucketToolSchemas = {
760
818
  description: z.string().optional().describe("The pull request description"),
761
819
  fromRefId: z.string().describe("The source branch reference ID (e.g., 'refs/heads/feature-branch')"),
762
820
  toRefId: z.string().describe("The destination branch reference ID (e.g., 'refs/heads/main')"),
763
- reviewers: z.array(z.string()).optional().describe("Optional array of reviewer usernames")
821
+ reviewers: z.array(z.string()).optional().describe("Optional array of reviewer usernames"),
822
+ output: z.enum(['ack', 'full']).optional().describe("Return a compact acknowledgement or the full API response. Defaults to ack.")
764
823
  },
765
824
  updatePullRequest: {
766
825
  projectKey: z.string().describe("The project key"),
@@ -769,7 +828,8 @@ export const bitbucketToolSchemas = {
769
828
  version: z.number().describe("The current version of the pull request (required for optimistic locking)"),
770
829
  title: z.string().optional().describe("The new title for the pull request"),
771
830
  description: z.string().optional().describe("The new description for the pull request"),
772
- reviewers: z.array(z.string()).optional().describe("Optional array of reviewer usernames to set")
831
+ reviewers: z.array(z.string()).optional().describe("Optional array of reviewer usernames to set"),
832
+ output: z.enum(['ack', 'full']).optional().describe("Return a compact acknowledgement or the full API response. Defaults to ack.")
773
833
  },
774
834
  getRequiredReviewers: {
775
835
  projectKey: z.string().describe("The project key"),
@@ -785,10 +845,10 @@ export const bitbucketToolSchemas = {
785
845
  closedSince: z.number().optional().describe("Timestamp in milliseconds. If state is not OPEN, return only PRs closed after this date"),
786
846
  order: z.enum(['NEWEST', 'OLDEST', 'PARTICIPANT']).optional().default('NEWEST').describe("Order of results: NEWEST (default), OLDEST, or PARTICIPANT"),
787
847
  start: z.number().optional().describe("Start number for pagination"),
788
- limit: z.number().optional().default(10).describe("Number of items to return (default: 10)")
848
+ limit: z.number().optional().describe("Number of items to return. If not passed, the package default page size is used.")
789
849
  },
790
850
  getInboxPullRequests: {
791
851
  start: z.number().optional().describe("Start number for the page (inclusive). If not passed, first page is assumed"),
792
- limit: z.number().optional().default(25).describe("Number of items to return. If not passed, a page size of 25 is used")
852
+ limit: z.number().optional().describe("Number of items to return. If not passed, the package default page size is used.")
793
853
  }
794
854
  };
package/src/config.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { getProductRuntimeConfig, validateProductRuntimeConfig } from '@atlassian-dc-mcp/common';
2
+
3
+ export function getBitbucketRuntimeConfig() {
4
+ return getProductRuntimeConfig('bitbucket');
5
+ }
6
+
7
+ export function getDefaultPageSize() {
8
+ return getBitbucketRuntimeConfig().defaultPageSize;
9
+ }
10
+
11
+ export function getMissingConfig() {
12
+ return validateProductRuntimeConfig('bitbucket');
13
+ }
package/src/index.ts CHANGED
@@ -1,9 +1,8 @@
1
- import { connectServer, createMcpServer, formatToolResponse } from '@atlassian-dc-mcp/common';
2
- import dotenv from 'dotenv';
1
+ import { connectServer, createMcpServer, formatToolResponse, initializeRuntimeConfig } from '@atlassian-dc-mcp/common';
3
2
  import { BitbucketService, bitbucketToolSchemas } from './bitbucket-service.js';
3
+ import { getBitbucketRuntimeConfig, getDefaultPageSize } from './config.js';
4
4
 
5
- // Load environment variables
6
- dotenv.config();
5
+ initializeRuntimeConfig();
7
6
 
8
7
  const missingVars = BitbucketService.validateConfig();
9
8
  if (missingVars.length > 0) {
@@ -11,10 +10,12 @@ if (missingVars.length > 0) {
11
10
  process.exit(1);
12
11
  }
13
12
 
13
+ const bitbucketConfig = getBitbucketRuntimeConfig();
14
14
  const bitbucketService = new BitbucketService(
15
- process.env.BITBUCKET_HOST!,
16
- process.env.BITBUCKET_API_TOKEN!,
17
- process.env.BITBUCKET_API_BASE_PATH,
15
+ bitbucketConfig.host,
16
+ () => getBitbucketRuntimeConfig().token,
17
+ bitbucketConfig.apiBasePath,
18
+ getDefaultPageSize,
18
19
  );
19
20
 
20
21
  const server = createMcpServer({
@@ -96,8 +97,8 @@ server.tool(
96
97
  "bitbucket_getPR_CommentsAndAction",
97
98
  "Get comments for a Bitbucket pull request and other actions, like approvals",
98
99
  bitbucketToolSchemas.getPullRequestComments,
99
- async ({ projectKey, repositorySlug, pullRequestId, start, limit }) => {
100
- const result = await bitbucketService.getPullRequestCommentsAndActions(projectKey, repositorySlug, pullRequestId, start, limit);
100
+ async ({ projectKey, repositorySlug, pullRequestId, start, limit, output }) => {
101
+ const result = await bitbucketService.getPullRequestCommentsAndActions(projectKey, repositorySlug, pullRequestId, start, limit, output);
101
102
  return formatToolResponse(result);
102
103
  }
103
104
  );
@@ -106,8 +107,8 @@ server.tool(
106
107
  "bitbucket_getPullRequestChanges",
107
108
  "Get the changes for a Bitbucket pull request",
108
109
  bitbucketToolSchemas.getPullRequestChanges,
109
- async ({ projectKey, repositorySlug, pullRequestId, sinceId, changeScope, untilId, withComments, start, limit }) => {
110
- const result = await bitbucketService.getPullRequestChanges(projectKey, repositorySlug, pullRequestId, sinceId, changeScope, untilId, withComments, start, limit);
110
+ async ({ projectKey, repositorySlug, pullRequestId, sinceId, changeScope, untilId, withComments, start, limit, output }) => {
111
+ const result = await bitbucketService.getPullRequestChanges(projectKey, repositorySlug, pullRequestId, sinceId, changeScope, untilId, withComments, start, limit, output);
111
112
  return formatToolResponse(result);
112
113
  }
113
114
  );
@@ -126,8 +127,8 @@ server.tool(
126
127
  "bitbucket_postPullRequestComment",
127
128
  "Post a comment to a Bitbucket pull request. Use pending: true to create a draft comment that is only visible to you until you call bitbucket_submitPullRequestReview. NOTE: pending only works when filePath is provided (file-level or inline comments). True top-level PR comments (no filePath) are always posted live and cannot be drafted.",
128
129
  bitbucketToolSchemas.postPullRequestComment,
129
- async ({ projectKey, repositorySlug, pullRequestId, text, parentId, filePath, line, lineType, pending }) => {
130
- const result = await bitbucketService.postPullRequestComment(projectKey, repositorySlug, pullRequestId, text, parentId, filePath, line, lineType, pending);
130
+ async ({ projectKey, repositorySlug, pullRequestId, text, parentId, filePath, line, lineType, pending, output }) => {
131
+ const result = await bitbucketService.postPullRequestComment(projectKey, repositorySlug, pullRequestId, text, parentId, filePath, line, lineType, pending, output);
131
132
  return formatToolResponse(result);
132
133
  }
133
134
  );
@@ -157,8 +158,8 @@ server.tool(
157
158
  "bitbucket_createPullRequest",
158
159
  "Create a new pull request in a Bitbucket repository. IMPORTANT: Before creating a PR, use bitbucket_getRequiredReviewers to fetch required reviewers for the source and target branches to ensure the PR is not created without mandatory reviewers.",
159
160
  bitbucketToolSchemas.createPullRequest,
160
- async ({ projectKey, repositorySlug, title, description, fromRefId, toRefId, reviewers }) => {
161
- const result = await bitbucketService.createPullRequest(projectKey, repositorySlug, title, description, fromRefId, toRefId, reviewers);
161
+ async ({ projectKey, repositorySlug, title, description, fromRefId, toRefId, reviewers, output }) => {
162
+ const result = await bitbucketService.createPullRequest(projectKey, repositorySlug, title, description, fromRefId, toRefId, reviewers, output);
162
163
  return formatToolResponse(result);
163
164
  }
164
165
  );
@@ -167,8 +168,8 @@ server.tool(
167
168
  "bitbucket_updatePullRequest",
168
169
  "Update the title, description, reviewers, destination branch or draft status of an existing pull request. IMPORTANT: The reviewers parameter replaces ALL existing reviewers. If you want to preserve existing reviewers, first fetch the current PR details (using bitbucket_getPullRequests filtered by ID) and include those reviewers along with any new ones you want to add.",
169
170
  bitbucketToolSchemas.updatePullRequest,
170
- async ({ projectKey, repositorySlug, pullRequestId, version, title, description, reviewers }) => {
171
- const result = await bitbucketService.updatePullRequest(projectKey, repositorySlug, pullRequestId, version, title, description, reviewers);
171
+ async ({ projectKey, repositorySlug, pullRequestId, version, title, description, reviewers, output }) => {
172
+ const result = await bitbucketService.updatePullRequest(projectKey, repositorySlug, pullRequestId, version, title, description, reviewers, output);
172
173
  return formatToolResponse(result);
173
174
  }
174
175
  );