@dalcontak/blogger-mcp-server 1.0.0 → 1.0.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/.github/workflows/publish.yml +3 -0
- package/AGENTS.md +2 -2
- package/README.md +201 -100
- package/RELEASE.md +64 -32
- package/dist/bloggerService.d.ts +7 -100
- package/dist/bloggerService.js +17 -146
- package/dist/config.d.ts +3 -0
- package/dist/config.js +12 -12
- package/dist/index.js +80 -154
- package/dist/server.d.ts +0 -11
- package/dist/server.js +59 -339
- package/dist/types.d.ts +15 -44
- package/dist/ui-manager.js +8 -16
- package/package.json +5 -1
- package/src/bloggerService.test.ts +5 -1
- package/src/bloggerService.ts +26 -161
- package/src/config.test.ts +34 -20
- package/src/config.ts +17 -16
- package/src/index.ts +115 -194
- package/src/server.test.ts +128 -0
- package/src/server.ts +63 -332
- package/src/types.ts +12 -60
- package/src/ui-manager.ts +17 -26
- package/Dockerfile +0 -64
- package/dist/mcp-sdk-mock.d.ts +0 -57
- package/dist/mcp-sdk-mock.js +0 -227
package/dist/server.js
CHANGED
|
@@ -4,42 +4,32 @@ exports.createToolDefinitions = createToolDefinitions;
|
|
|
4
4
|
exports.initMCPServer = initMCPServer;
|
|
5
5
|
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
6
6
|
const zod_1 = require("zod");
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
function createToolHandler(toolName, fn) {
|
|
8
|
+
return async () => {
|
|
9
|
+
try {
|
|
10
|
+
const result = await fn();
|
|
11
|
+
return {
|
|
12
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }]
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
console.error(`Error in ${toolName}:`, error);
|
|
17
|
+
return {
|
|
18
|
+
content: [{ type: 'text', text: `Error in ${toolName}: ${error}` }],
|
|
19
|
+
isError: true
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
12
24
|
function createToolDefinitions(bloggerService) {
|
|
13
25
|
return [
|
|
14
26
|
{
|
|
15
27
|
name: 'list_blogs',
|
|
16
28
|
description: 'Lists all accessible blogs',
|
|
17
29
|
args: zod_1.z.object({}),
|
|
18
|
-
handler:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
content: [
|
|
23
|
-
{
|
|
24
|
-
type: 'text',
|
|
25
|
-
text: JSON.stringify({ blogs }, null, 2)
|
|
26
|
-
}
|
|
27
|
-
]
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
catch (error) {
|
|
31
|
-
console.error('Error fetching blogs:', error);
|
|
32
|
-
return {
|
|
33
|
-
content: [
|
|
34
|
-
{
|
|
35
|
-
type: 'text',
|
|
36
|
-
text: `Error fetching blogs: ${error}`
|
|
37
|
-
}
|
|
38
|
-
],
|
|
39
|
-
isError: true
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
}
|
|
30
|
+
handler: createToolHandler('list_blogs', () => {
|
|
31
|
+
return bloggerService.listBlogs().then(blogs => ({ blogs }));
|
|
32
|
+
})
|
|
43
33
|
},
|
|
44
34
|
{
|
|
45
35
|
name: 'get_blog',
|
|
@@ -47,31 +37,9 @@ function createToolDefinitions(bloggerService) {
|
|
|
47
37
|
args: zod_1.z.object({
|
|
48
38
|
blogId: zod_1.z.string().describe('Blog ID')
|
|
49
39
|
}),
|
|
50
|
-
handler:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return {
|
|
54
|
-
content: [
|
|
55
|
-
{
|
|
56
|
-
type: 'text',
|
|
57
|
-
text: JSON.stringify({ blog }, null, 2)
|
|
58
|
-
}
|
|
59
|
-
]
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
catch (error) {
|
|
63
|
-
console.error(`Error fetching blog ${args.blogId}:`, error);
|
|
64
|
-
return {
|
|
65
|
-
content: [
|
|
66
|
-
{
|
|
67
|
-
type: 'text',
|
|
68
|
-
text: `Error fetching blog: ${error}`
|
|
69
|
-
}
|
|
70
|
-
],
|
|
71
|
-
isError: true
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
}
|
|
40
|
+
handler: (args) => createToolHandler('get_blog', () => {
|
|
41
|
+
return bloggerService.getBlog(args.blogId).then(blog => ({ blog }));
|
|
42
|
+
})()
|
|
75
43
|
},
|
|
76
44
|
{
|
|
77
45
|
name: 'get_blog_by_url',
|
|
@@ -79,50 +47,9 @@ function createToolDefinitions(bloggerService) {
|
|
|
79
47
|
args: zod_1.z.object({
|
|
80
48
|
url: zod_1.z.string().describe('Blog URL')
|
|
81
49
|
}),
|
|
82
|
-
handler:
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return {
|
|
86
|
-
content: [
|
|
87
|
-
{
|
|
88
|
-
type: 'text',
|
|
89
|
-
text: JSON.stringify({ blog }, null, 2)
|
|
90
|
-
}
|
|
91
|
-
]
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
catch (error) {
|
|
95
|
-
console.error(`Error fetching blog by URL ${args.url}:`, error);
|
|
96
|
-
return {
|
|
97
|
-
content: [
|
|
98
|
-
{
|
|
99
|
-
type: 'text',
|
|
100
|
-
text: `Error fetching blog by URL: ${error}`
|
|
101
|
-
}
|
|
102
|
-
],
|
|
103
|
-
isError: true
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
name: 'create_blog',
|
|
110
|
-
description: 'Creates a new blog (not supported by the Blogger API)',
|
|
111
|
-
args: zod_1.z.object({
|
|
112
|
-
name: zod_1.z.string().describe('Blog name'),
|
|
113
|
-
description: zod_1.z.string().optional().describe('Blog description')
|
|
114
|
-
}),
|
|
115
|
-
handler: async (_args, _extra) => {
|
|
116
|
-
return {
|
|
117
|
-
content: [
|
|
118
|
-
{
|
|
119
|
-
type: 'text',
|
|
120
|
-
text: 'Blog creation is not supported by the Blogger API. Please create a blog via the Blogger web interface.'
|
|
121
|
-
}
|
|
122
|
-
],
|
|
123
|
-
isError: true
|
|
124
|
-
};
|
|
125
|
-
}
|
|
50
|
+
handler: (args) => createToolHandler('get_blog_by_url', () => {
|
|
51
|
+
return bloggerService.getBlogByUrl(args.url).then(blog => ({ blog }));
|
|
52
|
+
})()
|
|
126
53
|
},
|
|
127
54
|
{
|
|
128
55
|
name: 'list_posts',
|
|
@@ -131,31 +58,9 @@ function createToolDefinitions(bloggerService) {
|
|
|
131
58
|
blogId: zod_1.z.string().describe('Blog ID'),
|
|
132
59
|
maxResults: zod_1.z.number().optional().describe('Maximum number of results to return')
|
|
133
60
|
}),
|
|
134
|
-
handler:
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return {
|
|
138
|
-
content: [
|
|
139
|
-
{
|
|
140
|
-
type: 'text',
|
|
141
|
-
text: JSON.stringify({ posts }, null, 2)
|
|
142
|
-
}
|
|
143
|
-
]
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
catch (error) {
|
|
147
|
-
console.error(`Error fetching posts for blog ${args.blogId}:`, error);
|
|
148
|
-
return {
|
|
149
|
-
content: [
|
|
150
|
-
{
|
|
151
|
-
type: 'text',
|
|
152
|
-
text: `Error fetching posts: ${error}`
|
|
153
|
-
}
|
|
154
|
-
],
|
|
155
|
-
isError: true
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
}
|
|
61
|
+
handler: (args) => createToolHandler('list_posts', () => {
|
|
62
|
+
return bloggerService.listPosts(args.blogId, args.maxResults).then(posts => ({ posts }));
|
|
63
|
+
})()
|
|
159
64
|
},
|
|
160
65
|
{
|
|
161
66
|
name: 'search_posts',
|
|
@@ -165,31 +70,9 @@ function createToolDefinitions(bloggerService) {
|
|
|
165
70
|
query: zod_1.z.string().describe('Search term'),
|
|
166
71
|
maxResults: zod_1.z.number().optional().describe('Maximum number of results to return')
|
|
167
72
|
}),
|
|
168
|
-
handler:
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return {
|
|
172
|
-
content: [
|
|
173
|
-
{
|
|
174
|
-
type: 'text',
|
|
175
|
-
text: JSON.stringify({ posts }, null, 2)
|
|
176
|
-
}
|
|
177
|
-
]
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
catch (error) {
|
|
181
|
-
console.error(`Error searching posts in blog ${args.blogId}:`, error);
|
|
182
|
-
return {
|
|
183
|
-
content: [
|
|
184
|
-
{
|
|
185
|
-
type: 'text',
|
|
186
|
-
text: `Error searching posts: ${error}`
|
|
187
|
-
}
|
|
188
|
-
],
|
|
189
|
-
isError: true
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
}
|
|
73
|
+
handler: (args) => createToolHandler('search_posts', () => {
|
|
74
|
+
return bloggerService.searchPosts(args.blogId, args.query, args.maxResults).then(posts => ({ posts }));
|
|
75
|
+
})()
|
|
193
76
|
},
|
|
194
77
|
{
|
|
195
78
|
name: 'get_post',
|
|
@@ -198,31 +81,9 @@ function createToolDefinitions(bloggerService) {
|
|
|
198
81
|
blogId: zod_1.z.string().describe('Blog ID'),
|
|
199
82
|
postId: zod_1.z.string().describe('Post ID')
|
|
200
83
|
}),
|
|
201
|
-
handler:
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
return {
|
|
205
|
-
content: [
|
|
206
|
-
{
|
|
207
|
-
type: 'text',
|
|
208
|
-
text: JSON.stringify({ post }, null, 2)
|
|
209
|
-
}
|
|
210
|
-
]
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
catch (error) {
|
|
214
|
-
console.error(`Error fetching post ${args.postId}:`, error);
|
|
215
|
-
return {
|
|
216
|
-
content: [
|
|
217
|
-
{
|
|
218
|
-
type: 'text',
|
|
219
|
-
text: `Error fetching post: ${error}`
|
|
220
|
-
}
|
|
221
|
-
],
|
|
222
|
-
isError: true
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
}
|
|
84
|
+
handler: (args) => createToolHandler('get_post', () => {
|
|
85
|
+
return bloggerService.getPost(args.blogId, args.postId).then(post => ({ post }));
|
|
86
|
+
})()
|
|
226
87
|
},
|
|
227
88
|
{
|
|
228
89
|
name: 'create_post',
|
|
@@ -233,35 +94,13 @@ function createToolDefinitions(bloggerService) {
|
|
|
233
94
|
content: zod_1.z.string().describe('Post content'),
|
|
234
95
|
labels: zod_1.z.array(zod_1.z.string()).optional().describe('Labels to associate with the post')
|
|
235
96
|
}),
|
|
236
|
-
handler:
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
return {
|
|
244
|
-
content: [
|
|
245
|
-
{
|
|
246
|
-
type: 'text',
|
|
247
|
-
text: JSON.stringify({ post }, null, 2)
|
|
248
|
-
}
|
|
249
|
-
]
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
catch (error) {
|
|
253
|
-
console.error(`Error creating post in blog ${args.blogId}:`, error);
|
|
254
|
-
return {
|
|
255
|
-
content: [
|
|
256
|
-
{
|
|
257
|
-
type: 'text',
|
|
258
|
-
text: `Error creating post: ${error}`
|
|
259
|
-
}
|
|
260
|
-
],
|
|
261
|
-
isError: true
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
}
|
|
97
|
+
handler: (args) => createToolHandler('create_post', () => {
|
|
98
|
+
return bloggerService.createPost(args.blogId, {
|
|
99
|
+
title: args.title,
|
|
100
|
+
content: args.content,
|
|
101
|
+
labels: args.labels
|
|
102
|
+
}).then(post => ({ post }));
|
|
103
|
+
})()
|
|
265
104
|
},
|
|
266
105
|
{
|
|
267
106
|
name: 'update_post',
|
|
@@ -273,35 +112,13 @@ function createToolDefinitions(bloggerService) {
|
|
|
273
112
|
content: zod_1.z.string().optional().describe('New post content'),
|
|
274
113
|
labels: zod_1.z.array(zod_1.z.string()).optional().describe('New labels to associate with the post')
|
|
275
114
|
}),
|
|
276
|
-
handler:
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
return {
|
|
284
|
-
content: [
|
|
285
|
-
{
|
|
286
|
-
type: 'text',
|
|
287
|
-
text: JSON.stringify({ post }, null, 2)
|
|
288
|
-
}
|
|
289
|
-
]
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
catch (error) {
|
|
293
|
-
console.error(`Error updating post ${args.postId}:`, error);
|
|
294
|
-
return {
|
|
295
|
-
content: [
|
|
296
|
-
{
|
|
297
|
-
type: 'text',
|
|
298
|
-
text: `Error updating post: ${error}`
|
|
299
|
-
}
|
|
300
|
-
],
|
|
301
|
-
isError: true
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
}
|
|
115
|
+
handler: (args) => createToolHandler('update_post', () => {
|
|
116
|
+
return bloggerService.updatePost(args.blogId, args.postId, {
|
|
117
|
+
title: args.title,
|
|
118
|
+
content: args.content,
|
|
119
|
+
labels: args.labels
|
|
120
|
+
}).then(post => ({ post }));
|
|
121
|
+
})()
|
|
305
122
|
},
|
|
306
123
|
{
|
|
307
124
|
name: 'delete_post',
|
|
@@ -310,31 +127,9 @@ function createToolDefinitions(bloggerService) {
|
|
|
310
127
|
blogId: zod_1.z.string().describe('Blog ID'),
|
|
311
128
|
postId: zod_1.z.string().describe('Post ID')
|
|
312
129
|
}),
|
|
313
|
-
handler:
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
return {
|
|
317
|
-
content: [
|
|
318
|
-
{
|
|
319
|
-
type: 'text',
|
|
320
|
-
text: JSON.stringify({ success: true }, null, 2)
|
|
321
|
-
}
|
|
322
|
-
]
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
catch (error) {
|
|
326
|
-
console.error(`Error deleting post ${args.postId}:`, error);
|
|
327
|
-
return {
|
|
328
|
-
content: [
|
|
329
|
-
{
|
|
330
|
-
type: 'text',
|
|
331
|
-
text: `Error deleting post: ${error}`
|
|
332
|
-
}
|
|
333
|
-
],
|
|
334
|
-
isError: true
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
}
|
|
130
|
+
handler: (args) => createToolHandler('delete_post', () => {
|
|
131
|
+
return bloggerService.deletePost(args.blogId, args.postId).then(() => ({ success: true }));
|
|
132
|
+
})()
|
|
338
133
|
},
|
|
339
134
|
{
|
|
340
135
|
name: 'list_labels',
|
|
@@ -342,31 +137,9 @@ function createToolDefinitions(bloggerService) {
|
|
|
342
137
|
args: zod_1.z.object({
|
|
343
138
|
blogId: zod_1.z.string().describe('Blog ID')
|
|
344
139
|
}),
|
|
345
|
-
handler:
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
return {
|
|
349
|
-
content: [
|
|
350
|
-
{
|
|
351
|
-
type: 'text',
|
|
352
|
-
text: JSON.stringify({ labels }, null, 2)
|
|
353
|
-
}
|
|
354
|
-
]
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
catch (error) {
|
|
358
|
-
console.error(`Error fetching labels for blog ${args.blogId}:`, error);
|
|
359
|
-
return {
|
|
360
|
-
content: [
|
|
361
|
-
{
|
|
362
|
-
type: 'text',
|
|
363
|
-
text: `Error fetching labels: ${error}`
|
|
364
|
-
}
|
|
365
|
-
],
|
|
366
|
-
isError: true
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
}
|
|
140
|
+
handler: (args) => createToolHandler('list_labels', () => {
|
|
141
|
+
return bloggerService.listLabels(args.blogId).then(labels => ({ labels: labels.items }));
|
|
142
|
+
})()
|
|
370
143
|
},
|
|
371
144
|
{
|
|
372
145
|
name: 'get_label',
|
|
@@ -375,74 +148,21 @@ function createToolDefinitions(bloggerService) {
|
|
|
375
148
|
blogId: zod_1.z.string().describe('Blog ID'),
|
|
376
149
|
labelName: zod_1.z.string().describe('Label name')
|
|
377
150
|
}),
|
|
378
|
-
handler:
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
return {
|
|
382
|
-
content: [
|
|
383
|
-
{
|
|
384
|
-
type: 'text',
|
|
385
|
-
text: JSON.stringify({ label }, null, 2)
|
|
386
|
-
}
|
|
387
|
-
]
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
catch (error) {
|
|
391
|
-
console.error(`Error fetching label ${args.labelName}:`, error);
|
|
392
|
-
return {
|
|
393
|
-
content: [
|
|
394
|
-
{
|
|
395
|
-
type: 'text',
|
|
396
|
-
text: `Error fetching label: ${error}`
|
|
397
|
-
}
|
|
398
|
-
],
|
|
399
|
-
isError: true
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
}
|
|
151
|
+
handler: (args) => createToolHandler('get_label', () => {
|
|
152
|
+
return bloggerService.getLabel(args.blogId, args.labelName).then(label => ({ label }));
|
|
153
|
+
})()
|
|
403
154
|
}
|
|
404
155
|
];
|
|
405
156
|
}
|
|
406
|
-
/**
|
|
407
|
-
* Initializes the MCP server with all Blogger tools
|
|
408
|
-
* @param bloggerService Blogger service to interact with the API
|
|
409
|
-
* @param config Server configuration
|
|
410
|
-
* @returns MCP server instance
|
|
411
|
-
*/
|
|
412
157
|
function initMCPServer(bloggerService, config) {
|
|
413
|
-
// Create a new MCP server instance with server information
|
|
414
158
|
const server = new mcp_js_1.McpServer({
|
|
415
159
|
name: "Blogger MCP Server",
|
|
416
160
|
version: "1.0.4",
|
|
417
161
|
vendor: "mcproadev"
|
|
418
162
|
});
|
|
419
|
-
// Get all tool definitions
|
|
420
163
|
const toolDefinitions = createToolDefinitions(bloggerService);
|
|
421
|
-
// Register each tool with the MCP server
|
|
422
164
|
for (const tool of toolDefinitions) {
|
|
423
|
-
|
|
424
|
-
// The MCP SDK expects the shape, not the Zod object itself for the 'args' parameter in server.tool()
|
|
425
|
-
// However, looking at the previous code:
|
|
426
|
-
// server.tool('name', 'desc', { param: z.string() }, handler)
|
|
427
|
-
// The previous code passed an object with Zod schemas as values.
|
|
428
|
-
// Our ToolDefinition.args is a z.ZodType<any>, which is likely a z.object({...}).
|
|
429
|
-
// We need to extract the shape from the z.object to pass it to server.tool if we want to match the signature.
|
|
430
|
-
// Actually, looking at the SDK, server.tool takes:
|
|
431
|
-
// name: string, description: string, args: ToolArgs, handler: ToolCallback
|
|
432
|
-
// where ToolArgs is Record<string, ZodType<any>>
|
|
433
|
-
// So my ToolDefinition.args should probably be Record<string, ZodType<any>> instead of z.ZodType<any>
|
|
434
|
-
// to make it easier to spread.
|
|
435
|
-
// Let's adjust the implementation in the loop.
|
|
436
|
-
// Since I defined args as z.ZodType<any> (which is z.object({...})), I can cast it or access .shape if it's a ZodObject.
|
|
437
|
-
if (tool.args instanceof zod_1.z.ZodObject) {
|
|
438
|
-
server.tool(tool.name, tool.description, tool.args.shape, tool.handler);
|
|
439
|
-
}
|
|
440
|
-
else {
|
|
441
|
-
// Fallback for empty objects or other schemas if we had them (list_blogs has empty object)
|
|
442
|
-
// If it's not a ZodObject, we might have issues if the SDK expects a shape map.
|
|
443
|
-
// list_blogs used {} which is compatible with Record<string, ZodType>
|
|
444
|
-
server.tool(tool.name, tool.description, {}, tool.handler);
|
|
445
|
-
}
|
|
165
|
+
server.tool(tool.name, tool.description, tool.args.shape, tool.handler);
|
|
446
166
|
}
|
|
447
167
|
return server;
|
|
448
168
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,52 +1,23 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
handler: (args: any, extra?: any) => Promise<any>;
|
|
2
|
+
import { blogger_v3 } from 'googleapis';
|
|
3
|
+
export interface ToolResult {
|
|
4
|
+
content: Array<{
|
|
5
|
+
type: string;
|
|
6
|
+
text: string;
|
|
7
|
+
}>;
|
|
8
|
+
isError?: boolean;
|
|
10
9
|
}
|
|
11
|
-
export interface
|
|
12
|
-
id: string;
|
|
10
|
+
export interface ToolDefinition<T extends z.ZodRawShape = z.ZodRawShape> {
|
|
13
11
|
name: string;
|
|
14
|
-
description
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
posts?: BloggerPost[];
|
|
18
|
-
labels?: BloggerLabel[];
|
|
19
|
-
}
|
|
20
|
-
export interface BloggerPost {
|
|
21
|
-
id: string;
|
|
22
|
-
blogId: string;
|
|
23
|
-
title: string;
|
|
24
|
-
content: string;
|
|
25
|
-
url?: string;
|
|
26
|
-
published?: string;
|
|
27
|
-
updated?: string;
|
|
28
|
-
author?: {
|
|
29
|
-
id: string;
|
|
30
|
-
displayName: string;
|
|
31
|
-
url: string;
|
|
32
|
-
image?: {
|
|
33
|
-
url: string;
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
labels?: string[];
|
|
12
|
+
description: string;
|
|
13
|
+
args: z.ZodObject<T>;
|
|
14
|
+
handler: (args: z.infer<z.ZodObject<T>>) => Promise<ToolResult>;
|
|
37
15
|
}
|
|
38
|
-
export
|
|
39
|
-
|
|
16
|
+
export type BloggerBlog = blogger_v3.Schema$Blog;
|
|
17
|
+
export type BloggerPost = blogger_v3.Schema$Post;
|
|
18
|
+
export type BloggerLabel = {
|
|
40
19
|
name: string;
|
|
41
|
-
}
|
|
42
|
-
export interface SearchParams {
|
|
43
|
-
query: string;
|
|
44
|
-
maxResults?: number;
|
|
45
|
-
}
|
|
46
|
-
export interface PaginationParams {
|
|
47
|
-
pageToken?: string;
|
|
48
|
-
maxResults?: number;
|
|
49
|
-
}
|
|
20
|
+
};
|
|
50
21
|
export type ServerMode = {
|
|
51
22
|
type: 'stdio';
|
|
52
23
|
} | {
|
package/dist/ui-manager.js
CHANGED
|
@@ -8,7 +8,6 @@ const express_1 = __importDefault(require("express"));
|
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const http_1 = require("http");
|
|
10
10
|
const socket_io_1 = require("socket.io");
|
|
11
|
-
// UI manager implementation
|
|
12
11
|
class WebUIManager {
|
|
13
12
|
constructor() {
|
|
14
13
|
this.server = null;
|
|
@@ -28,40 +27,33 @@ class WebUIManager {
|
|
|
28
27
|
toolUsage: {}
|
|
29
28
|
};
|
|
30
29
|
this.app = (0, express_1.default)();
|
|
31
|
-
// Express configuration
|
|
32
30
|
this.app.use(express_1.default.json());
|
|
33
31
|
this.app.use(express_1.default.static(path_1.default.join(__dirname, '../public')));
|
|
34
|
-
|
|
35
|
-
this.app.get('/api/status', (req, res) => {
|
|
32
|
+
this.app.get('/api/status', (_req, res) => {
|
|
36
33
|
res.json(this.status);
|
|
37
34
|
});
|
|
38
|
-
this.app.get('/api/connections', (
|
|
35
|
+
this.app.get('/api/connections', (_req, res) => {
|
|
39
36
|
res.json(this.connections);
|
|
40
37
|
});
|
|
41
|
-
this.app.get('/api/stats', (
|
|
38
|
+
this.app.get('/api/stats', (_req, res) => {
|
|
42
39
|
res.json(this.stats);
|
|
43
40
|
});
|
|
44
|
-
|
|
45
|
-
this.app.get('/', (req, res) => {
|
|
41
|
+
this.app.get('/', (_req, res) => {
|
|
46
42
|
res.sendFile(path_1.default.join(__dirname, '../public/index.html'));
|
|
47
43
|
});
|
|
48
44
|
}
|
|
49
45
|
async start(port) {
|
|
50
|
-
return new Promise((resolve) => {
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
51
47
|
this.server = new http_1.Server(this.app);
|
|
52
48
|
this.io = new socket_io_1.Server(this.server);
|
|
53
|
-
|
|
49
|
+
this.server.on('error', (err) => {
|
|
50
|
+
reject(err);
|
|
51
|
+
});
|
|
54
52
|
this.io.on('connection', (socket) => {
|
|
55
53
|
console.log('New UI connection:', socket.id);
|
|
56
|
-
// Send initial data
|
|
57
54
|
socket.emit('status', this.status);
|
|
58
55
|
socket.emit('connections', this.connections);
|
|
59
56
|
socket.emit('stats', this.stats);
|
|
60
|
-
// Handle user actions
|
|
61
|
-
socket.on('restart-server', () => {
|
|
62
|
-
console.log('Server restart request received');
|
|
63
|
-
// Restart logic to be implemented
|
|
64
|
-
});
|
|
65
57
|
});
|
|
66
58
|
this.server.listen(port, () => {
|
|
67
59
|
console.log(`Web UI started on port ${port}`);
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dalcontak/blogger-mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "MCP Server for Blogger API",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/dalcontak/blogger-mcp-server.git"
|
|
9
|
+
},
|
|
6
10
|
"main": "dist/index.js",
|
|
7
11
|
"types": "dist/index.d.ts",
|
|
8
12
|
"scripts": {
|
|
@@ -361,7 +361,11 @@ describe('write operations (OAuth2)', () => {
|
|
|
361
361
|
const result = await service.createPost('blog1', newPost);
|
|
362
362
|
expect(mockPostsInsert).toHaveBeenCalledWith({
|
|
363
363
|
blogId: 'blog1',
|
|
364
|
-
requestBody:
|
|
364
|
+
requestBody: {
|
|
365
|
+
title: 'New',
|
|
366
|
+
content: '<p>Hello</p>',
|
|
367
|
+
labels: ['test']
|
|
368
|
+
}
|
|
365
369
|
});
|
|
366
370
|
expect(result.title).toBe('New');
|
|
367
371
|
});
|