@atlassian-dc-mcp/bitbucket 0.9.8 → 0.9.10

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.
@@ -99,6 +99,73 @@ export class BitbucketService {
99
99
  );
100
100
  }
101
101
 
102
+ /**
103
+ * Get pull requests for a repository
104
+ * @param projectKey The project key
105
+ * @param repositorySlug The repository slug
106
+ * @param withAttributes Optional flag to return additional pull request attributes (default: true)
107
+ * @param at Optional fully-qualified branch ID to find pull requests to or from (e.g., refs/heads/master)
108
+ * @param withProperties Optional flag to return additional pull request properties (default: true)
109
+ * @param draft Optional draft status filter
110
+ * @param filterText Optional text filter for title or description
111
+ * @param state Optional state filter (OPEN, DECLINED, MERGED, or ALL; default: OPEN)
112
+ * @param order Optional order (NEWEST or OLDEST; default: NEWEST)
113
+ * @param direction Optional direction relative to repository (INCOMING or OUTGOING; default: INCOMING)
114
+ * @param start Optional pagination start
115
+ * @param limit Optional pagination limit (default: 25)
116
+ * @returns Promise with pull requests data
117
+ */
118
+ async getPullRequests(
119
+ projectKey: string,
120
+ repositorySlug: string,
121
+ withAttributes?: string,
122
+ at?: string,
123
+ withProperties?: string,
124
+ draft?: string,
125
+ filterText?: string,
126
+ state?: string,
127
+ order?: string,
128
+ direction?: string,
129
+ start?: number,
130
+ limit: number = 25
131
+ ) {
132
+ return handleApiOperation(
133
+ () => PullRequestsService.getPage(
134
+ projectKey,
135
+ repositorySlug,
136
+ withAttributes,
137
+ at,
138
+ withProperties,
139
+ draft,
140
+ filterText,
141
+ state,
142
+ order,
143
+ direction,
144
+ start,
145
+ limit
146
+ ),
147
+ 'Error fetching pull requests'
148
+ );
149
+ }
150
+
151
+ /**
152
+ * Get a specific pull request by ID
153
+ * @param projectKey The project key
154
+ * @param repositorySlug The repository slug
155
+ * @param pullRequestId The ID of the pull request within the repository
156
+ * @returns Promise with pull request data
157
+ */
158
+ async getPullRequest(
159
+ projectKey: string,
160
+ repositorySlug: string,
161
+ pullRequestId: string
162
+ ) {
163
+ return handleApiOperation(
164
+ () => PullRequestsService.get3(projectKey, pullRequestId, repositorySlug),
165
+ 'Error fetching pull request'
166
+ );
167
+ }
168
+
102
169
  async getPullRequestCommentsAndActions(projectKey: string, repositorySlug: string, pullRequestId: string, start?: number,
103
170
  limit: number = 25
104
171
  ) {
@@ -293,6 +360,142 @@ export class BitbucketService {
293
360
  );
294
361
  }
295
362
 
