@stubbedev/atlassian-mcp 0.2.8 → 0.2.9
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/README.md +1 -1
- package/dist/bitbucket.js +26 -3
- package/dist/index.js +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for **s
|
|
|
39
39
|
| `bitbucket_search` | Discover resources: `pull_requests` (default), `repos`, or `branches` via `resource` param; `mine=true` for your inbox |
|
|
40
40
|
| `bitbucket_get_pr` | Full PR details: metadata, commits, comments, blockers, build status, and optional diff |
|
|
41
41
|
| `bitbucket_mutate` | Create/update a PR, or perform lifecycle actions: `approve`, `unapprove`, `merge`, `decline` |
|
|
42
|
-
| `bitbucket_comment` | Add, update, or delete a PR comment;
|
|
42
|
+
| `bitbucket_comment` | Add, update, or delete a PR comment; for code changes use `suggestion` so Bitbucket shows Apply suggestion (no trailing text after a suggestion block) |
|
|
43
43
|
| `bitbucket_get_file` | Raw file content from Bitbucket at a branch, tag, or commit |
|
|
44
44
|
| `bitbucket_pr_tasks` | Manage PR tasks (checklist items): `list`, `create`, `resolve`, `reopen`, `delete` |
|
|
45
45
|
|
package/dist/bitbucket.js
CHANGED
|
@@ -180,6 +180,18 @@ function validateCommentText(textValue) {
|
|
|
180
180
|
}
|
|
181
181
|
return trimmed;
|
|
182
182
|
}
|
|
183
|
+
function validateSuggestionPlacement(textValue) {
|
|
184
|
+
if (!textValue.includes('```suggestion'))
|
|
185
|
+
return;
|
|
186
|
+
const match = textValue.match(/```suggestion[^\n]*\n[\s\S]*?\n```/);
|
|
187
|
+
if (!match || match.index === undefined) {
|
|
188
|
+
throw new Error('Invalid suggestion block format. Use the suggestion field to post code suggestions.');
|
|
189
|
+
}
|
|
190
|
+
const trailingText = textValue.slice(match.index + match[0].length).trim();
|
|
191
|
+
if (trailingText.length > 0) {
|
|
192
|
+
throw new Error('When using ```suggestion```, do not add text after the closing code fence. Put any explanation before the suggestion block or use the suggestion field.');
|
|
193
|
+
}
|
|
194
|
+
}
|
|
183
195
|
export class BitbucketClient {
|
|
184
196
|
baseUrl;
|
|
185
197
|
headers;
|
|
@@ -810,10 +822,21 @@ export class BitbucketClient {
|
|
|
810
822
|
|| args.multilineStartLineType !== undefined)) {
|
|
811
823
|
throw new Error('Replies must target an existing comment thread only. Omit filePath/line and other anchor fields when replying.');
|
|
812
824
|
}
|
|
813
|
-
|
|
825
|
+
if (args.text === undefined && args.suggestion === undefined) {
|
|
826
|
+
throw new Error('Either text or suggestion is required when adding a comment.');
|
|
827
|
+
}
|
|
828
|
+
let commentText = args.text ?? '';
|
|
814
829
|
if (args.suggestion !== undefined) {
|
|
815
|
-
const
|
|
816
|
-
|
|
830
|
+
const suggestion = args.suggestion.trim();
|
|
831
|
+
if (!suggestion) {
|
|
832
|
+
throw new Error('suggestion must not be empty.');
|
|
833
|
+
}
|
|
834
|
+
const suggestionBlock = `\`\`\`suggestion\n${suggestion}\n\`\`\``;
|
|
835
|
+
const prefix = (args.text ?? '').trim();
|
|
836
|
+
commentText = prefix ? `${prefix}\n\n${suggestionBlock}` : suggestionBlock;
|
|
837
|
+
}
|
|
838
|
+
else {
|
|
839
|
+
validateSuggestionPlacement(commentText);
|
|
817
840
|
}
|
|
818
841
|
const body = { text: validateCommentText(commentText) };
|
|
819
842
|
if (args.severity)
|
package/dist/index.js
CHANGED
|
@@ -348,7 +348,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
348
348
|
},
|
|
349
349
|
{
|
|
350
350
|
name: 'bitbucket_comment',
|
|
351
|
-
description: `Add, update, or delete a PR comment. action defaults to "add". For
|
|
351
|
+
description: `Add, update, or delete a PR comment. action defaults to "add". For code changes, ALWAYS use inline comments with suggestion when exact replacement code is available. Keep any explanatory text before the suggestion block only (never after), or Bitbucket may hide Apply suggestion. Replies MUST use commentId. Keep comments concise, no emojis. Only call proactively (without being asked) when you are a reviewer on the PR (i.e. "Viewing as" says "you are a reviewer") — never post unsolicited comments on PRs you authored.`,
|
|
352
352
|
inputSchema: {
|
|
353
353
|
type: 'object',
|
|
354
354
|
properties: {
|
|
@@ -359,7 +359,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
359
359
|
repo: { type: 'string', description: 'Alias for repoSlug' },
|
|
360
360
|
prId: { type: 'number', description: 'Pull request number' },
|
|
361
361
|
commentId: { type: 'number', description: 'Comment ID to reply to, update, or delete' },
|
|
362
|
-
text: { type: 'string', description: 'Comment text. No filler, no emojis.
|
|
362
|
+
text: { type: 'string', description: 'Comment text for add/update. No filler, no emojis. If suggestion is used, keep this optional and brief; it is placed before the suggestion block.' },
|
|
363
363
|
filePath: { type: 'string', description: 'File path for inline comment (must pair with line)' },
|
|
364
364
|
srcPath: { type: 'string', description: 'Source path if file was renamed (optional, defaults to filePath)' },
|
|
365
365
|
line: { type: 'number', description: 'Line number to anchor inline comment (must pair with filePath)' },
|
|
@@ -367,7 +367,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
367
367
|
fileType: { type: 'string', enum: ['TO', 'FROM'], description: 'Diff side: TO (new, default) or FROM (old)' },
|
|
368
368
|
multilineStartLine: { type: 'number', description: 'First line of multiline anchor (pair with line as last line)' },
|
|
369
369
|
multilineStartLineType: { type: 'string', enum: ['ADDED', 'REMOVED', 'CONTEXT'], description: 'Line type for multilineStartLine' },
|
|
370
|
-
suggestion: { type: 'string', description: 'Replacement code to suggest
|
|
370
|
+
suggestion: { type: 'string', description: 'Replacement code to suggest. Use whenever proposing a concrete code change. Posted as the final ```suggestion``` block so Apply suggestion appears. Requires filePath + line.' },
|
|
371
371
|
state: { type: 'string', enum: ['OPEN', 'RESOLVED'], description: 'Task state for BLOCKER comments (update only)' },
|
|
372
372
|
threadResolved: { type: 'boolean', description: 'Resolve/reopen normal comment thread (update only)' },
|
|
373
373
|
severity: { type: 'string', enum: ['NORMAL', 'BLOCKER'], description: 'Comment severity. BLOCKER = checklist task.' },
|