@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.
- package/CHANGELOG.md +12 -0
- package/README.md +45 -2
- package/build/__tests__/bitbucket-service.test.js +106 -17
- package/build/__tests__/bitbucket-service.test.js.map +1 -1
- package/build/__tests__/bitbucket-token-optimization.test.d.ts +2 -0
- package/build/__tests__/bitbucket-token-optimization.test.d.ts.map +1 -0
- package/build/__tests__/bitbucket-token-optimization.test.js +281 -0
- package/build/__tests__/bitbucket-token-optimization.test.js.map +1 -0
- package/build/__tests__/config.test.d.ts +2 -0
- package/build/__tests__/config.test.d.ts.map +1 -0
- package/build/__tests__/config.test.js +49 -0
- package/build/__tests__/config.test.js.map +1 -0
- package/build/bitbucket-response-mapper.d.ts +8 -0
- package/build/bitbucket-response-mapper.d.ts.map +1 -0
- package/build/bitbucket-response-mapper.js +95 -0
- package/build/bitbucket-response-mapper.js.map +1 -0
- package/build/bitbucket-service.d.ts +24 -22
- package/build/bitbucket-service.d.ts.map +1 -1
- package/build/bitbucket-service.js +88 -54
- package/build/bitbucket-service.js.map +1 -1
- package/build/config.d.ts +4 -0
- package/build/config.d.ts.map +1 -0
- package/build/config.js +11 -0
- package/build/config.js.map +1 -0
- package/build/index.js +15 -15
- package/build/index.js.map +1 -1
- package/package.json +3 -3
- package/server.json +11 -4
- package/src/__tests__/bitbucket-service.test.ts +109 -17
- package/src/__tests__/bitbucket-token-optimization.test.ts +314 -0
- package/src/__tests__/config.test.ts +64 -0
- package/src/bitbucket-response-mapper.ts +112 -0
- package/src/bitbucket-service.ts +117 -57
- package/src/config.ts +13 -0
- package/src/index.ts +18 -17
- package/tsconfig.tsbuildinfo +1 -1
package/src/bitbucket-service.ts
CHANGED
|
@@ -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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
171
|
-
|
|
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:
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
|
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 (
|
|
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
|
|
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
|
-
|
|
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().
|
|
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().
|
|
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().
|
|
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().
|
|
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().
|
|
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().
|
|
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().
|
|
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().
|
|
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
|
-
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
);
|