@stubbedev/atlassian-mcp 0.1.9 → 0.1.11

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/dist/bitbucket.js CHANGED
@@ -442,8 +442,8 @@ export class BitbucketClient {
442
442
  const existing = await this.request('GET', `/projects/${projectKey}/repos/${repoSlug}/pull-requests/${args.prId}`);
443
443
  if (!existing)
444
444
  throw new Error(`PR #${args.prId} not found.`);
445
- const buildBody = (version) => {
446
- const body = { version };
445
+ const buildBody = (pr) => {
446
+ const body = { version: pr.version };
447
447
  if (args.title !== undefined)
448
448
  body.title = args.title;
449
449
  if (args.description !== undefined)
@@ -454,14 +454,16 @@ export class BitbucketClient {
454
454
  repository: { slug: repoSlug, project: { key: projectKey } },
455
455
  };
456
456
  }
457
- if (args.reviewers !== undefined) {
458
- body.reviewers = args.reviewers.map((name) => ({ user: { name } }));
459
- }
457
+ // Always include reviewers to avoid Bitbucket clearing them on PUT.
458
+ // Only replace them when explicitly provided by the caller.
459
+ body.reviewers = args.reviewers !== undefined
460
+ ? args.reviewers.map((name) => ({ user: { name } }))
461
+ : pr.reviewers.map((r) => ({ user: { name: r.user.name } }));
460
462
  return body;
461
463
  };
462
464
  let updated;
463
465
  try {
464
- updated = await this.request('PUT', `/projects/${projectKey}/repos/${repoSlug}/pull-requests/${args.prId}`, buildBody(existing.version));
466
+ updated = await this.request('PUT', `/projects/${projectKey}/repos/${repoSlug}/pull-requests/${args.prId}`, buildBody(existing));
465
467
  }
466
468
  catch (error) {
467
469
  const message = error instanceof Error ? error.message : String(error);
@@ -470,7 +472,7 @@ export class BitbucketClient {
470
472
  const latest = await this.request('GET', `/projects/${projectKey}/repos/${repoSlug}/pull-requests/${args.prId}`);
471
473
  if (!latest)
472
474
  throw error;
473
- updated = await this.request('PUT', `/projects/${projectKey}/repos/${repoSlug}/pull-requests/${args.prId}`, buildBody(latest.version));
475
+ updated = await this.request('PUT', `/projects/${projectKey}/repos/${repoSlug}/pull-requests/${args.prId}`, buildBody(latest));
474
476
  }
475
477
  if (!updated)
476
478
  return text(`Updated PR #${args.prId}.`);
@@ -678,16 +680,40 @@ export class BitbucketClient {
678
680
  }
679
681
  async addPrComment(args) {
680
682
  const { projectKey, repoSlug } = this.resolveProjectAndRepo(args.projectKey, args.repoSlug);
681
- const body = { text: validateCommentText(args.text) };
683
+ let commentText = args.text;
684
+ if (args.suggestion !== undefined) {
685
+ const suggestionBlock = `\`\`\`suggestion\n${args.suggestion}\n\`\`\``;
686
+ commentText = args.text ? `${args.text}\n\n${suggestionBlock}` : suggestionBlock;
687
+ }
688
+ const body = { text: validateCommentText(commentText) };
682
689
  if (args.parentCommentId)
683
690
  body.parent = { id: args.parentCommentId };
691
+ if (args.filePath !== undefined && args.line !== undefined) {
692
+ const pr = await this.request('GET', `/projects/${projectKey}/repos/${repoSlug}/pull-requests/${args.prId}`);
693
+ const anchor = {
694
+ diffType: 'EFFECTIVE',
695
+ fileType: args.fileType ?? 'TO',
696
+ fromHash: pr?.fromRef.latestCommit ?? '',
697
+ toHash: pr?.toRef.latestCommit ?? '',
698
+ line: args.line,
699
+ lineType: args.lineType ?? 'ADDED',
700
+ path: args.filePath,
701
+ srcPath: args.srcPath ?? args.filePath,
702
+ };
703
+ if (args.multilineStartLine !== undefined) {
704
+ anchor.multilineStartLine = args.multilineStartLine;
705
+ anchor.multilineStartLineType = args.multilineStartLineType ?? args.lineType ?? 'ADDED';
706
+ }
707
+ body.anchor = anchor;
708
+ }
684
709
  const created = await this.request('POST', `/projects/${projectKey}/repos/${repoSlug}/pull-requests/${args.prId}/comments`, body);
685
710
  if (!created)
686
711
  return text(`Comment added to PR #${args.prId}.`);
687
712
  if (args.parentCommentId) {
688
713
  return text(`Reply #${created.id} added to comment #${args.parentCommentId} on PR #${args.prId}.`);
689
714
  }
690
- return text(`Comment #${created.id} added to PR #${args.prId}.`);
715
+ const location = args.filePath && args.line ? ` on ${args.filePath}:${args.line}` : '';
716
+ return text(`Comment #${created.id} added to PR #${args.prId}${location}.`);
691
717
  }
692
718
  async updatePrComment(args) {
693
719
  const { projectKey, repoSlug } = this.resolveProjectAndRepo(args.projectKey, args.repoSlug);
package/dist/index.js CHANGED
@@ -569,7 +569,13 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
569
569
  },
570
570
  {
571
571
  name: 'bitbucket_add_pr_comment',
572
- description: 'Use when you want to add a PR review comment or reply to an existing thread. Keep comments concise, plain text, and free of filler. Never include emojis. You can pass projectKey/repoSlug or project/repo.',
572
+ description: `Add a PR review comment or reply to an existing thread.
573
+
574
+ INLINE COMMENTS ARE STRONGLY PREFERRED: Whenever your comment refers to a specific line or block of code, you MUST provide filePath and line to anchor it as an inline comment on the diff. General top-level comments (no filePath/line) should only be used for overall PR feedback that does not relate to any particular line.
575
+
576
+ SUGGESTIONS ARE STRONGLY PREFERRED OVER PLAIN COMMENTS: When you are pointing out something that should be changed, always provide a suggestion (the corrected code) rather than describing the change in words. A suggestion lets the author apply the fix with one click. Only omit suggestion if you are asking a question or raising a concern that has no clear single answer.
577
+
578
+ Keep comments concise, plain text, and free of filler. Never include emojis. You can pass projectKey/repoSlug or project/repo.`,
573
579
  inputSchema: {
574
580
  type: 'object',
575
581
  properties: {
@@ -579,7 +585,15 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
579
585
  repo: { type: 'string', description: 'Alias for repoSlug' },
580
586
  prId: { type: 'number', description: 'Pull request number (PR ID)' },
581
587
  parentCommentId: { type: 'number', description: 'Parent comment ID for reply mode (optional)' },
582
- text: { type: 'string', description: 'Concise comment text only. No filler. Do not include emojis.' },
588
+ text: { type: 'string', description: 'Concise comment text. No filler. Do not include emojis. If suggestion is also provided, this text appears above the suggestion block.' },
589
+ filePath: { type: 'string', description: 'Destination file path for inline comment, e.g. "src/index.ts". Must be provided together with line.' },
590
+ srcPath: { type: 'string', description: 'Source file path. Only needed when the file was renamed; otherwise omit (defaults to filePath).' },
591
+ line: { type: 'number', description: 'Line number in the file to anchor the comment to. Must be provided together with filePath.' },
592
+ lineType: { type: 'string', enum: ['ADDED', 'REMOVED', 'CONTEXT'], description: 'The type of the anchored line in the diff. Defaults to ADDED. Use CONTEXT for unchanged lines, REMOVED for deleted lines.' },
593
+ fileType: { type: 'string', enum: ['TO', 'FROM'], description: 'Which side of the diff the anchor refers to: TO (destination/new file, default) or FROM (source/old file).' },
594
+ multilineStartLine: { type: 'number', description: 'First line of a multiline anchor. Set together with line (last line) to span multiple lines.' },
595
+ multilineStartLineType: { type: 'string', enum: ['ADDED', 'REMOVED', 'CONTEXT'], description: 'Line type for the multilineStartLine. Defaults to lineType.' },
596
+ suggestion: { type: 'string', description: 'Replacement code to suggest. Rendered as a suggestion block the author can apply with one click. STRONGLY PREFERRED whenever you are proposing a code change. Must be used with filePath and line.' },
583
597
  },
584
598
  required: ['prId', 'text'],
585
599
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stubbedev/atlassian-mcp",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "MCP server for self-hosted Jira and Bitbucket",
5
5
  "license": "MIT",
6
6
  "type": "module",