363
+ /**
364
+ * Create a pull request
365
+ * @param projectKey The project key
366
+ * @param repositorySlug The repository slug
367
+ * @param title The pull request title
368
+ * @param description Optional pull request description
369
+ * @param fromRefId The source branch (e.g., 'refs/heads/feature-branch')
370
+ * @param toRefId The destination branch (e.g., 'refs/heads/main')
371
+ * @param reviewers Optional array of reviewer usernames
372
+ * @returns Promise with created pull request data
373
+ */
374
+ async createPullRequest(
375
+ projectKey: string,
376
+ repositorySlug: string,
377
+ title: string,
378
+ description: string | undefined,
379
+ fromRefId: string,
380
+ toRefId: string,
381
+ reviewers?: string[]
382
+ ) {
383
+ const pullRequestData: any = {
384
+ title,
385
+ description,
386
+ fromRef: {
387
+ id: fromRefId,
388
+ repository: {
389
+ slug: repositorySlug,
390
+ project: {
391
+ key: projectKey
392
+ }
393
+ }
394
+ },
395
+ toRef: {
396
+ id: toRefId,
397
+ repository: {
398
+ slug: repositorySlug,
399
+ project: {
400
+ key: projectKey
401
+ }
402
+ }
403
+ }
404
+ };
405
+
406
+ if (reviewers && reviewers.length > 0) {
407
+ pullRequestData.reviewers = reviewers.map(username => ({
408
+ user: {
409
+ name: username
410
+ }
411
+ }));
412
+ }
413
+
414
+ return handleApiOperation(
415
+ () => PullRequestsService.create(projectKey, repositorySlug, pullRequestData),
416
+ 'Error creating pull request'
417
+ );
418
+ }
419
+
420
+ /**
421
+ * Update a pull request
422
+ * @param projectKey The project key
423
+ * @param repositorySlug The repository slug
424
+ * @param pullRequestId The pull request ID
425
+ * @param version The version of the pull request (required for optimistic locking)
426
+ * @param title Optional new title for the pull request
427
+ * @param description Optional new description for the pull request
428
+ * @param reviewers Optional array of reviewer usernames to set
429
+ * @returns Promise with updated pull request data
430
+ */
431
+ async updatePullRequest(
432
+ projectKey: string,
433
+ repositorySlug: string,
434
+ pullRequestId: string,
435
+ version: number,
436
+ title?: string,
437
+ description?: string,
438
+ reviewers?: string[]
439
+ ) {
440
+ const pullRequestData: any = {
441
+ version
442
+ };
443
+
444
+ if (title !== undefined) {
445
+ pullRequestData.title = title;
446
+ }
447
+
448
+ if (description !== undefined) {
449
+ pullRequestData.description = description;
450
+ }
451
+
452
+ if (reviewers && reviewers.length > 0) {
453
+ pullRequestData.reviewers = reviewers.map(username => ({
454
+ user: {
455
+ name: username
456
+ }
457
+ }));
458
+ }
459
+
460
+ return handleApiOperation(
461
+ () => PullRequestsService.update(projectKey, pullRequestId, repositorySlug, pullRequestData),
462
+ 'Error updating pull request'
463
+ );
464
+ }
465
+
466
+ /**
467
+ * Get required reviewers for PR creation
468
+ * Returns a set of users who are required reviewers for pull requests created from the given source repository
469
+ * and ref to the given target ref in this repository.
470
+ * @param projectKey The project key
471
+ * @param repositorySlug The repository slug
472
+ * @param sourceRefId The ID of the source ref (e.g., 'refs/heads/feature-branch')
473
+ * @param targetRefId The ID of the target ref (e.g., 'refs/heads/main')
474
+ * @param sourceRepoId Optional ID of the repository in which the source ref exists
475
+ * @param targetRepoId Optional ID of the repository in which the target ref exists
476
+ * @returns Promise with required reviewers data
477
+ */
478
+ async getRequiredReviewers(
479
+ projectKey: string,
480
+ repositorySlug: string,
481
+ sourceRefId: string,
482
+ targetRefId: string,
483
+ sourceRepoId?: string,
484
+ targetRepoId?: string
485
+ ) {
486
+ return handleApiOperation(
487
+ () => PullRequestsService.getReviewers(
488
+ projectKey,
489
+ repositorySlug,
490
+ targetRepoId,
491
+ sourceRepoId,
492
+ sourceRefId,
493
+ targetRefId
494
+ ),
495
+ 'Error fetching required reviewers'
496
+ );
497
+ }
498
+
296
499
  static validateConfig(): string[] {
297
500
  // Check for BITBUCKET_HOST or its alternative BITBUCKET_API_BASE_PATH
298
501
  const requiredEnvVars = ['BITBUCKET_API_TOKEN'] as const;
@@ -314,6 +517,25 @@ export const bitbucketToolSchemas = {
314
517
  start: z.number().optional().describe("Start number for pagination"),
315
518
  limit: z.number().optional().default(25).describe("Number of items to return")
316
519
  },
520
+ getPullRequests: {
521
+ projectKey: z.string().describe("The project key"),
522
+ repositorySlug: z.string().describe("The repository slug"),
523
+ withAttributes: z.string().optional().describe("(optional) defaults to true, whether to return additional pull request attributes"),
524
+ at: z.string().optional().describe("(optional) a fully-qualified branch ID to find pull requests to or from, such as refs/heads/master"),
525
+ withProperties: z.string().optional().describe("(optional) defaults to true, whether to return additional pull request properties"),
526
+ draft: z.string().optional().describe("(optional) If specified, only pull requests matching the supplied draft status will be returned"),
527
+ filterText: z.string().optional().describe("(optional) If specified, only pull requests where the title or description contains the supplied string will be returned"),
528
+ state: z.string().optional().describe("(optional, defaults to OPEN). Supply ALL to return pull request in any state. If a state is supplied only pull requests in the specified state will be returned. Either OPEN, DECLINED or MERGED"),
529
+ order: z.string().optional().describe("(optional, defaults to NEWEST) the order to return pull requests in, either OLDEST (as in: \"oldest first\") or NEWEST"),
530
+ direction: z.string().optional().describe("(optional, defaults to INCOMING) the direction relative to the specified repository. Either INCOMING or OUTGOING"),
531
+ start: z.number().optional().describe("Start number for the page (inclusive). If not passed, first page is assumed"),
532
+ limit: z.number().optional().default(25).describe("Number of items to return. If not passed, a page size of 25 is used")
533
+ },
534
+ getPullRequest: {
535
+ projectKey: z.string().describe("The project key"),
536
+ repositorySlug: z.string().describe("The repository slug"),
537
+ pullRequestId: z.string().describe("The ID of the pull request within the repository")
538
+ },
317
539
  getProject: {
318
540
  projectKey: z.string().describe("The project key")
319
541
  },
@@ -373,5 +595,31 @@ export const bitbucketToolSchemas = {
373
595
  diffType: z.string().optional().describe("The type of diff being requested"),
374
596
  untilId: z.string().optional().describe("The until commit hash to stream a diff between two arbitrary hashes"),
375
597
  whitespace: z.string().optional().describe("Optional whitespace flag which can be set to 'ignore-all'")
598
+ },
599
+ createPullRequest: {
600
+ projectKey: z.string().describe("The project key"),
601
+ repositorySlug: z.string().describe("The repository slug"),
602
+ title: z.string().describe("The pull request title"),
603
+ description: z.string().optional().describe("The pull request description"),
604
+ fromRefId: z.string().describe("The source branch reference ID (e.g., 'refs/heads/feature-branch')"),
605
+ toRefId: z.string().describe("The destination branch reference ID (e.g., 'refs/heads/main')"),
606
+ reviewers: z.array(z.string()).optional().describe("Optional array of reviewer usernames")
607
+ },
608
+ updatePullRequest: {
609
+ projectKey: z.string().describe("The project key"),
610
+ repositorySlug: z.string().describe("The repository slug"),
611
+ pullRequestId: z.string().describe("The pull request ID"),
612
+ version: z.number().describe("The current version of the pull request (required for optimistic locking)"),
613
+ title: z.string().optional().describe("The new title for the pull request"),
614
+ description: z.string().optional().describe("The new description for the pull request"),
615
+ reviewers: z.array(z.string()).optional().describe("Optional array of reviewer usernames to set")
616
+ },
617
+ getRequiredReviewers: {
618
+ projectKey: z.string().describe("The project key"),
619
+ repositorySlug: z.string().describe("The repository slug"),
620
+ sourceRefId: z.string().describe("The ID of the source ref (e.g., 'refs/heads/feature-branch')"),
621
+ targetRefId: z.string().describe("The ID of the target ref (e.g., 'refs/heads/main')"),
622
+ sourceRepoId: z.string().optional().describe("Optional ID of the repository in which the source ref exists"),
623
+ targetRepoId: z.string().optional().describe("Optional ID of the repository in which the target ref exists")
376
624
  }
377
625
  };
