@ecubelabs/atlassian-mcp 1.2.0-next.5 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.js +6 -6
- package/dist/index.js +1576 -6
- package/dist/libs/base-client.js +2 -29
- package/package.json +3 -4
- package/dist/confluence-tools-register.js +0 -615
- package/dist/jira-tools-register.js +0 -1593
- package/dist/libs/confluence-client.js +0 -277
package/dist/libs/base-client.js
CHANGED
|
@@ -19,42 +19,15 @@ export class BaseApiService {
|
|
|
19
19
|
}
|
|
20
20
|
setupAxiosClient() {
|
|
21
21
|
const auth = Buffer.from(`${this.config.email}:${this.config.apiToken}`).toString('base64');
|
|
22
|
-
const baseURL = this.serviceName === 'ConfluenceService'
|
|
23
|
-
? `${this.config.host}/wiki/api/v${this.config.apiVersion}`
|
|
24
|
-
: `${this.config.host}/rest/api/${this.config.apiVersion}`;
|
|
25
22
|
return axios.create({
|
|
26
|
-
baseURL
|
|
23
|
+
baseURL: `${this.config.host}/rest/api/${this.config.apiVersion}`,
|
|
27
24
|
headers: {
|
|
28
25
|
Authorization: `Basic ${auth}`,
|
|
29
26
|
Accept: 'application/json',
|
|
30
27
|
'Content-Type': 'application/json',
|
|
31
28
|
},
|
|
32
29
|
timeout: 30000,
|
|
33
|
-
paramsSerializer: (params) => {
|
|
34
|
-
return this.serviceName === 'ConfluenceService'
|
|
35
|
-
? this.serializeConfluenceParams(params)
|
|
36
|
-
: new URLSearchParams(params).toString();
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
serializeConfluenceParams(params) {
|
|
41
|
-
const searchParams = new URLSearchParams();
|
|
42
|
-
Object.entries(params).forEach(([key, value]) => {
|
|
43
|
-
if (value === undefined || value === null)
|
|
44
|
-
return;
|
|
45
|
-
if (Array.isArray(value)) {
|
|
46
|
-
// 배열의 경우 각 값을 개별적으로 추가 (대괄호 없이)
|
|
47
|
-
value.forEach((item) => {
|
|
48
|
-
if (item !== undefined && item !== null) {
|
|
49
|
-
searchParams.append(key, String(item));
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
searchParams.append(key, String(value));
|
|
55
|
-
}
|
|
56
30
|
});
|
|
57
|
-
return searchParams.toString();
|
|
58
31
|
}
|
|
59
32
|
setupInterceptors() {
|
|
60
33
|
// Request 인터셉터
|
|
@@ -112,7 +85,7 @@ export class BaseApiService {
|
|
|
112
85
|
if (response.data?.message) {
|
|
113
86
|
return response.data.message;
|
|
114
87
|
}
|
|
115
|
-
return
|
|
88
|
+
return 'Unknown error occurred';
|
|
116
89
|
}
|
|
117
90
|
// Rate limited request wrapper
|
|
118
91
|
async makeRequest(requestFn) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ecubelabs/atlassian-mcp",
|
|
3
|
-
"version": "1.2.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"bin": "./dist/index.js",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/Ecube-Labs/skynet.git"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"type": "module",
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@modelcontextprotocol/sdk": "^1.17.3",
|
|
23
|
-
"axios": "^1.
|
|
23
|
+
"axios": "^1.12.0",
|
|
24
24
|
"axios-retry": "^4.5.0",
|
|
25
25
|
"dotenv": "^17.2.0",
|
|
26
26
|
"marklassian": "^1.1.0",
|
|
@@ -37,6 +37,5 @@
|
|
|
37
37
|
"semantic-release-yarn": "^3.0.2",
|
|
38
38
|
"ts-node": "^10.9.2",
|
|
39
39
|
"typescript": "^5.8.2"
|
|
40
|
-
}
|
|
41
|
-
"stableVersion": "1.0.0"
|
|
40
|
+
}
|
|
42
41
|
}
|
|
@@ -1,615 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { ConfluenceService } from './libs/confluence-client.js';
|
|
3
|
-
export const registerConfluenceTools = (server) => {
|
|
4
|
-
// Initialize Confluence service
|
|
5
|
-
const confluenceService = new ConfluenceService();
|
|
6
|
-
// Register get-pages tool
|
|
7
|
-
server.tool('get-pages', 'Get list of pages from Confluence', {
|
|
8
|
-
id: z.array(z.string()).optional().describe('List of page IDs to retrieve'),
|
|
9
|
-
spaceId: z.array(z.string()).optional().describe('Filter pages by space IDs'),
|
|
10
|
-
title: z.string().optional().describe('Filter pages by title (partial match)'),
|
|
11
|
-
status: z
|
|
12
|
-
.array(z.enum(['current', 'trashed', 'historical', 'draft']))
|
|
13
|
-
.optional()
|
|
14
|
-
.describe('Filter pages by status'),
|
|
15
|
-
bodyFormat: z
|
|
16
|
-
.array(z.enum(['storage', 'atlas_doc_format', 'view']))
|
|
17
|
-
.optional()
|
|
18
|
-
.describe('Format of the page body to retrieve'),
|
|
19
|
-
cursor: z.string().optional().describe('Cursor for pagination'),
|
|
20
|
-
limit: z
|
|
21
|
-
.number()
|
|
22
|
-
.min(1)
|
|
23
|
-
.max(250)
|
|
24
|
-
.optional()
|
|
25
|
-
.describe('Maximum number of results to return (default: 25, max: 250)'),
|
|
26
|
-
sort: z
|
|
27
|
-
.enum([
|
|
28
|
-
'id',
|
|
29
|
-
'-id',
|
|
30
|
-
'created-date',
|
|
31
|
-
'-created-date',
|
|
32
|
-
'modified-date',
|
|
33
|
-
'-modified-date',
|
|
34
|
-
'title',
|
|
35
|
-
'-title',
|
|
36
|
-
])
|
|
37
|
-
.optional()
|
|
38
|
-
.describe('Sort order for results'),
|
|
39
|
-
}, async ({ id, spaceId, title, status, bodyFormat, cursor, limit, sort }) => {
|
|
40
|
-
try {
|
|
41
|
-
const result = await confluenceService.getPages({
|
|
42
|
-
id,
|
|
43
|
-
spaceId,
|
|
44
|
-
title,
|
|
45
|
-
status,
|
|
46
|
-
bodyFormat,
|
|
47
|
-
cursor,
|
|
48
|
-
limit,
|
|
49
|
-
sort,
|
|
50
|
-
});
|
|
51
|
-
return {
|
|
52
|
-
content: [
|
|
53
|
-
{
|
|
54
|
-
type: 'text',
|
|
55
|
-
text: JSON.stringify(result),
|
|
56
|
-
},
|
|
57
|
-
],
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
catch (error) {
|
|
61
|
-
return {
|
|
62
|
-
content: [
|
|
63
|
-
{
|
|
64
|
-
type: 'text',
|
|
65
|
-
text: `Failed to retrieve pages: ${error instanceof Error ? error.message : String(error)}`,
|
|
66
|
-
},
|
|
67
|
-
],
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
// Register get-pages-for-labels tool
|
|
72
|
-
server.tool('get-pages-for-labels', 'Get pages associated with a specific label', {
|
|
73
|
-
labelId: z.string().describe('ID of the label to search for'),
|
|
74
|
-
bodyFormat: z
|
|
75
|
-
.array(z.enum(['storage', 'atlas_doc_format', 'view']))
|
|
76
|
-
.optional()
|
|
77
|
-
.describe('Format of the page body to retrieve'),
|
|
78
|
-
sort: z
|
|
79
|
-
.enum([
|
|
80
|
-
'id',
|
|
81
|
-
'-id',
|
|
82
|
-
'created-date',
|
|
83
|
-
'-created-date',
|
|
84
|
-
'modified-date',
|
|
85
|
-
'-modified-date',
|
|
86
|
-
'title',
|
|
87
|
-
'-title',
|
|
88
|
-
])
|
|
89
|
-
.optional()
|
|
90
|
-
.describe('Sort order for results'),
|
|
91
|
-
cursor: z.string().optional().describe('Cursor for pagination'),
|
|
92
|
-
limit: z
|
|
93
|
-
.number()
|
|
94
|
-
.min(1)
|
|
95
|
-
.max(250)
|
|
96
|
-
.optional()
|
|
97
|
-
.describe('Maximum number of results to return (default: 25, max: 250)'),
|
|
98
|
-
}, async ({ labelId, bodyFormat, sort, cursor, limit }) => {
|
|
99
|
-
try {
|
|
100
|
-
const result = await confluenceService.getPagesByLabel(labelId, {
|
|
101
|
-
bodyFormat,
|
|
102
|
-
sort,
|
|
103
|
-
cursor,
|
|
104
|
-
limit,
|
|
105
|
-
});
|
|
106
|
-
return {
|
|
107
|
-
content: [
|
|
108
|
-
{
|
|
109
|
-
type: 'text',
|
|
110
|
-
text: JSON.stringify(result),
|
|
111
|
-
},
|
|
112
|
-
],
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
catch (error) {
|
|
116
|
-
return {
|
|
117
|
-
content: [
|
|
118
|
-
{
|
|
119
|
-
type: 'text',
|
|
120
|
-
text: `Failed to retrieve pages for label: ${JSON.stringify(error instanceof Error ? error.message : String(error))}`,
|
|
121
|
-
},
|
|
122
|
-
],
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
// Register get-page-by-id tool
|
|
127
|
-
server.tool('get-page-by-id', 'Get a specific page by its ID', {
|
|
128
|
-
pageId: z.string().describe('ID of the page to retrieve'),
|
|
129
|
-
bodyFormat: z
|
|
130
|
-
.array(z.enum(['storage', 'atlas_doc_format', 'view']))
|
|
131
|
-
.optional()
|
|
132
|
-
.describe('Format of the page body to retrieve'),
|
|
133
|
-
getDraft: z.boolean().optional().describe('Whether to get the draft version of the page'),
|
|
134
|
-
version: z.number().optional().describe('Specific version of the page to retrieve'),
|
|
135
|
-
}, async ({ pageId, bodyFormat, getDraft, version }) => {
|
|
136
|
-
try {
|
|
137
|
-
const page = await confluenceService.getPageById(pageId, {
|
|
138
|
-
bodyFormat,
|
|
139
|
-
getDraft,
|
|
140
|
-
version,
|
|
141
|
-
});
|
|
142
|
-
return {
|
|
143
|
-
content: [
|
|
144
|
-
{
|
|
145
|
-
type: 'text',
|
|
146
|
-
text: JSON.stringify(page),
|
|
147
|
-
},
|
|
148
|
-
],
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
catch (error) {
|
|
152
|
-
return {
|
|
153
|
-
content: [
|
|
154
|
-
{
|
|
155
|
-
type: 'text',
|
|
156
|
-
text: `Failed to retrieve page: ${error instanceof Error ? error.message : String(error)}`,
|
|
157
|
-
},
|
|
158
|
-
],
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
// Register a helper tool to get labels (useful for finding label IDs)
|
|
163
|
-
server.tool('get-labels', 'Get list of labels from Confluence', {
|
|
164
|
-
ids: z.array(z.string()).optional().describe('Filter labels by IDs'),
|
|
165
|
-
prefix: z.array(z.string()).optional().describe('Filter labels by prefix'),
|
|
166
|
-
cursor: z.string().optional().describe('Cursor for pagination'),
|
|
167
|
-
limit: z
|
|
168
|
-
.number()
|
|
169
|
-
.min(1)
|
|
170
|
-
.max(250)
|
|
171
|
-
.optional()
|
|
172
|
-
.describe('Maximum number of results to return (default: 25, max: 250)'),
|
|
173
|
-
sort: z
|
|
174
|
-
.enum(['id', '-id', 'name', '-name', 'created-date', '-created-date'])
|
|
175
|
-
.optional()
|
|
176
|
-
.describe('Sort order for results'),
|
|
177
|
-
}, async ({ ids, prefix, cursor, limit, sort }) => {
|
|
178
|
-
try {
|
|
179
|
-
const result = await confluenceService.getLabels({
|
|
180
|
-
ids,
|
|
181
|
-
prefix,
|
|
182
|
-
cursor,
|
|
183
|
-
limit,
|
|
184
|
-
sort,
|
|
185
|
-
});
|
|
186
|
-
return {
|
|
187
|
-
content: [
|
|
188
|
-
{
|
|
189
|
-
type: 'text',
|
|
190
|
-
text: JSON.stringify(result),
|
|
191
|
-
},
|
|
192
|
-
],
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
catch (error) {
|
|
196
|
-
return {
|
|
197
|
-
content: [
|
|
198
|
-
{
|
|
199
|
-
type: 'text',
|
|
200
|
-
text: `Failed to retrieve labels: ${error instanceof Error ? error.message : String(error)}`,
|
|
201
|
-
},
|
|
202
|
-
],
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
// Register a convenience tool to find pages by label name directly
|
|
207
|
-
server.tool('find-pages-by-label-name', 'Find pages by label name (convenience tool that combines label search and page retrieval)', {
|
|
208
|
-
labelName: z
|
|
209
|
-
.string()
|
|
210
|
-
.describe('Name of the label to search for (e.g., "business-kb", "api", "documentation")'),
|
|
211
|
-
bodyFormat: z
|
|
212
|
-
.array(z.enum(['storage', 'atlas_doc_format', 'view']))
|
|
213
|
-
.optional()
|
|
214
|
-
.describe('Format of the page body to retrieve'),
|
|
215
|
-
sort: z
|
|
216
|
-
.enum([
|
|
217
|
-
'id',
|
|
218
|
-
'-id',
|
|
219
|
-
'created-date',
|
|
220
|
-
'-created-date',
|
|
221
|
-
'modified-date',
|
|
222
|
-
'-modified-date',
|
|
223
|
-
'title',
|
|
224
|
-
'-title',
|
|
225
|
-
])
|
|
226
|
-
.optional()
|
|
227
|
-
.describe('Sort order for results'),
|
|
228
|
-
cursor: z.string().optional().describe('Cursor for pagination'),
|
|
229
|
-
limit: z
|
|
230
|
-
.number()
|
|
231
|
-
.min(1)
|
|
232
|
-
.max(250)
|
|
233
|
-
.optional()
|
|
234
|
-
.describe('Maximum number of results to return (default: 25, max: 250)'),
|
|
235
|
-
}, async ({ labelName, bodyFormat, sort, cursor, limit }) => {
|
|
236
|
-
try {
|
|
237
|
-
const result = await confluenceService.getPagesByLabelName(labelName, {
|
|
238
|
-
bodyFormat,
|
|
239
|
-
sort,
|
|
240
|
-
cursor,
|
|
241
|
-
limit,
|
|
242
|
-
});
|
|
243
|
-
return {
|
|
244
|
-
content: [
|
|
245
|
-
{
|
|
246
|
-
type: 'text',
|
|
247
|
-
text: JSON.stringify(result),
|
|
248
|
-
},
|
|
249
|
-
],
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
catch (error) {
|
|
253
|
-
return {
|
|
254
|
-
content: [
|
|
255
|
-
{
|
|
256
|
-
type: 'text',
|
|
257
|
-
text: `Failed to find pages for label "${labelName}": ${error instanceof Error ? error.message : String(error)}`,
|
|
258
|
-
},
|
|
259
|
-
],
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
});
|
|
263
|
-
// Register a tool to find label by name (convenience tool)
|
|
264
|
-
server.tool('find-label-by-name', 'Find a specific label by its name', {
|
|
265
|
-
labelName: z.string().describe('Name of the label to find'),
|
|
266
|
-
}, async ({ labelName }) => {
|
|
267
|
-
try {
|
|
268
|
-
const label = await confluenceService.findLabelByName(labelName);
|
|
269
|
-
if (label) {
|
|
270
|
-
return {
|
|
271
|
-
content: [
|
|
272
|
-
{
|
|
273
|
-
type: 'text',
|
|
274
|
-
text: JSON.stringify(label),
|
|
275
|
-
},
|
|
276
|
-
],
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
else {
|
|
280
|
-
return {
|
|
281
|
-
content: [
|
|
282
|
-
{
|
|
283
|
-
type: 'text',
|
|
284
|
-
text: `Label "${labelName}" not found`,
|
|
285
|
-
},
|
|
286
|
-
],
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
catch (error) {
|
|
291
|
-
return {
|
|
292
|
-
content: [
|
|
293
|
-
{
|
|
294
|
-
type: 'text',
|
|
295
|
-
text: `Failed to find label "${labelName}": ${error instanceof Error ? error.message : String(error)}`,
|
|
296
|
-
},
|
|
297
|
-
],
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
});
|
|
301
|
-
// Register get-page-children tool
|
|
302
|
-
server.tool('get-page-children', 'Get direct child pages of a specific page', {
|
|
303
|
-
pageId: z.string().describe('ID of the parent page'),
|
|
304
|
-
cursor: z.string().optional().describe('Cursor for pagination'),
|
|
305
|
-
limit: z
|
|
306
|
-
.number()
|
|
307
|
-
.min(1)
|
|
308
|
-
.max(250)
|
|
309
|
-
.optional()
|
|
310
|
-
.describe('Maximum number of results to return (default: 25, max: 250)'),
|
|
311
|
-
sort: z
|
|
312
|
-
.enum([
|
|
313
|
-
'id',
|
|
314
|
-
'-id',
|
|
315
|
-
'created-date',
|
|
316
|
-
'-created-date',
|
|
317
|
-
'modified-date',
|
|
318
|
-
'-modified-date',
|
|
319
|
-
'title',
|
|
320
|
-
'-title',
|
|
321
|
-
])
|
|
322
|
-
.optional()
|
|
323
|
-
.describe('Sort order for results'),
|
|
324
|
-
}, async ({ pageId, cursor, limit, sort }) => {
|
|
325
|
-
try {
|
|
326
|
-
const result = await confluenceService.getPageChildren(pageId, {
|
|
327
|
-
cursor,
|
|
328
|
-
limit,
|
|
329
|
-
sort,
|
|
330
|
-
});
|
|
331
|
-
return {
|
|
332
|
-
content: [
|
|
333
|
-
{
|
|
334
|
-
type: 'text',
|
|
335
|
-
text: JSON.stringify(result),
|
|
336
|
-
},
|
|
337
|
-
],
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
catch (error) {
|
|
341
|
-
return {
|
|
342
|
-
content: [
|
|
343
|
-
{
|
|
344
|
-
type: 'text',
|
|
345
|
-
text: `Failed to retrieve child pages: ${error instanceof Error ? error.message : String(error)}`,
|
|
346
|
-
},
|
|
347
|
-
],
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
});
|
|
351
|
-
// Register get-page-children-tree tool (recursive tree fetching)
|
|
352
|
-
server.tool('get-page-children-tree', 'Get the complete hierarchical tree of child pages for a specific page (recursive)', {
|
|
353
|
-
pageId: z.string().describe('ID of the root page'),
|
|
354
|
-
limit: z
|
|
355
|
-
.number()
|
|
356
|
-
.min(1)
|
|
357
|
-
.max(250)
|
|
358
|
-
.optional()
|
|
359
|
-
.describe('Maximum number of results per level (default: 25, max: 250)'),
|
|
360
|
-
sort: z
|
|
361
|
-
.enum([
|
|
362
|
-
'id',
|
|
363
|
-
'-id',
|
|
364
|
-
'created-date',
|
|
365
|
-
'-created-date',
|
|
366
|
-
'modified-date',
|
|
367
|
-
'-modified-date',
|
|
368
|
-
'title',
|
|
369
|
-
'-title',
|
|
370
|
-
])
|
|
371
|
-
.optional()
|
|
372
|
-
.describe('Sort order for results'),
|
|
373
|
-
maxDepth: z
|
|
374
|
-
.number()
|
|
375
|
-
.min(-1)
|
|
376
|
-
.max(20)
|
|
377
|
-
.optional()
|
|
378
|
-
.default(10)
|
|
379
|
-
.describe('Maximum depth to traverse (default: 10, unlimited: -1, max: 20)'),
|
|
380
|
-
}, async ({ pageId, limit, sort, maxDepth = 10 }) => {
|
|
381
|
-
try {
|
|
382
|
-
const result = await confluenceService.getPageChildrenTree(pageId, {
|
|
383
|
-
limit,
|
|
384
|
-
sort,
|
|
385
|
-
}, maxDepth);
|
|
386
|
-
return {
|
|
387
|
-
content: [
|
|
388
|
-
{
|
|
389
|
-
type: 'text',
|
|
390
|
-
text: JSON.stringify(result, null, 2),
|
|
391
|
-
},
|
|
392
|
-
],
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
catch (error) {
|
|
396
|
-
return {
|
|
397
|
-
content: [
|
|
398
|
-
{
|
|
399
|
-
type: 'text',
|
|
400
|
-
text: `Failed to retrieve page children tree: ${error instanceof Error ? error.message : String(error)}`,
|
|
401
|
-
},
|
|
402
|
-
],
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
});
|
|
406
|
-
// Register get-spaces tool
|
|
407
|
-
server.tool('get-spaces', 'Get list of spaces from Confluence', {
|
|
408
|
-
id: z.array(z.string()).optional().describe('Filter spaces by IDs'),
|
|
409
|
-
keys: z.array(z.string()).optional().describe('Filter spaces by keys'),
|
|
410
|
-
type: z
|
|
411
|
-
.array(z.enum(['global', 'personal']))
|
|
412
|
-
.optional()
|
|
413
|
-
.describe('Filter spaces by type'),
|
|
414
|
-
status: z
|
|
415
|
-
.array(z.enum(['current', 'archived']))
|
|
416
|
-
.optional()
|
|
417
|
-
.describe('Filter spaces by status'),
|
|
418
|
-
sort: z
|
|
419
|
-
.enum([
|
|
420
|
-
'id',
|
|
421
|
-
'-id',
|
|
422
|
-
'key',
|
|
423
|
-
'-key',
|
|
424
|
-
'name',
|
|
425
|
-
'-name',
|
|
426
|
-
'created-date',
|
|
427
|
-
'-created-date',
|
|
428
|
-
'modified-date',
|
|
429
|
-
'-modified-date',
|
|
430
|
-
])
|
|
431
|
-
.optional()
|
|
432
|
-
.describe('Sort order for results'),
|
|
433
|
-
cursor: z.string().optional().describe('Cursor for pagination'),
|
|
434
|
-
limit: z
|
|
435
|
-
.number()
|
|
436
|
-
.min(1)
|
|
437
|
-
.max(250)
|
|
438
|
-
.optional()
|
|
439
|
-
.describe('Maximum number of results to return (default: 25, max: 250)'),
|
|
440
|
-
}, async ({ id, keys, type, status, sort, cursor, limit }) => {
|
|
441
|
-
try {
|
|
442
|
-
const result = await confluenceService.getSpaces({
|
|
443
|
-
id,
|
|
444
|
-
keys,
|
|
445
|
-
type,
|
|
446
|
-
status,
|
|
447
|
-
sort,
|
|
448
|
-
cursor,
|
|
449
|
-
limit,
|
|
450
|
-
});
|
|
451
|
-
return {
|
|
452
|
-
content: [
|
|
453
|
-
{
|
|
454
|
-
type: 'text',
|
|
455
|
-
text: JSON.stringify(result),
|
|
456
|
-
},
|
|
457
|
-
],
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
catch (error) {
|
|
461
|
-
return {
|
|
462
|
-
content: [
|
|
463
|
-
{
|
|
464
|
-
type: 'text',
|
|
465
|
-
text: `Failed to retrieve spaces: ${error instanceof Error ? error.message : String(error)}`,
|
|
466
|
-
},
|
|
467
|
-
],
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
});
|
|
471
|
-
// Register get-space-by-id tool
|
|
472
|
-
server.tool('get-space-by-id', 'Get a specific space by its ID', {
|
|
473
|
-
spaceId: z.string().describe('ID of the space to retrieve'),
|
|
474
|
-
}, async ({ spaceId }) => {
|
|
475
|
-
try {
|
|
476
|
-
const space = await confluenceService.getSpaceById(spaceId);
|
|
477
|
-
return {
|
|
478
|
-
content: [
|
|
479
|
-
{
|
|
480
|
-
type: 'text',
|
|
481
|
-
text: JSON.stringify(space),
|
|
482
|
-
},
|
|
483
|
-
],
|
|
484
|
-
};
|
|
485
|
-
}
|
|
486
|
-
catch (error) {
|
|
487
|
-
return {
|
|
488
|
-
content: [
|
|
489
|
-
{
|
|
490
|
-
type: 'text',
|
|
491
|
-
text: `Failed to retrieve space: ${error instanceof Error ? error.message : String(error)}`,
|
|
492
|
-
},
|
|
493
|
-
],
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
});
|
|
497
|
-
// Register find-space-by-name tool
|
|
498
|
-
server.tool('find-space-by-name', 'Find a space by its name', {
|
|
499
|
-
spaceName: z.string().describe('Name of the space to find'),
|
|
500
|
-
}, async ({ spaceName }) => {
|
|
501
|
-
try {
|
|
502
|
-
const space = await confluenceService.findSpaceByName(spaceName);
|
|
503
|
-
if (space) {
|
|
504
|
-
return {
|
|
505
|
-
content: [
|
|
506
|
-
{
|
|
507
|
-
type: 'text',
|
|
508
|
-
text: JSON.stringify(space),
|
|
509
|
-
},
|
|
510
|
-
],
|
|
511
|
-
};
|
|
512
|
-
}
|
|
513
|
-
else {
|
|
514
|
-
return {
|
|
515
|
-
content: [
|
|
516
|
-
{
|
|
517
|
-
type: 'text',
|
|
518
|
-
text: `Space with name "${spaceName}" not found`,
|
|
519
|
-
},
|
|
520
|
-
],
|
|
521
|
-
};
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
catch (error) {
|
|
525
|
-
return {
|
|
526
|
-
content: [
|
|
527
|
-
{
|
|
528
|
-
type: 'text',
|
|
529
|
-
text: `Failed to find space with name "${spaceName}": ${error instanceof Error ? error.message : String(error)}`,
|
|
530
|
-
},
|
|
531
|
-
],
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
});
|
|
535
|
-
// Register get-recently-updated-pages tool
|
|
536
|
-
server.tool('get-recently-updated-pages', 'Get recently updated pages from Confluence (sorted by modification date)', {
|
|
537
|
-
spaceId: z.array(z.string()).optional().describe('Filter by space IDs'),
|
|
538
|
-
limit: z
|
|
539
|
-
.number()
|
|
540
|
-
.min(1)
|
|
541
|
-
.max(250)
|
|
542
|
-
.optional()
|
|
543
|
-
.describe('Maximum number of results to return (default: 25, max: 250)'),
|
|
544
|
-
bodyFormat: z
|
|
545
|
-
.array(z.enum(['storage', 'atlas_doc_format', 'view']))
|
|
546
|
-
.optional()
|
|
547
|
-
.describe('Format of the page body to retrieve'),
|
|
548
|
-
}, async ({ spaceId, limit, bodyFormat }) => {
|
|
549
|
-
try {
|
|
550
|
-
const result = await confluenceService.getRecentlyUpdatedPages({
|
|
551
|
-
spaceId,
|
|
552
|
-
limit,
|
|
553
|
-
bodyFormat,
|
|
554
|
-
});
|
|
555
|
-
return {
|
|
556
|
-
content: [
|
|
557
|
-
{
|
|
558
|
-
type: 'text',
|
|
559
|
-
text: JSON.stringify(result),
|
|
560
|
-
},
|
|
561
|
-
],
|
|
562
|
-
};
|
|
563
|
-
}
|
|
564
|
-
catch (error) {
|
|
565
|
-
return {
|
|
566
|
-
content: [
|
|
567
|
-
{
|
|
568
|
-
type: 'text',
|
|
569
|
-
text: `Failed to retrieve recently updated pages: ${error instanceof Error ? error.message : String(error)}`,
|
|
570
|
-
},
|
|
571
|
-
],
|
|
572
|
-
};
|
|
573
|
-
}
|
|
574
|
-
});
|
|
575
|
-
// Register get-recently-created-pages tool
|
|
576
|
-
server.tool('get-recently-created-pages', 'Get recently created pages from Confluence (sorted by creation date)', {
|
|
577
|
-
spaceId: z.array(z.string()).optional().describe('Filter by space IDs'),
|
|
578
|
-
limit: z
|
|
579
|
-
.number()
|
|
580
|
-
.min(1)
|
|
581
|
-
.max(250)
|
|
582
|
-
.optional()
|
|
583
|
-
.describe('Maximum number of results to return (default: 25, max: 250)'),
|
|
584
|
-
bodyFormat: z
|
|
585
|
-
.array(z.enum(['storage', 'atlas_doc_format', 'view']))
|
|
586
|
-
.optional()
|
|
587
|
-
.describe('Format of the page body to retrieve'),
|
|
588
|
-
}, async ({ spaceId, limit, bodyFormat }) => {
|
|
589
|
-
try {
|
|
590
|
-
const result = await confluenceService.getRecentlyCreatedPages({
|
|
591
|
-
spaceId,
|
|
592
|
-
limit,
|
|
593
|
-
bodyFormat,
|
|
594
|
-
});
|
|
595
|
-
return {
|
|
596
|
-
content: [
|
|
597
|
-
{
|
|
598
|
-
type: 'text',
|
|
599
|
-
text: JSON.stringify(result),
|
|
600
|
-
},
|
|
601
|
-
],
|
|
602
|
-
};
|
|
603
|
-
}
|
|
604
|
-
catch (error) {
|
|
605
|
-
return {
|
|
606
|
-
content: [
|
|
607
|
-
{
|
|
608
|
-
type: 'text',
|
|
609
|
-
text: `Failed to retrieve recently created pages: ${error instanceof Error ? error.message : String(error)}`,
|
|
610
|
-
},
|
|
611
|
-
],
|
|
612
|
-
};
|
|
613
|
-
}
|
|
614
|
-
});
|
|
615
|
-
};
|