mcp-for-memos 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 (58) hide show
  1. package/README.md +334 -0
  2. package/dist/client.d.ts +15 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +155 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/config.d.ts +18 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +27 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/http.d.ts +4 -0
  11. package/dist/http.d.ts.map +1 -0
  12. package/dist/http.js +342 -0
  13. package/dist/http.js.map +1 -0
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +79 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/prompts/index.d.ts +3 -0
  19. package/dist/prompts/index.d.ts.map +1 -0
  20. package/dist/prompts/index.js +68 -0
  21. package/dist/prompts/index.js.map +1 -0
  22. package/dist/resources/index.d.ts +4 -0
  23. package/dist/resources/index.d.ts.map +1 -0
  24. package/dist/resources/index.js +52 -0
  25. package/dist/resources/index.js.map +1 -0
  26. package/dist/server.d.ts +9 -0
  27. package/dist/server.d.ts.map +1 -0
  28. package/dist/server.js +40 -0
  29. package/dist/server.js.map +1 -0
  30. package/dist/tools/memos.d.ts +9 -0
  31. package/dist/tools/memos.d.ts.map +1 -0
  32. package/dist/tools/memos.js +137 -0
  33. package/dist/tools/memos.js.map +1 -0
  34. package/dist/tools/relations.d.ts +4 -0
  35. package/dist/tools/relations.d.ts.map +1 -0
  36. package/dist/tools/relations.js +108 -0
  37. package/dist/tools/relations.js.map +1 -0
  38. package/dist/tools/resources.d.ts +4 -0
  39. package/dist/tools/resources.d.ts.map +1 -0
  40. package/dist/tools/resources.js +90 -0
  41. package/dist/tools/resources.js.map +1 -0
  42. package/dist/tools/review.d.ts +4 -0
  43. package/dist/tools/review.d.ts.map +1 -0
  44. package/dist/tools/review.js +208 -0
  45. package/dist/tools/review.js.map +1 -0
  46. package/dist/tools/tags.d.ts +4 -0
  47. package/dist/tools/tags.d.ts.map +1 -0
  48. package/dist/tools/tags.js +164 -0
  49. package/dist/tools/tags.js.map +1 -0
  50. package/dist/tools/utils.d.ts +6 -0
  51. package/dist/tools/utils.d.ts.map +1 -0
  52. package/dist/tools/utils.js +68 -0
  53. package/dist/tools/utils.js.map +1 -0
  54. package/dist/types.d.ts +36 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +2 -0
  57. package/dist/types.js.map +1 -0
  58. package/package.json +49 -0