package/src/index.ts CHANGED
@@ -72,6 +72,26 @@ server.tool(
72
72
  }
73
73
  );
74
74
 
75
+ server.tool(
76
+ "bitbucket_getPullRequests",
77
+ "Get pull requests for a Bitbucket repository",
78
+ bitbucketToolSchemas.getPullRequests,
79
+ async ({ projectKey, repositorySlug, withAttributes, at, withProperties, draft, filterText, state, order, direction, start, limit }) => {
80
+ const result = await bitbucketService.getPullRequests(projectKey, repositorySlug, withAttributes, at, withProperties, draft, filterText, state, order, direction, start, limit);
81
+ return formatToolResponse(result);
82
+ }
83
+ );
84
+
85
+ server.tool(
86
+ "bitbucket_getPullRequest",
87
+ "Get a specific pull request by ID. Returns full details including title, description, reviewers, participants, author, source/target branches, and current state.",
88
+ bitbucketToolSchemas.getPullRequest,
89
+ async ({ projectKey, repositorySlug, pullRequestId }) => {
90
+ const result = await bitbucketService.getPullRequest(projectKey, repositorySlug, pullRequestId);
91
+ return formatToolResponse(result);
92
+ }
93
+ );
94
+
75
95
  server.tool(
76
96
  "bitbucket_getPR_CommentsAndAction",
77
97
  "Get comments for a Bitbucket pull request and other actions, like approvals",
@@ -113,4 +133,34 @@ server.tool(
113
133
  }
114
134
  );
115
135
 
136
+ server.tool(
137
+ "bitbucket_createPullRequest",
138
+ "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.",
139
+ bitbucketToolSchemas.createPullRequest,
140
+ async ({ projectKey, repositorySlug, title, description, fromRefId, toRefId, reviewers }) => {
141
+ const result = await bitbucketService.createPullRequest(projectKey, repositorySlug, title, description, fromRefId, toRefId, reviewers);
142
+ return formatToolResponse(result);
143
+ }
144
+ );
145
+
146
+ server.tool(
147
+ "bitbucket_updatePullRequest",
148
+ "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.",
149
+ bitbucketToolSchemas.updatePullRequest,
150
+ async ({ projectKey, repositorySlug, pullRequestId, version, title, description, reviewers }) => {
151
+ const result = await bitbucketService.updatePullRequest(projectKey, repositorySlug, pullRequestId, version, title, description, reviewers);
152
+ return formatToolResponse(result);
153
+ }
154
+ );
155
+
156
+ server.tool(
157
+ "bitbucket_getRequiredReviewers",
158
+ "Get required reviewers for pull request creation. Returns a set of users who are required reviewers for pull requests created from the given source repository and ref to the given target ref in this repository.",
159
+ bitbucketToolSchemas.getRequiredReviewers,
160
+ async ({ projectKey, repositorySlug, sourceRefId, targetRefId, sourceRepoId, targetRepoId }) => {
161
+ const result = await bitbucketService.getRequiredReviewers(projectKey, repositorySlug, sourceRefId, targetRefId, sourceRepoId, targetRepoId);
162
+ return formatToolResponse(result);
163
+ }
164
+ );
165
+
116
166
  await connectServer(server);