alog-mcp 1.0.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.
Files changed (3) hide show
  1. package/README.md +78 -0
  2. package/dist/index.js +516 -0
  3. package/package.json +46 -0
package/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # alog-mcp
2
+
3
+ MCP(Model Context Protocol)Server for [Alog](https://github.com/your-org/alog) — 让 AI 工具直接读写你的工作日志。
4
+
5
+ ## 功能
6
+
7
+ | Tool | 说明 |
8
+ |------|------|
9
+ | `push_log` | 写入日报或技术博客 |
10
+ | `search_logs` | 全文检索 + 多条件筛选 |
11
+ | `get_log` | 读取单条日志完整内容 |
12
+ | `update_log` | 编辑标题 / 正文 / 标签 |
13
+ | `delete_log` | 永久删除日志 |
14
+ | `get_tags` | 获取所有标签列表 |
15
+ | `get_authors` | 获取所有作者统计 |
16
+
17
+ | Resource | URI | 说明 |
18
+ |----------|-----|------|
19
+ | 最近日志 | `alog://logs/recent` | 最新 20 条摘要 |
20
+ | 单条日志 | `alog://logs/{id}` | 完整正文 |
21
+ | 标签列表 | `alog://tags` | 含数量 |
22
+ | 作者列表 | `alog://authors` | 含统计 |
23
+
24
+ | Prompt | 说明 |
25
+ |--------|------|
26
+ | `write_daily_log` | 生成日报并写入 |
27
+ | `write_blog_post` | 提炼博客并写入 |
28
+
29
+ ## 接入 Claude Desktop
30
+
31
+ 编辑 `%APPDATA%\Claude\claude_desktop_config.json`(Windows)或
32
+ `~/Library/Application Support/Claude/claude_desktop_config.json`(Mac):
33
+
34
+ ```json
35
+ {
36
+ "mcpServers": {
37
+ "alog": {
38
+ "command": "npx",
39
+ "args": ["-y", "alog-mcp"],
40
+ "env": {
41
+ "ALOG_SERVER_URL": "http://your-server:3000",
42
+ "ALOG_API_KEY": "alog_xxxx",
43
+ "ALOG_SOURCE": "claude-desktop"
44
+ }
45
+ }
46
+ }
47
+ }
48
+ ```
49
+
50
+ 重启 Claude Desktop 即可。
51
+
52
+ ## 接入 Cursor
53
+
54
+ 在项目 `.cursor/mcp.json`(或全局配置)中添加同样配置。
55
+
56
+ ## 环境变量
57
+
58
+ | 变量 | 必填 | 说明 |
59
+ |------|------|------|
60
+ | `ALOG_SERVER_URL` | 是 | Alog 服务地址,如 `http://hiki.site:3001` |
61
+ | `ALOG_API_KEY` | 是(写操作) | API Key,在 `/setup` 页面创建 |
62
+ | `ALOG_SOURCE` | 否 | 来源标识,默认 `mcp` |
63
+
64
+ ## 本地开发
65
+
66
+ ```bash
67
+ git clone https://github.com/your-org/alog
68
+ cd alog/alog-mcp
69
+ npm install
70
+ npm run build
71
+
72
+ # 测试运行
73
+ ALOG_SERVER_URL=http://localhost:3000 ALOG_API_KEY=alog_xxx node dist/index.js
74
+ ```
75
+
76
+ ## License
77
+
78
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,516 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // src/index.ts
5
+ var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
6
+
7
+ // src/server.ts
8
+ var import_mcp2 = require("@modelcontextprotocol/sdk/server/mcp.js");
9
+
10
+ // src/tools/push-log.ts
11
+ var import_zod = require("zod");
12
+
13
+ // src/config.ts
14
+ var config = {
15
+ serverUrl: (process.env.ALOG_SERVER_URL ?? "http://localhost:3000").replace(/\/$/, ""),
16
+ apiKey: process.env.ALOG_API_KEY ?? "",
17
+ source: process.env.ALOG_SOURCE ?? "mcp"
18
+ };
19
+ if (!config.apiKey) {
20
+ process.stderr.write(
21
+ "[alog-mcp] Warning: ALOG_API_KEY is not set. Write operations (push_log, update_log, delete_log) will fail.\n"
22
+ );
23
+ }
24
+
25
+ // src/client.ts
26
+ function authHeaders() {
27
+ return {
28
+ Authorization: `Bearer ${config.apiKey}`,
29
+ "Content-Type": "application/json; charset=utf-8"
30
+ };
31
+ }
32
+ async function request(path, opts) {
33
+ const url = `${config.serverUrl}${path}`;
34
+ const res = await fetch(url, opts);
35
+ if (!res.ok) {
36
+ const body = await res.text().catch(() => "");
37
+ throw new Error(`ALOG API ${res.status}: ${body || res.statusText}`);
38
+ }
39
+ return res.json();
40
+ }
41
+ async function listLogs(params) {
42
+ const qs = new URLSearchParams();
43
+ for (const [k, v] of Object.entries(params)) {
44
+ if (v !== void 0 && v !== "") qs.set(k, String(v));
45
+ }
46
+ return request(`/api/logs?${qs}`);
47
+ }
48
+ async function getLog(id) {
49
+ return request(`/api/logs/${id}`);
50
+ }
51
+ async function getTags() {
52
+ return request("/api/tags");
53
+ }
54
+ async function getAuthors() {
55
+ return request("/api/authors");
56
+ }
57
+ async function pushLog(body) {
58
+ return request("/api/logs", {
59
+ method: "POST",
60
+ headers: authHeaders(),
61
+ body: JSON.stringify({ ...body, source: body.source ?? config.source })
62
+ });
63
+ }
64
+ async function updateLog(id, body) {
65
+ return request(`/api/logs/${id}`, {
66
+ method: "PATCH",
67
+ headers: authHeaders(),
68
+ body: JSON.stringify(body)
69
+ });
70
+ }
71
+ async function deleteLog(id) {
72
+ return request(`/api/logs/${id}`, {
73
+ method: "DELETE",
74
+ headers: authHeaders()
75
+ });
76
+ }
77
+
78
+ // src/tools/push-log.ts
79
+ function registerPushLog(server) {
80
+ server.tool(
81
+ "push_log",
82
+ "\u5C06\u65E5\u62A5\uFF08daily\uFF09\u6216\u535A\u5BA2\uFF08blog\uFF09\u5199\u5165 Alog \u5DE5\u4F5C\u65E5\u5FD7\u7CFB\u7EDF\u3002content \u4F7F\u7528 Markdown \u683C\u5F0F\u3002",
83
+ {
84
+ type: import_zod.z.enum(["daily", "blog"]).describe("\u65E5\u5FD7\u7C7B\u578B\uFF1Adaily=\u65E5\u62A5\uFF0Cblog=\u6280\u672F\u535A\u5BA2"),
85
+ content: import_zod.z.string().min(1).describe("Markdown \u6B63\u6587\u5185\u5BB9"),
86
+ title: import_zod.z.string().optional().describe("\u6807\u9898\uFF0C\u4E0D\u586B\u65F6\u7CFB\u7EDF\u81EA\u52A8\u751F\u6210"),
87
+ tags: import_zod.z.string().optional().describe('\u9017\u53F7\u5206\u9694\u7684\u6807\u7B7E\uFF0C\u5982 "TypeScript,React,MCP"'),
88
+ workspace: import_zod.z.string().optional().describe('\u5F53\u524D\u5DE5\u4F5C\u533A\u8DEF\u5F84\uFF0C\u5982 "D:/my-project"')
89
+ },
90
+ async ({ type, content, title, tags, workspace }) => {
91
+ try {
92
+ const data = await pushLog({ type, content, title, tags, workspace });
93
+ return {
94
+ content: [
95
+ {
96
+ type: "text",
97
+ text: `\u2705 \u65E5\u5FD7\u5199\u5165\u6210\u529F
98
+ \u6807\u9898\uFF1A${data.log.title}
99
+ ID\uFF1A${data.log.id}
100
+ \u7C7B\u578B\uFF1A${data.log.type}`
101
+ }
102
+ ]
103
+ };
104
+ } catch (err) {
105
+ return {
106
+ content: [{ type: "text", text: `\u274C \u5199\u5165\u5931\u8D25\uFF1A${err.message}` }],
107
+ isError: true
108
+ };
109
+ }
110
+ }
111
+ );
112
+ }
113
+
114
+ // src/tools/search-logs.ts
115
+ var import_zod2 = require("zod");
116
+ function registerSearchLogs(server) {
117
+ server.tool(
118
+ "search_logs",
119
+ "\u5168\u6587\u68C0\u7D22\u548C\u7B5B\u9009 Alog \u65E5\u5FD7\uFF0C\u652F\u6301\u5173\u952E\u5B57\u3001\u7C7B\u578B\u3001\u4F5C\u8005\u3001\u6807\u7B7E\u3001\u65F6\u95F4\u8303\u56F4\u7B49\u591A\u7EF4\u5EA6\u67E5\u8BE2\u3002",
120
+ {
121
+ q: import_zod2.z.string().optional().describe("\u5173\u952E\u5B57\u641C\u7D22\uFF0C\u5339\u914D\u6807\u9898\u3001\u6B63\u6587\u548C\u6807\u7B7E"),
122
+ type: import_zod2.z.enum(["daily", "blog"]).optional().describe("\u65E5\u5FD7\u7C7B\u578B\u7B5B\u9009"),
123
+ author: import_zod2.z.string().optional().describe("\u6309\u4F5C\u8005\u540D\u79F0\u7CBE\u786E\u7B5B\u9009"),
124
+ tag: import_zod2.z.string().optional().describe('\u6309\u6807\u7B7E slug \u7CBE\u786E\u7B5B\u9009\uFF0C\u5982 "typescript"'),
125
+ from: import_zod2.z.string().optional().describe("\u5F00\u59CB\u65E5\u671F YYYY-MM-DD"),
126
+ to: import_zod2.z.string().optional().describe("\u7ED3\u675F\u65E5\u671F YYYY-MM-DD"),
127
+ page: import_zod2.z.number().int().min(1).optional().default(1).describe("\u9875\u7801\uFF0C\u4ECE 1 \u8D77"),
128
+ pageSize: import_zod2.z.number().int().min(1).max(50).optional().default(10).describe("\u6BCF\u9875\u6570\u91CF\uFF0C\u6700\u5927 50")
129
+ },
130
+ async ({ q, type, author, tag, from, to, page, pageSize }) => {
131
+ try {
132
+ const params = { page: page ?? 1, pageSize: pageSize ?? 10 };
133
+ if (q) params.q = q;
134
+ if (type) params.type = type;
135
+ if (author) params.author = author;
136
+ if (tag) params.tag = tag;
137
+ if (from) params.from = from;
138
+ if (to) params.to = to;
139
+ const data = await listLogs(params);
140
+ if (data.logs.length === 0) {
141
+ return { content: [{ type: "text", text: "\u672A\u627E\u5230\u5339\u914D\u7684\u65E5\u5FD7" }] };
142
+ }
143
+ const lines = [
144
+ `\u5171 ${data.total} \u6761\u8BB0\u5F55\uFF08\u7B2C ${data.page}/${data.totalPages} \u9875\uFF09`,
145
+ "",
146
+ ...data.logs.map((log, i) => {
147
+ const tags = log.tags.map((t) => t.tag.name).join(", ");
148
+ return [
149
+ `${i + 1}. [${log.type.toUpperCase()}] ${log.title}`,
150
+ ` ID: ${log.id}`,
151
+ ` \u4F5C\u8005: ${log.author || "\u672A\u77E5"} | \u65F6\u95F4: ${log.createdAt.slice(0, 10)}`,
152
+ tags ? ` \u6807\u7B7E: ${tags}` : ""
153
+ ].filter(Boolean).join("\n");
154
+ })
155
+ ];
156
+ return { content: [{ type: "text", text: lines.join("\n") }] };
157
+ } catch (err) {
158
+ return {
159
+ content: [{ type: "text", text: `\u274C \u67E5\u8BE2\u5931\u8D25\uFF1A${err.message}` }],
160
+ isError: true
161
+ };
162
+ }
163
+ }
164
+ );
165
+ }
166
+
167
+ // src/tools/get-log.ts
168
+ var import_zod3 = require("zod");
169
+ function registerGetLog(server) {
170
+ server.tool(
171
+ "get_log",
172
+ "\u6839\u636E ID \u83B7\u53D6\u5355\u6761\u65E5\u5FD7\u7684\u5B8C\u6574\u5185\u5BB9\uFF08\u5305\u542B\u6B63\u6587\u3001\u6807\u7B7E\u3001\u5143\u6570\u636E\uFF09\u3002",
173
+ {
174
+ id: import_zod3.z.string().uuid().describe("\u65E5\u5FD7 UUID\uFF0C\u53EF\u901A\u8FC7 search_logs \u83B7\u53D6")
175
+ },
176
+ async ({ id }) => {
177
+ try {
178
+ const { log } = await getLog(id);
179
+ const tags = log.tags.map((t) => t.tag.name).join(", ");
180
+ const text = [
181
+ `# ${log.title}`,
182
+ `\u7C7B\u578B: ${log.type} | \u4F5C\u8005: ${log.author || "\u672A\u77E5"} | \u6765\u6E90: ${log.source}`,
183
+ `\u65F6\u95F4: ${log.createdAt.slice(0, 10)} | \u9605\u8BFB: ${log.viewCount}`,
184
+ tags ? `\u6807\u7B7E: ${tags}` : "",
185
+ "",
186
+ "---",
187
+ "",
188
+ log.content
189
+ ].filter((l) => l !== void 0).join("\n");
190
+ return { content: [{ type: "text", text }] };
191
+ } catch (err) {
192
+ return {
193
+ content: [{ type: "text", text: `\u274C \u83B7\u53D6\u5931\u8D25\uFF1A${err.message}` }],
194
+ isError: true
195
+ };
196
+ }
197
+ }
198
+ );
199
+ }
200
+
201
+ // src/tools/update-log.ts
202
+ var import_zod4 = require("zod");
203
+ function registerUpdateLog(server) {
204
+ server.tool(
205
+ "update_log",
206
+ "\u7F16\u8F91\u5DF2\u6709\u65E5\u5FD7\u7684\u6807\u9898\u3001\u6B63\u6587\u6216\u6807\u7B7E\u3002\u9700\u8981\u63D0\u4F9B\u65E5\u5FD7 ID\uFF0C\u4EC5\u63D0\u4F9B\u9700\u8981\u4FEE\u6539\u7684\u5B57\u6BB5\u3002\u9700\u8981 ALOG_API_KEY \u6743\u9650\u3002",
207
+ {
208
+ id: import_zod4.z.string().uuid().describe("\u8981\u7F16\u8F91\u7684\u65E5\u5FD7 UUID"),
209
+ title: import_zod4.z.string().optional().describe("\u65B0\u6807\u9898\uFF08\u4E0D\u586B\u5219\u4E0D\u4FEE\u6539\uFF09"),
210
+ content: import_zod4.z.string().optional().describe("\u65B0\u7684 Markdown \u6B63\u6587\uFF08\u4E0D\u586B\u5219\u4E0D\u4FEE\u6539\uFF09"),
211
+ tags: import_zod4.z.string().optional().describe("\u65B0\u6807\u7B7E\uFF0C\u9017\u53F7\u5206\u9694\uFF08\u4E0D\u586B\u5219\u4E0D\u4FEE\u6539\uFF09")
212
+ },
213
+ async ({ id, title, content, tags }) => {
214
+ if (!title && !content && !tags) {
215
+ return {
216
+ content: [{ type: "text", text: "\u274C \u8BF7\u81F3\u5C11\u63D0\u4F9B\u4E00\u4E2A\u8981\u4FEE\u6539\u7684\u5B57\u6BB5\uFF08title\u3001content \u6216 tags\uFF09" }],
217
+ isError: true
218
+ };
219
+ }
220
+ try {
221
+ const { log } = await updateLog(id, { title, content, tags });
222
+ return {
223
+ content: [
224
+ {
225
+ type: "text",
226
+ text: `\u2705 \u65E5\u5FD7\u66F4\u65B0\u6210\u529F
227
+ \u6807\u9898\uFF1A${log.title}
228
+ ID\uFF1A${log.id}`
229
+ }
230
+ ]
231
+ };
232
+ } catch (err) {
233
+ return {
234
+ content: [{ type: "text", text: `\u274C \u66F4\u65B0\u5931\u8D25\uFF1A${err.message}` }],
235
+ isError: true
236
+ };
237
+ }
238
+ }
239
+ );
240
+ }
241
+
242
+ // src/tools/delete-log.ts
243
+ var import_zod5 = require("zod");
244
+ function registerDeleteLog(server) {
245
+ server.tool(
246
+ "delete_log",
247
+ "\u6C38\u4E45\u5220\u9664\u6307\u5B9A\u65E5\u5FD7\u3002\u6B64\u64CD\u4F5C\u4E0D\u53EF\u64A4\u9500\uFF0C\u8BF7\u8C28\u614E\u4F7F\u7528\u3002\u9700\u8981 ALOG_API_KEY \u6743\u9650\u3002",
248
+ {
249
+ id: import_zod5.z.string().uuid().describe("\u8981\u5220\u9664\u7684\u65E5\u5FD7 UUID"),
250
+ confirm: import_zod5.z.literal("yes").describe('\u786E\u8BA4\u5220\u9664\uFF0C\u5FC5\u987B\u4F20\u5165\u5B57\u7B26\u4E32 "yes" \u4EE5\u9632\u6B62\u8BEF\u64CD\u4F5C')
251
+ },
252
+ async ({ id, confirm }) => {
253
+ if (confirm !== "yes") {
254
+ return {
255
+ content: [{ type: "text", text: '\u274C \u8BF7\u5C06 confirm \u53C2\u6570\u8BBE\u7F6E\u4E3A "yes" \u4EE5\u786E\u8BA4\u5220\u9664' }],
256
+ isError: true
257
+ };
258
+ }
259
+ try {
260
+ await deleteLog(id);
261
+ return {
262
+ content: [{ type: "text", text: `\u2705 \u65E5\u5FD7 ${id} \u5DF2\u6C38\u4E45\u5220\u9664` }]
263
+ };
264
+ } catch (err) {
265
+ return {
266
+ content: [{ type: "text", text: `\u274C \u5220\u9664\u5931\u8D25\uFF1A${err.message}` }],
267
+ isError: true
268
+ };
269
+ }
270
+ }
271
+ );
272
+ }
273
+
274
+ // src/tools/get-tags.ts
275
+ function registerGetTags(server) {
276
+ server.tool(
277
+ "get_tags",
278
+ "\u83B7\u53D6\u6240\u6709\u6807\u7B7E\u5217\u8868\u53CA\u6BCF\u4E2A\u6807\u7B7E\u7684\u65E5\u5FD7\u6570\u91CF\uFF0C\u53EF\u7528\u4E8E\u63A8\u8350\u6807\u7B7E\u6216\u4E86\u89E3\u77E5\u8BC6\u5206\u5E03\u3002",
279
+ {},
280
+ async () => {
281
+ try {
282
+ const { tags } = await getTags();
283
+ if (tags.length === 0) {
284
+ return { content: [{ type: "text", text: "\u6682\u65E0\u6807\u7B7E" }] };
285
+ }
286
+ const lines = tags.map(
287
+ (t) => `\u2022 ${t.name} (${t.slug}) \u2014 ${t.count} \u6761\u65E5\u5FD7`
288
+ );
289
+ return {
290
+ content: [
291
+ {
292
+ type: "text",
293
+ text: `\u5171 ${tags.length} \u4E2A\u6807\u7B7E\uFF1A
294
+
295
+ ${lines.join("\n")}`
296
+ }
297
+ ]
298
+ };
299
+ } catch (err) {
300
+ return {
301
+ content: [{ type: "text", text: `\u274C \u83B7\u53D6\u6807\u7B7E\u5931\u8D25\uFF1A${err.message}` }],
302
+ isError: true
303
+ };
304
+ }
305
+ }
306
+ );
307
+ }
308
+
309
+ // src/tools/get-authors.ts
310
+ function registerGetAuthors(server) {
311
+ server.tool(
312
+ "get_authors",
313
+ "\u83B7\u53D6\u6240\u6709\u4F5C\u8005\u53CA\u5176\u65E5\u5FD7\u7EDF\u8BA1\u4FE1\u606F\uFF08\u603B\u6570\u3001\u65E5\u62A5\u6570\u3001\u535A\u5BA2\u6570\uFF09\u3002",
314
+ {},
315
+ async () => {
316
+ try {
317
+ const { authors } = await getAuthors();
318
+ if (authors.length === 0) {
319
+ return { content: [{ type: "text", text: "\u6682\u65E0\u4F5C\u8005\u6570\u636E" }] };
320
+ }
321
+ const lines = authors.map(
322
+ (a) => `\u2022 ${a.name || "\u533F\u540D"} (${a.source}) \u2014 \u5171 ${a.logCount} \u6761\uFF0C\u65E5\u62A5 ${a.dailyCount}\uFF0C\u535A\u5BA2 ${a.blogCount}`
323
+ );
324
+ return {
325
+ content: [
326
+ {
327
+ type: "text",
328
+ text: `\u5171 ${authors.length} \u4F4D\u4F5C\u8005\uFF1A
329
+
330
+ ${lines.join("\n")}`
331
+ }
332
+ ]
333
+ };
334
+ } catch (err) {
335
+ return {
336
+ content: [{ type: "text", text: `\u274C \u83B7\u53D6\u4F5C\u8005\u5931\u8D25\uFF1A${err.message}` }],
337
+ isError: true
338
+ };
339
+ }
340
+ }
341
+ );
342
+ }
343
+
344
+ // src/resources/index.ts
345
+ var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
346
+ function registerResources(server) {
347
+ server.resource("recent-logs", "alog://logs/recent", async () => {
348
+ const { logs, total } = await listLogs({ pageSize: 20 });
349
+ const lines = [
350
+ `Alog \u6700\u8FD1\u65E5\u5FD7\uFF08\u5171 ${total} \u6761\uFF09`,
351
+ "",
352
+ ...logs.map((l) => {
353
+ const tags = l.tags.map((t) => t.tag.name).join(", ");
354
+ return [
355
+ `[${l.type.toUpperCase()}] ${l.title}`,
356
+ ` ID: ${l.id} | ${l.createdAt.slice(0, 10)} | \u4F5C\u8005: ${l.author || "\u672A\u77E5"}`,
357
+ tags ? ` \u6807\u7B7E: ${tags}` : ""
358
+ ].filter(Boolean).join("\n");
359
+ })
360
+ ];
361
+ return {
362
+ contents: [{ uri: "alog://logs/recent", mimeType: "text/plain", text: lines.join("\n") }]
363
+ };
364
+ });
365
+ server.resource("tags", "alog://tags", async () => {
366
+ const { tags } = await getTags();
367
+ const text = tags.map((t) => `${t.name} (${t.slug}): ${t.count} \u6761`).join("\n");
368
+ return {
369
+ contents: [{ uri: "alog://tags", mimeType: "text/plain", text: text || "\u6682\u65E0\u6807\u7B7E" }]
370
+ };
371
+ });
372
+ server.resource("authors", "alog://authors", async () => {
373
+ const { authors } = await getAuthors();
374
+ const text = authors.map((a) => `${a.name || "\u533F\u540D"} (${a.source}): ${a.logCount} \u6761`).join("\n");
375
+ return {
376
+ contents: [{ uri: "alog://authors", mimeType: "text/plain", text: text || "\u6682\u65E0\u4F5C\u8005" }]
377
+ };
378
+ });
379
+ server.resource(
380
+ "log-by-id",
381
+ new import_mcp.ResourceTemplate("alog://logs/{id}", { list: void 0 }),
382
+ async (uri, { id }) => {
383
+ const logId = Array.isArray(id) ? id[0] : id;
384
+ if (!logId) throw new Error("Missing log ID in URI");
385
+ const { log } = await getLog(logId);
386
+ const tags = log.tags.map((t) => t.tag.name).join(", ");
387
+ const text = [
388
+ `# ${log.title}`,
389
+ `\u7C7B\u578B: ${log.type} | \u65F6\u95F4: ${log.createdAt.slice(0, 10)} | \u9605\u8BFB: ${log.viewCount}`,
390
+ tags ? `\u6807\u7B7E: ${tags}` : "",
391
+ "",
392
+ log.content
393
+ ].filter((l) => l !== void 0).join("\n");
394
+ return {
395
+ contents: [{ uri: uri.href, mimeType: "text/plain", text }]
396
+ };
397
+ }
398
+ );
399
+ }
400
+
401
+ // src/prompts/index.ts
402
+ function registerPrompts(server) {
403
+ server.prompt(
404
+ "write_daily_log",
405
+ "\u6839\u636E\u5F53\u524D\u5BF9\u8BDD\u4E0A\u4E0B\u6587\u751F\u6210\u7ED3\u6784\u5316\u5DE5\u4F5C\u65E5\u62A5\uFF0C\u5E76\u81EA\u52A8\u8C03\u7528 push_log \u5199\u5165 Alog",
406
+ [
407
+ { name: "date", description: "\u65E5\u671F\uFF0C\u683C\u5F0F YYYY-MM-DD\uFF0C\u9ED8\u8BA4\u4ECA\u5929", required: false },
408
+ { name: "tags", description: '\u6807\u7B7E\uFF0C\u9017\u53F7\u5206\u9694\uFF0C\u5982 "TypeScript,React"', required: false }
409
+ ],
410
+ ({ date, tags }) => {
411
+ const d = date ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
412
+ return {
413
+ messages: [
414
+ {
415
+ role: "user",
416
+ content: {
417
+ type: "text",
418
+ text: `\u8BF7\u6839\u636E\u6211\u4EEC\u4ECA\u5929\uFF08${d}\uFF09\u7684\u5BF9\u8BDD\u5185\u5BB9\uFF0C\u751F\u6210\u4E00\u7BC7\u7ED3\u6784\u5316\u5DE5\u4F5C\u65E5\u62A5\u3002
419
+
420
+ \u65E5\u62A5\u683C\u5F0F\uFF08Markdown\uFF09\uFF1A
421
+ ## \u4ECA\u65E5\u5B8C\u6210\u4EFB\u52A1
422
+ - \u4EFB\u52A11
423
+ - \u4EFB\u52A12
424
+
425
+ ## \u6280\u672F\u8981\u70B9
426
+ - \u5173\u952E\u51B3\u7B56\u6216\u6280\u672F\u7EC6\u8282
427
+
428
+ ## \u9047\u5230\u7684\u95EE\u9898
429
+ - \u95EE\u9898\u63CF\u8FF0\uFF08\u65E0\u5219\u5199"\u65E0"\uFF09
430
+
431
+ ## \u660E\u65E5\u8BA1\u5212
432
+ - \u4E0B\u4E00\u6B65\u8BA1\u5212
433
+
434
+ \u751F\u6210\u5B8C\u6BD5\u540E\uFF0C\u7ACB\u5373\u8C03\u7528 push_log \u5DE5\u5177\u5199\u5165 Alog\uFF1A
435
+ - type: "daily"
436
+ - title: "\u65E5\u62A5 \u2014 ${d}"
437
+ - tags: "${tags ?? "\uFF08\u4ECE\u5185\u5BB9\u63D0\u53D6\uFF09"}"
438
+
439
+ \u4E0D\u8981\u7B49\u7528\u6237\u786E\u8BA4\uFF0C\u76F4\u63A5\u6267\u884C\u3002`
440
+ }
441
+ }
442
+ ]
443
+ };
444
+ }
445
+ );
446
+ server.prompt(
447
+ "write_blog_post",
448
+ "\u5C06\u672C\u6B21\u5BF9\u8BDD\u7684\u6280\u672F\u5B9E\u73B0\u63D0\u70BC\u4E3A\u6280\u672F\u535A\u5BA2\uFF0C\u81EA\u52A8\u8C03\u7528 push_log \u5199\u5165 Alog",
449
+ [
450
+ { name: "title", description: "\u535A\u5BA2\u6807\u9898", required: false },
451
+ { name: "tags", description: "\u6807\u7B7E\uFF0C\u9017\u53F7\u5206\u9694", required: false }
452
+ ],
453
+ ({ title, tags }) => ({
454
+ messages: [
455
+ {
456
+ role: "user",
457
+ content: {
458
+ type: "text",
459
+ text: `\u8BF7\u5C06\u672C\u6B21\u5BF9\u8BDD\u6D89\u53CA\u7684\u6280\u672F\u5B9E\u73B0\u63D0\u70BC\u4E3A\u4E00\u7BC7\u6280\u672F\u535A\u5BA2\u3002
460
+
461
+ \u535A\u5BA2\u683C\u5F0F\uFF08Markdown\uFF09\uFF1A
462
+ ## \u80CC\u666F\u4E0E\u76EE\u6807
463
+ \uFF08\u95EE\u9898\u63CF\u8FF0\uFF0C\u4E3A\u4EC0\u4E48\u8981\u505A\u8FD9\u4EF6\u4E8B\uFF09
464
+
465
+ ## \u5B9E\u73B0\u65B9\u6848
466
+ \uFF08\u6280\u672F\u601D\u8DEF\uFF0C\u67B6\u6784\u8BBE\u8BA1\uFF09
467
+
468
+ ## \u5173\u952E\u5B9E\u73B0
469
+ \uFF08\u6838\u5FC3\u4EE3\u7801\u7247\u6BB5\u548C\u8BF4\u660E\uFF09
470
+
471
+ ## \u603B\u7ED3
472
+ \uFF08\u4EF7\u503C\u3001\u6536\u83B7\u3001\u540E\u7EED\u65B9\u5411\uFF09
473
+
474
+ \u535A\u5BA2\u6807\u9898\uFF1A${title ?? "\uFF08\u8BF7\u6839\u636E\u5185\u5BB9\u751F\u6210\u5408\u9002\u6807\u9898\uFF09"}
475
+ \u6807\u7B7E\uFF1A${tags ?? "\uFF08\u4ECE\u5185\u5BB9\u63D0\u53D6\uFF0C2-5 \u4E2A\uFF09"}
476
+
477
+ \u751F\u6210\u5B8C\u6BD5\u540E\u7ACB\u5373\u8C03\u7528 push_log \u5199\u5165 Alog\uFF1A
478
+ - type: "blog"
479
+ \u4E0D\u8981\u7B49\u7528\u6237\u786E\u8BA4\uFF0C\u76F4\u63A5\u6267\u884C\u3002`
480
+ }
481
+ }
482
+ ]
483
+ })
484
+ );
485
+ }
486
+
487
+ // src/server.ts
488
+ function createServer() {
489
+ const server = new import_mcp2.McpServer({
490
+ name: "alog-mcp",
491
+ version: "1.0.0"
492
+ });
493
+ registerPushLog(server);
494
+ registerSearchLogs(server);
495
+ registerGetLog(server);
496
+ registerUpdateLog(server);
497
+ registerDeleteLog(server);
498
+ registerGetTags(server);
499
+ registerGetAuthors(server);
500
+ registerResources(server);
501
+ registerPrompts(server);
502
+ return server;
503
+ }
504
+
505
+ // src/index.ts
506
+ async function main() {
507
+ const server = createServer();
508
+ const transport = new import_stdio.StdioServerTransport();
509
+ await server.connect(transport);
510
+ process.stderr.write("[alog-mcp] Server started (stdio transport)\n");
511
+ }
512
+ main().catch((err) => {
513
+ process.stderr.write(`[alog-mcp] Fatal error: ${err}
514
+ `);
515
+ process.exit(1);
516
+ });
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "alog-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP Server for Alog work log system — push, search, edit and delete logs via AI tools",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "alog-mcp": "dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "README.md"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsup src/index.ts --format cjs --clean",
15
+ "dev": "tsup src/index.ts --format cjs --watch",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "keywords": [
19
+ "mcp",
20
+ "model-context-protocol",
21
+ "alog",
22
+ "work-log",
23
+ "ai",
24
+ "claude",
25
+ "cursor"
26
+ ],
27
+ "author": "Alog Contributors",
28
+ "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/your-org/alog"
32
+ },
33
+ "homepage": "https://github.com/your-org/alog#readme",
34
+ "dependencies": {
35
+ "@modelcontextprotocol/sdk": "^1.10.2",
36
+ "zod": "^3.24.2"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^22.0.0",
40
+ "tsup": "^8.4.0",
41
+ "typescript": "^5.7.3"
42
+ },
43
+ "engines": {
44
+ "node": ">=18"
45
+ }
46
+ }