@ecubelabs/atlassian-mcp 1.4.0-next.1 → 1.4.0-next.2
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/confluence-tools/add-labels-to-page.js +37 -0
- package/dist/confluence-tools/confluence-storage-format-help.js +257 -0
- package/dist/confluence-tools/create-page.js +51 -0
- package/dist/confluence-tools/delete-page.js +39 -0
- package/dist/confluence-tools/find-label-by-name.js +40 -0
- package/dist/confluence-tools/find-pages-by-label-name.js +59 -0
- package/dist/confluence-tools/find-space-by-name.js +40 -0
- package/dist/confluence-tools/get-labels.js +46 -0
- package/dist/confluence-tools/get-page-by-id.js +38 -0
- package/dist/confluence-tools/get-page-children-tree.js +57 -0
- package/dist/confluence-tools/get-page-children.js +52 -0
- package/dist/confluence-tools/get-pages-for-label.js +57 -0
- package/dist/confluence-tools/get-pages.js +67 -0
- package/dist/confluence-tools/get-recently-created-pages.js +42 -0
- package/dist/confluence-tools/get-recently-updated-pages.js +42 -0
- package/dist/confluence-tools/get-space-by-id.js +28 -0
- package/dist/confluence-tools/get-spaces.js +67 -0
- package/dist/confluence-tools/index.js +22 -0
- package/dist/confluence-tools/remove-label-from-page.js +29 -0
- package/dist/confluence-tools/update-page.js +54 -0
- package/dist/confluence-tools-register.js +23 -610
- package/dist/libs/confluence-client.js +77 -0
- package/package.json +1 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const registerGetPageChildren = (server, confluenceService) => {
|
|
3
|
+
server.tool('get-page-children', 'Get direct child pages of a specific page', {
|
|
4
|
+
pageId: z.string().describe('ID of the parent page'),
|
|
5
|
+
cursor: z.string().optional().describe('Cursor for pagination'),
|
|
6
|
+
limit: z
|
|
7
|
+
.number()
|
|
8
|
+
.min(1)
|
|
9
|
+
.max(250)
|
|
10
|
+
.optional()
|
|
11
|
+
.describe('Maximum number of results to return (default: 25, max: 250)'),
|
|
12
|
+
sort: z
|
|
13
|
+
.enum([
|
|
14
|
+
'id',
|
|
15
|
+
'-id',
|
|
16
|
+
'created-date',
|
|
17
|
+
'-created-date',
|
|
18
|
+
'modified-date',
|
|
19
|
+
'-modified-date',
|
|
20
|
+
'title',
|
|
21
|
+
'-title',
|
|
22
|
+
])
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('Sort order for results'),
|
|
25
|
+
}, async ({ pageId, cursor, limit, sort }) => {
|
|
26
|
+
try {
|
|
27
|
+
const result = await confluenceService.getPageChildren(pageId, {
|
|
28
|
+
cursor,
|
|
29
|
+
limit,
|
|
30
|
+
sort,
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
content: [
|
|
34
|
+
{
|
|
35
|
+
type: 'text',
|
|
36
|
+
text: JSON.stringify(result),
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
return {
|
|
43
|
+
content: [
|
|
44
|
+
{
|
|
45
|
+
type: 'text',
|
|
46
|
+
text: `Failed to retrieve child pages: ${error instanceof Error ? error.message : String(error)}`,
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const registerGetPagesForLabel = (server, confluenceService) => {
|
|
3
|
+
server.tool('get-pages-for-label', 'Get pages associated with a specific label', {
|
|
4
|
+
labelId: z.string().describe('ID of the label to search for'),
|
|
5
|
+
bodyFormat: z
|
|
6
|
+
.array(z.enum(['storage', 'atlas_doc_format', 'view']))
|
|
7
|
+
.optional()
|
|
8
|
+
.describe('Format of the page body to retrieve'),
|
|
9
|
+
sort: z
|
|
10
|
+
.enum([
|
|
11
|
+
'id',
|
|
12
|
+
'-id',
|
|
13
|
+
'created-date',
|
|
14
|
+
'-created-date',
|
|
15
|
+
'modified-date',
|
|
16
|
+
'-modified-date',
|
|
17
|
+
'title',
|
|
18
|
+
'-title',
|
|
19
|
+
])
|
|
20
|
+
.optional()
|
|
21
|
+
.describe('Sort order for results'),
|
|
22
|
+
cursor: z.string().optional().describe('Cursor for pagination'),
|
|
23
|
+
limit: z
|
|
24
|
+
.number()
|
|
25
|
+
.min(1)
|
|
26
|
+
.max(250)
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('Maximum number of results to return (default: 25, max: 250)'),
|
|
29
|
+
}, async ({ labelId, bodyFormat, sort, cursor, limit }) => {
|
|
30
|
+
try {
|
|
31
|
+
const result = await confluenceService.getPagesByLabel(labelId, {
|
|
32
|
+
bodyFormat,
|
|
33
|
+
sort,
|
|
34
|
+
cursor,
|
|
35
|
+
limit,
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: 'text',
|
|
41
|
+
text: JSON.stringify(result),
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
return {
|
|
48
|
+
content: [
|
|
49
|
+
{
|
|
50
|
+
type: 'text',
|
|
51
|
+
text: `Failed to retrieve pages for label: ${JSON.stringify(error instanceof Error ? error.message : String(error))}`,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const registerGetPages = (server, confluenceService) => {
|
|
3
|
+
server.tool('get-pages', 'Get list of pages from Confluence', {
|
|
4
|
+
id: z.array(z.string()).optional().describe('List of page IDs to retrieve'),
|
|
5
|
+
spaceId: z.array(z.string()).optional().describe('Filter pages by space IDs'),
|
|
6
|
+
title: z.string().optional().describe('Filter pages by title (partial match)'),
|
|
7
|
+
status: z
|
|
8
|
+
.array(z.enum(['current', 'trashed', 'historical', 'draft']))
|
|
9
|
+
.optional()
|
|
10
|
+
.describe('Filter pages by status'),
|
|
11
|
+
bodyFormat: z
|
|
12
|
+
.array(z.enum(['storage', 'atlas_doc_format', 'view']))
|
|
13
|
+
.optional()
|
|
14
|
+
.describe('Format of the page body to retrieve'),
|
|
15
|
+
cursor: z.string().optional().describe('Cursor for pagination'),
|
|
16
|
+
limit: z
|
|
17
|
+
.number()
|
|
18
|
+
.min(1)
|
|
19
|
+
.max(250)
|
|
20
|
+
.optional()
|
|
21
|
+
.describe('Maximum number of results to return (default: 25, max: 250)'),
|
|
22
|
+
sort: z
|
|
23
|
+
.enum([
|
|
24
|
+
'id',
|
|
25
|
+
'-id',
|
|
26
|
+
'created-date',
|
|
27
|
+
'-created-date',
|
|
28
|
+
'modified-date',
|
|
29
|
+
'-modified-date',
|
|
30
|
+
'title',
|
|
31
|
+
'-title',
|
|
32
|
+
])
|
|
33
|
+
.optional()
|
|
34
|
+
.describe('Sort order for results'),
|
|
35
|
+
}, async ({ id, spaceId, title, status, bodyFormat, cursor, limit, sort }) => {
|
|
36
|
+
try {
|
|
37
|
+
const result = await confluenceService.getPages({
|
|
38
|
+
id,
|
|
39
|
+
spaceId,
|
|
40
|
+
title,
|
|
41
|
+
status,
|
|
42
|
+
bodyFormat,
|
|
43
|
+
cursor,
|
|
44
|
+
limit,
|
|
45
|
+
sort,
|
|
46
|
+
});
|
|
47
|
+
return {
|
|
48
|
+
content: [
|
|
49
|
+
{
|
|
50
|
+
type: 'text',
|
|
51
|
+
text: JSON.stringify(result),
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
return {
|
|
58
|
+
content: [
|
|
59
|
+
{
|
|
60
|
+
type: 'text',
|
|
61
|
+
text: `Failed to retrieve pages: ${error instanceof Error ? error.message : String(error)}`,
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const registerGetRecentlyCreatedPages = (server, confluenceService) => {
|
|
3
|
+
server.tool('get-recently-created-pages', 'Get recently created pages from Confluence (sorted by creation date)', {
|
|
4
|
+
spaceId: z.array(z.string()).optional().describe('Filter by space IDs'),
|
|
5
|
+
limit: z
|
|
6
|
+
.number()
|
|
7
|
+
.min(1)
|
|
8
|
+
.max(250)
|
|
9
|
+
.optional()
|
|
10
|
+
.describe('Maximum number of results to return (default: 25, max: 250)'),
|
|
11
|
+
bodyFormat: z
|
|
12
|
+
.array(z.enum(['storage', 'atlas_doc_format', 'view']))
|
|
13
|
+
.optional()
|
|
14
|
+
.describe('Format of the page body to retrieve'),
|
|
15
|
+
}, async ({ spaceId, limit, bodyFormat }) => {
|
|
16
|
+
try {
|
|
17
|
+
const result = await confluenceService.getRecentlyCreatedPages({
|
|
18
|
+
spaceId,
|
|
19
|
+
limit,
|
|
20
|
+
bodyFormat,
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
content: [
|
|
24
|
+
{
|
|
25
|
+
type: 'text',
|
|
26
|
+
text: JSON.stringify(result),
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
return {
|
|
33
|
+
content: [
|
|
34
|
+
{
|
|
35
|
+
type: 'text',
|
|
36
|
+
text: `Failed to retrieve recently created pages: ${error instanceof Error ? error.message : String(error)}`,
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const registerGetRecentlyUpdatedPages = (server, confluenceService) => {
|
|
3
|
+
server.tool('get-recently-updated-pages', 'Get recently updated pages from Confluence (sorted by modification date)', {
|
|
4
|
+
spaceId: z.array(z.string()).optional().describe('Filter by space IDs'),
|
|
5
|
+
limit: z
|
|
6
|
+
.number()
|
|
7
|
+
.min(1)
|
|
8
|
+
.max(250)
|
|
9
|
+
.optional()
|
|
10
|
+
.describe('Maximum number of results to return (default: 25, max: 250)'),
|
|
11
|
+
bodyFormat: z
|
|
12
|
+
.array(z.enum(['storage', 'atlas_doc_format', 'view']))
|
|
13
|
+
.optional()
|
|
14
|
+
.describe('Format of the page body to retrieve'),
|
|
15
|
+
}, async ({ spaceId, limit, bodyFormat }) => {
|
|
16
|
+
try {
|
|
17
|
+
const result = await confluenceService.getRecentlyUpdatedPages({
|
|
18
|
+
spaceId,
|
|
19
|
+
limit,
|
|
20
|
+
bodyFormat,
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
content: [
|
|
24
|
+
{
|
|
25
|
+
type: 'text',
|
|
26
|
+
text: JSON.stringify(result),
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
return {
|
|
33
|
+
content: [
|
|
34
|
+
{
|
|
35
|
+
type: 'text',
|
|
36
|
+
text: `Failed to retrieve recently updated pages: ${error instanceof Error ? error.message : String(error)}`,
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const registerGetSpaceById = (server, confluenceService) => {
|
|
3
|
+
server.tool('get-space-by-id', 'Get a specific space by its ID', {
|
|
4
|
+
spaceId: z.string().describe('ID of the space to retrieve'),
|
|
5
|
+
}, async ({ spaceId }) => {
|
|
6
|
+
try {
|
|
7
|
+
const space = await confluenceService.getSpaceById(spaceId);
|
|
8
|
+
return {
|
|
9
|
+
content: [
|
|
10
|
+
{
|
|
11
|
+
type: 'text',
|
|
12
|
+
text: JSON.stringify(space),
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
return {
|
|
19
|
+
content: [
|
|
20
|
+
{
|
|
21
|
+
type: 'text',
|
|
22
|
+
text: `Failed to retrieve space: ${error instanceof Error ? error.message : String(error)}`,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const registerGetSpaces = (server, confluenceService) => {
|
|
3
|
+
server.tool('get-spaces', 'Get list of spaces from Confluence', {
|
|
4
|
+
id: z.array(z.string()).optional().describe('Filter spaces by IDs'),
|
|
5
|
+
keys: z.array(z.string()).optional().describe('Filter spaces by keys'),
|
|
6
|
+
type: z
|
|
7
|
+
.array(z.enum(['global', 'personal']))
|
|
8
|
+
.optional()
|
|
9
|
+
.describe('Filter spaces by type'),
|
|
10
|
+
status: z
|
|
11
|
+
.array(z.enum(['current', 'archived']))
|
|
12
|
+
.optional()
|
|
13
|
+
.describe('Filter spaces by status'),
|
|
14
|
+
sort: z
|
|
15
|
+
.enum([
|
|
16
|
+
'id',
|
|
17
|
+
'-id',
|
|
18
|
+
'key',
|
|
19
|
+
'-key',
|
|
20
|
+
'name',
|
|
21
|
+
'-name',
|
|
22
|
+
'created-date',
|
|
23
|
+
'-created-date',
|
|
24
|
+
'modified-date',
|
|
25
|
+
'-modified-date',
|
|
26
|
+
])
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('Sort order for results'),
|
|
29
|
+
cursor: z.string().optional().describe('Cursor for pagination'),
|
|
30
|
+
limit: z
|
|
31
|
+
.number()
|
|
32
|
+
.min(1)
|
|
33
|
+
.max(250)
|
|
34
|
+
.optional()
|
|
35
|
+
.describe('Maximum number of results to return (default: 25, max: 250)'),
|
|
36
|
+
}, async ({ id, keys, type, status, sort, cursor, limit }) => {
|
|
37
|
+
try {
|
|
38
|
+
const result = await confluenceService.getSpaces({
|
|
39
|
+
id,
|
|
40
|
+
keys,
|
|
41
|
+
type,
|
|
42
|
+
status,
|
|
43
|
+
sort,
|
|
44
|
+
cursor,
|
|
45
|
+
limit,
|
|
46
|
+
});
|
|
47
|
+
return {
|
|
48
|
+
content: [
|
|
49
|
+
{
|
|
50
|
+
type: 'text',
|
|
51
|
+
text: JSON.stringify(result),
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
return {
|
|
58
|
+
content: [
|
|
59
|
+
{
|
|
60
|
+
type: 'text',
|
|
61
|
+
text: `Failed to retrieve spaces: ${error instanceof Error ? error.message : String(error)}`,
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Read-only tools
|
|
2
|
+
export { registerGetPages } from './get-pages.js';
|
|
3
|
+
export { registerGetPagesForLabel } from './get-pages-for-label.js';
|
|
4
|
+
export { registerGetPageById } from './get-page-by-id.js';
|
|
5
|
+
export { registerGetLabels } from './get-labels.js';
|
|
6
|
+
export { registerFindPagesByLabelName } from './find-pages-by-label-name.js';
|
|
7
|
+
export { registerFindLabelByName } from './find-label-by-name.js';
|
|
8
|
+
export { registerGetPageChildren } from './get-page-children.js';
|
|
9
|
+
export { registerGetPageChildrenTree } from './get-page-children-tree.js';
|
|
10
|
+
export { registerGetSpaces } from './get-spaces.js';
|
|
11
|
+
export { registerGetSpaceById } from './get-space-by-id.js';
|
|
12
|
+
export { registerFindSpaceByName } from './find-space-by-name.js';
|
|
13
|
+
export { registerGetRecentlyUpdatedPages } from './get-recently-updated-pages.js';
|
|
14
|
+
export { registerGetRecentlyCreatedPages } from './get-recently-created-pages.js';
|
|
15
|
+
// Write tools
|
|
16
|
+
export { registerCreatePage } from './create-page.js';
|
|
17
|
+
export { registerUpdatePage } from './update-page.js';
|
|
18
|
+
export { registerDeletePage } from './delete-page.js';
|
|
19
|
+
export { registerAddLabelsToPage } from './add-labels-to-page.js';
|
|
20
|
+
export { registerRemoveLabelFromPage } from './remove-label-from-page.js';
|
|
21
|
+
// Help tool
|
|
22
|
+
export { registerConfluenceStorageFormatHelp } from './confluence-storage-format-help.js';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const registerRemoveLabelFromPage = (server, confluenceService) => {
|
|
3
|
+
server.tool('remove-label-from-page', 'Remove a label from a Confluence page', {
|
|
4
|
+
pageId: z.string().describe('ID of the page to remove the label from'),
|
|
5
|
+
labelName: z.string().describe('Name of the label to remove'),
|
|
6
|
+
}, async ({ pageId, labelName }) => {
|
|
7
|
+
try {
|
|
8
|
+
await confluenceService.removeLabelFromPage(pageId, labelName);
|
|
9
|
+
return {
|
|
10
|
+
content: [
|
|
11
|
+
{
|
|
12
|
+
type: 'text',
|
|
13
|
+
text: `Label "${labelName}" has been removed from page ${pageId}`,
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
return {
|
|
20
|
+
content: [
|
|
21
|
+
{
|
|
22
|
+
type: 'text',
|
|
23
|
+
text: `Failed to remove label from page: ${error instanceof Error ? error.message : String(error)}`,
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const registerUpdatePage = (server, confluenceService) => {
|
|
3
|
+
server.tool('update-page', '⚠️ Update an existing Confluence page. 🚫 CRITICAL: NEVER use wiki markup ({info}, {code}), placeholder text ([Info Panel]), or plain text for Jira/dates/users. ✅ MANDATORY: MUST use confluence-storage-format-help tool BEFORE calling this. ONLY use storage format XML: <ac:structured-macro> for macros, <time> for dates, <ac:link> for users.', {
|
|
4
|
+
pageId: z.string().describe('ID of the page to update'),
|
|
5
|
+
title: z.string().describe('New title for the page'),
|
|
6
|
+
bodyRepresentation: z
|
|
7
|
+
.enum(['storage', 'atlas_doc_format', 'view'])
|
|
8
|
+
.default('storage')
|
|
9
|
+
.describe('Format of the page body content (default: storage)'),
|
|
10
|
+
bodyValue: z
|
|
11
|
+
.string()
|
|
12
|
+
.describe('🚫 NEVER use wiki markup ({info}, {code}) or placeholders ([Panel]). ✅ ONLY use storage format XML. MUST check confluence-storage-format-help tool first. Example: Panels use <ac:structured-macro ac:name="info"><ac:rich-text-body><p>text</p></ac:rich-text-body></ac:structured-macro>, Jira uses <ac:structured-macro ac:name="jira"><ac:parameter ac:name="key">KEY-123</ac:parameter></ac:structured-macro>, dates use <time datetime="YYYY-MM-DD"/>, users use <ac:link><ri:user ri:account-id="ID"/></ac:link>.'),
|
|
13
|
+
versionNumber: z.number().describe('Current version number of the page (must be incremented by 1)'),
|
|
14
|
+
versionMessage: z.string().optional().describe('Optional message describing the changes in this version'),
|
|
15
|
+
status: z
|
|
16
|
+
.enum(['current', 'draft'])
|
|
17
|
+
.optional()
|
|
18
|
+
.default('current')
|
|
19
|
+
.describe('Status of the page (default: current)'),
|
|
20
|
+
}, async ({ pageId, title, bodyRepresentation, bodyValue, versionNumber, versionMessage, status = 'current' }) => {
|
|
21
|
+
try {
|
|
22
|
+
const result = await confluenceService.updatePage(pageId, {
|
|
23
|
+
title,
|
|
24
|
+
body: {
|
|
25
|
+
representation: bodyRepresentation,
|
|
26
|
+
value: bodyValue,
|
|
27
|
+
},
|
|
28
|
+
version: {
|
|
29
|
+
number: versionNumber,
|
|
30
|
+
message: versionMessage,
|
|
31
|
+
},
|
|
32
|
+
status,
|
|
33
|
+
});
|
|
34
|
+
return {
|
|
35
|
+
content: [
|
|
36
|
+
{
|
|
37
|
+
type: 'text',
|
|
38
|
+
text: JSON.stringify(result),
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
return {
|
|
45
|
+
content: [
|
|
46
|
+
{
|
|
47
|
+
type: 'text',
|
|
48
|
+
text: `Failed to update page: ${error instanceof Error ? error.message : String(error)}`,
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
};
|