@jagadeesh52423/atlassian-mcp-server 1.0.2 → 1.0.3
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/clients/base-client.d.ts +26 -0
- package/dist/clients/base-client.d.ts.map +1 -0
- package/dist/clients/base-client.js +58 -0
- package/dist/clients/base-client.js.map +1 -0
- package/dist/clients/bitbucket-client.d.ts +17 -0
- package/dist/clients/bitbucket-client.d.ts.map +1 -0
- package/dist/clients/bitbucket-client.js +36 -0
- package/dist/clients/bitbucket-client.js.map +1 -0
- package/dist/clients/confluence-client.d.ts +8 -0
- package/dist/clients/confluence-client.d.ts.map +1 -0
- package/dist/clients/confluence-client.js +16 -0
- package/dist/clients/confluence-client.js.map +1 -0
- package/dist/clients/index.d.ts +5 -0
- package/dist/clients/index.d.ts.map +1 -0
- package/dist/clients/index.js +5 -0
- package/dist/clients/index.js.map +1 -0
- package/dist/clients/jira-client.d.ts +8 -0
- package/dist/clients/jira-client.d.ts.map +1 -0
- package/dist/clients/jira-client.js +16 -0
- package/dist/clients/jira-client.js.map +1 -0
- package/dist/constants.d.ts +67 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +78 -0
- package/dist/constants.js.map +1 -0
- package/dist/error-handler.d.ts +77 -0
- package/dist/error-handler.d.ts.map +1 -0
- package/dist/error-handler.js +135 -0
- package/dist/error-handler.js.map +1 -0
- package/dist/formatters/adf-formatter.d.ts +25 -0
- package/dist/formatters/adf-formatter.d.ts.map +1 -0
- package/dist/formatters/adf-formatter.js +609 -0
- package/dist/formatters/adf-formatter.js.map +1 -0
- package/dist/formatters/index.d.ts +2 -0
- package/dist/formatters/index.d.ts.map +1 -0
- package/dist/formatters/index.js +2 -0
- package/dist/formatters/index.js.map +1 -0
- package/dist/handlers/bitbucket-handlers.d.ts +94 -0
- package/dist/handlers/bitbucket-handlers.d.ts.map +1 -0
- package/dist/handlers/bitbucket-handlers.js +251 -0
- package/dist/handlers/bitbucket-handlers.js.map +1 -0
- package/dist/handlers/confluence-handlers.d.ts +84 -0
- package/dist/handlers/confluence-handlers.d.ts.map +1 -0
- package/dist/handlers/confluence-handlers.js +255 -0
- package/dist/handlers/confluence-handlers.js.map +1 -0
- package/dist/handlers/index.d.ts +4 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +4 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/handlers/jira-handlers.d.ts +153 -0
- package/dist/handlers/jira-handlers.d.ts.map +1 -0
- package/dist/handlers/jira-handlers.js +577 -0
- package/dist/handlers/jira-handlers.js.map +1 -0
- package/dist/index.js +147 -2536
- package/dist/index.js.map +1 -1
- package/dist/services/bitbucket.d.ts +11 -1
- package/dist/services/bitbucket.d.ts.map +1 -1
- package/dist/services/bitbucket.js +78 -0
- package/dist/services/bitbucket.js.map +1 -1
- package/dist/services/confluence.d.ts.map +1 -1
- package/dist/services/confluence.js +5 -4
- package/dist/services/confluence.js.map +1 -1
- package/dist/services/jira.d.ts +4 -0
- package/dist/services/jira.d.ts.map +1 -1
- package/dist/services/jira.js +159 -24
- package/dist/services/jira.js.map +1 -1
- package/dist/tools/bitbucket-tools.d.ts +6 -0
- package/dist/tools/bitbucket-tools.d.ts.map +1 -0
- package/dist/tools/bitbucket-tools.js +386 -0
- package/dist/tools/bitbucket-tools.js.map +1 -0
- package/dist/tools/confluence-tools.d.ts +17 -0
- package/dist/tools/confluence-tools.d.ts.map +1 -0
- package/dist/tools/confluence-tools.js +337 -0
- package/dist/tools/confluence-tools.js.map +1 -0
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +15 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/jira-tools.d.ts +6 -0
- package/dist/tools/jira-tools.d.ts.map +1 -0
- package/dist/tools/jira-tools.js +656 -0
- package/dist/tools/jira-tools.js.map +1 -0
- package/dist/types.d.ts +23 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,6 +6,13 @@ import { validateConfig } from './config.js';
|
|
|
6
6
|
import { ConfluenceService } from './services/confluence.js';
|
|
7
7
|
import { JiraService } from './services/jira.js';
|
|
8
8
|
import { BitbucketService } from './services/bitbucket.js';
|
|
9
|
+
// Import modular tool definitions
|
|
10
|
+
import { allTools } from './tools/index.js';
|
|
11
|
+
// Import modular handlers
|
|
12
|
+
import { ConfluenceHandlers } from './handlers/confluence-handlers.js';
|
|
13
|
+
import { JiraHandlers } from './handlers/jira-handlers.js';
|
|
14
|
+
import { BitbucketHandlers } from './handlers/bitbucket-handlers.js';
|
|
15
|
+
import { ERROR_MESSAGES } from './constants.js';
|
|
9
16
|
const server = new Server({
|
|
10
17
|
name: 'atlassian-mcp-server',
|
|
11
18
|
version: '1.0.0',
|
|
@@ -14,2554 +21,158 @@ const server = new Server({
|
|
|
14
21
|
tools: {},
|
|
15
22
|
},
|
|
16
23
|
});
|
|
24
|
+
// Initialize services
|
|
17
25
|
const confluenceService = new ConfluenceService();
|
|
18
26
|
const jiraService = new JiraService();
|
|
19
27
|
const bitbucketService = new BitbucketService();
|
|
28
|
+
// Initialize handlers
|
|
29
|
+
const confluenceHandlers = new ConfluenceHandlers(confluenceService);
|
|
30
|
+
const jiraHandlers = new JiraHandlers(jiraService);
|
|
31
|
+
const bitbucketHandlers = new BitbucketHandlers(bitbucketService);
|
|
32
|
+
/**
|
|
33
|
+
* List all available tools
|
|
34
|
+
*/
|
|
20
35
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
21
|
-
return {
|
|
22
|
-
tools: [
|
|
23
|
-
// Confluence Tools
|
|
24
|
-
{
|
|
25
|
-
name: 'confluence_search_pages',
|
|
26
|
-
description: 'Search Confluence pages by text query',
|
|
27
|
-
inputSchema: {
|
|
28
|
-
type: 'object',
|
|
29
|
-
properties: {
|
|
30
|
-
query: {
|
|
31
|
-
type: 'string',
|
|
32
|
-
description: 'Text to search for in pages'
|
|
33
|
-
},
|
|
34
|
-
limit: {
|
|
35
|
-
type: 'number',
|
|
36
|
-
description: 'Maximum number of results (default: 25)',
|
|
37
|
-
default: 25
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
name: 'confluence_get_page',
|
|
44
|
-
description: 'Get a specific Confluence page by ID',
|
|
45
|
-
inputSchema: {
|
|
46
|
-
type: 'object',
|
|
47
|
-
properties: {
|
|
48
|
-
pageId: {
|
|
49
|
-
type: 'string',
|
|
50
|
-
description: 'The page ID to retrieve'
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
required: ['pageId']
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
name: 'confluence_create_page',
|
|
58
|
-
description: 'Create a new Confluence page',
|
|
59
|
-
inputSchema: {
|
|
60
|
-
type: 'object',
|
|
61
|
-
properties: {
|
|
62
|
-
spaceKey: {
|
|
63
|
-
type: 'string',
|
|
64
|
-
description: 'The space key where to create the page'
|
|
65
|
-
},
|
|
66
|
-
title: {
|
|
67
|
-
type: 'string',
|
|
68
|
-
description: 'Page title'
|
|
69
|
-
},
|
|
70
|
-
content: {
|
|
71
|
-
type: 'string',
|
|
72
|
-
description: 'Page content in Confluence storage format'
|
|
73
|
-
},
|
|
74
|
-
parentId: {
|
|
75
|
-
type: 'string',
|
|
76
|
-
description: 'Optional parent page ID'
|
|
77
|
-
},
|
|
78
|
-
images: {
|
|
79
|
-
type: 'array',
|
|
80
|
-
description: 'Optional array of images to upload and embed. Use {{IMAGE:filename}} placeholders in content to position images inline, or they will be appended at the end. Provide either filePath or fileContent for each image.',
|
|
81
|
-
items: {
|
|
82
|
-
type: 'object',
|
|
83
|
-
properties: {
|
|
84
|
-
filePath: {
|
|
85
|
-
type: 'string',
|
|
86
|
-
description: 'Local file path (e.g., "/path/to/image.png"). Filename is auto-detected. Use {{IMAGE:image.png}} in content.'
|
|
87
|
-
},
|
|
88
|
-
filename: {
|
|
89
|
-
type: 'string',
|
|
90
|
-
description: 'Image filename (optional if filePath provided). Use {{IMAGE:filename}} in content to position it.'
|
|
91
|
-
},
|
|
92
|
-
fileContent: {
|
|
93
|
-
type: 'string',
|
|
94
|
-
description: 'Base64 encoded image content (alternative to filePath)'
|
|
95
|
-
},
|
|
96
|
-
alt: {
|
|
97
|
-
type: 'string',
|
|
98
|
-
description: 'Optional alt text for the image'
|
|
99
|
-
},
|
|
100
|
-
caption: {
|
|
101
|
-
type: 'string',
|
|
102
|
-
description: 'Optional caption to display below the image'
|
|
103
|
-
},
|
|
104
|
-
width: {
|
|
105
|
-
type: 'number',
|
|
106
|
-
description: 'Optional width in pixels'
|
|
107
|
-
},
|
|
108
|
-
align: {
|
|
109
|
-
type: 'string',
|
|
110
|
-
enum: ['left', 'center', 'right'],
|
|
111
|
-
description: 'Optional alignment'
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
required: []
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
},
|
|
118
|
-
required: ['spaceKey', 'title', 'content']
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
name: 'confluence_update_page',
|
|
123
|
-
description: 'Update an existing Confluence page',
|
|
124
|
-
inputSchema: {
|
|
125
|
-
type: 'object',
|
|
126
|
-
properties: {
|
|
127
|
-
pageId: {
|
|
128
|
-
type: 'string',
|
|
129
|
-
description: 'The page ID to update'
|
|
130
|
-
},
|
|
131
|
-
title: {
|
|
132
|
-
type: 'string',
|
|
133
|
-
description: 'New page title'
|
|
134
|
-
},
|
|
135
|
-
content: {
|
|
136
|
-
type: 'string',
|
|
137
|
-
description: 'New page content in Confluence storage format'
|
|
138
|
-
},
|
|
139
|
-
version: {
|
|
140
|
-
type: 'number',
|
|
141
|
-
description: 'Current version number of the page'
|
|
142
|
-
}
|
|
143
|
-
},
|
|
144
|
-
required: ['pageId', 'title', 'content', 'version']
|
|
145
|
-
}
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
name: 'confluence_get_spaces',
|
|
149
|
-
description: 'Get list of Confluence spaces',
|
|
150
|
-
inputSchema: {
|
|
151
|
-
type: 'object',
|
|
152
|
-
properties: {
|
|
153
|
-
limit: {
|
|
154
|
-
type: 'number',
|
|
155
|
-
description: 'Maximum number of spaces to return (default: 25)',
|
|
156
|
-
default: 25
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
name: 'confluence_get_pages_by_space',
|
|
163
|
-
description: 'Get pages from a specific Confluence space',
|
|
164
|
-
inputSchema: {
|
|
165
|
-
type: 'object',
|
|
166
|
-
properties: {
|
|
167
|
-
spaceKey: {
|
|
168
|
-
type: 'string',
|
|
169
|
-
description: 'The space key to get pages from'
|
|
170
|
-
},
|
|
171
|
-
limit: {
|
|
172
|
-
type: 'number',
|
|
173
|
-
description: 'Maximum number of pages to return (default: 25)',
|
|
174
|
-
default: 25
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
required: ['spaceKey']
|
|
178
|
-
}
|
|
179
|
-
},
|
|
180
|
-
{
|
|
181
|
-
name: 'confluence_get_attachments',
|
|
182
|
-
description: 'Get all attachments for a Confluence page',
|
|
183
|
-
inputSchema: {
|
|
184
|
-
type: 'object',
|
|
185
|
-
properties: {
|
|
186
|
-
pageId: {
|
|
187
|
-
type: 'string',
|
|
188
|
-
description: 'The page ID to get attachments for'
|
|
189
|
-
}
|
|
190
|
-
},
|
|
191
|
-
required: ['pageId']
|
|
192
|
-
}
|
|
193
|
-
},
|
|
194
|
-
{
|
|
195
|
-
name: 'confluence_add_attachment',
|
|
196
|
-
description: 'Add an attachment to a Confluence page. Provide either filePath (local file) or fileContent (base64).',
|
|
197
|
-
inputSchema: {
|
|
198
|
-
type: 'object',
|
|
199
|
-
properties: {
|
|
200
|
-
pageId: {
|
|
201
|
-
type: 'string',
|
|
202
|
-
description: 'The page ID to attach file to'
|
|
203
|
-
},
|
|
204
|
-
filePath: {
|
|
205
|
-
type: 'string',
|
|
206
|
-
description: 'Local file path to attach (e.g., "/path/to/file.svg"). If provided, filename is auto-detected.'
|
|
207
|
-
},
|
|
208
|
-
filename: {
|
|
209
|
-
type: 'string',
|
|
210
|
-
description: 'The filename for the attachment (optional if filePath is provided)'
|
|
211
|
-
},
|
|
212
|
-
fileContent: {
|
|
213
|
-
type: 'string',
|
|
214
|
-
description: 'Base64 encoded file content (alternative to filePath)'
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
required: ['pageId']
|
|
218
|
-
}
|
|
219
|
-
},
|
|
220
|
-
{
|
|
221
|
-
name: 'confluence_delete_attachment',
|
|
222
|
-
description: 'Delete an attachment from a Confluence page',
|
|
223
|
-
inputSchema: {
|
|
224
|
-
type: 'object',
|
|
225
|
-
properties: {
|
|
226
|
-
attachmentId: {
|
|
227
|
-
type: 'string',
|
|
228
|
-
description: 'The attachment ID to delete'
|
|
229
|
-
}
|
|
230
|
-
},
|
|
231
|
-
required: ['attachmentId']
|
|
232
|
-
}
|
|
233
|
-
},
|
|
234
|
-
{
|
|
235
|
-
name: 'confluence_embed_image',
|
|
236
|
-
description: 'Attach an image to a Confluence page and embed it in the content. Provide either filePath (local file) or fileContent (base64).',
|
|
237
|
-
inputSchema: {
|
|
238
|
-
type: 'object',
|
|
239
|
-
properties: {
|
|
240
|
-
pageId: {
|
|
241
|
-
type: 'string',
|
|
242
|
-
description: 'The page ID to embed the image in'
|
|
243
|
-
},
|
|
244
|
-
filePath: {
|
|
245
|
-
type: 'string',
|
|
246
|
-
description: 'Local file path to the image (e.g., "/path/to/diagram.svg"). If provided, filename is auto-detected.'
|
|
247
|
-
},
|
|
248
|
-
filename: {
|
|
249
|
-
type: 'string',
|
|
250
|
-
description: 'The filename for the image (optional if filePath is provided)'
|
|
251
|
-
},
|
|
252
|
-
fileContent: {
|
|
253
|
-
type: 'string',
|
|
254
|
-
description: 'Base64 encoded image content (alternative to filePath)'
|
|
255
|
-
},
|
|
256
|
-
alt: {
|
|
257
|
-
type: 'string',
|
|
258
|
-
description: 'Alt text for the image (defaults to filename)'
|
|
259
|
-
},
|
|
260
|
-
caption: {
|
|
261
|
-
type: 'string',
|
|
262
|
-
description: 'Optional caption to display below the image'
|
|
263
|
-
},
|
|
264
|
-
width: {
|
|
265
|
-
type: 'number',
|
|
266
|
-
description: 'Optional width in pixels for the image'
|
|
267
|
-
},
|
|
268
|
-
align: {
|
|
269
|
-
type: 'string',
|
|
270
|
-
enum: ['left', 'center', 'right'],
|
|
271
|
-
description: 'Image alignment (default: no alignment)'
|
|
272
|
-
},
|
|
273
|
-
position: {
|
|
274
|
-
type: 'string',
|
|
275
|
-
enum: ['top', 'bottom', 'after-heading'],
|
|
276
|
-
description: 'Where to insert the image (default: bottom)'
|
|
277
|
-
},
|
|
278
|
-
headingText: {
|
|
279
|
-
type: 'string',
|
|
280
|
-
description: 'If position is "after-heading", the heading text to insert after'
|
|
281
|
-
}
|
|
282
|
-
},
|
|
283
|
-
required: ['pageId']
|
|
284
|
-
}
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
name: 'confluence_get_comments',
|
|
288
|
-
description: 'Get all comments for a Confluence page',
|
|
289
|
-
inputSchema: {
|
|
290
|
-
type: 'object',
|
|
291
|
-
properties: {
|
|
292
|
-
pageId: {
|
|
293
|
-
type: 'string',
|
|
294
|
-
description: 'The page ID to get comments for'
|
|
295
|
-
}
|
|
296
|
-
},
|
|
297
|
-
required: ['pageId']
|
|
298
|
-
}
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
name: 'confluence_add_comment',
|
|
302
|
-
description: 'Add a comment to a Confluence page',
|
|
303
|
-
inputSchema: {
|
|
304
|
-
type: 'object',
|
|
305
|
-
properties: {
|
|
306
|
-
pageId: {
|
|
307
|
-
type: 'string',
|
|
308
|
-
description: 'The page ID to add comment to'
|
|
309
|
-
},
|
|
310
|
-
body: {
|
|
311
|
-
type: 'string',
|
|
312
|
-
description: 'Comment content in Confluence storage format (HTML)'
|
|
313
|
-
}
|
|
314
|
-
},
|
|
315
|
-
required: ['pageId', 'body']
|
|
316
|
-
}
|
|
317
|
-
},
|
|
318
|
-
{
|
|
319
|
-
name: 'confluence_update_comment',
|
|
320
|
-
description: 'Update an existing comment on a Confluence page',
|
|
321
|
-
inputSchema: {
|
|
322
|
-
type: 'object',
|
|
323
|
-
properties: {
|
|
324
|
-
commentId: {
|
|
325
|
-
type: 'string',
|
|
326
|
-
description: 'The comment ID to update'
|
|
327
|
-
},
|
|
328
|
-
body: {
|
|
329
|
-
type: 'string',
|
|
330
|
-
description: 'New comment content in Confluence storage format (HTML)'
|
|
331
|
-
},
|
|
332
|
-
version: {
|
|
333
|
-
type: 'number',
|
|
334
|
-
description: 'Current version number of the comment'
|
|
335
|
-
}
|
|
336
|
-
},
|
|
337
|
-
required: ['commentId', 'body', 'version']
|
|
338
|
-
}
|
|
339
|
-
},
|
|
340
|
-
{
|
|
341
|
-
name: 'confluence_delete_comment',
|
|
342
|
-
description: 'Delete a comment from a Confluence page',
|
|
343
|
-
inputSchema: {
|
|
344
|
-
type: 'object',
|
|
345
|
-
properties: {
|
|
346
|
-
commentId: {
|
|
347
|
-
type: 'string',
|
|
348
|
-
description: 'The comment ID to delete'
|
|
349
|
-
}
|
|
350
|
-
},
|
|
351
|
-
required: ['commentId']
|
|
352
|
-
}
|
|
353
|
-
},
|
|
354
|
-
// Jira Tools
|
|
355
|
-
{
|
|
356
|
-
name: 'jira_search_issues',
|
|
357
|
-
description: 'Search Jira issues by text query',
|
|
358
|
-
inputSchema: {
|
|
359
|
-
type: 'object',
|
|
360
|
-
properties: {
|
|
361
|
-
query: {
|
|
362
|
-
type: 'string',
|
|
363
|
-
description: 'Text to search for in issues'
|
|
364
|
-
},
|
|
365
|
-
limit: {
|
|
366
|
-
type: 'number',
|
|
367
|
-
description: 'Maximum number of results (default: 50)',
|
|
368
|
-
default: 50
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
},
|
|
373
|
-
{
|
|
374
|
-
name: 'jira_get_issue',
|
|
375
|
-
description: 'Get a specific Jira issue by key',
|
|
376
|
-
inputSchema: {
|
|
377
|
-
type: 'object',
|
|
378
|
-
properties: {
|
|
379
|
-
issueKey: {
|
|
380
|
-
type: 'string',
|
|
381
|
-
description: 'The issue key (e.g., PROJ-123)'
|
|
382
|
-
}
|
|
383
|
-
},
|
|
384
|
-
required: ['issueKey']
|
|
385
|
-
}
|
|
386
|
-
},
|
|
387
|
-
{
|
|
388
|
-
name: 'jira_create_issue',
|
|
389
|
-
description: 'Create a new Jira issue with support for custom fields including due dates',
|
|
390
|
-
inputSchema: {
|
|
391
|
-
type: 'object',
|
|
392
|
-
properties: {
|
|
393
|
-
projectKey: {
|
|
394
|
-
type: 'string',
|
|
395
|
-
description: 'The project key where to create the issue'
|
|
396
|
-
},
|
|
397
|
-
summary: {
|
|
398
|
-
type: 'string',
|
|
399
|
-
description: 'Issue summary/title'
|
|
400
|
-
},
|
|
401
|
-
description: {
|
|
402
|
-
type: 'string',
|
|
403
|
-
description: 'Issue description'
|
|
404
|
-
},
|
|
405
|
-
issueType: {
|
|
406
|
-
type: 'string',
|
|
407
|
-
description: 'Issue type (default: Task)',
|
|
408
|
-
default: 'Task'
|
|
409
|
-
},
|
|
410
|
-
duedate: {
|
|
411
|
-
type: 'string',
|
|
412
|
-
description: 'Due date in YYYY-MM-DD format (e.g., 2024-12-31)'
|
|
413
|
-
},
|
|
414
|
-
priority: {
|
|
415
|
-
type: 'string',
|
|
416
|
-
description: 'Priority name (e.g., High, Medium, Low)'
|
|
417
|
-
},
|
|
418
|
-
labels: {
|
|
419
|
-
type: 'array',
|
|
420
|
-
items: { type: 'string' },
|
|
421
|
-
description: 'Array of label strings'
|
|
422
|
-
},
|
|
423
|
-
components: {
|
|
424
|
-
type: 'array',
|
|
425
|
-
items: { type: 'string' },
|
|
426
|
-
description: 'Array of component names'
|
|
427
|
-
},
|
|
428
|
-
assignee: {
|
|
429
|
-
type: 'string',
|
|
430
|
-
description: 'Account ID of the assignee'
|
|
431
|
-
},
|
|
432
|
-
customFields: {
|
|
433
|
-
type: 'object',
|
|
434
|
-
description: 'Additional custom fields as key-value pairs'
|
|
435
|
-
}
|
|
436
|
-
},
|
|
437
|
-
required: ['projectKey', 'summary', 'description']
|
|
438
|
-
}
|
|
439
|
-
},
|
|
440
|
-
{
|
|
441
|
-
name: 'jira_update_issue',
|
|
442
|
-
description: 'Update an existing Jira issue',
|
|
443
|
-
inputSchema: {
|
|
444
|
-
type: 'object',
|
|
445
|
-
properties: {
|
|
446
|
-
issueKey: {
|
|
447
|
-
type: 'string',
|
|
448
|
-
description: 'The issue key to update'
|
|
449
|
-
},
|
|
450
|
-
summary: {
|
|
451
|
-
type: 'string',
|
|
452
|
-
description: 'New issue summary'
|
|
453
|
-
},
|
|
454
|
-
description: {
|
|
455
|
-
type: 'string',
|
|
456
|
-
description: 'New issue description'
|
|
457
|
-
},
|
|
458
|
-
assignee: {
|
|
459
|
-
type: 'string',
|
|
460
|
-
description: 'Account ID of the assignee'
|
|
461
|
-
}
|
|
462
|
-
},
|
|
463
|
-
required: ['issueKey']
|
|
464
|
-
}
|
|
465
|
-
},
|
|
466
|
-
{
|
|
467
|
-
name: 'jira_add_comment',
|
|
468
|
-
description: 'Add a comment to a Jira issue',
|
|
469
|
-
inputSchema: {
|
|
470
|
-
type: 'object',
|
|
471
|
-
properties: {
|
|
472
|
-
issueKey: {
|
|
473
|
-
type: 'string',
|
|
474
|
-
description: 'The issue key to comment on'
|
|
475
|
-
},
|
|
476
|
-
comment: {
|
|
477
|
-
type: 'string',
|
|
478
|
-
description: 'Comment text'
|
|
479
|
-
}
|
|
480
|
-
},
|
|
481
|
-
required: ['issueKey', 'comment']
|
|
482
|
-
}
|
|
483
|
-
},
|
|
484
|
-
{
|
|
485
|
-
name: 'jira_get_comments',
|
|
486
|
-
description: 'Get all comments for a Jira issue',
|
|
487
|
-
inputSchema: {
|
|
488
|
-
type: 'object',
|
|
489
|
-
properties: {
|
|
490
|
-
issueKey: {
|
|
491
|
-
type: 'string',
|
|
492
|
-
description: 'The issue key to get comments for'
|
|
493
|
-
}
|
|
494
|
-
},
|
|
495
|
-
required: ['issueKey']
|
|
496
|
-
}
|
|
497
|
-
},
|
|
498
|
-
{
|
|
499
|
-
name: 'jira_update_comment',
|
|
500
|
-
description: 'Update an existing comment on a Jira issue',
|
|
501
|
-
inputSchema: {
|
|
502
|
-
type: 'object',
|
|
503
|
-
properties: {
|
|
504
|
-
issueKey: {
|
|
505
|
-
type: 'string',
|
|
506
|
-
description: 'The issue key (e.g., PROJ-123)'
|
|
507
|
-
},
|
|
508
|
-
commentId: {
|
|
509
|
-
type: 'string',
|
|
510
|
-
description: 'The comment ID to update'
|
|
511
|
-
},
|
|
512
|
-
comment: {
|
|
513
|
-
type: 'string',
|
|
514
|
-
description: 'New comment text'
|
|
515
|
-
}
|
|
516
|
-
},
|
|
517
|
-
required: ['issueKey', 'commentId', 'comment']
|
|
518
|
-
}
|
|
519
|
-
},
|
|
520
|
-
{
|
|
521
|
-
name: 'jira_delete_comment',
|
|
522
|
-
description: 'Delete a comment from a Jira issue',
|
|
523
|
-
inputSchema: {
|
|
524
|
-
type: 'object',
|
|
525
|
-
properties: {
|
|
526
|
-
issueKey: {
|
|
527
|
-
type: 'string',
|
|
528
|
-
description: 'The issue key (e.g., PROJ-123)'
|
|
529
|
-
},
|
|
530
|
-
commentId: {
|
|
531
|
-
type: 'string',
|
|
532
|
-
description: 'The comment ID to delete'
|
|
533
|
-
}
|
|
534
|
-
},
|
|
535
|
-
required: ['issueKey', 'commentId']
|
|
536
|
-
}
|
|
537
|
-
},
|
|
538
|
-
{
|
|
539
|
-
name: 'jira_get_projects',
|
|
540
|
-
description: 'Get list of Jira projects',
|
|
541
|
-
inputSchema: {
|
|
542
|
-
type: 'object',
|
|
543
|
-
properties: {}
|
|
544
|
-
}
|
|
545
|
-
},
|
|
546
|
-
{
|
|
547
|
-
name: 'jira_get_issue_transitions',
|
|
548
|
-
description: 'Get available transitions for a Jira issue',
|
|
549
|
-
inputSchema: {
|
|
550
|
-
type: 'object',
|
|
551
|
-
properties: {
|
|
552
|
-
issueKey: {
|
|
553
|
-
type: 'string',
|
|
554
|
-
description: 'The issue key (e.g., PROJECT-123)'
|
|
555
|
-
}
|
|
556
|
-
},
|
|
557
|
-
required: ['issueKey']
|
|
558
|
-
}
|
|
559
|
-
},
|
|
560
|
-
{
|
|
561
|
-
name: 'jira_transition_issue',
|
|
562
|
-
description: 'Transition a Jira issue to a different status with smart field handling',
|
|
563
|
-
inputSchema: {
|
|
564
|
-
type: 'object',
|
|
565
|
-
properties: {
|
|
566
|
-
issueKey: {
|
|
567
|
-
type: 'string',
|
|
568
|
-
description: 'The issue key to transition'
|
|
569
|
-
},
|
|
570
|
-
transitionId: {
|
|
571
|
-
type: 'string',
|
|
572
|
-
description: 'The transition ID'
|
|
573
|
-
},
|
|
574
|
-
fieldValues: {
|
|
575
|
-
type: 'object',
|
|
576
|
-
description: 'Optional field values for the transition'
|
|
577
|
-
}
|
|
578
|
-
},
|
|
579
|
-
required: ['issueKey', 'transitionId']
|
|
580
|
-
}
|
|
581
|
-
},
|
|
582
|
-
{
|
|
583
|
-
name: 'jira_transition_issue_interactive',
|
|
584
|
-
description: 'Transition a Jira issue with automatic field suggestion and validation',
|
|
585
|
-
inputSchema: {
|
|
586
|
-
type: 'object',
|
|
587
|
-
properties: {
|
|
588
|
-
issueKey: {
|
|
589
|
-
type: 'string',
|
|
590
|
-
description: 'The issue key to transition'
|
|
591
|
-
},
|
|
592
|
-
transitionId: {
|
|
593
|
-
type: 'string',
|
|
594
|
-
description: 'The transition ID'
|
|
595
|
-
},
|
|
596
|
-
fieldValues: {
|
|
597
|
-
type: 'object',
|
|
598
|
-
description: 'Optional field values for the transition'
|
|
599
|
-
}
|
|
600
|
-
},
|
|
601
|
-
required: ['issueKey', 'transitionId']
|
|
602
|
-
}
|
|
603
|
-
},
|
|
604
|
-
{
|
|
605
|
-
name: 'jira_get_attachments',
|
|
606
|
-
description: 'Get all attachments for a Jira issue',
|
|
607
|
-
inputSchema: {
|
|
608
|
-
type: 'object',
|
|
609
|
-
properties: {
|
|
610
|
-
issueKey: {
|
|
611
|
-
type: 'string',
|
|
612
|
-
description: 'The issue key to get attachments for'
|
|
613
|
-
}
|
|
614
|
-
},
|
|
615
|
-
required: ['issueKey']
|
|
616
|
-
}
|
|
617
|
-
},
|
|
618
|
-
{
|
|
619
|
-
name: 'jira_add_attachment',
|
|
620
|
-
description: 'Add an attachment to a Jira issue',
|
|
621
|
-
inputSchema: {
|
|
622
|
-
type: 'object',
|
|
623
|
-
properties: {
|
|
624
|
-
issueKey: {
|
|
625
|
-
type: 'string',
|
|
626
|
-
description: 'The issue key to attach file to'
|
|
627
|
-
},
|
|
628
|
-
filename: {
|
|
629
|
-
type: 'string',
|
|
630
|
-
description: 'The filename for the attachment'
|
|
631
|
-
},
|
|
632
|
-
fileContent: {
|
|
633
|
-
type: 'string',
|
|
634
|
-
description: 'Base64 encoded file content'
|
|
635
|
-
}
|
|
636
|
-
},
|
|
637
|
-
required: ['issueKey', 'filename', 'fileContent']
|
|
638
|
-
}
|
|
639
|
-
},
|
|
640
|
-
{
|
|
641
|
-
name: 'jira_delete_attachment',
|
|
642
|
-
description: 'Delete an attachment from a Jira issue',
|
|
643
|
-
inputSchema: {
|
|
644
|
-
type: 'object',
|
|
645
|
-
properties: {
|
|
646
|
-
attachmentId: {
|
|
647
|
-
type: 'string',
|
|
648
|
-
description: 'The attachment ID to delete'
|
|
649
|
-
}
|
|
650
|
-
},
|
|
651
|
-
required: ['attachmentId']
|
|
652
|
-
}
|
|
653
|
-
},
|
|
654
|
-
{
|
|
655
|
-
name: 'jira_get_issue_links',
|
|
656
|
-
description: 'Get all issue links for a Jira issue',
|
|
657
|
-
inputSchema: {
|
|
658
|
-
type: 'object',
|
|
659
|
-
properties: {
|
|
660
|
-
issueKey: {
|
|
661
|
-
type: 'string',
|
|
662
|
-
description: 'The issue key to get links for'
|
|
663
|
-
}
|
|
664
|
-
},
|
|
665
|
-
required: ['issueKey']
|
|
666
|
-
}
|
|
667
|
-
},
|
|
668
|
-
{
|
|
669
|
-
name: 'jira_create_issue_link',
|
|
670
|
-
description: 'Create a link between two Jira issues',
|
|
671
|
-
inputSchema: {
|
|
672
|
-
type: 'object',
|
|
673
|
-
properties: {
|
|
674
|
-
inwardIssueKey: {
|
|
675
|
-
type: 'string',
|
|
676
|
-
description: 'The inward issue key'
|
|
677
|
-
},
|
|
678
|
-
outwardIssueKey: {
|
|
679
|
-
type: 'string',
|
|
680
|
-
description: 'The outward issue key'
|
|
681
|
-
},
|
|
682
|
-
linkType: {
|
|
683
|
-
type: 'string',
|
|
684
|
-
description: 'Link type name (e.g., "Blocks", "Relates", "Duplicates")'
|
|
685
|
-
}
|
|
686
|
-
},
|
|
687
|
-
required: ['inwardIssueKey', 'outwardIssueKey', 'linkType']
|
|
688
|
-
}
|
|
689
|
-
},
|
|
690
|
-
{
|
|
691
|
-
name: 'jira_delete_issue_link',
|
|
692
|
-
description: 'Delete a link between Jira issues',
|
|
693
|
-
inputSchema: {
|
|
694
|
-
type: 'object',
|
|
695
|
-
properties: {
|
|
696
|
-
linkId: {
|
|
697
|
-
type: 'string',
|
|
698
|
-
description: 'The link ID to delete'
|
|
699
|
-
}
|
|
700
|
-
},
|
|
701
|
-
required: ['linkId']
|
|
702
|
-
}
|
|
703
|
-
},
|
|
704
|
-
{
|
|
705
|
-
name: 'jira_get_link_types',
|
|
706
|
-
description: 'Get all available issue link types in Jira',
|
|
707
|
-
inputSchema: {
|
|
708
|
-
type: 'object',
|
|
709
|
-
properties: {}
|
|
710
|
-
}
|
|
711
|
-
},
|
|
712
|
-
{
|
|
713
|
-
name: 'jira_get_worklogs',
|
|
714
|
-
description: 'Get all work logs (time tracking entries) for a Jira issue',
|
|
715
|
-
inputSchema: {
|
|
716
|
-
type: 'object',
|
|
717
|
-
properties: {
|
|
718
|
-
issueKey: {
|
|
719
|
-
type: 'string',
|
|
720
|
-
description: 'The issue key to get work logs for'
|
|
721
|
-
}
|
|
722
|
-
},
|
|
723
|
-
required: ['issueKey']
|
|
724
|
-
}
|
|
725
|
-
},
|
|
726
|
-
{
|
|
727
|
-
name: 'jira_add_worklog',
|
|
728
|
-
description: 'Add a work log (time spent) to a Jira issue',
|
|
729
|
-
inputSchema: {
|
|
730
|
-
type: 'object',
|
|
731
|
-
properties: {
|
|
732
|
-
issueKey: {
|
|
733
|
-
type: 'string',
|
|
734
|
-
description: 'The issue key to log work on'
|
|
735
|
-
},
|
|
736
|
-
timeSpentSeconds: {
|
|
737
|
-
type: 'number',
|
|
738
|
-
description: 'Time spent in seconds (e.g., 3600 for 1 hour)'
|
|
739
|
-
},
|
|
740
|
-
comment: {
|
|
741
|
-
type: 'string',
|
|
742
|
-
description: 'Optional comment describing the work done'
|
|
743
|
-
},
|
|
744
|
-
started: {
|
|
745
|
-
type: 'string',
|
|
746
|
-
description: 'Optional start date/time in ISO 8601 format (e.g., 2024-01-15T14:30:00.000+0000)'
|
|
747
|
-
}
|
|
748
|
-
},
|
|
749
|
-
required: ['issueKey', 'timeSpentSeconds']
|
|
750
|
-
}
|
|
751
|
-
},
|
|
752
|
-
{
|
|
753
|
-
name: 'jira_update_worklog',
|
|
754
|
-
description: 'Update an existing work log entry',
|
|
755
|
-
inputSchema: {
|
|
756
|
-
type: 'object',
|
|
757
|
-
properties: {
|
|
758
|
-
issueKey: {
|
|
759
|
-
type: 'string',
|
|
760
|
-
description: 'The issue key'
|
|
761
|
-
},
|
|
762
|
-
worklogId: {
|
|
763
|
-
type: 'string',
|
|
764
|
-
description: 'The work log ID to update'
|
|
765
|
-
},
|
|
766
|
-
timeSpentSeconds: {
|
|
767
|
-
type: 'number',
|
|
768
|
-
description: 'Updated time spent in seconds'
|
|
769
|
-
},
|
|
770
|
-
comment: {
|
|
771
|
-
type: 'string',
|
|
772
|
-
description: 'Updated comment'
|
|
773
|
-
}
|
|
774
|
-
},
|
|
775
|
-
required: ['issueKey', 'worklogId']
|
|
776
|
-
}
|
|
777
|
-
},
|
|
778
|
-
{
|
|
779
|
-
name: 'jira_delete_worklog',
|
|
780
|
-
description: 'Delete a work log entry from a Jira issue',
|
|
781
|
-
inputSchema: {
|
|
782
|
-
type: 'object',
|
|
783
|
-
properties: {
|
|
784
|
-
issueKey: {
|
|
785
|
-
type: 'string',
|
|
786
|
-
description: 'The issue key'
|
|
787
|
-
},
|
|
788
|
-
worklogId: {
|
|
789
|
-
type: 'string',
|
|
790
|
-
description: 'The work log ID to delete'
|
|
791
|
-
}
|
|
792
|
-
},
|
|
793
|
-
required: ['issueKey', 'worklogId']
|
|
794
|
-
}
|
|
795
|
-
},
|
|
796
|
-
{
|
|
797
|
-
name: 'jira_get_watchers',
|
|
798
|
-
description: 'Get all watchers for a Jira issue',
|
|
799
|
-
inputSchema: {
|
|
800
|
-
type: 'object',
|
|
801
|
-
properties: {
|
|
802
|
-
issueKey: {
|
|
803
|
-
type: 'string',
|
|
804
|
-
description: 'The issue key to get watchers for'
|
|
805
|
-
}
|
|
806
|
-
},
|
|
807
|
-
required: ['issueKey']
|
|
808
|
-
}
|
|
809
|
-
},
|
|
810
|
-
{
|
|
811
|
-
name: 'jira_add_watcher',
|
|
812
|
-
description: 'Add a watcher to a Jira issue',
|
|
813
|
-
inputSchema: {
|
|
814
|
-
type: 'object',
|
|
815
|
-
properties: {
|
|
816
|
-
issueKey: {
|
|
817
|
-
type: 'string',
|
|
818
|
-
description: 'The issue key'
|
|
819
|
-
},
|
|
820
|
-
accountId: {
|
|
821
|
-
type: 'string',
|
|
822
|
-
description: 'Account ID of the user to add as watcher'
|
|
823
|
-
}
|
|
824
|
-
},
|
|
825
|
-
required: ['issueKey', 'accountId']
|
|
826
|
-
}
|
|
827
|
-
},
|
|
828
|
-
{
|
|
829
|
-
name: 'jira_remove_watcher',
|
|
830
|
-
description: 'Remove a watcher from a Jira issue',
|
|
831
|
-
inputSchema: {
|
|
832
|
-
type: 'object',
|
|
833
|
-
properties: {
|
|
834
|
-
issueKey: {
|
|
835
|
-
type: 'string',
|
|
836
|
-
description: 'The issue key'
|
|
837
|
-
},
|
|
838
|
-
accountId: {
|
|
839
|
-
type: 'string',
|
|
840
|
-
description: 'Account ID of the user to remove as watcher'
|
|
841
|
-
}
|
|
842
|
-
},
|
|
843
|
-
required: ['issueKey', 'accountId']
|
|
844
|
-
}
|
|
845
|
-
},
|
|
846
|
-
{
|
|
847
|
-
name: 'jira_get_subtasks',
|
|
848
|
-
description: 'Get all sub-tasks for a Jira issue',
|
|
849
|
-
inputSchema: {
|
|
850
|
-
type: 'object',
|
|
851
|
-
properties: {
|
|
852
|
-
issueKey: {
|
|
853
|
-
type: 'string',
|
|
854
|
-
description: 'The parent issue key'
|
|
855
|
-
}
|
|
856
|
-
},
|
|
857
|
-
required: ['issueKey']
|
|
858
|
-
}
|
|
859
|
-
},
|
|
860
|
-
{
|
|
861
|
-
name: 'jira_create_subtask',
|
|
862
|
-
description: 'Create a sub-task under a parent Jira issue',
|
|
863
|
-
inputSchema: {
|
|
864
|
-
type: 'object',
|
|
865
|
-
properties: {
|
|
866
|
-
parentKey: {
|
|
867
|
-
type: 'string',
|
|
868
|
-
description: 'The parent issue key'
|
|
869
|
-
},
|
|
870
|
-
summary: {
|
|
871
|
-
type: 'string',
|
|
872
|
-
description: 'Sub-task summary/title'
|
|
873
|
-
},
|
|
874
|
-
description: {
|
|
875
|
-
type: 'string',
|
|
876
|
-
description: 'Sub-task description'
|
|
877
|
-
}
|
|
878
|
-
},
|
|
879
|
-
required: ['parentKey', 'summary', 'description']
|
|
880
|
-
}
|
|
881
|
-
},
|
|
882
|
-
{
|
|
883
|
-
name: 'jira_get_issue_history',
|
|
884
|
-
description: 'Get complete change history for a Jira issue',
|
|
885
|
-
inputSchema: {
|
|
886
|
-
type: 'object',
|
|
887
|
-
properties: {
|
|
888
|
-
issueKey: {
|
|
889
|
-
type: 'string',
|
|
890
|
-
description: 'The issue key to get history for'
|
|
891
|
-
}
|
|
892
|
-
},
|
|
893
|
-
required: ['issueKey']
|
|
894
|
-
}
|
|
895
|
-
},
|
|
896
|
-
// Bitbucket Tools
|
|
897
|
-
{
|
|
898
|
-
name: 'bitbucket_get_repositories',
|
|
899
|
-
description: 'Get list of Bitbucket repositories in workspace',
|
|
900
|
-
inputSchema: {
|
|
901
|
-
type: 'object',
|
|
902
|
-
properties: {
|
|
903
|
-
query: {
|
|
904
|
-
type: 'string',
|
|
905
|
-
description: 'Search query for repository names'
|
|
906
|
-
},
|
|
907
|
-
limit: {
|
|
908
|
-
type: 'number',
|
|
909
|
-
description: 'Maximum number of repositories (default: 10)',
|
|
910
|
-
default: 10
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
},
|
|
915
|
-
{
|
|
916
|
-
name: 'bitbucket_get_repository',
|
|
917
|
-
description: 'Get details of a specific Bitbucket repository',
|
|
918
|
-
inputSchema: {
|
|
919
|
-
type: 'object',
|
|
920
|
-
properties: {
|
|
921
|
-
repoName: {
|
|
922
|
-
type: 'string',
|
|
923
|
-
description: 'Repository name'
|
|
924
|
-
}
|
|
925
|
-
},
|
|
926
|
-
required: ['repoName']
|
|
927
|
-
}
|
|
928
|
-
},
|
|
929
|
-
{
|
|
930
|
-
name: 'bitbucket_create_repository',
|
|
931
|
-
description: 'Create a new Bitbucket repository',
|
|
932
|
-
inputSchema: {
|
|
933
|
-
type: 'object',
|
|
934
|
-
properties: {
|
|
935
|
-
name: {
|
|
936
|
-
type: 'string',
|
|
937
|
-
description: 'Repository name'
|
|
938
|
-
},
|
|
939
|
-
description: {
|
|
940
|
-
type: 'string',
|
|
941
|
-
description: 'Repository description'
|
|
942
|
-
},
|
|
943
|
-
isPrivate: {
|
|
944
|
-
type: 'boolean',
|
|
945
|
-
description: 'Whether the repository should be private (default: true)',
|
|
946
|
-
default: true
|
|
947
|
-
},
|
|
948
|
-
language: {
|
|
949
|
-
type: 'string',
|
|
950
|
-
description: 'Primary programming language'
|
|
951
|
-
}
|
|
952
|
-
},
|
|
953
|
-
required: ['name']
|
|
954
|
-
}
|
|
955
|
-
},
|
|
956
|
-
{
|
|
957
|
-
name: 'bitbucket_get_pull_requests',
|
|
958
|
-
description: 'Get pull requests for a repository',
|
|
959
|
-
inputSchema: {
|
|
960
|
-
type: 'object',
|
|
961
|
-
properties: {
|
|
962
|
-
repoName: {
|
|
963
|
-
type: 'string',
|
|
964
|
-
description: 'Repository name'
|
|
965
|
-
},
|
|
966
|
-
state: {
|
|
967
|
-
type: 'string',
|
|
968
|
-
description: 'Pull request state (OPEN, MERGED, DECLINED)',
|
|
969
|
-
default: 'OPEN'
|
|
970
|
-
},
|
|
971
|
-
limit: {
|
|
972
|
-
type: 'number',
|
|
973
|
-
description: 'Maximum number of pull requests (default: 10)',
|
|
974
|
-
default: 10
|
|
975
|
-
}
|
|
976
|
-
},
|
|
977
|
-
required: ['repoName']
|
|
978
|
-
}
|
|
979
|
-
},
|
|
980
|
-
{
|
|
981
|
-
name: 'bitbucket_get_pull_request',
|
|
982
|
-
description: 'Get details of a specific pull request',
|
|
983
|
-
inputSchema: {
|
|
984
|
-
type: 'object',
|
|
985
|
-
properties: {
|
|
986
|
-
repoName: {
|
|
987
|
-
type: 'string',
|
|
988
|
-
description: 'Repository name'
|
|
989
|
-
},
|
|
990
|
-
prId: {
|
|
991
|
-
type: 'number',
|
|
992
|
-
description: 'Pull request ID'
|
|
993
|
-
},
|
|
994
|
-
includeDiff: {
|
|
995
|
-
type: 'boolean',
|
|
996
|
-
description: 'Whether to include the code diff/changes (default: false)',
|
|
997
|
-
default: false
|
|
998
|
-
}
|
|
999
|
-
},
|
|
1000
|
-
required: ['repoName', 'prId']
|
|
1001
|
-
}
|
|
1002
|
-
},
|
|
1003
|
-
{
|
|
1004
|
-
name: 'bitbucket_create_pull_request',
|
|
1005
|
-
description: 'Create a new pull request',
|
|
1006
|
-
inputSchema: {
|
|
1007
|
-
type: 'object',
|
|
1008
|
-
properties: {
|
|
1009
|
-
repoName: {
|
|
1010
|
-
type: 'string',
|
|
1011
|
-
description: 'Repository name'
|
|
1012
|
-
},
|
|
1013
|
-
title: {
|
|
1014
|
-
type: 'string',
|
|
1015
|
-
description: 'Pull request title'
|
|
1016
|
-
},
|
|
1017
|
-
sourceBranch: {
|
|
1018
|
-
type: 'string',
|
|
1019
|
-
description: 'Source branch name'
|
|
1020
|
-
},
|
|
1021
|
-
destinationBranch: {
|
|
1022
|
-
type: 'string',
|
|
1023
|
-
description: 'Destination branch name (default: main)',
|
|
1024
|
-
default: 'main'
|
|
1025
|
-
},
|
|
1026
|
-
description: {
|
|
1027
|
-
type: 'string',
|
|
1028
|
-
description: 'Pull request description'
|
|
1029
|
-
}
|
|
1030
|
-
},
|
|
1031
|
-
required: ['repoName', 'title', 'sourceBranch']
|
|
1032
|
-
}
|
|
1033
|
-
},
|
|
1034
|
-
{
|
|
1035
|
-
name: 'bitbucket_get_branches',
|
|
1036
|
-
description: 'Get branches for a repository',
|
|
1037
|
-
inputSchema: {
|
|
1038
|
-
type: 'object',
|
|
1039
|
-
properties: {
|
|
1040
|
-
repoName: {
|
|
1041
|
-
type: 'string',
|
|
1042
|
-
description: 'Repository name'
|
|
1043
|
-
},
|
|
1044
|
-
limit: {
|
|
1045
|
-
type: 'number',
|
|
1046
|
-
description: 'Maximum number of branches (default: 10)',
|
|
1047
|
-
default: 10
|
|
1048
|
-
}
|
|
1049
|
-
},
|
|
1050
|
-
required: ['repoName']
|
|
1051
|
-
}
|
|
1052
|
-
},
|
|
1053
|
-
{
|
|
1054
|
-
name: 'bitbucket_get_commits',
|
|
1055
|
-
description: 'Get commits for a repository',
|
|
1056
|
-
inputSchema: {
|
|
1057
|
-
type: 'object',
|
|
1058
|
-
properties: {
|
|
1059
|
-
repoName: {
|
|
1060
|
-
type: 'string',
|
|
1061
|
-
description: 'Repository name'
|
|
1062
|
-
},
|
|
1063
|
-
branch: {
|
|
1064
|
-
type: 'string',
|
|
1065
|
-
description: 'Branch name (default: main)',
|
|
1066
|
-
default: 'main'
|
|
1067
|
-
},
|
|
1068
|
-
limit: {
|
|
1069
|
-
type: 'number',
|
|
1070
|
-
description: 'Maximum number of commits (default: 10)',
|
|
1071
|
-
default: 10
|
|
1072
|
-
}
|
|
1073
|
-
},
|
|
1074
|
-
required: ['repoName']
|
|
1075
|
-
}
|
|
1076
|
-
},
|
|
1077
|
-
{
|
|
1078
|
-
name: 'bitbucket_get_issues',
|
|
1079
|
-
description: 'Get issues for a repository',
|
|
1080
|
-
inputSchema: {
|
|
1081
|
-
type: 'object',
|
|
1082
|
-
properties: {
|
|
1083
|
-
repoName: {
|
|
1084
|
-
type: 'string',
|
|
1085
|
-
description: 'Repository name'
|
|
1086
|
-
},
|
|
1087
|
-
state: {
|
|
1088
|
-
type: 'string',
|
|
1089
|
-
description: 'Issue state (open, closed)',
|
|
1090
|
-
default: 'open'
|
|
1091
|
-
},
|
|
1092
|
-
limit: {
|
|
1093
|
-
type: 'number',
|
|
1094
|
-
description: 'Maximum number of issues (default: 10)',
|
|
1095
|
-
default: 10
|
|
1096
|
-
}
|
|
1097
|
-
},
|
|
1098
|
-
required: ['repoName']
|
|
1099
|
-
}
|
|
1100
|
-
},
|
|
1101
|
-
{
|
|
1102
|
-
name: 'bitbucket_create_issue',
|
|
1103
|
-
description: 'Create a new issue in a repository',
|
|
1104
|
-
inputSchema: {
|
|
1105
|
-
type: 'object',
|
|
1106
|
-
properties: {
|
|
1107
|
-
repoName: {
|
|
1108
|
-
type: 'string',
|
|
1109
|
-
description: 'Repository name'
|
|
1110
|
-
},
|
|
1111
|
-
title: {
|
|
1112
|
-
type: 'string',
|
|
1113
|
-
description: 'Issue title'
|
|
1114
|
-
},
|
|
1115
|
-
content: {
|
|
1116
|
-
type: 'string',
|
|
1117
|
-
description: 'Issue content/description'
|
|
1118
|
-
},
|
|
1119
|
-
kind: {
|
|
1120
|
-
type: 'string',
|
|
1121
|
-
description: 'Issue kind (bug, enhancement, proposal, task)',
|
|
1122
|
-
default: 'bug'
|
|
1123
|
-
}
|
|
1124
|
-
},
|
|
1125
|
-
required: ['repoName', 'title']
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
]
|
|
1129
|
-
};
|
|
36
|
+
return { tools: allTools };
|
|
1130
37
|
});
|
|
38
|
+
/**
|
|
39
|
+
* Handle tool calls by routing to appropriate handlers
|
|
40
|
+
*/
|
|
1131
41
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
1132
42
|
const { name, arguments: args } = request.params;
|
|
1133
43
|
try {
|
|
44
|
+
// Confluence Tools
|
|
1134
45
|
switch (name) {
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
const { pageId } = args;
|
|
1164
|
-
try {
|
|
1165
|
-
const page = await confluenceService.getPage(pageId);
|
|
1166
|
-
return {
|
|
1167
|
-
content: [
|
|
1168
|
-
{
|
|
1169
|
-
type: 'text',
|
|
1170
|
-
text: JSON.stringify(page, null, 2)
|
|
1171
|
-
}
|
|
1172
|
-
]
|
|
1173
|
-
};
|
|
1174
|
-
}
|
|
1175
|
-
catch (error) {
|
|
1176
|
-
const errorDetails = error.response?.data || error.message;
|
|
1177
|
-
return {
|
|
1178
|
-
content: [
|
|
1179
|
-
{
|
|
1180
|
-
type: 'text',
|
|
1181
|
-
text: `❌ Failed to get Confluence page\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Page ID: ${pageId}\n\n**Tip:** Check if the page ID exists and you have permission to view it.`
|
|
1182
|
-
}
|
|
1183
|
-
],
|
|
1184
|
-
isError: true
|
|
1185
|
-
};
|
|
1186
|
-
}
|
|
1187
|
-
}
|
|
1188
|
-
case 'confluence_create_page': {
|
|
1189
|
-
const { spaceKey, title, content, parentId, images } = args;
|
|
1190
|
-
try {
|
|
1191
|
-
const page = await confluenceService.createPageWithImages(spaceKey, title, content, parentId, images);
|
|
1192
|
-
const imageCount = images?.length || 0;
|
|
1193
|
-
const resultText = imageCount > 0
|
|
1194
|
-
? `✅ Confluence page created successfully with ${imageCount} image(s)\n\n${JSON.stringify(page, null, 2)}`
|
|
1195
|
-
: JSON.stringify(page, null, 2);
|
|
1196
|
-
return {
|
|
1197
|
-
content: [
|
|
1198
|
-
{
|
|
1199
|
-
type: 'text',
|
|
1200
|
-
text: resultText
|
|
1201
|
-
}
|
|
1202
|
-
]
|
|
1203
|
-
};
|
|
1204
|
-
}
|
|
1205
|
-
catch (error) {
|
|
1206
|
-
const errorDetails = error.response?.data || error.message;
|
|
1207
|
-
const imageInfo = images?.length ? `\n- Images: ${images.length} image(s) to upload` : '';
|
|
1208
|
-
return {
|
|
1209
|
-
content: [
|
|
1210
|
-
{
|
|
1211
|
-
type: 'text',
|
|
1212
|
-
text: `❌ Failed to create Confluence page\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Space Key: ${spaceKey}\n- Title: ${title}\n- Parent ID: ${parentId || 'none'}${imageInfo}\n\n**Tip:** Check if the space exists and you have permission to create pages in it. For images, ensure they are properly base64 encoded.`
|
|
1213
|
-
}
|
|
1214
|
-
],
|
|
1215
|
-
isError: true
|
|
1216
|
-
};
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
case 'confluence_update_page': {
|
|
1220
|
-
const { pageId, title, content, version } = args;
|
|
1221
|
-
try {
|
|
1222
|
-
const page = await confluenceService.updatePage(pageId, title, content, version);
|
|
1223
|
-
return {
|
|
1224
|
-
content: [
|
|
1225
|
-
{
|
|
1226
|
-
type: 'text',
|
|
1227
|
-
text: JSON.stringify(page, null, 2)
|
|
1228
|
-
}
|
|
1229
|
-
]
|
|
1230
|
-
};
|
|
1231
|
-
}
|
|
1232
|
-
catch (error) {
|
|
1233
|
-
const errorDetails = error.response?.data || error.message;
|
|
1234
|
-
return {
|
|
1235
|
-
content: [
|
|
1236
|
-
{
|
|
1237
|
-
type: 'text',
|
|
1238
|
-
text: `❌ Failed to update Confluence page\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Page ID: ${pageId}\n- Title: ${title}\n- Version: ${version}\n\n**Tip:** Check if the page exists, version is correct, and you have permission to edit it.`
|
|
1239
|
-
}
|
|
1240
|
-
],
|
|
1241
|
-
isError: true
|
|
1242
|
-
};
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
case 'confluence_get_spaces': {
|
|
1246
|
-
const { limit } = args;
|
|
1247
|
-
try {
|
|
1248
|
-
const spaces = await confluenceService.getSpaces(limit);
|
|
1249
|
-
return {
|
|
1250
|
-
content: [
|
|
1251
|
-
{
|
|
1252
|
-
type: 'text',
|
|
1253
|
-
text: JSON.stringify(spaces, null, 2)
|
|
1254
|
-
}
|
|
1255
|
-
]
|
|
1256
|
-
};
|
|
1257
|
-
}
|
|
1258
|
-
catch (error) {
|
|
1259
|
-
const errorDetails = error.response?.data || error.message;
|
|
1260
|
-
return {
|
|
1261
|
-
content: [
|
|
1262
|
-
{
|
|
1263
|
-
type: 'text',
|
|
1264
|
-
text: `❌ Failed to get Confluence spaces\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Limit: ${limit || 25}\n\n**Tip:** Check your Confluence permissions and API access.`
|
|
1265
|
-
}
|
|
1266
|
-
],
|
|
1267
|
-
isError: true
|
|
1268
|
-
};
|
|
1269
|
-
}
|
|
1270
|
-
}
|
|
1271
|
-
case 'confluence_get_pages_by_space': {
|
|
1272
|
-
const { spaceKey, limit } = args;
|
|
1273
|
-
try {
|
|
1274
|
-
const pages = await confluenceService.getPagesBySpace(spaceKey, limit);
|
|
1275
|
-
return {
|
|
1276
|
-
content: [
|
|
1277
|
-
{
|
|
1278
|
-
type: 'text',
|
|
1279
|
-
text: JSON.stringify(pages, null, 2)
|
|
1280
|
-
}
|
|
1281
|
-
]
|
|
1282
|
-
};
|
|
1283
|
-
}
|
|
1284
|
-
catch (error) {
|
|
1285
|
-
const errorDetails = error.response?.data || error.message;
|
|
1286
|
-
return {
|
|
1287
|
-
content: [
|
|
1288
|
-
{
|
|
1289
|
-
type: 'text',
|
|
1290
|
-
text: `❌ Failed to get pages from Confluence space\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Space Key: ${spaceKey}\n- Limit: ${limit || 25}\n\n**Tip:** Check if the space key exists and you have permission to view it.`
|
|
1291
|
-
}
|
|
1292
|
-
],
|
|
1293
|
-
isError: true
|
|
1294
|
-
};
|
|
1295
|
-
}
|
|
1296
|
-
}
|
|
1297
|
-
case 'confluence_get_attachments': {
|
|
1298
|
-
const { pageId } = args;
|
|
1299
|
-
try {
|
|
1300
|
-
const attachments = await confluenceService.getAttachments(pageId);
|
|
1301
|
-
return {
|
|
1302
|
-
content: [
|
|
1303
|
-
{
|
|
1304
|
-
type: 'text',
|
|
1305
|
-
text: JSON.stringify(attachments, null, 2)
|
|
1306
|
-
}
|
|
1307
|
-
]
|
|
1308
|
-
};
|
|
1309
|
-
}
|
|
1310
|
-
catch (error) {
|
|
1311
|
-
const errorDetails = error.response?.data || error.message;
|
|
1312
|
-
return {
|
|
1313
|
-
content: [
|
|
1314
|
-
{
|
|
1315
|
-
type: 'text',
|
|
1316
|
-
text: `❌ Failed to get attachments for Confluence page\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Page ID: ${pageId}\n\n**Tip:** Check if the page exists and you have permission to view it.`
|
|
1317
|
-
}
|
|
1318
|
-
],
|
|
1319
|
-
isError: true
|
|
1320
|
-
};
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
case 'confluence_add_attachment': {
|
|
1324
|
-
const { pageId, filename, fileContent, filePath } = args;
|
|
1325
|
-
// Validate: need either filePath or fileContent
|
|
1326
|
-
if (!filePath && !fileContent) {
|
|
1327
|
-
return {
|
|
1328
|
-
content: [{ type: 'text', text: '❌ Either filePath or fileContent must be provided' }],
|
|
1329
|
-
isError: true
|
|
1330
|
-
};
|
|
1331
|
-
}
|
|
1332
|
-
try {
|
|
1333
|
-
const result = await confluenceService.addAttachment(pageId, filename, fileContent, filePath);
|
|
1334
|
-
const attachedFilename = result.results?.[0]?.title || filename || filePath?.split('/').pop() || 'attachment';
|
|
1335
|
-
return {
|
|
1336
|
-
content: [
|
|
1337
|
-
{
|
|
1338
|
-
type: 'text',
|
|
1339
|
-
text: `✅ Attachment "${attachedFilename}" added successfully to page ${pageId}\n\n${JSON.stringify(result, null, 2)}`
|
|
1340
|
-
}
|
|
1341
|
-
]
|
|
1342
|
-
};
|
|
1343
|
-
}
|
|
1344
|
-
catch (error) {
|
|
1345
|
-
const errorDetails = error.response?.data || error.message;
|
|
1346
|
-
const source = filePath ? `File Path: ${filePath}` : `Filename: ${filename}`;
|
|
1347
|
-
return {
|
|
1348
|
-
content: [
|
|
1349
|
-
{
|
|
1350
|
-
type: 'text',
|
|
1351
|
-
text: `❌ Failed to add attachment to Confluence page\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Page ID: ${pageId}\n- ${source}\n\n**Tip:** Check if the page exists, you have permission to attach files, and the file path exists or content is properly base64 encoded.`
|
|
1352
|
-
}
|
|
1353
|
-
],
|
|
1354
|
-
isError: true
|
|
1355
|
-
};
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
case 'confluence_delete_attachment': {
|
|
1359
|
-
const { attachmentId } = args;
|
|
1360
|
-
try {
|
|
1361
|
-
await confluenceService.deleteAttachment(attachmentId);
|
|
1362
|
-
return {
|
|
1363
|
-
content: [
|
|
1364
|
-
{
|
|
1365
|
-
type: 'text',
|
|
1366
|
-
text: `✅ Attachment ${attachmentId} deleted successfully`
|
|
1367
|
-
}
|
|
1368
|
-
]
|
|
1369
|
-
};
|
|
1370
|
-
}
|
|
1371
|
-
catch (error) {
|
|
1372
|
-
const errorDetails = error.response?.data || error.message;
|
|
1373
|
-
return {
|
|
1374
|
-
content: [
|
|
1375
|
-
{
|
|
1376
|
-
type: 'text',
|
|
1377
|
-
text: `❌ Failed to delete attachment\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Attachment ID: ${attachmentId}\n\n**Tip:** Check if the attachment exists and you have permission to delete it.`
|
|
1378
|
-
}
|
|
1379
|
-
],
|
|
1380
|
-
isError: true
|
|
1381
|
-
};
|
|
1382
|
-
}
|
|
1383
|
-
}
|
|
1384
|
-
case 'confluence_embed_image': {
|
|
1385
|
-
const { pageId, filename, fileContent, filePath, alt, caption, width, align, position, headingText } = args;
|
|
1386
|
-
// Validate: need either filePath or fileContent
|
|
1387
|
-
if (!filePath && !fileContent) {
|
|
1388
|
-
return {
|
|
1389
|
-
content: [{ type: 'text', text: '❌ Either filePath or fileContent must be provided' }],
|
|
1390
|
-
isError: true
|
|
1391
|
-
};
|
|
1392
|
-
}
|
|
1393
|
-
try {
|
|
1394
|
-
const result = await confluenceService.embedImage(pageId, filename, fileContent, filePath, {
|
|
1395
|
-
alt,
|
|
1396
|
-
caption,
|
|
1397
|
-
width,
|
|
1398
|
-
align,
|
|
1399
|
-
position,
|
|
1400
|
-
headingText
|
|
1401
|
-
});
|
|
1402
|
-
const embeddedFilename = result.attachment.results?.[0]?.title || filename || filePath?.split('/').pop() || 'image';
|
|
1403
|
-
return {
|
|
1404
|
-
content: [
|
|
1405
|
-
{
|
|
1406
|
-
type: 'text',
|
|
1407
|
-
text: `✅ Image "${embeddedFilename}" attached and embedded successfully!\n\n**Attachment ID:** ${result.attachment.results?.[0]?.id}\n**Page Version:** ${result.page.version}\n**Position:** ${position || 'bottom'}\n${align ? `**Alignment:** ${align}` : ''}\n${width ? `**Width:** ${width}px` : ''}\n${caption ? `**Caption:** ${caption}` : ''}`
|
|
1408
|
-
}
|
|
1409
|
-
]
|
|
1410
|
-
};
|
|
1411
|
-
}
|
|
1412
|
-
catch (error) {
|
|
1413
|
-
const errorDetails = error.response?.data || error.message;
|
|
1414
|
-
const source = filePath ? `File Path: ${filePath}` : `Filename: ${filename}`;
|
|
1415
|
-
return {
|
|
1416
|
-
content: [
|
|
1417
|
-
{
|
|
1418
|
-
type: 'text',
|
|
1419
|
-
text: `❌ Failed to embed image in Confluence page\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Page ID: ${pageId}\n- ${source}\n- Position: ${position || 'bottom'}\n\n**Tip:** Check if the page exists, you have edit permission, and the file path exists or content is properly base64 encoded.`
|
|
1420
|
-
}
|
|
1421
|
-
],
|
|
1422
|
-
isError: true
|
|
1423
|
-
};
|
|
1424
|
-
}
|
|
1425
|
-
}
|
|
1426
|
-
case 'confluence_get_comments': {
|
|
1427
|
-
const { pageId } = args;
|
|
1428
|
-
try {
|
|
1429
|
-
const comments = await confluenceService.getComments(pageId);
|
|
1430
|
-
return {
|
|
1431
|
-
content: [
|
|
1432
|
-
{
|
|
1433
|
-
type: 'text',
|
|
1434
|
-
text: JSON.stringify(comments, null, 2)
|
|
1435
|
-
}
|
|
1436
|
-
]
|
|
1437
|
-
};
|
|
1438
|
-
}
|
|
1439
|
-
catch (error) {
|
|
1440
|
-
const errorDetails = error.response?.data || error.message;
|
|
1441
|
-
return {
|
|
1442
|
-
content: [
|
|
1443
|
-
{
|
|
1444
|
-
type: 'text',
|
|
1445
|
-
text: `❌ Failed to get comments\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Page ID: ${pageId}\n\n**Tip:** Check if the page exists and you have permission to view it.`
|
|
1446
|
-
}
|
|
1447
|
-
],
|
|
1448
|
-
isError: true
|
|
1449
|
-
};
|
|
1450
|
-
}
|
|
1451
|
-
}
|
|
1452
|
-
case 'confluence_add_comment': {
|
|
1453
|
-
const { pageId, body } = args;
|
|
1454
|
-
try {
|
|
1455
|
-
const comment = await confluenceService.addComment(pageId, body);
|
|
1456
|
-
return {
|
|
1457
|
-
content: [
|
|
1458
|
-
{
|
|
1459
|
-
type: 'text',
|
|
1460
|
-
text: `✅ Comment added successfully!\n\n**Comment ID:** ${comment.id}\n**Author:** ${comment.author}\n**Created:** ${comment.created}`
|
|
1461
|
-
}
|
|
1462
|
-
]
|
|
1463
|
-
};
|
|
1464
|
-
}
|
|
1465
|
-
catch (error) {
|
|
1466
|
-
const errorDetails = error.response?.data || error.message;
|
|
1467
|
-
return {
|
|
1468
|
-
content: [
|
|
1469
|
-
{
|
|
1470
|
-
type: 'text',
|
|
1471
|
-
text: `❌ Failed to add comment\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Page ID: ${pageId}\n\n**Tip:** Check if the page exists and you have permission to comment on it.`
|
|
1472
|
-
}
|
|
1473
|
-
],
|
|
1474
|
-
isError: true
|
|
1475
|
-
};
|
|
1476
|
-
}
|
|
1477
|
-
}
|
|
1478
|
-
case 'confluence_update_comment': {
|
|
1479
|
-
const { commentId, body, version } = args;
|
|
1480
|
-
try {
|
|
1481
|
-
const comment = await confluenceService.updateComment(commentId, body, version);
|
|
1482
|
-
return {
|
|
1483
|
-
content: [
|
|
1484
|
-
{
|
|
1485
|
-
type: 'text',
|
|
1486
|
-
text: `✅ Comment updated successfully!\n\n**Comment ID:** ${comment.id}\n**New Version:** ${comment.version}\n**Updated:** ${comment.updated}`
|
|
1487
|
-
}
|
|
1488
|
-
]
|
|
1489
|
-
};
|
|
1490
|
-
}
|
|
1491
|
-
catch (error) {
|
|
1492
|
-
const errorDetails = error.response?.data || error.message;
|
|
1493
|
-
return {
|
|
1494
|
-
content: [
|
|
1495
|
-
{
|
|
1496
|
-
type: 'text',
|
|
1497
|
-
text: `❌ Failed to update comment\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Comment ID: ${commentId}\n- Version: ${version}\n\n**Tip:** Check if the comment exists, you have permission to edit it, and the version number is correct.`
|
|
1498
|
-
}
|
|
1499
|
-
],
|
|
1500
|
-
isError: true
|
|
1501
|
-
};
|
|
1502
|
-
}
|
|
1503
|
-
}
|
|
1504
|
-
case 'confluence_delete_comment': {
|
|
1505
|
-
const { commentId } = args;
|
|
1506
|
-
try {
|
|
1507
|
-
await confluenceService.deleteComment(commentId);
|
|
1508
|
-
return {
|
|
1509
|
-
content: [
|
|
1510
|
-
{
|
|
1511
|
-
type: 'text',
|
|
1512
|
-
text: `✅ Comment ${commentId} deleted successfully`
|
|
1513
|
-
}
|
|
1514
|
-
]
|
|
1515
|
-
};
|
|
1516
|
-
}
|
|
1517
|
-
catch (error) {
|
|
1518
|
-
const errorDetails = error.response?.data || error.message;
|
|
1519
|
-
return {
|
|
1520
|
-
content: [
|
|
1521
|
-
{
|
|
1522
|
-
type: 'text',
|
|
1523
|
-
text: `❌ Failed to delete comment\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Comment ID: ${commentId}\n\n**Tip:** Check if the comment exists and you have permission to delete it.`
|
|
1524
|
-
}
|
|
1525
|
-
],
|
|
1526
|
-
isError: true
|
|
1527
|
-
};
|
|
1528
|
-
}
|
|
1529
|
-
}
|
|
46
|
+
case 'confluence_search_pages':
|
|
47
|
+
return confluenceHandlers.searchPages(args);
|
|
48
|
+
case 'confluence_get_page':
|
|
49
|
+
return confluenceHandlers.getPage(args);
|
|
50
|
+
case 'confluence_create_page':
|
|
51
|
+
return confluenceHandlers.createPage(args);
|
|
52
|
+
case 'confluence_update_page':
|
|
53
|
+
return confluenceHandlers.updatePage(args);
|
|
54
|
+
case 'confluence_get_spaces':
|
|
55
|
+
return confluenceHandlers.getSpaces(args);
|
|
56
|
+
case 'confluence_get_pages_by_space':
|
|
57
|
+
return confluenceHandlers.getPagesBySpace(args);
|
|
58
|
+
case 'confluence_get_attachments':
|
|
59
|
+
return confluenceHandlers.getAttachments(args);
|
|
60
|
+
case 'confluence_add_attachment':
|
|
61
|
+
return confluenceHandlers.addAttachment(args);
|
|
62
|
+
case 'confluence_delete_attachment':
|
|
63
|
+
return confluenceHandlers.deleteAttachment(args);
|
|
64
|
+
case 'confluence_embed_image':
|
|
65
|
+
return confluenceHandlers.embedImage(args);
|
|
66
|
+
case 'confluence_get_comments':
|
|
67
|
+
return confluenceHandlers.getComments(args);
|
|
68
|
+
case 'confluence_add_comment':
|
|
69
|
+
return confluenceHandlers.addComment(args);
|
|
70
|
+
case 'confluence_update_comment':
|
|
71
|
+
return confluenceHandlers.updateComment(args);
|
|
72
|
+
case 'confluence_delete_comment':
|
|
73
|
+
return confluenceHandlers.deleteComment(args);
|
|
1530
74
|
// Jira Tools
|
|
1531
|
-
case 'jira_search_issues':
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
case '
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
case '
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
if (duedate)
|
|
1598
|
-
optionalFields.push(`📅 **Due Date:** ${duedate}`);
|
|
1599
|
-
if (priority)
|
|
1600
|
-
optionalFields.push(`🔥 **Priority:** ${priority}`);
|
|
1601
|
-
if (labels && labels.length > 0)
|
|
1602
|
-
optionalFields.push(`🏷️ **Labels:** ${labels.join(', ')}`);
|
|
1603
|
-
if (components && components.length > 0)
|
|
1604
|
-
optionalFields.push(`🧩 **Components:** ${components.join(', ')}`);
|
|
1605
|
-
if (assignee)
|
|
1606
|
-
optionalFields.push(`👤 **Assignee:** ${issue.assignee || assignee}`);
|
|
1607
|
-
const optionalFieldsText = optionalFields.length > 0 ? `\n\n${optionalFields.join('\n')}` : '';
|
|
1608
|
-
return {
|
|
1609
|
-
content: [
|
|
1610
|
-
{
|
|
1611
|
-
type: 'text',
|
|
1612
|
-
text: `✅ **Jira Issue Created Successfully**
|
|
1613
|
-
|
|
1614
|
-
🎫 **Issue Key:** ${issue.key}
|
|
1615
|
-
📝 **Summary:** ${issue.summary}
|
|
1616
|
-
📋 **Issue Type:** ${issueType || 'Task'}
|
|
1617
|
-
📊 **Status:** ${issue.status}
|
|
1618
|
-
📅 **Created:** ${new Date(issue.created).toLocaleString()}${optionalFieldsText}
|
|
1619
|
-
|
|
1620
|
-
📄 **Description:** Successfully created with provided content
|
|
1621
|
-
|
|
1622
|
-
🔗 **Issue URL:** [View Issue](https://${process.env.JIRA_DOMAIN || process.env.ATLASSIAN_DOMAIN || 'your-domain.atlassian.net'}/browse/${issue.key})`
|
|
1623
|
-
}
|
|
1624
|
-
]
|
|
1625
|
-
};
|
|
1626
|
-
}
|
|
1627
|
-
catch (error) {
|
|
1628
|
-
const errorDetails = error.response?.data || error.message;
|
|
1629
|
-
return {
|
|
1630
|
-
content: [
|
|
1631
|
-
{
|
|
1632
|
-
type: 'text',
|
|
1633
|
-
text: `❌ Failed to create Jira issue\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Project: ${projectKey}\n- Summary: ${summary}\n- Issue Type: ${issueType || 'Task'}\n- Due Date: ${duedate || 'none'}\n- Priority: ${priority || 'none'}\n- Labels: ${labels?.join(', ') || 'none'}\n- Components: ${components?.join(', ') || 'none'}\n- Assignee: ${assignee || 'none'}\n\n**Tip:** Check if all required fields are provided and project exists. For custom fields, ensure field IDs are correct.`
|
|
1634
|
-
}
|
|
1635
|
-
],
|
|
1636
|
-
isError: true
|
|
1637
|
-
};
|
|
1638
|
-
}
|
|
1639
|
-
}
|
|
1640
|
-
case 'jira_update_issue': {
|
|
1641
|
-
const { issueKey, summary, description, assignee } = args;
|
|
1642
|
-
try {
|
|
1643
|
-
const issue = await jiraService.updateIssue(issueKey, { summary, description, assignee });
|
|
1644
|
-
// Format the updated fields display
|
|
1645
|
-
const updatedFields = [];
|
|
1646
|
-
if (summary)
|
|
1647
|
-
updatedFields.push(`📝 **Summary:** Updated to "${issue.summary}"`);
|
|
1648
|
-
if (description)
|
|
1649
|
-
updatedFields.push(`📄 **Description:** Updated successfully`);
|
|
1650
|
-
if (assignee)
|
|
1651
|
-
updatedFields.push(`👤 **Assignee:** ${issue.assignee || assignee}`);
|
|
1652
|
-
const updatedFieldsText = updatedFields.length > 0 ? `\n\n**Updated Fields:**\n${updatedFields.join('\n')}` : '';
|
|
1653
|
-
return {
|
|
1654
|
-
content: [
|
|
1655
|
-
{
|
|
1656
|
-
type: 'text',
|
|
1657
|
-
text: `✅ **Jira Issue Updated Successfully**
|
|
1658
|
-
|
|
1659
|
-
🎫 **Issue Key:** ${issue.key}
|
|
1660
|
-
📊 **Current Status:** ${issue.status}
|
|
1661
|
-
📅 **Last Updated:** ${new Date(issue.updated).toLocaleString()}${updatedFieldsText}
|
|
1662
|
-
|
|
1663
|
-
🔗 **Issue URL:** [View Issue](https://${process.env.JIRA_DOMAIN || process.env.ATLASSIAN_DOMAIN || 'your-domain.atlassian.net'}/browse/${issue.key})`
|
|
1664
|
-
}
|
|
1665
|
-
]
|
|
1666
|
-
};
|
|
1667
|
-
}
|
|
1668
|
-
catch (error) {
|
|
1669
|
-
const errorDetails = error.response?.data || error.message;
|
|
1670
|
-
return {
|
|
1671
|
-
content: [
|
|
1672
|
-
{
|
|
1673
|
-
type: 'text',
|
|
1674
|
-
text: `❌ Failed to update Jira issue ${issueKey}\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request Fields:**\n- Summary: ${summary || 'unchanged'}\n- Description: ${description || 'unchanged'}\n- Assignee: ${assignee || 'unchanged'}\n\n**Tip:** Check if the issue exists and you have permission to update it.`
|
|
1675
|
-
}
|
|
1676
|
-
],
|
|
1677
|
-
isError: true
|
|
1678
|
-
};
|
|
1679
|
-
}
|
|
1680
|
-
}
|
|
1681
|
-
case 'jira_add_comment': {
|
|
1682
|
-
const { issueKey, comment } = args;
|
|
1683
|
-
try {
|
|
1684
|
-
await jiraService.addComment(issueKey, comment);
|
|
1685
|
-
return {
|
|
1686
|
-
content: [
|
|
1687
|
-
{
|
|
1688
|
-
type: 'text',
|
|
1689
|
-
text: `Comment added to issue ${issueKey}`
|
|
1690
|
-
}
|
|
1691
|
-
]
|
|
1692
|
-
};
|
|
1693
|
-
}
|
|
1694
|
-
catch (error) {
|
|
1695
|
-
const errorDetails = error.response?.data || error.message;
|
|
1696
|
-
return {
|
|
1697
|
-
content: [
|
|
1698
|
-
{
|
|
1699
|
-
type: 'text',
|
|
1700
|
-
text: `❌ Failed to add comment to Jira issue\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n- Comment: ${comment.substring(0, 100)}...\n\n**Tip:** Check if the issue exists and you have permission to comment on it.`
|
|
1701
|
-
}
|
|
1702
|
-
],
|
|
1703
|
-
isError: true
|
|
1704
|
-
};
|
|
1705
|
-
}
|
|
1706
|
-
}
|
|
1707
|
-
case 'jira_get_comments': {
|
|
1708
|
-
const { issueKey } = args;
|
|
1709
|
-
try {
|
|
1710
|
-
const comments = await jiraService.getComments(issueKey);
|
|
1711
|
-
return {
|
|
1712
|
-
content: [
|
|
1713
|
-
{
|
|
1714
|
-
type: 'text',
|
|
1715
|
-
text: JSON.stringify(comments, null, 2)
|
|
1716
|
-
}
|
|
1717
|
-
]
|
|
1718
|
-
};
|
|
1719
|
-
}
|
|
1720
|
-
catch (error) {
|
|
1721
|
-
const errorDetails = error.response?.data || error.message;
|
|
1722
|
-
return {
|
|
1723
|
-
content: [
|
|
1724
|
-
{
|
|
1725
|
-
type: 'text',
|
|
1726
|
-
text: `❌ Failed to get comments for Jira issue\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n\n**Tip:** Check if the issue exists and you have permission to view it.`
|
|
1727
|
-
}
|
|
1728
|
-
],
|
|
1729
|
-
isError: true
|
|
1730
|
-
};
|
|
1731
|
-
}
|
|
1732
|
-
}
|
|
1733
|
-
case 'jira_update_comment': {
|
|
1734
|
-
const { issueKey, commentId, comment } = args;
|
|
1735
|
-
try {
|
|
1736
|
-
const result = await jiraService.updateComment(issueKey, commentId, comment);
|
|
1737
|
-
return {
|
|
1738
|
-
content: [
|
|
1739
|
-
{
|
|
1740
|
-
type: 'text',
|
|
1741
|
-
text: `✅ Comment ${commentId} updated successfully on issue ${issueKey}\n\n${JSON.stringify(result, null, 2)}`
|
|
1742
|
-
}
|
|
1743
|
-
]
|
|
1744
|
-
};
|
|
1745
|
-
}
|
|
1746
|
-
catch (error) {
|
|
1747
|
-
const errorDetails = error.response?.data || error.message;
|
|
1748
|
-
return {
|
|
1749
|
-
content: [
|
|
1750
|
-
{
|
|
1751
|
-
type: 'text',
|
|
1752
|
-
text: `❌ Failed to update comment on Jira issue\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n- Comment ID: ${commentId}\n\n**Tip:** Check if the comment exists, you are the author, and you have permission to edit it.`
|
|
1753
|
-
}
|
|
1754
|
-
],
|
|
1755
|
-
isError: true
|
|
1756
|
-
};
|
|
1757
|
-
}
|
|
1758
|
-
}
|
|
1759
|
-
case 'jira_delete_comment': {
|
|
1760
|
-
const { issueKey, commentId } = args;
|
|
1761
|
-
try {
|
|
1762
|
-
await jiraService.deleteComment(issueKey, commentId);
|
|
1763
|
-
return {
|
|
1764
|
-
content: [
|
|
1765
|
-
{
|
|
1766
|
-
type: 'text',
|
|
1767
|
-
text: `✅ Comment ${commentId} deleted successfully from issue ${issueKey}`
|
|
1768
|
-
}
|
|
1769
|
-
]
|
|
1770
|
-
};
|
|
1771
|
-
}
|
|
1772
|
-
catch (error) {
|
|
1773
|
-
const errorDetails = error.response?.data || error.message;
|
|
1774
|
-
return {
|
|
1775
|
-
content: [
|
|
1776
|
-
{
|
|
1777
|
-
type: 'text',
|
|
1778
|
-
text: `❌ Failed to delete comment from Jira issue\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n- Comment ID: ${commentId}\n\n**Tip:** Check if the comment exists and you have permission to delete it.`
|
|
1779
|
-
}
|
|
1780
|
-
],
|
|
1781
|
-
isError: true
|
|
1782
|
-
};
|
|
1783
|
-
}
|
|
1784
|
-
}
|
|
1785
|
-
case 'jira_get_projects': {
|
|
1786
|
-
try {
|
|
1787
|
-
const projects = await jiraService.getProjects();
|
|
1788
|
-
return {
|
|
1789
|
-
content: [
|
|
1790
|
-
{
|
|
1791
|
-
type: 'text',
|
|
1792
|
-
text: JSON.stringify(projects, null, 2)
|
|
1793
|
-
}
|
|
1794
|
-
]
|
|
1795
|
-
};
|
|
1796
|
-
}
|
|
1797
|
-
catch (error) {
|
|
1798
|
-
const errorDetails = error.response?.data || error.message;
|
|
1799
|
-
return {
|
|
1800
|
-
content: [
|
|
1801
|
-
{
|
|
1802
|
-
type: 'text',
|
|
1803
|
-
text: `❌ Failed to get Jira projects\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Tip:** Check your Jira permissions and API access.`
|
|
1804
|
-
}
|
|
1805
|
-
],
|
|
1806
|
-
isError: true
|
|
1807
|
-
};
|
|
1808
|
-
}
|
|
1809
|
-
}
|
|
1810
|
-
case 'jira_get_issue_transitions': {
|
|
1811
|
-
const { issueKey } = args;
|
|
1812
|
-
try {
|
|
1813
|
-
const transitions = await jiraService.getIssueTransitions(issueKey);
|
|
1814
|
-
const transitionInfo = transitions.map(t => ({
|
|
1815
|
-
id: t.id,
|
|
1816
|
-
name: t.name,
|
|
1817
|
-
to: t.to?.name || 'Unknown status'
|
|
1818
|
-
}));
|
|
1819
|
-
return {
|
|
1820
|
-
content: [
|
|
1821
|
-
{
|
|
1822
|
-
type: 'text',
|
|
1823
|
-
text: `Available transitions for ${issueKey}:\n\n${transitionInfo.map(t => `• **${t.name}** (ID: ${t.id}) → ${t.to}`).join('\n')}\n\nUse the transition ID with jira_transition_issue_interactive for smart field handling.`
|
|
1824
|
-
}
|
|
1825
|
-
]
|
|
1826
|
-
};
|
|
1827
|
-
}
|
|
1828
|
-
catch (error) {
|
|
1829
|
-
const errorDetails = error.response?.data || error.message;
|
|
1830
|
-
return {
|
|
1831
|
-
content: [
|
|
1832
|
-
{
|
|
1833
|
-
type: 'text',
|
|
1834
|
-
text: `❌ Failed to get transitions for Jira issue\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n\n**Tip:** Check if the issue exists and you have permission to view it.`
|
|
1835
|
-
}
|
|
1836
|
-
],
|
|
1837
|
-
isError: true
|
|
1838
|
-
};
|
|
1839
|
-
}
|
|
1840
|
-
}
|
|
1841
|
-
case 'jira_transition_issue': {
|
|
1842
|
-
const { issueKey, transitionId, fieldValues } = args;
|
|
1843
|
-
try {
|
|
1844
|
-
const result = await jiraService.transitionIssue(issueKey, transitionId, fieldValues);
|
|
1845
|
-
if (result.success) {
|
|
1846
|
-
return {
|
|
1847
|
-
content: [
|
|
1848
|
-
{
|
|
1849
|
-
type: 'text',
|
|
1850
|
-
text: result.message || `Issue ${issueKey} transitioned successfully`
|
|
1851
|
-
}
|
|
1852
|
-
]
|
|
1853
|
-
};
|
|
1854
|
-
}
|
|
1855
|
-
else if (result.requiresInput && result.requiredFields) {
|
|
1856
|
-
// Format required fields information for user
|
|
1857
|
-
const fieldInfo = result.requiredFields.map(field => {
|
|
1858
|
-
let info = `• **${field.name}** (${field.key})`;
|
|
1859
|
-
if (field.options) {
|
|
1860
|
-
info += `\n Options: ${field.options.map(opt => `${opt.value} (${opt.id})`).join(', ')}`;
|
|
1861
|
-
}
|
|
1862
|
-
if (field.suggestion) {
|
|
1863
|
-
info += `\n 💡 Suggestion: "${field.suggestion.value}" - ${field.suggestion.reason}`;
|
|
1864
|
-
}
|
|
1865
|
-
return info;
|
|
1866
|
-
}).join('\n\n');
|
|
1867
|
-
return {
|
|
1868
|
-
content: [
|
|
1869
|
-
{
|
|
1870
|
-
type: 'text',
|
|
1871
|
-
text: `${result.message}\n\n**Required Fields:**\n${fieldInfo}\n\n**Next Steps:**\nUse jira_transition_issue_interactive for automatic field suggestion, or provide fieldValues with the correct field IDs and values.`
|
|
1872
|
-
}
|
|
1873
|
-
]
|
|
1874
|
-
};
|
|
1875
|
-
}
|
|
1876
|
-
else {
|
|
1877
|
-
return {
|
|
1878
|
-
content: [
|
|
1879
|
-
{
|
|
1880
|
-
type: 'text',
|
|
1881
|
-
text: result.message || 'Transition failed with unknown error'
|
|
1882
|
-
}
|
|
1883
|
-
],
|
|
1884
|
-
isError: true
|
|
1885
|
-
};
|
|
1886
|
-
}
|
|
1887
|
-
}
|
|
1888
|
-
catch (error) {
|
|
1889
|
-
const errorDetails = error.response?.data || error.message;
|
|
1890
|
-
return {
|
|
1891
|
-
content: [
|
|
1892
|
-
{
|
|
1893
|
-
type: 'text',
|
|
1894
|
-
text: `❌ Failed to transition Jira issue ${issueKey}\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Transition ID: ${transitionId}\n- Field Values: ${JSON.stringify(fieldValues || {}, null, 2)}\n\n**Tip:** Check if the transition ID is valid for this issue and you have permission to transition it.`
|
|
1895
|
-
}
|
|
1896
|
-
],
|
|
1897
|
-
isError: true
|
|
1898
|
-
};
|
|
1899
|
-
}
|
|
1900
|
-
}
|
|
1901
|
-
case 'jira_transition_issue_interactive': {
|
|
1902
|
-
const { issueKey, transitionId, fieldValues } = args;
|
|
1903
|
-
try {
|
|
1904
|
-
const result = await jiraService.transitionIssueInteractive(issueKey, transitionId, fieldValues);
|
|
1905
|
-
if (result.success) {
|
|
1906
|
-
return {
|
|
1907
|
-
content: [
|
|
1908
|
-
{
|
|
1909
|
-
type: 'text',
|
|
1910
|
-
text: result.message || `Issue ${issueKey} transitioned successfully`
|
|
1911
|
-
}
|
|
1912
|
-
]
|
|
1913
|
-
};
|
|
1914
|
-
}
|
|
1915
|
-
else if (result.requiresInput && result.requiredFields) {
|
|
1916
|
-
// Still need user input even after smart suggestions
|
|
1917
|
-
const fieldInfo = result.requiredFields.map(field => {
|
|
1918
|
-
let info = `• **${field.name}** (${field.key})`;
|
|
1919
|
-
if (field.options) {
|
|
1920
|
-
info += `\n Options: ${field.options.map(opt => `${opt.value} (${opt.id})`).join(', ')}`;
|
|
1921
|
-
}
|
|
1922
|
-
if (field.suggestion) {
|
|
1923
|
-
info += `\n 💡 Suggestion: "${field.suggestion.value}" - ${field.suggestion.reason}`;
|
|
1924
|
-
}
|
|
1925
|
-
return info;
|
|
1926
|
-
}).join('\n\n');
|
|
1927
|
-
return {
|
|
1928
|
-
content: [
|
|
1929
|
-
{
|
|
1930
|
-
type: 'text',
|
|
1931
|
-
text: `${result.message}\n\n**Fields still requiring input:**\n${fieldInfo}`
|
|
1932
|
-
}
|
|
1933
|
-
]
|
|
1934
|
-
};
|
|
1935
|
-
}
|
|
1936
|
-
else {
|
|
1937
|
-
return {
|
|
1938
|
-
content: [
|
|
1939
|
-
{
|
|
1940
|
-
type: 'text',
|
|
1941
|
-
text: result.message || 'Transition failed with unknown error'
|
|
1942
|
-
}
|
|
1943
|
-
],
|
|
1944
|
-
isError: true
|
|
1945
|
-
};
|
|
1946
|
-
}
|
|
1947
|
-
}
|
|
1948
|
-
catch (error) {
|
|
1949
|
-
const errorDetails = error.response?.data || error.message;
|
|
1950
|
-
return {
|
|
1951
|
-
content: [
|
|
1952
|
-
{
|
|
1953
|
-
type: 'text',
|
|
1954
|
-
text: `❌ Failed to transition Jira issue ${issueKey} (interactive mode)\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Transition ID: ${transitionId}\n- Field Values: ${JSON.stringify(fieldValues || {}, null, 2)}\n\n**Tip:** Check if the transition ID is valid for this issue and you have permission to transition it.`
|
|
1955
|
-
}
|
|
1956
|
-
],
|
|
1957
|
-
isError: true
|
|
1958
|
-
};
|
|
1959
|
-
}
|
|
1960
|
-
}
|
|
1961
|
-
case 'jira_get_attachments': {
|
|
1962
|
-
const { issueKey } = args;
|
|
1963
|
-
try {
|
|
1964
|
-
const attachments = await jiraService.getAttachments(issueKey);
|
|
1965
|
-
return {
|
|
1966
|
-
content: [
|
|
1967
|
-
{
|
|
1968
|
-
type: 'text',
|
|
1969
|
-
text: JSON.stringify(attachments, null, 2)
|
|
1970
|
-
}
|
|
1971
|
-
]
|
|
1972
|
-
};
|
|
1973
|
-
}
|
|
1974
|
-
catch (error) {
|
|
1975
|
-
const errorDetails = error.response?.data || error.message;
|
|
1976
|
-
return {
|
|
1977
|
-
content: [
|
|
1978
|
-
{
|
|
1979
|
-
type: 'text',
|
|
1980
|
-
text: `❌ Failed to get attachments for Jira issue\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n\n**Tip:** Check if the issue exists and you have permission to view it.`
|
|
1981
|
-
}
|
|
1982
|
-
],
|
|
1983
|
-
isError: true
|
|
1984
|
-
};
|
|
1985
|
-
}
|
|
1986
|
-
}
|
|
1987
|
-
case 'jira_add_attachment': {
|
|
1988
|
-
const { issueKey, filename, fileContent } = args;
|
|
1989
|
-
try {
|
|
1990
|
-
const result = await jiraService.addAttachment(issueKey, filename, fileContent);
|
|
1991
|
-
return {
|
|
1992
|
-
content: [
|
|
1993
|
-
{
|
|
1994
|
-
type: 'text',
|
|
1995
|
-
text: `Attachment "${filename}" added to issue ${issueKey}\n\n${JSON.stringify(result, null, 2)}`
|
|
1996
|
-
}
|
|
1997
|
-
]
|
|
1998
|
-
};
|
|
1999
|
-
}
|
|
2000
|
-
catch (error) {
|
|
2001
|
-
const errorDetails = error.response?.data || error.message;
|
|
2002
|
-
return {
|
|
2003
|
-
content: [
|
|
2004
|
-
{
|
|
2005
|
-
type: 'text',
|
|
2006
|
-
text: `❌ Failed to add attachment to Jira issue\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n- Filename: ${filename}\n\n**Tip:** Check if the issue exists, you have permission to attach files, and the file content is properly base64 encoded.`
|
|
2007
|
-
}
|
|
2008
|
-
],
|
|
2009
|
-
isError: true
|
|
2010
|
-
};
|
|
2011
|
-
}
|
|
2012
|
-
}
|
|
2013
|
-
case 'jira_delete_attachment': {
|
|
2014
|
-
const { attachmentId } = args;
|
|
2015
|
-
try {
|
|
2016
|
-
await jiraService.deleteAttachment(attachmentId);
|
|
2017
|
-
return {
|
|
2018
|
-
content: [
|
|
2019
|
-
{
|
|
2020
|
-
type: 'text',
|
|
2021
|
-
text: `Attachment ${attachmentId} deleted successfully`
|
|
2022
|
-
}
|
|
2023
|
-
]
|
|
2024
|
-
};
|
|
2025
|
-
}
|
|
2026
|
-
catch (error) {
|
|
2027
|
-
const errorDetails = error.response?.data || error.message;
|
|
2028
|
-
return {
|
|
2029
|
-
content: [
|
|
2030
|
-
{
|
|
2031
|
-
type: 'text',
|
|
2032
|
-
text: `❌ Failed to delete attachment\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Attachment ID: ${attachmentId}\n\n**Tip:** Check if the attachment exists and you have permission to delete it.`
|
|
2033
|
-
}
|
|
2034
|
-
],
|
|
2035
|
-
isError: true
|
|
2036
|
-
};
|
|
2037
|
-
}
|
|
2038
|
-
}
|
|
2039
|
-
case 'jira_get_issue_links': {
|
|
2040
|
-
const { issueKey } = args;
|
|
2041
|
-
try {
|
|
2042
|
-
const links = await jiraService.getIssueLinks(issueKey);
|
|
2043
|
-
return {
|
|
2044
|
-
content: [
|
|
2045
|
-
{
|
|
2046
|
-
type: 'text',
|
|
2047
|
-
text: JSON.stringify(links, null, 2)
|
|
2048
|
-
}
|
|
2049
|
-
]
|
|
2050
|
-
};
|
|
2051
|
-
}
|
|
2052
|
-
catch (error) {
|
|
2053
|
-
const errorDetails = error.response?.data || error.message;
|
|
2054
|
-
return {
|
|
2055
|
-
content: [
|
|
2056
|
-
{
|
|
2057
|
-
type: 'text',
|
|
2058
|
-
text: `❌ Failed to get issue links\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n\n**Tip:** Check if the issue exists and you have permission to view it.`
|
|
2059
|
-
}
|
|
2060
|
-
],
|
|
2061
|
-
isError: true
|
|
2062
|
-
};
|
|
2063
|
-
}
|
|
2064
|
-
}
|
|
2065
|
-
case 'jira_create_issue_link': {
|
|
2066
|
-
const { inwardIssueKey, outwardIssueKey, linkType } = args;
|
|
2067
|
-
try {
|
|
2068
|
-
await jiraService.createIssueLink(inwardIssueKey, outwardIssueKey, linkType);
|
|
2069
|
-
return {
|
|
2070
|
-
content: [
|
|
2071
|
-
{
|
|
2072
|
-
type: 'text',
|
|
2073
|
-
text: `Link created: ${inwardIssueKey} ${linkType} ${outwardIssueKey}`
|
|
2074
|
-
}
|
|
2075
|
-
]
|
|
2076
|
-
};
|
|
2077
|
-
}
|
|
2078
|
-
catch (error) {
|
|
2079
|
-
const errorDetails = error.response?.data || error.message;
|
|
2080
|
-
return {
|
|
2081
|
-
content: [
|
|
2082
|
-
{
|
|
2083
|
-
type: 'text',
|
|
2084
|
-
text: `❌ Failed to create issue link\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Inward Issue: ${inwardIssueKey}\n- Outward Issue: ${outwardIssueKey}\n- Link Type: ${linkType}\n\n**Tip:** Check if both issues exist, the link type is valid, and you have permission to link issues. Use jira_get_link_types to see available link types.`
|
|
2085
|
-
}
|
|
2086
|
-
],
|
|
2087
|
-
isError: true
|
|
2088
|
-
};
|
|
2089
|
-
}
|
|
2090
|
-
}
|
|
2091
|
-
case 'jira_delete_issue_link': {
|
|
2092
|
-
const { linkId } = args;
|
|
2093
|
-
try {
|
|
2094
|
-
await jiraService.deleteIssueLink(linkId);
|
|
2095
|
-
return {
|
|
2096
|
-
content: [
|
|
2097
|
-
{
|
|
2098
|
-
type: 'text',
|
|
2099
|
-
text: `Issue link ${linkId} deleted successfully`
|
|
2100
|
-
}
|
|
2101
|
-
]
|
|
2102
|
-
};
|
|
2103
|
-
}
|
|
2104
|
-
catch (error) {
|
|
2105
|
-
const errorDetails = error.response?.data || error.message;
|
|
2106
|
-
return {
|
|
2107
|
-
content: [
|
|
2108
|
-
{
|
|
2109
|
-
type: 'text',
|
|
2110
|
-
text: `❌ Failed to delete issue link\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Link ID: ${linkId}\n\n**Tip:** Check if the link exists and you have permission to delete it. Use jira_get_issue_links to get link IDs.`
|
|
2111
|
-
}
|
|
2112
|
-
],
|
|
2113
|
-
isError: true
|
|
2114
|
-
};
|
|
2115
|
-
}
|
|
2116
|
-
}
|
|
2117
|
-
case 'jira_get_link_types': {
|
|
2118
|
-
try {
|
|
2119
|
-
const linkTypes = await jiraService.getIssueLinkTypes();
|
|
2120
|
-
return {
|
|
2121
|
-
content: [
|
|
2122
|
-
{
|
|
2123
|
-
type: 'text',
|
|
2124
|
-
text: JSON.stringify(linkTypes, null, 2)
|
|
2125
|
-
}
|
|
2126
|
-
]
|
|
2127
|
-
};
|
|
2128
|
-
}
|
|
2129
|
-
catch (error) {
|
|
2130
|
-
const errorDetails = error.response?.data || error.message;
|
|
2131
|
-
return {
|
|
2132
|
-
content: [
|
|
2133
|
-
{
|
|
2134
|
-
type: 'text',
|
|
2135
|
-
text: `❌ Failed to get issue link types\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Tip:** Check your Jira permissions and API access.`
|
|
2136
|
-
}
|
|
2137
|
-
],
|
|
2138
|
-
isError: true
|
|
2139
|
-
};
|
|
2140
|
-
}
|
|
2141
|
-
}
|
|
2142
|
-
case 'jira_get_worklogs': {
|
|
2143
|
-
const { issueKey } = args;
|
|
2144
|
-
try {
|
|
2145
|
-
const worklogs = await jiraService.getWorkLogs(issueKey);
|
|
2146
|
-
return {
|
|
2147
|
-
content: [
|
|
2148
|
-
{
|
|
2149
|
-
type: 'text',
|
|
2150
|
-
text: JSON.stringify(worklogs, null, 2)
|
|
2151
|
-
}
|
|
2152
|
-
]
|
|
2153
|
-
};
|
|
2154
|
-
}
|
|
2155
|
-
catch (error) {
|
|
2156
|
-
const errorDetails = error.response?.data || error.message;
|
|
2157
|
-
return {
|
|
2158
|
-
content: [
|
|
2159
|
-
{
|
|
2160
|
-
type: 'text',
|
|
2161
|
-
text: `❌ Failed to get work logs\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n\n**Tip:** Check if the issue exists and you have permission to view it.`
|
|
2162
|
-
}
|
|
2163
|
-
],
|
|
2164
|
-
isError: true
|
|
2165
|
-
};
|
|
2166
|
-
}
|
|
2167
|
-
}
|
|
2168
|
-
case 'jira_add_worklog': {
|
|
2169
|
-
const { issueKey, timeSpentSeconds, comment, started } = args;
|
|
2170
|
-
try {
|
|
2171
|
-
const result = await jiraService.addWorkLog(issueKey, timeSpentSeconds, comment, started);
|
|
2172
|
-
return {
|
|
2173
|
-
content: [
|
|
2174
|
-
{
|
|
2175
|
-
type: 'text',
|
|
2176
|
-
text: `Work log added to ${issueKey}\nTime spent: ${Math.floor(timeSpentSeconds / 3600)}h ${Math.floor((timeSpentSeconds % 3600) / 60)}m\n\n${JSON.stringify(result, null, 2)}`
|
|
2177
|
-
}
|
|
2178
|
-
]
|
|
2179
|
-
};
|
|
2180
|
-
}
|
|
2181
|
-
catch (error) {
|
|
2182
|
-
const errorDetails = error.response?.data || error.message;
|
|
2183
|
-
return {
|
|
2184
|
-
content: [
|
|
2185
|
-
{
|
|
2186
|
-
type: 'text',
|
|
2187
|
-
text: `❌ Failed to add work log\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n- Time Spent: ${timeSpentSeconds}s\n- Comment: ${comment || 'none'}\n\n**Tip:** Check if the issue exists and you have permission to log work.`
|
|
2188
|
-
}
|
|
2189
|
-
],
|
|
2190
|
-
isError: true
|
|
2191
|
-
};
|
|
2192
|
-
}
|
|
2193
|
-
}
|
|
2194
|
-
case 'jira_update_worklog': {
|
|
2195
|
-
const { issueKey, worklogId, timeSpentSeconds, comment } = args;
|
|
2196
|
-
try {
|
|
2197
|
-
const result = await jiraService.updateWorkLog(issueKey, worklogId, timeSpentSeconds, comment);
|
|
2198
|
-
return {
|
|
2199
|
-
content: [
|
|
2200
|
-
{
|
|
2201
|
-
type: 'text',
|
|
2202
|
-
text: `Work log ${worklogId} updated\n\n${JSON.stringify(result, null, 2)}`
|
|
2203
|
-
}
|
|
2204
|
-
]
|
|
2205
|
-
};
|
|
2206
|
-
}
|
|
2207
|
-
catch (error) {
|
|
2208
|
-
const errorDetails = error.response?.data || error.message;
|
|
2209
|
-
return {
|
|
2210
|
-
content: [
|
|
2211
|
-
{
|
|
2212
|
-
type: 'text',
|
|
2213
|
-
text: `❌ Failed to update work log\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n- Worklog ID: ${worklogId}\n\n**Tip:** Check if the work log exists and you have permission to update it.`
|
|
2214
|
-
}
|
|
2215
|
-
],
|
|
2216
|
-
isError: true
|
|
2217
|
-
};
|
|
2218
|
-
}
|
|
2219
|
-
}
|
|
2220
|
-
case 'jira_delete_worklog': {
|
|
2221
|
-
const { issueKey, worklogId } = args;
|
|
2222
|
-
try {
|
|
2223
|
-
await jiraService.deleteWorkLog(issueKey, worklogId);
|
|
2224
|
-
return {
|
|
2225
|
-
content: [
|
|
2226
|
-
{
|
|
2227
|
-
type: 'text',
|
|
2228
|
-
text: `Work log ${worklogId} deleted from ${issueKey}`
|
|
2229
|
-
}
|
|
2230
|
-
]
|
|
2231
|
-
};
|
|
2232
|
-
}
|
|
2233
|
-
catch (error) {
|
|
2234
|
-
const errorDetails = error.response?.data || error.message;
|
|
2235
|
-
return {
|
|
2236
|
-
content: [
|
|
2237
|
-
{
|
|
2238
|
-
type: 'text',
|
|
2239
|
-
text: `❌ Failed to delete work log\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n- Worklog ID: ${worklogId}\n\n**Tip:** Check if the work log exists and you have permission to delete it.`
|
|
2240
|
-
}
|
|
2241
|
-
],
|
|
2242
|
-
isError: true
|
|
2243
|
-
};
|
|
2244
|
-
}
|
|
2245
|
-
}
|
|
2246
|
-
case 'jira_get_watchers': {
|
|
2247
|
-
const { issueKey } = args;
|
|
2248
|
-
try {
|
|
2249
|
-
const watchers = await jiraService.getWatchers(issueKey);
|
|
2250
|
-
return {
|
|
2251
|
-
content: [
|
|
2252
|
-
{
|
|
2253
|
-
type: 'text',
|
|
2254
|
-
text: JSON.stringify(watchers, null, 2)
|
|
2255
|
-
}
|
|
2256
|
-
]
|
|
2257
|
-
};
|
|
2258
|
-
}
|
|
2259
|
-
catch (error) {
|
|
2260
|
-
const errorDetails = error.response?.data || error.message;
|
|
2261
|
-
return {
|
|
2262
|
-
content: [
|
|
2263
|
-
{
|
|
2264
|
-
type: 'text',
|
|
2265
|
-
text: `❌ Failed to get watchers\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n\n**Tip:** Check if the issue exists and you have permission to view it.`
|
|
2266
|
-
}
|
|
2267
|
-
],
|
|
2268
|
-
isError: true
|
|
2269
|
-
};
|
|
2270
|
-
}
|
|
2271
|
-
}
|
|
2272
|
-
case 'jira_add_watcher': {
|
|
2273
|
-
const { issueKey, accountId } = args;
|
|
2274
|
-
try {
|
|
2275
|
-
await jiraService.addWatcher(issueKey, accountId);
|
|
2276
|
-
return {
|
|
2277
|
-
content: [
|
|
2278
|
-
{
|
|
2279
|
-
type: 'text',
|
|
2280
|
-
text: `Watcher added to ${issueKey}`
|
|
2281
|
-
}
|
|
2282
|
-
]
|
|
2283
|
-
};
|
|
2284
|
-
}
|
|
2285
|
-
catch (error) {
|
|
2286
|
-
const errorDetails = error.response?.data || error.message;
|
|
2287
|
-
return {
|
|
2288
|
-
content: [
|
|
2289
|
-
{
|
|
2290
|
-
type: 'text',
|
|
2291
|
-
text: `❌ Failed to add watcher\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n- Account ID: ${accountId}\n\n**Tip:** Check if the issue and user exist, and you have permission to add watchers.`
|
|
2292
|
-
}
|
|
2293
|
-
],
|
|
2294
|
-
isError: true
|
|
2295
|
-
};
|
|
2296
|
-
}
|
|
2297
|
-
}
|
|
2298
|
-
case 'jira_remove_watcher': {
|
|
2299
|
-
const { issueKey, accountId } = args;
|
|
2300
|
-
try {
|
|
2301
|
-
await jiraService.removeWatcher(issueKey, accountId);
|
|
2302
|
-
return {
|
|
2303
|
-
content: [
|
|
2304
|
-
{
|
|
2305
|
-
type: 'text',
|
|
2306
|
-
text: `Watcher removed from ${issueKey}`
|
|
2307
|
-
}
|
|
2308
|
-
]
|
|
2309
|
-
};
|
|
2310
|
-
}
|
|
2311
|
-
catch (error) {
|
|
2312
|
-
const errorDetails = error.response?.data || error.message;
|
|
2313
|
-
return {
|
|
2314
|
-
content: [
|
|
2315
|
-
{
|
|
2316
|
-
type: 'text',
|
|
2317
|
-
text: `❌ Failed to remove watcher\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n- Account ID: ${accountId}\n\n**Tip:** Check if the issue exists and you have permission to remove watchers.`
|
|
2318
|
-
}
|
|
2319
|
-
],
|
|
2320
|
-
isError: true
|
|
2321
|
-
};
|
|
2322
|
-
}
|
|
2323
|
-
}
|
|
2324
|
-
case 'jira_get_subtasks': {
|
|
2325
|
-
const { issueKey } = args;
|
|
2326
|
-
try {
|
|
2327
|
-
const subtasks = await jiraService.getSubTasks(issueKey);
|
|
2328
|
-
return {
|
|
2329
|
-
content: [
|
|
2330
|
-
{
|
|
2331
|
-
type: 'text',
|
|
2332
|
-
text: JSON.stringify(subtasks, null, 2)
|
|
2333
|
-
}
|
|
2334
|
-
]
|
|
2335
|
-
};
|
|
2336
|
-
}
|
|
2337
|
-
catch (error) {
|
|
2338
|
-
const errorDetails = error.response?.data || error.message;
|
|
2339
|
-
return {
|
|
2340
|
-
content: [
|
|
2341
|
-
{
|
|
2342
|
-
type: 'text',
|
|
2343
|
-
text: `❌ Failed to get sub-tasks\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n\n**Tip:** Check if the issue exists and you have permission to view it.`
|
|
2344
|
-
}
|
|
2345
|
-
],
|
|
2346
|
-
isError: true
|
|
2347
|
-
};
|
|
2348
|
-
}
|
|
2349
|
-
}
|
|
2350
|
-
case 'jira_create_subtask': {
|
|
2351
|
-
const { parentKey, summary, description } = args;
|
|
2352
|
-
try {
|
|
2353
|
-
const subtask = await jiraService.createSubTask(parentKey, summary, description);
|
|
2354
|
-
return {
|
|
2355
|
-
content: [
|
|
2356
|
-
{
|
|
2357
|
-
type: 'text',
|
|
2358
|
-
text: `Sub-task created: ${subtask.key}\n\n${JSON.stringify(subtask, null, 2)}`
|
|
2359
|
-
}
|
|
2360
|
-
]
|
|
2361
|
-
};
|
|
2362
|
-
}
|
|
2363
|
-
catch (error) {
|
|
2364
|
-
const errorDetails = error.response?.data || error.message;
|
|
2365
|
-
return {
|
|
2366
|
-
content: [
|
|
2367
|
-
{
|
|
2368
|
-
type: 'text',
|
|
2369
|
-
text: `❌ Failed to create sub-task\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Parent Key: ${parentKey}\n- Summary: ${summary}\n\n**Tip:** Check if the parent issue exists, the project allows sub-tasks, and you have permission to create issues.`
|
|
2370
|
-
}
|
|
2371
|
-
],
|
|
2372
|
-
isError: true
|
|
2373
|
-
};
|
|
2374
|
-
}
|
|
2375
|
-
}
|
|
2376
|
-
case 'jira_get_issue_history': {
|
|
2377
|
-
const { issueKey } = args;
|
|
2378
|
-
try {
|
|
2379
|
-
const history = await jiraService.getIssueHistory(issueKey);
|
|
2380
|
-
return {
|
|
2381
|
-
content: [
|
|
2382
|
-
{
|
|
2383
|
-
type: 'text',
|
|
2384
|
-
text: JSON.stringify(history, null, 2)
|
|
2385
|
-
}
|
|
2386
|
-
]
|
|
2387
|
-
};
|
|
2388
|
-
}
|
|
2389
|
-
catch (error) {
|
|
2390
|
-
const errorDetails = error.response?.data || error.message;
|
|
2391
|
-
return {
|
|
2392
|
-
content: [
|
|
2393
|
-
{
|
|
2394
|
-
type: 'text',
|
|
2395
|
-
text: `❌ Failed to get issue history\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Issue Key: ${issueKey}\n\n**Tip:** Check if the issue exists and you have permission to view it.`
|
|
2396
|
-
}
|
|
2397
|
-
],
|
|
2398
|
-
isError: true
|
|
2399
|
-
};
|
|
2400
|
-
}
|
|
2401
|
-
}
|
|
75
|
+
case 'jira_search_issues':
|
|
76
|
+
return jiraHandlers.searchIssues(args);
|
|
77
|
+
case 'jira_get_issue':
|
|
78
|
+
return jiraHandlers.getIssue(args);
|
|
79
|
+
case 'jira_create_issue':
|
|
80
|
+
return jiraHandlers.createIssue(args);
|
|
81
|
+
case 'jira_update_issue':
|
|
82
|
+
return jiraHandlers.updateIssue(args);
|
|
83
|
+
case 'jira_add_comment':
|
|
84
|
+
return jiraHandlers.addComment(args);
|
|
85
|
+
case 'jira_get_comments':
|
|
86
|
+
return jiraHandlers.getComments(args);
|
|
87
|
+
case 'jira_update_comment':
|
|
88
|
+
return jiraHandlers.updateComment(args);
|
|
89
|
+
case 'jira_delete_comment':
|
|
90
|
+
return jiraHandlers.deleteComment(args);
|
|
91
|
+
case 'jira_get_projects':
|
|
92
|
+
return jiraHandlers.getProjects();
|
|
93
|
+
case 'jira_get_issue_transitions':
|
|
94
|
+
return jiraHandlers.getIssueTransitions(args);
|
|
95
|
+
case 'jira_transition_issue':
|
|
96
|
+
return jiraHandlers.transitionIssue(args);
|
|
97
|
+
case 'jira_transition_issue_interactive':
|
|
98
|
+
return jiraHandlers.transitionIssueInteractive(args);
|
|
99
|
+
case 'jira_get_attachments':
|
|
100
|
+
return jiraHandlers.getAttachments(args);
|
|
101
|
+
case 'jira_add_attachment':
|
|
102
|
+
return jiraHandlers.addAttachment(args);
|
|
103
|
+
case 'jira_delete_attachment':
|
|
104
|
+
return jiraHandlers.deleteAttachment(args);
|
|
105
|
+
case 'jira_get_issue_links':
|
|
106
|
+
return jiraHandlers.getIssueLinks(args);
|
|
107
|
+
case 'jira_create_issue_link':
|
|
108
|
+
return jiraHandlers.createIssueLink(args);
|
|
109
|
+
case 'jira_delete_issue_link':
|
|
110
|
+
return jiraHandlers.deleteIssueLink(args);
|
|
111
|
+
case 'jira_get_link_types':
|
|
112
|
+
return jiraHandlers.getLinkTypes();
|
|
113
|
+
case 'jira_get_worklogs':
|
|
114
|
+
return jiraHandlers.getWorklogs(args);
|
|
115
|
+
case 'jira_add_worklog':
|
|
116
|
+
return jiraHandlers.addWorklog(args);
|
|
117
|
+
case 'jira_update_worklog':
|
|
118
|
+
return jiraHandlers.updateWorklog(args);
|
|
119
|
+
case 'jira_delete_worklog':
|
|
120
|
+
return jiraHandlers.deleteWorklog(args);
|
|
121
|
+
case 'jira_get_watchers':
|
|
122
|
+
return jiraHandlers.getWatchers(args);
|
|
123
|
+
case 'jira_add_watcher':
|
|
124
|
+
return jiraHandlers.addWatcher(args);
|
|
125
|
+
case 'jira_remove_watcher':
|
|
126
|
+
return jiraHandlers.removeWatcher(args);
|
|
127
|
+
case 'jira_get_subtasks':
|
|
128
|
+
return jiraHandlers.getSubtasks(args);
|
|
129
|
+
case 'jira_create_subtask':
|
|
130
|
+
return jiraHandlers.createSubtask(args);
|
|
131
|
+
case 'jira_get_issue_history':
|
|
132
|
+
return jiraHandlers.getIssueHistory(args);
|
|
133
|
+
case 'jira_get_fields':
|
|
134
|
+
return jiraHandlers.getFields(args);
|
|
135
|
+
case 'jira_get_labels':
|
|
136
|
+
return jiraHandlers.getLabels(args);
|
|
137
|
+
case 'jira_add_labels':
|
|
138
|
+
return jiraHandlers.addLabels(args);
|
|
139
|
+
case 'jira_remove_labels':
|
|
140
|
+
return jiraHandlers.removeLabels(args);
|
|
2402
141
|
// Bitbucket Tools
|
|
2403
|
-
case 'bitbucket_get_repositories':
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
case '
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
{
|
|
2436
|
-
type: 'text',
|
|
2437
|
-
text: JSON.stringify(repo, null, 2)
|
|
2438
|
-
}
|
|
2439
|
-
]
|
|
2440
|
-
};
|
|
2441
|
-
}
|
|
2442
|
-
catch (error) {
|
|
2443
|
-
const errorDetails = error.response?.data || error.message;
|
|
2444
|
-
return {
|
|
2445
|
-
content: [
|
|
2446
|
-
{
|
|
2447
|
-
type: 'text',
|
|
2448
|
-
text: `❌ Failed to get Bitbucket repository\n\n**Error Details:**\n${JSON.stringify(errorDetails, null, 2)}\n\n**Request:**\n- Repository: ${repoName}\n\n**Tip:** Check if the repository exists and you have access to it.`
|
|
2449
|
-
}
|
|
2450
|
-
],
|
|
2451
|
-
isError: true
|
|
2452
|
-
};
|
|
2453
|
-
}
|
|
2454
|
-
}
|
|
2455
|
-
case 'bitbucket_create_repository': {
|
|
2456
|
-
const { name, description, isPrivate, language } = args;
|
|
2457
|
-
const repo = await bitbucketService.createRepository(name, description, isPrivate, language);
|
|
2458
|
-
return {
|
|
2459
|
-
content: [
|
|
2460
|
-
{
|
|
2461
|
-
type: 'text',
|
|
2462
|
-
text: JSON.stringify(repo, null, 2)
|
|
2463
|
-
}
|
|
2464
|
-
]
|
|
2465
|
-
};
|
|
2466
|
-
}
|
|
2467
|
-
case 'bitbucket_get_pull_requests': {
|
|
2468
|
-
const { repoName, state, limit } = args;
|
|
2469
|
-
const prs = await bitbucketService.getPullRequests(repoName, state, limit);
|
|
2470
|
-
return {
|
|
2471
|
-
content: [
|
|
2472
|
-
{
|
|
2473
|
-
type: 'text',
|
|
2474
|
-
text: JSON.stringify(prs, null, 2)
|
|
2475
|
-
}
|
|
2476
|
-
]
|
|
2477
|
-
};
|
|
2478
|
-
}
|
|
2479
|
-
case 'bitbucket_get_pull_request': {
|
|
2480
|
-
const { repoName, prId, includeDiff = false } = args;
|
|
2481
|
-
const pr = await bitbucketService.getPullRequest(repoName, prId, includeDiff);
|
|
2482
|
-
if (includeDiff && pr.diff) {
|
|
2483
|
-
return {
|
|
2484
|
-
content: [
|
|
2485
|
-
{
|
|
2486
|
-
type: 'text',
|
|
2487
|
-
text: `Pull Request #${prId} Details:\n\n${JSON.stringify(pr, null, 2)}\n\n---\n\nCode Diff:\n\n\`\`\`diff\n${pr.diff}\n\`\`\``
|
|
2488
|
-
}
|
|
2489
|
-
]
|
|
2490
|
-
};
|
|
2491
|
-
}
|
|
2492
|
-
else {
|
|
2493
|
-
return {
|
|
2494
|
-
content: [
|
|
2495
|
-
{
|
|
2496
|
-
type: 'text',
|
|
2497
|
-
text: JSON.stringify(pr, null, 2)
|
|
2498
|
-
}
|
|
2499
|
-
]
|
|
2500
|
-
};
|
|
2501
|
-
}
|
|
2502
|
-
}
|
|
2503
|
-
case 'bitbucket_create_pull_request': {
|
|
2504
|
-
const { repoName, title, sourceBranch, destinationBranch, description } = args;
|
|
2505
|
-
const pr = await bitbucketService.createPullRequest(repoName, title, sourceBranch, destinationBranch, description);
|
|
2506
|
-
return {
|
|
2507
|
-
content: [
|
|
2508
|
-
{
|
|
2509
|
-
type: 'text',
|
|
2510
|
-
text: JSON.stringify(pr, null, 2)
|
|
2511
|
-
}
|
|
2512
|
-
]
|
|
2513
|
-
};
|
|
2514
|
-
}
|
|
2515
|
-
case 'bitbucket_get_branches': {
|
|
2516
|
-
const { repoName, limit } = args;
|
|
2517
|
-
const branches = await bitbucketService.getBranches(repoName, limit);
|
|
2518
|
-
return {
|
|
2519
|
-
content: [
|
|
2520
|
-
{
|
|
2521
|
-
type: 'text',
|
|
2522
|
-
text: JSON.stringify(branches, null, 2)
|
|
2523
|
-
}
|
|
2524
|
-
]
|
|
2525
|
-
};
|
|
2526
|
-
}
|
|
2527
|
-
case 'bitbucket_get_commits': {
|
|
2528
|
-
const { repoName, branch, limit } = args;
|
|
2529
|
-
const commits = await bitbucketService.getCommits(repoName, branch, limit);
|
|
2530
|
-
return {
|
|
2531
|
-
content: [
|
|
2532
|
-
{
|
|
2533
|
-
type: 'text',
|
|
2534
|
-
text: JSON.stringify(commits, null, 2)
|
|
2535
|
-
}
|
|
2536
|
-
]
|
|
2537
|
-
};
|
|
2538
|
-
}
|
|
2539
|
-
case 'bitbucket_get_issues': {
|
|
2540
|
-
const { repoName, state, limit } = args;
|
|
2541
|
-
const issues = await bitbucketService.getIssues(repoName, state, limit);
|
|
2542
|
-
return {
|
|
2543
|
-
content: [
|
|
2544
|
-
{
|
|
2545
|
-
type: 'text',
|
|
2546
|
-
text: JSON.stringify(issues, null, 2)
|
|
2547
|
-
}
|
|
2548
|
-
]
|
|
2549
|
-
};
|
|
2550
|
-
}
|
|
2551
|
-
case 'bitbucket_create_issue': {
|
|
2552
|
-
const { repoName, title, content, kind } = args;
|
|
2553
|
-
const issue = await bitbucketService.createIssue(repoName, title, content, kind);
|
|
2554
|
-
return {
|
|
2555
|
-
content: [
|
|
2556
|
-
{
|
|
2557
|
-
type: 'text',
|
|
2558
|
-
text: JSON.stringify(issue, null, 2)
|
|
2559
|
-
}
|
|
2560
|
-
]
|
|
2561
|
-
};
|
|
2562
|
-
}
|
|
142
|
+
case 'bitbucket_get_repositories':
|
|
143
|
+
return bitbucketHandlers.getRepositories(args);
|
|
144
|
+
case 'bitbucket_get_repository':
|
|
145
|
+
return bitbucketHandlers.getRepository(args);
|
|
146
|
+
case 'bitbucket_create_repository':
|
|
147
|
+
return bitbucketHandlers.createRepository(args);
|
|
148
|
+
case 'bitbucket_get_pull_requests':
|
|
149
|
+
return bitbucketHandlers.getPullRequests(args);
|
|
150
|
+
case 'bitbucket_get_pull_request':
|
|
151
|
+
return bitbucketHandlers.getPullRequest(args);
|
|
152
|
+
case 'bitbucket_create_pull_request':
|
|
153
|
+
return bitbucketHandlers.createPullRequest(args);
|
|
154
|
+
case 'bitbucket_get_branches':
|
|
155
|
+
return bitbucketHandlers.getBranches(args);
|
|
156
|
+
case 'bitbucket_get_commits':
|
|
157
|
+
return bitbucketHandlers.getCommits(args);
|
|
158
|
+
case 'bitbucket_get_issues':
|
|
159
|
+
return bitbucketHandlers.getIssues(args);
|
|
160
|
+
case 'bitbucket_create_issue':
|
|
161
|
+
return bitbucketHandlers.createIssue(args);
|
|
162
|
+
case 'bitbucket_get_pr_comments':
|
|
163
|
+
return bitbucketHandlers.getPRComments(args);
|
|
164
|
+
case 'bitbucket_add_pr_comment':
|
|
165
|
+
return bitbucketHandlers.addPRComment(args);
|
|
166
|
+
case 'bitbucket_update_pr_comment':
|
|
167
|
+
return bitbucketHandlers.updatePRComment(args);
|
|
168
|
+
case 'bitbucket_delete_pr_comment':
|
|
169
|
+
return bitbucketHandlers.deletePRComment(args);
|
|
170
|
+
case 'bitbucket_resolve_pr_comment':
|
|
171
|
+
return bitbucketHandlers.resolvePRComment(args);
|
|
172
|
+
case 'bitbucket_unresolve_pr_comment':
|
|
173
|
+
return bitbucketHandlers.unresolvePRComment(args);
|
|
2563
174
|
default:
|
|
2564
|
-
throw new Error(
|
|
175
|
+
throw new Error(ERROR_MESSAGES.UNKNOWN_TOOL(name));
|
|
2565
176
|
}
|
|
2566
177
|
}
|
|
2567
178
|
catch (error) {
|