@@ -0,0 +1,208 @@
1
+ import { z } from "zod";
2
+ import { summarizeMemo } from "./utils.js";
3
+ function escapeCel(str) {
4
+ return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
5
+ }
6
+ function parseRelativeDate(input) {
7
+ const now = new Date();
8
+ const lower = input.toLowerCase().trim();
9
+ const toMidnight = (d) => { d.setUTCHours(0, 0, 0, 0); return d; };
10
+ if (lower === "today")
11
+ return toMidnight(new Date(now));
12
+ if (lower === "tomorrow") {
13
+ const d = new Date(now);
14
+ d.setUTCDate(d.getUTCDate() + 1);
15
+ return toMidnight(d);
16
+ }
17
+ if (lower === "yesterday") {
18
+ const d = new Date(now);
19
+ d.setUTCDate(d.getUTCDate() - 1);
20
+ return toMidnight(d);
21
+ }
22
+ if (lower === "next_week") {
23
+ const d = new Date(now);
24
+ d.setUTCDate(d.getUTCDate() + 7);
25
+ return toMidnight(d);
26
+ }
27
+ if (lower === "last_week") {
28
+ const d = new Date(now);
29
+ d.setUTCDate(d.getUTCDate() - 7);
30
+ return toMidnight(d);
31
+ }
32
+ if (lower === "this_week")
33
+ return toMidnight(new Date(now));
34
+ if (lower === "next_month") {
35
+ const d = new Date(now);
36
+ d.setUTCMonth(d.getUTCMonth() + 1);
37
+ return toMidnight(d);
38
+ }
39
+ if (lower === "last_month") {
40
+ const d = new Date(now);
41
+ d.setUTCMonth(d.getUTCMonth() - 1);
42
+ return toMidnight(d);
43
+ }
44
+ if (lower === "this_month")
45
+ return toMidnight(new Date(now));
46
+ const dayNames = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
47
+ const nextDayMatch = lower.match(/^next_(sunday|monday|tuesday|wednesday|thursday|friday|saturday)$/);
48
+ if (nextDayMatch) {
49
+ const targetDay = dayNames.indexOf(nextDayMatch[1]);
50
+ const d = new Date(now);
51
+ d.setUTCDate(d.getUTCDate() + ((targetDay - d.getUTCDay() + 7) % 7 || 7));
52
+ return toMidnight(d);
53
+ }
54
+ const lastDayMatch = lower.match(/^last_(sunday|monday|tuesday|wednesday|thursday|friday|saturday)$/);
55
+ if (lastDayMatch) {
56
+ const targetDay = dayNames.indexOf(lastDayMatch[1]);
57
+ const d = new Date(now);
58
+ d.setUTCDate(d.getUTCDate() - ((d.getUTCDay() - targetDay + 7) % 7 || 7));
59
+ return toMidnight(d);
60
+ }
61
+ const daysAgoMatch = lower.match(/^(\d+)_days_ago$/);
62
+ if (daysAgoMatch) {
63
+ const d = new Date(now);
64
+ d.setUTCDate(d.getUTCDate() - parseInt(daysAgoMatch[1]));
65
+ return toMidnight(d);
66
+ }
67
+ const inDaysMatch = lower.match(/^in_(\d+)_days$/);
68
+ if (inDaysMatch) {
69
+ const d = new Date(now);
70
+ d.setUTCDate(d.getUTCDate() + parseInt(inDaysMatch[1]));
71
+ return toMidnight(d);
72
+ }
73
+ const weeksAgoMatch = lower.match(/^(\d+)_weeks_ago$/);
74
+ if (weeksAgoMatch) {
75
+ const d = new Date(now);
76
+ d.setUTCDate(d.getUTCDate() - parseInt(weeksAgoMatch[1]) * 7);
77
+ return toMidnight(d);
78
+ }
79
+ const inWeeksMatch = lower.match(/^in_(\d+)_weeks$/);
80
+ if (inWeeksMatch) {
81
+ const d = new Date(now);
82
+ d.setUTCDate(d.getUTCDate() + parseInt(inWeeksMatch[1]) * 7);
83
+ return toMidnight(d);
84
+ }
85
+ const parsed = new Date(input);
86
+ if (!isNaN(parsed.getTime()))
87
+ return parsed;
88
+ throw new Error(`Cannot parse date: "${input}". Use ISO 8601, "today", "yesterday", "next_monday", "3_days_ago", etc.`);
89
+ }
90
+ function getWeekBoundaries(refDate) {
91
+ const d = new Date(refDate);
92
+ const day = d.getUTCDay();
93
+ const diffToMonday = (day === 0 ? -6 : 1) - day;
94
+ const start = new Date(d);
95
+ start.setUTCDate(d.getUTCDate() + diffToMonday);
96
+ start.setUTCHours(0, 0, 0, 0);
97
+ const end = new Date(start);
98
+ end.setUTCDate(start.getUTCDate() + 6);
99
+ end.setUTCHours(23, 59, 59, 999);
100
+ return { start, end };
101
+ }
102
+ export const registerSearchTool = (server, client) => {
103
+ server.registerTool("search", {
104
+ description: [
105
+ "Search memos. Unified tool for date-based, tag-based, and content-based search.",
106
+ "",
107
+ "Date (optional, accepts):",
108
+ " ISO: '2025-06-15' | Relative: 'today', 'yesterday', 'tomorrow'",
109
+ " Relative: 'next_monday', 'last_friday', 'next_week', 'this_month'",
110
+ " Relative: 'in_7_days', '3_days_ago', 'in_2_weeks'",
111
+ " week=true: auto full week (Mon-Sun)",
112
+ "",
113
+ "Filters (all optional, combined with AND):",
114
+ " tags: ['work', 'meeting'] | query: 'text search'",
115
+ " visibility: ['PRIVATE'] | pinned: true",
116
+ " state: 'ARCHIVED' | hasIncompleteTasks: true",
117
+ " hasAttachments: true | Only memos with file attachments",
118
+ "",
119
+ "No date = all memos. No filters = all memos.",
120
+ ].join("\n"),
121
+ inputSchema: {
122
+ date: z.string().optional().describe("Date (ISO 8601 or relative). Omit to search all memos."),
123
+ endDate: z.string().optional().describe("End date for range. Omit for single-day."),
124
+ week: z.boolean().optional().describe("Auto full week (Mon-Sun) around date"),
125
+ tags: z.array(z.string()).optional().describe("Filter by tags"),
126
+ query: z.string().optional().describe("Full-text search in content"),
127
+ visibility: z.array(z.enum(["PRIVATE", "PROTECTED", "PUBLIC"])).optional().describe("Filter by visibility"),
128
+ pinned: z.boolean().optional().describe("Only pinned memos"),
129
+ state: z.enum(["NORMAL", "ARCHIVED"]).optional().describe("Filter by state"),
130
+ hasIncompleteTasks: z.boolean().optional().describe("Only memos with incomplete tasks"),
131
+ hasAttachments: z.boolean().optional().describe("Only memos with file attachments"),
132
+ pageSize: z.number().int().min(1).max(100).default(20).describe("Results per page"),
133
+ pageToken: z.string().optional().describe("Pagination token"),
134
+ },
135
+ annotations: { readOnlyHint: true, openWorldHint: false },
136
+ }, async (args) => {
137
+ let currentUser;
138
+ try {
139
+ currentUser = await client.getCurrentUser();
140
+ }
141
+ catch {
142
+ currentUser = "";
143
+ }
144
+ // Build CEL filter
145
+ const parts = [];
146
+ if (currentUser)
147
+ parts.push(`creator == "${escapeCel(currentUser)}"`);
148
+ // Date filtering
149
+ if (args.date) {
150
+ try {
151
+ const refDate = parseRelativeDate(args.date);
152
+ let startTs;
153
+ let endTs;
154
+ if (args.week) {
155
+ const b = getWeekBoundaries(refDate);
156
+ startTs = Math.floor(b.start.getTime() / 1000);
157
+ endTs = Math.floor(b.end.getTime() / 1000);
158
+ }
159
+ else {
160
+ startTs = Math.floor(refDate.getTime() / 1000);
161
+ endTs = args.endDate ? Math.floor(parseRelativeDate(args.endDate).getTime() / 1000) : startTs + 86400;
162
+ }
163
+ parts.push(`created_ts >= ${startTs}`);
164
+ parts.push(`created_ts <= ${endTs}`);
165
+ }
166
+ catch (e) {
167
+ return { content: [{ type: "text", text: String(e) }] };
168
+ }
169
+ }
170
+ // Other filters
171
+ if (args.tags?.length) {
172
+ const tagList = args.tags.map((t) => `"${escapeCel(t)}"`).join(", ");
173
+ parts.push(`tag in [${tagList}]`);
174
+ }
175
+ if (args.query)
176
+ parts.push(`content.contains("${escapeCel(args.query)}")`);
177
+ if (args.visibility?.length) {
178
+ const visList = args.visibility.map((v) => `"${v}"`).join(", ");
179
+ parts.push(`visibility in [${visList}]`);
180
+ }
181
+ if (args.pinned !== undefined)
182
+ parts.push(`pinned == ${args.pinned}`);
183
+ if (args.state)
184
+ parts.push(`row_status == "${args.state === "ARCHIVED" ? "ARCHIVED" : "NORMAL"}"`);
185
+ if (args.hasIncompleteTasks)
186
+ parts.push(`has_incomplete_tasks == true`);
187
+ const filter = parts.length > 0 ? parts.join(" && ") : "";
188
+ const params = {
189
+ pageSize: String(args.pageSize),
190
+ orderBy: "create_time desc",
191
+ };
192
+ if (filter)
193
+ params.filter = filter;
194
+ if (args.pageToken)
195
+ params.pageToken = args.pageToken;
196
+ const result = await client.get("/api/v1/memos", params);
197
+ let summaries = (result.memos || []).map((m) => summarizeMemo(m));
198
+ // Filter by attachments count (post-fetch since Memos API doesn't support this in CEL)
199
+ if (args.hasAttachments) {
200
+ summaries = summaries.filter((s) => s.attachmentsCount > 0);
201
+ }
202
+ const output = { memos: summaries, totalFound: summaries.length };
203
+ if (result.nextPageToken)
204
+ output.nextPageToken = result.nextPageToken;
205
+ return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }] };
206
+ });
207
+ };
208
+ //# sourceMappingURL=review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/tools/review.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,SAAS,SAAS,CAAC,GAAW;IAC5B,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACzD,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa;IACtC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IACzC,MAAM,UAAU,GAAG,CAAC,CAAO,EAAE,EAAE,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzE,IAAI,KAAK,KAAK,OAAO;QAAE,OAAO,UAAU,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACxD,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;QAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAC9G,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;QAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAC/G,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;QAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAC/G,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;QAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAC/G,IAAI,KAAK,KAAK,WAAW;QAAE,OAAO,UAAU,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5D,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;QAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAClH,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;QAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAClH,IAAI,KAAK,KAAK,YAAY;QAAE,OAAO,UAAU,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAE7D,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;IAChG,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACtG,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC1E,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IACD,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACtG,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,GAAG,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC1E,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACrD,IAAI,YAAY,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAC9H,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACnD,IAAI,WAAW,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAC5H,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACvD,IAAI,aAAa,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IACpI,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACrD,IAAI,YAAY,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAElI,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAAE,OAAO,MAAM,CAAC;IAC5C,MAAM,IAAI,KAAK,CAAC,uBAAuB,KAAK,0EAA0E,CAAC,CAAC;AAC1H,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAa;IACtC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5B,MAAM,GAAG,GAAG,CAAC,CAAC,SAAS,EAAE,CAAC;IAC1B,MAAM,YAAY,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;IAChD,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,YAAY,CAAC,CAAC;IAChD,KAAK,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9B,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;IACvC,GAAG,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;IACjC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,MAAiB,EAAE,MAAmB,EAAE,EAAE;IAC3E,MAAM,CAAC,YAAY,CACjB,QAAQ,EACR;QACE,WAAW,EAAE;YACX,iFAAiF;YACjF,EAAE;YACF,2BAA2B;YAC3B,oEAAoE;YACpE,qEAAqE;YACrE,qDAAqD;YACrD,uCAAuC;YACvC,EAAE;YACF,4CAA4C;YAC5C,sDAAsD;YACtD,+CAA+C;YAC/C,2DAA2D;YAC3D,mEAAmE;YACnE,EAAE;YACF,8CAA8C;SAC/C,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,WAAW,EAAE;YACX,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wDAAwD,CAAC;YAC9F,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;YACnF,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;YAC7E,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YAC/D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;YACpE,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;YAC3G,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;YAC5D,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;YAC5E,kBAAkB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;YACvF,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;YACnF,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,kBAAkB,CAAC;YACnF,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;SAC9D;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KAC1D,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,WAAmB,CAAC;QACxB,IAAI,CAAC;YACH,WAAW,GAAG,MAAM,MAAM,CAAC,cAAc,EAAE,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,WAAW,GAAG,EAAE,CAAC;QACnB,CAAC;QAED,mBAAmB;QACnB,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,IAAI,WAAW;YAAE,KAAK,CAAC,IAAI,CAAC,eAAe,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAEtE,iBAAiB;QACjB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC7C,IAAI,OAAe,CAAC;gBACpB,IAAI,KAAa,CAAC;gBAClB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;oBACd,MAAM,CAAC,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;oBACrC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;oBAC/C,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;gBAC7C,CAAC;qBAAM,CAAC;oBACN,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;oBAC/C,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC;gBACxG,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,iBAAiB,OAAO,EAAE,CAAC,CAAC;gBACvC,KAAK,CAAC,IAAI,CAAC,iBAAiB,KAAK,EAAE,CAAC,CAAC;YACvC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YACnE,CAAC;QACH,CAAC;QAED,gBAAgB;QAChB,IAAI,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrE,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,GAAG,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,IAAI,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,qBAAqB,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3E,IAAI,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChE,KAAK,CAAC,IAAI,CAAC,kBAAkB,OAAO,GAAG,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACtE,IAAI,IAAI,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;QACnG,IAAI,IAAI,CAAC,kBAAkB;YAAE,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAExE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAE1D,MAAM,MAAM,GAA2B;YACrC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,kBAAkB;SAC5B,CAAC;QACF,IAAI,MAAM;YAAE,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;QACnC,IAAI,IAAI,CAAC,SAAS;YAAE,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAEtD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAA4C,eAAe,EAAE,MAAM,CAAC,CAAC;QACpG,IAAI,SAAS,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAuC,CAAC,CAAC,CAAC;QAExG,uFAAuF;QACvF,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,CAAC,CAAC,gBAA2B,GAAG,CAAC,CAAC,CAAC;QAC1E,CAAC;QAED,MAAM,MAAM,GAA4B,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC;QAC3F,IAAI,MAAM,CAAC,aAAa;YAAE,MAAM,CAAC,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;QAEtE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC,CACF,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { MemosClient } from "../client.js";
3
+ export declare const registerTagTools: (server: McpServer, client: MemosClient) => void;
4
+ //# sourceMappingURL=tags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/tools/tags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAqJ3C,eAAO,MAAM,gBAAgB,GAAI,QAAQ,SAAS,EAAE,QAAQ,WAAW,SAmDtE,CAAC"}
@@ -0,0 +1,164 @@
1
+ import { z } from "zod";
2
+ const tagsCache = new Map();
3
+ const TAGS_CACHE_TTL_MS = 60_000; // 1 minuto
4
+ const TAGS_MAX_PAGES = 20; // Máximo 20 páginas (10,000 memos) para evitar fetch infinito
5
+ // Sweep periódico del cache
6
+ setInterval(() => {
7
+ const now = Date.now();
8
+ for (const [key, entry] of tagsCache) {
9
+ if (now - entry.timestamp > TAGS_CACHE_TTL_MS) {
10
+ tagsCache.delete(key);
11
+ }
12
+ }
13
+ }, 30_000);
14
+ function getCachedTags(key) {
15
+ const entry = tagsCache.get(key);
16
+ if (!entry)
17
+ return null;
18
+ if (Date.now() - entry.timestamp > TAGS_CACHE_TTL_MS) {
19
+ tagsCache.delete(key);
20
+ return null;
21
+ }
22
+ return entry.tagCounts;
23
+ }
24
+ function setCachedTags(key, tagCounts) {
25
+ tagsCache.set(key, { tagCounts, timestamp: Date.now() });
26
+ }
27
+ function hasChildTags(allTags, tagName) {
28
+ const prefix = tagName + "/";
29
+ for (const tag of allTags) {
30
+ if (tag.startsWith(prefix) && tag !== tagName)
31
+ return true;
32
+ }
33
+ return false;
34
+ }
35
+ function getTopLevelTags(tagCounts) {
36
+ const allTags = new Set(tagCounts.keys());
37
+ const result = [];
38
+ for (const [name, count] of tagCounts) {
39
+ if (!name.includes("/")) {
40
+ result.push({ name, count, hasChildren: hasChildTags(allTags, name) });
41
+ }
42
+ }
43
+ return result.sort((a, b) => b.count - a.count || a.name.localeCompare(b.name));
44
+ }
45
+ function getChildTags(tagCounts, parent) {
46
+ const allTags = new Set(tagCounts.keys());
47
+ const prefix = parent + "/";
48
+ const result = [];
49
+ const seen = new Set();
50
+ for (const tag of allTags) {
51
+ if (tag.startsWith(prefix) && tag !== parent) {
52
+ const remainder = tag.slice(prefix.length);
53
+ const firstChild = remainder.split("/")[0];
54
+ const childTag = prefix + firstChild;
55
+ if (!seen.has(childTag)) {
56
+ seen.add(childTag);
57
+ let totalCount = 0;
58
+ for (const t of allTags) {
59
+ if (t === childTag || t.startsWith(childTag + "/")) {
60
+ totalCount += tagCounts.get(t) || 0;
61
+ }
62
+ }
63
+ result.push({
64
+ name: childTag,
65
+ count: totalCount,
66
+ hasChildren: hasChildTags(allTags, childTag),
67
+ });
68
+ }
69
+ }
70
+ }
71
+ return result.sort((a, b) => b.count - a.count || a.name.localeCompare(b.name));
72
+ }
73
+ function getAllTags(tagCounts) {
74
+ const allTagNames = new Set(tagCounts.keys());
75
+ const result = [];
76
+ for (const [name, count] of tagCounts) {
77
+ result.push({
78
+ name,
79
+ count,
80
+ hasChildren: name.includes("/") ? false : hasChildTags(allTagNames, name),
81
+ });
82
+ }
83
+ return result.sort((a, b) => b.count - a.count || a.name.localeCompare(b.name));
84
+ }
85
+ // Fetch tags del usuario con cache y límite de páginas
86
+ async function fetchTagsForUser(client) {
87
+ const currentUser = await client.getCurrentUser();
88
+ const cacheKey = `tags:${currentUser}`;
89
+ const cached = getCachedTags(cacheKey);
90
+ if (cached)
91
+ return cached;
92
+ const tagCounts = new Map();
93
+ let pageToken;
94
+ let pageCount = 0;
95
+ do {
96
+ const params = {
97
+ pageSize: "500",
98
+ filter: `creator == "${currentUser}"`,
99
+ };
100
+ if (pageToken)
101
+ params.pageToken = pageToken;
102
+ const result = await client.get("/api/v1/memos", params);
103
+ if (result.memos) {
104
+ for (const memo of result.memos) {
105
+ for (const tag of memo.tags ?? []) {
106
+ tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1);
107
+ }
108
+ }
109
+ }
110
+ pageToken = result.nextPageToken;
111
+ pageCount++;
112
+ // Límite de seguridad para evitar fetch infinito
113
+ if (pageCount >= TAGS_MAX_PAGES)
114
+ break;
115
+ } while (pageToken);
116
+ setCachedTags(cacheKey, tagCounts);
117
+ return tagCounts;
118
+ }
119
+ export const registerTagTools = (server, client) => {
120
+ server.registerTool("tags", {
121
+ description: [
122
+ "List tags with usage counts extracted from your memo content.",
123
+ "Tags are hashtags like #project or #work/meeting in your memos.",
124
+ "Results are cached for 60 seconds.",
125
+ "",
126
+ "Usage modes:",
127
+ "- No args: top-level tags only (e.g. 'project', 'work')",
128
+ "- parent='work': children of 'work' (e.g. 'work/meeting', 'work/notes')",
129
+ "- recursive=true: all tags flat (useful for tag recommendations)",
130
+ ].join("\n"),
131
+ inputSchema: {
132
+ parent: z.string().optional().describe("Parent tag to filter children. E.g. 'project' to see 'project/backend', 'project/frontend'"),
133
+ recursive: z.boolean().optional().describe("Return ALL tags including nested ones"),
134
+ },
135
+ annotations: { readOnlyHint: true, openWorldHint: false },
136
+ }, async ({ parent, recursive }) => {
137
+ const tagCounts = await fetchTagsForUser(client);
138
+ if (tagCounts.size === 0) {
139
+ return {
140
+ content: [{ type: "text", text: "No tags found in your memos." }],
141
+ };
142
+ }
143
+ let results;
144
+ if (recursive) {
145
+ results = getAllTags(tagCounts);
146
+ }
147
+ else if (parent) {
148
+ results = getChildTags(tagCounts, parent);
149
+ }
150
+ else {
151
+ results = getTopLevelTags(tagCounts);
152
+ }
153
+ if (results.length === 0) {
154
+ const msg = parent
155
+ ? `No child tags found under "${parent}".`
156
+ : "No tags found.";
157
+ return { content: [{ type: "text", text: msg }] };
158
+ }
159
+ return {
160
+ content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
161
+ };
162
+ });
163
+ };
164
+ //# sourceMappingURL=tags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tags.js","sourceRoot":"","sources":["../../src/tools/tags.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgBxB,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0B,CAAC;AACpD,MAAM,iBAAiB,GAAG,MAAM,CAAC,CAAC,WAAW;AAC7C,MAAM,cAAc,GAAG,EAAE,CAAC,CAAC,8DAA8D;AAEzF,4BAA4B;AAC5B,WAAW,CAAC,GAAG,EAAE;IACf,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;QACrC,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,GAAG,iBAAiB,EAAE,CAAC;YAC9C,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;AACH,CAAC,EAAE,MAAM,CAAC,CAAC;AAEX,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,GAAG,iBAAiB,EAAE,CAAC;QACrD,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC,SAAS,CAAC;AACzB,CAAC;AAED,SAAS,aAAa,CAAC,GAAW,EAAE,SAA8B;IAChE,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,YAAY,CAAC,OAAoB,EAAE,OAAe;IACzD,MAAM,MAAM,GAAG,OAAO,GAAG,GAAG,CAAC;IAC7B,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,GAAG,KAAK,OAAO;YAAE,OAAO,IAAI,CAAC;IAC7D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,eAAe,CAAC,SAA8B;IACrD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAc,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAClF,CAAC;AAED,SAAS,YAAY,CAAC,SAA8B,EAAE,MAAc;IAClE,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC;IAC5B,MAAM,MAAM,GAAc,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YAC7C,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC3C,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3C,MAAM,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;YAErC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACxB,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACnB,IAAI,UAAU,GAAG,CAAC,CAAC;gBACnB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;oBACxB,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAC,EAAE,CAAC;wBACnD,UAAU,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBACtC,CAAC;gBACH,CAAC;gBACD,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,QAAQ;oBACd,KAAK,EAAE,UAAU;oBACjB,WAAW,EAAE,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC;iBAC7C,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAClF,CAAC;AAED,SAAS,UAAU,CAAC,SAA8B;IAChD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAc,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;QACtC,MAAM,CAAC,IAAI,CAAC;YACV,IAAI;YACJ,KAAK;YACL,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC;SAC1E,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAClF,CAAC;AAED,uDAAuD;AACvD,KAAK,UAAU,gBAAgB,CAAC,MAAmB;IACjD,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,cAAc,EAAE,CAAC;IAClD,MAAM,QAAQ,GAAG,QAAQ,WAAW,EAAE,CAAC;IAEvC,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,IAAI,SAA6B,CAAC;IAClC,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,GAAG,CAAC;QACF,MAAM,MAAM,GAA2B;YACrC,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,eAAe,WAAW,GAAG;SACtC,CAAC;QACF,IAAI,SAAS;YAAE,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;QAE5C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAC7B,eAAe,EACf,MAAM,CACP,CAAC;QAEF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBAChC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;oBAClC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACpD,CAAC;YACH,CAAC;QACH,CAAC;QAED,SAAS,GAAG,MAAM,CAAC,aAAa,CAAC;QACjC,SAAS,EAAE,CAAC;QAEZ,iDAAiD;QACjD,IAAI,SAAS,IAAI,cAAc;YAAE,MAAM;IACzC,CAAC,QAAQ,SAAS,EAAE;IAEpB,aAAa,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACnC,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAiB,EAAE,MAAmB,EAAE,EAAE;IACzE,MAAM,CAAC,YAAY,CACjB,MAAM,EACN;QACE,WAAW,EAAE;YACX,+DAA+D;YAC/D,iEAAiE;YACjE,oCAAoC;YACpC,EAAE;YACF,cAAc;YACd,yDAAyD;YACzD,yEAAyE;YACzE,kEAAkE;SACnE,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,WAAW,EAAE;YACX,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4FAA4F,CAAC;YACpI,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;SACpF;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KAC1D,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE;QAC9B,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAEjD,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,8BAA8B,EAAE,CAAC;aAC3E,CAAC;QACJ,CAAC;QAED,IAAI,OAAkB,CAAC;QAEvB,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QAClC,CAAC;aAAM,IAAI,MAAM,EAAE,CAAC;YAClB,OAAO,GAAG,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QACvC,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,MAAM;gBAChB,CAAC,CAAC,8BAA8B,MAAM,IAAI;gBAC1C,CAAC,CAAC,gBAAgB,CAAC;YACrB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;QAC7D,CAAC;QAED,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC7E,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { MemosClient } from "../client.js";
2
+ export declare const SNIPPET_MAX_LENGTH = 200;
3
+ export declare function compactProperty(property: Record<string, unknown> | undefined): Record<string, unknown> | undefined;
4
+ export declare function summarizeMemo(memo: Record<string, unknown>): Record<string, unknown>;
5
+ export declare function resolveToMemoId(client: MemosClient, id: string): Promise<string>;
6
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/tools/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,uCAQ5E;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,2BAuC1D;AAID,wBAAsB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAetF"}
@@ -0,0 +1,68 @@
1
+ export const SNIPPET_MAX_LENGTH = 200;
2
+ export function compactProperty(property) {
3
+ if (!property)
4
+ return undefined;
5
+ const truthy = {};
6
+ for (const [k, v] of Object.entries(property)) {
7
+ // Only include truthy properties to reduce noise
8
+ if (v)
9
+ truthy[k] = v;
10
+ }
11
+ return Object.keys(truthy).length > 0 ? truthy : undefined;
12
+ }
13
+ export function summarizeMemo(memo) {
14
+ // Usar el snippet del memo si existe, de lo contrario generar uno del contenido
15
+ let snippet = memo.snippet;
16
+ if (!snippet) {
17
+ const content = memo.content || "";
18
+ snippet = content.length > SNIPPET_MAX_LENGTH
19
+ ? content.slice(0, SNIPPET_MAX_LENGTH) + "..."
20
+ : content;
21
+ }
22
+ const name = memo.name;
23
+ // Extract UID from name field (format: "memos/uid")
24
+ const uid = name?.match(/^memos\/(.+)$/)?.[1] || "";
25
+ const summary = {
26
+ name: name,
27
+ uid: uid,
28
+ createTime: memo.createTime,
29
+ snippet,
30
+ tags: memo.tags,
31
+ visibility: memo.visibility,
32
+ };
33
+ if (memo.updateTime && memo.updateTime !== memo.createTime) {
34
+ summary.updateTime = memo.updateTime;
35
+ }
36
+ if (memo.pinned)
37
+ summary.pinned = true;
38
+ const property = compactProperty(memo.property);
39
+ if (property)
40
+ summary.property = property;
41
+ // Include attachments count if present
42
+ const attachments = memo.attachments;
43
+ if (Array.isArray(attachments) && attachments.length > 0) {
44
+ summary.attachmentsCount = attachments.length;
45
+ }
46
+ return summary;
47
+ }
48
+ // Resolver un memo ID a su identifier usable en la API
49
+ // Memos 0.29.1 usa UIDs (memos/abc123) en vez de IDs numéricos
50
+ export async function resolveToMemoId(client, id) {
51
+ // Si ya es numérico, usarlo directo
52
+ if (/^\d+$/.test(id)) {
53
+ return id;
54
+ }
55
+ // Si ya parece un UID (letras + números, largo > 5), usarlo directo
56
+ if (/^[a-zA-Z0-9_-]{6,}$/.test(id)) {
57
+ return id;
58
+ }
59
+ // Intentar buscar por el path completo
60
+ const memo = await client.get(`/api/v1/memos/${id}`);
61
+ if (!memo?.name)
62
+ throw new Error(`Memo not found: ${id}`);
63
+ const match = memo.name.match(/^memos\/(.+)$/);
64
+ if (!match)
65
+ throw new Error(`Unexpected memo name format: ${memo.name}`);
66
+ return match[1];
67
+ }
68
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/tools/utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ export declare const VALID_VISIBILITIES: readonly ["PRIVATE", "PROTECTED", "PUBLIC"];
2
+ export type Visibility = (typeof VALID_VISIBILITIES)[number];
3
+ export interface Attachment {
4
+ name: string;
5
+ filename: string;
6
+ type: string;
7
+ size: string;
8
+ createTime: string;
9
+ externalLink?: string;
10
+ uiResourcePath?: string;
11
+ }
12
+ export interface Memo {
13
+ name: string;
14
+ uid: string;
15
+ rowStatus: string;
16
+ creator: string;
17
+ createTime: string;
18
+ updateTime: string;
19
+ content: string;
20
+ visibility: Visibility;
21
+ tags: string[];
22
+ pinned: boolean;
23
+ attachments: Attachment[];
24
+ relations: unknown[];
25
+ reactions: unknown[];
26
+ property?: MemoProperty;
27
+ parent?: string;
28
+ snippet?: string;
29
+ }
30
+ export interface MemoProperty {
31
+ hasLink: boolean;
32
+ hasTaskList: boolean;
33
+ hasCode: boolean;
34
+ hasIncompleteTasks: boolean;
35
+ }
36
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,6CAA8C,CAAC;AAC9E,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,SAAS,EAAE,OAAO,EAAE,CAAC;IACrB,SAAS,EAAE,OAAO,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,EAAE,OAAO,CAAC;CAC7B"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export const VALID_VISIBILITIES = ["PRIVATE", "PROTECTED", "PUBLIC"];
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAU,CAAC"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "mcp-for-memos",
3
+ "version": "1.0.0",
4
+ "description": "MCP server that turns Memos into a multi-purpose database for AI — notes, projects, tasks, agendas, knowledge base. Supports HTTP/SSE multi-tenant access.",
5
+ "type": "module",
6
+ "bin": {
7
+ "mcp-for-memos": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "dev": "tsx src/index.ts",
15
+ "dev:http": "tsx src/index.ts --http",
16
+ "start": "node dist/index.js",
17
+ "start:http": "node dist/index.js --http",
18
+ "prepublishOnly": "tsc"
19
+ },
20
+ "keywords": [
21
+ "mcp",
22
+ "model-context-protocol",
23
+ "memos",
24
+ "note-taking",
25
+ "sse",
26
+ "http",
27
+ "multi-tenant"
28
+ ],
29
+ "author": "guzman-lopez",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/CesarGuzmanLopez/memos-mcp.git"
34
+ },
35
+ "dependencies": {
36
+ "@modelcontextprotocol/sdk": "^1.29.0",
37
+ "express": "^5.2.1",
38
+ "zod": "^4.3.6"
39
+ },
40
+ "devDependencies": {
41
+ "@types/express": "^5.0.6",
42
+ "@types/node": "^25.9.2",
43
+ "tsx": "^4.22.4",
44
+ "typescript": "^6.0.3"
45
+ },
46
+ "engines": {
47
+ "node": ">=18.0.0"
48
+ }
49
+ }