@chriscurrycc/memos-mcp 0.1.1 → 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.
- package/README.md +47 -47
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +105 -30
- package/dist/prompts/index.js.map +1 -1
- package/dist/resources/index.d.ts.map +1 -1
- package/dist/resources/index.js +4 -5
- package/dist/resources/index.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +8 -9
- package/dist/server.js.map +1 -1
- package/dist/tools/memos.d.ts +6 -1
- package/dist/tools/memos.d.ts.map +1 -1
- package/dist/tools/memos.js +165 -54
- package/dist/tools/memos.js.map +1 -1
- package/dist/tools/relations.d.ts.map +1 -1
- package/dist/tools/relations.js +116 -31
- package/dist/tools/relations.js.map +1 -1
- package/dist/tools/resources.d.ts.map +1 -1
- package/dist/tools/resources.js +78 -17
- package/dist/tools/resources.js.map +1 -1
- package/dist/tools/review.d.ts.map +1 -1
- package/dist/tools/review.js +81 -52
- package/dist/tools/review.js.map +1 -1
- package/dist/tools/tags.d.ts.map +1 -1
- package/dist/tools/tags.js +136 -13
- package/dist/tools/tags.js.map +1 -1
- package/dist/tools/utils.d.ts +4 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +34 -0
- package/dist/tools/utils.js.map +1 -0
- package/dist/types.d.ts +6 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/tools/memos.js
CHANGED
|
@@ -1,59 +1,152 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
2
|
+
import { summarizeMemo } from "./utils.js";
|
|
3
|
+
function parseToUnixTimestamp(isoString, paramName) {
|
|
4
|
+
const date = new Date(isoString);
|
|
5
|
+
if (isNaN(date.getTime())) {
|
|
6
|
+
throw new Error(`Invalid date format for ${paramName}. Use ISO 8601 format (e.g., "2025-01-01" or "2025-01-01T00:00:00Z").`);
|
|
7
|
+
}
|
|
8
|
+
return Math.floor(date.getTime() / 1000);
|
|
9
|
+
}
|
|
10
|
+
function buildCelFilter(opts) {
|
|
11
|
+
const parts = [`creator == "${opts.creator}"`];
|
|
12
|
+
if (opts.query) {
|
|
13
|
+
const escaped = opts.query.replace(/"/g, '\\"');
|
|
14
|
+
parts.push(`content_search == ["${escaped}"]`);
|
|
15
|
+
}
|
|
16
|
+
if (opts.tags?.length) {
|
|
17
|
+
const tagList = opts.tags.map((t) => `"${t.replace(/"/g, '\\"')}"`).join(", ");
|
|
18
|
+
parts.push(`tag_search == [${tagList}]`);
|
|
19
|
+
}
|
|
20
|
+
if (opts.visibility?.length) {
|
|
21
|
+
const visList = opts.visibility.map((v) => `"${v}"`).join(", ");
|
|
22
|
+
parts.push(`visibilities == [${visList}]`);
|
|
23
|
+
}
|
|
24
|
+
if (opts.state) {
|
|
25
|
+
parts.push(`row_status == "${opts.state === "ARCHIVED" ? "ARCHIVED" : "ACTIVE"}"`);
|
|
26
|
+
}
|
|
27
|
+
if (opts.pinned !== undefined) {
|
|
28
|
+
parts.push(`pinned == ${opts.pinned}`);
|
|
29
|
+
}
|
|
30
|
+
if (opts.startDate) {
|
|
31
|
+
parts.push(`display_time_after == ${parseToUnixTimestamp(opts.startDate, "startDate")}`);
|
|
32
|
+
}
|
|
33
|
+
if (opts.endDate) {
|
|
34
|
+
parts.push(`display_time_before == ${parseToUnixTimestamp(opts.endDate, "endDate")}`);
|
|
35
|
+
}
|
|
36
|
+
if (opts.hasLink)
|
|
37
|
+
parts.push(`has_link == true`);
|
|
38
|
+
if (opts.hasTaskList)
|
|
39
|
+
parts.push(`has_task_list == true`);
|
|
40
|
+
if (opts.hasCode)
|
|
41
|
+
parts.push(`has_code == true`);
|
|
42
|
+
if (opts.hasIncompleteTasks)
|
|
43
|
+
parts.push(`has_incomplete_tasks == true`);
|
|
44
|
+
if (opts.random)
|
|
45
|
+
parts.push(`random == true`);
|
|
46
|
+
return parts.join(" && ");
|
|
47
|
+
}
|
|
48
|
+
async function resolveToNumericId(client, id) {
|
|
49
|
+
if (/^\d+$/.test(id)) {
|
|
50
|
+
return parseInt(id, 10);
|
|
51
|
+
}
|
|
52
|
+
const memo = await client.get(`/api/v1/memos:by-uid/${id}`);
|
|
53
|
+
const match = memo.name.match(/^memos\/(\d+)$/);
|
|
54
|
+
if (!match)
|
|
55
|
+
throw new Error(`Unexpected memo name format: ${memo.name}`);
|
|
56
|
+
return parseInt(match[1], 10);
|
|
57
|
+
}
|
|
58
|
+
function cleanMemo(memo) {
|
|
59
|
+
const { name, nodes, snippet, creator, ...rest } = memo;
|
|
60
|
+
const id = name?.match(/^memos\/(\d+)$/)?.[1];
|
|
61
|
+
if (id)
|
|
62
|
+
rest.id = Number(id);
|
|
63
|
+
for (const key of ["resources", "relations", "reactions"]) {
|
|
64
|
+
if (Array.isArray(rest[key]) && rest[key].length === 0) {
|
|
65
|
+
delete rest[key];
|
|
20
66
|
}
|
|
21
|
-
|
|
67
|
+
}
|
|
68
|
+
return rest;
|
|
69
|
+
}
|
|
70
|
+
export const registerMemoTools = (server, client, options) => {
|
|
71
|
+
const visibilityEnum = z.enum(["PRIVATE", "PROTECTED", "PUBLIC"]);
|
|
72
|
+
server.registerTool("list_memos", {
|
|
73
|
+
description: "Search and list memos. All filters are optional and combined with AND logic.",
|
|
74
|
+
inputSchema: {
|
|
75
|
+
query: z.string().optional().describe("Keyword search in memo content"),
|
|
76
|
+
tags: z.array(z.string()).optional().describe("Filter by tags, e.g. [\"project\", \"todo\"]"),
|
|
77
|
+
visibility: z.array(visibilityEnum).optional().describe("Filter by visibility levels"),
|
|
78
|
+
state: z.enum(["NORMAL", "ARCHIVED"]).optional().describe("Filter by memo state"),
|
|
79
|
+
pinned: z.boolean().optional().describe("Filter by pinned status"),
|
|
80
|
+
startDate: z.string().optional().describe("Return memos after this date (ISO 8601, e.g. \"2025-01-01\")"),
|
|
81
|
+
endDate: z.string().optional().describe("Return memos before this date (ISO 8601, e.g. \"2025-03-01\")"),
|
|
82
|
+
hasLink: z.boolean().optional().describe("Filter to memos containing links"),
|
|
83
|
+
hasTaskList: z.boolean().optional().describe("Filter to memos containing task lists"),
|
|
84
|
+
hasCode: z.boolean().optional().describe("Filter to memos containing code blocks"),
|
|
85
|
+
hasIncompleteTasks: z.boolean().optional().describe("Filter to memos with incomplete tasks"),
|
|
86
|
+
random: z.boolean().optional().describe("Return results in random order"),
|
|
87
|
+
pageSize: z.number().int().min(1).max(100).default(20).describe("Number of memos per page"),
|
|
88
|
+
pageToken: z.string().optional().describe("Token for fetching the next page"),
|
|
89
|
+
},
|
|
90
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
91
|
+
}, async (args) => {
|
|
92
|
+
const currentUser = await client.getCurrentUser();
|
|
93
|
+
const filter = buildCelFilter({ creator: currentUser, ...args });
|
|
94
|
+
const params = {
|
|
95
|
+
pageSize: String(args.pageSize),
|
|
96
|
+
filter,
|
|
97
|
+
};
|
|
98
|
+
if (args.pageToken)
|
|
99
|
+
params.pageToken = args.pageToken;
|
|
22
100
|
const result = await client.get("/api/v1/memos", params);
|
|
23
|
-
|
|
101
|
+
const summaries = (result.memos || []).map((m) => summarizeMemo(m));
|
|
102
|
+
const output = { memos: summaries };
|
|
103
|
+
if (result.nextPageToken)
|
|
104
|
+
output.nextPageToken = result.nextPageToken;
|
|
105
|
+
return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }] };
|
|
24
106
|
});
|
|
25
|
-
server.
|
|
26
|
-
|
|
107
|
+
server.registerTool("get_memo", {
|
|
108
|
+
description: "Get a single memo by its numeric ID or UID string (the ID from the memo URL).",
|
|
109
|
+
inputSchema: {
|
|
110
|
+
id: z.string().min(1).describe("Memo identifier. Numeric ID (e.g. \"42\") or UID string (e.g. \"AjF4AQJayxvDj2mrWzFWuP\")"),
|
|
111
|
+
},
|
|
112
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
27
113
|
}, async ({ id }) => {
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}, async ({ query, pageSize }) => {
|
|
35
|
-
const currentUser = await client.getCurrentUser();
|
|
36
|
-
const filter = `creator == "${currentUser}" && content_search == ["${query.replace(/"/g, '\\"')}"]`;
|
|
37
|
-
const result = await client.get("/api/v1/memos", {
|
|
38
|
-
pageSize: String(pageSize),
|
|
39
|
-
filter,
|
|
40
|
-
});
|
|
41
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
114
|
+
const path = /^\d+$/.test(id)
|
|
115
|
+
? `/api/v1/memos/${id}`
|
|
116
|
+
: `/api/v1/memos:by-uid/${id}`;
|
|
117
|
+
const memo = await client.get(path);
|
|
118
|
+
const cleaned = cleanMemo(memo);
|
|
119
|
+
return { content: [{ type: "text", text: JSON.stringify(cleaned, null, 2) }] };
|
|
42
120
|
});
|
|
43
|
-
server.
|
|
44
|
-
|
|
45
|
-
|
|
121
|
+
server.registerTool("create_memo", {
|
|
122
|
+
description: "Create a new memo with markdown content.",
|
|
123
|
+
inputSchema: {
|
|
124
|
+
content: z.string().min(1).describe("Memo content in markdown. Tags can be included with #tagname syntax"),
|
|
125
|
+
visibility: visibilityEnum.optional().describe("Memo visibility. Omit to use the configured default"),
|
|
126
|
+
},
|
|
127
|
+
annotations: { destructiveHint: false, openWorldHint: false },
|
|
46
128
|
}, async ({ content, visibility }) => {
|
|
47
|
-
const memo = await client.post("/api/v1/memos", {
|
|
48
|
-
|
|
129
|
+
const memo = await client.post("/api/v1/memos", {
|
|
130
|
+
content,
|
|
131
|
+
visibility: visibility ?? options.defaultVisibility,
|
|
132
|
+
});
|
|
133
|
+
const id = memo.name?.match(/^memos\/(\d+)$/)?.[1];
|
|
134
|
+
const result = { id: id ? Number(id) : undefined, uid: memo.uid, visibility: memo.visibility };
|
|
135
|
+
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
49
136
|
});
|
|
50
|
-
server.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
137
|
+
server.registerTool("update_memo", {
|
|
138
|
+
description: "Update an existing memo. Only the fields you provide will be modified.",
|
|
139
|
+
inputSchema: {
|
|
140
|
+
id: z.string().min(1).describe("Memo identifier. Numeric ID or UID string"),
|
|
141
|
+
content: z.string().optional().describe("New memo content in markdown"),
|
|
142
|
+
visibility: visibilityEnum.optional().describe("New visibility level"),
|
|
143
|
+
pinned: z.boolean().optional().describe("Pin or unpin the memo"),
|
|
144
|
+
state: z.enum(["NORMAL", "ARCHIVED"]).optional().describe("Set to ARCHIVED to archive, NORMAL to restore"),
|
|
145
|
+
preserveUpdateTime: z.boolean().optional().describe("When true, the memo's update time will not change. Use for formatting or style-only edits"),
|
|
146
|
+
},
|
|
147
|
+
annotations: { destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
148
|
+
}, async ({ id, content, visibility, pinned, state, preserveUpdateTime }) => {
|
|
149
|
+
const numericId = await resolveToNumericId(client, id);
|
|
57
150
|
const body = {};
|
|
58
151
|
const updateMaskPaths = [];
|
|
59
152
|
if (content !== undefined) {
|
|
@@ -72,15 +165,33 @@ export const registerMemoTools = (server, client) => {
|
|
|
72
165
|
body.rowStatus = state === "ARCHIVED" ? "ARCHIVED" : "ACTIVE";
|
|
73
166
|
updateMaskPaths.push("row_status");
|
|
74
167
|
}
|
|
75
|
-
|
|
168
|
+
if (updateMaskPaths.length === 0) {
|
|
169
|
+
return {
|
|
170
|
+
content: [
|
|
171
|
+
{
|
|
172
|
+
type: "text",
|
|
173
|
+
text: "No fields to update. Provide at least one of: content, visibility, pinned, state.",
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
const params = {
|
|
76
179
|
updateMask: updateMaskPaths.join(","),
|
|
77
|
-
}
|
|
78
|
-
|
|
180
|
+
};
|
|
181
|
+
if (preserveUpdateTime)
|
|
182
|
+
params.preserveUpdateTime = "true";
|
|
183
|
+
await client.patch(`/api/v1/memos/${numericId}`, body, params);
|
|
184
|
+
return { content: [{ type: "text", text: `Memo ${id} updated.` }] };
|
|
79
185
|
});
|
|
80
|
-
server.
|
|
81
|
-
|
|
186
|
+
server.registerTool("delete_memo", {
|
|
187
|
+
description: "Permanently delete a memo. This action cannot be undone.",
|
|
188
|
+
inputSchema: {
|
|
189
|
+
id: z.string().min(1).describe("Memo identifier. Numeric ID or UID string"),
|
|
190
|
+
},
|
|
191
|
+
annotations: { destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
82
192
|
}, async ({ id }) => {
|
|
83
|
-
await client
|
|
193
|
+
const numericId = await resolveToNumericId(client, id);
|
|
194
|
+
await client.delete(`/api/v1/memos/${numericId}`);
|
|
84
195
|
return { content: [{ type: "text", text: `Memo ${id} deleted.` }] };
|
|
85
196
|
});
|
|
86
197
|
};
|
package/dist/tools/memos.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memos.js","sourceRoot":"","sources":["../../src/tools/memos.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"memos.js","sourceRoot":"","sources":["../../src/tools/memos.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relations.d.ts","sourceRoot":"","sources":["../../src/tools/relations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"relations.d.ts","sourceRoot":"","sources":["../../src/tools/relations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAiE3C,eAAO,MAAM,qBAAqB,GAAI,QAAQ,SAAS,EAAE,QAAQ,WAAW,SAiG3E,CAAC"}
|
package/dist/tools/relations.js
CHANGED
|
@@ -1,40 +1,125 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
2
|
+
async function resolveToNumericId(client, id) {
|
|
3
|
+
if (/^\d+$/.test(id)) {
|
|
4
|
+
return parseInt(id, 10);
|
|
5
|
+
}
|
|
6
|
+
const memo = await client.get(`/api/v1/memos:by-uid/${id}`);
|
|
7
|
+
const match = memo.name.match(/^memos\/(\d+)$/);
|
|
8
|
+
if (!match)
|
|
9
|
+
throw new Error(`Unexpected memo name format: ${memo.name}`);
|
|
10
|
+
return parseInt(match[1], 10);
|
|
11
|
+
}
|
|
12
|
+
function extractId(memoRef) {
|
|
13
|
+
const name = typeof memoRef === "string" ? memoRef : memoRef?.name;
|
|
14
|
+
if (!name || typeof name !== "string")
|
|
15
|
+
return undefined;
|
|
16
|
+
const match = name.match(/^memos\/(\d+)$/);
|
|
17
|
+
return match ? parseInt(match[1], 10) : undefined;
|
|
18
|
+
}
|
|
19
|
+
async function buildRelationGraph(client, startId, maxDepth) {
|
|
20
|
+
const visited = new Set();
|
|
21
|
+
const edges = [];
|
|
22
|
+
const edgeSet = new Set();
|
|
23
|
+
const queue = [{ id: startId, depth: 0 }];
|
|
24
|
+
while (queue.length > 0) {
|
|
25
|
+
const { id, depth } = queue.shift();
|
|
26
|
+
if (visited.has(id))
|
|
27
|
+
continue;
|
|
28
|
+
visited.add(id);
|
|
6
29
|
const result = await client.get(`/api/v1/memos/${id}/relations`);
|
|
7
|
-
|
|
30
|
+
for (const r of result.relations || []) {
|
|
31
|
+
const fromId = extractId(r.memo);
|
|
32
|
+
const toId = extractId(r.relatedMemo);
|
|
33
|
+
if (fromId === undefined || toId === undefined)
|
|
34
|
+
continue;
|
|
35
|
+
const edgeKey = `${fromId}->${toId}:${r.type}`;
|
|
36
|
+
if (edgeSet.has(edgeKey))
|
|
37
|
+
continue;
|
|
38
|
+
edgeSet.add(edgeKey);
|
|
39
|
+
edges.push({ from: fromId, to: toId, type: r.type });
|
|
40
|
+
const neighborId = fromId === id ? toId : fromId;
|
|
41
|
+
if (depth < maxDepth && !visited.has(neighborId)) {
|
|
42
|
+
queue.push({ id: neighborId, depth: depth + 1 });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { nodes: [...visited], edges };
|
|
47
|
+
}
|
|
48
|
+
export const registerRelationTools = (server, client) => {
|
|
49
|
+
server.registerTool("list_memo_relations", {
|
|
50
|
+
description: [
|
|
51
|
+
"List relations of a memo. Returns edges with direction (from → to) and type.",
|
|
52
|
+
"- depth=1 (default): direct relations only.",
|
|
53
|
+
"- depth=2+: recursively expand related memos to build a relation graph.",
|
|
54
|
+
"Each edge shows {from, to, type}. Use get_memo to inspect specific nodes.",
|
|
55
|
+
].join(" "),
|
|
56
|
+
inputSchema: {
|
|
57
|
+
id: z.string().min(1).describe("Memo identifier. Numeric ID or UID string"),
|
|
58
|
+
depth: z.number().int().min(1).max(5).default(1).describe("How many levels deep to traverse. 1 = direct relations, 2+ = recursive graph"),
|
|
59
|
+
},
|
|
60
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
61
|
+
}, async ({ id, depth }) => {
|
|
62
|
+
const numericId = await resolveToNumericId(client, id);
|
|
63
|
+
const { nodes, edges } = await buildRelationGraph(client, numericId, depth);
|
|
64
|
+
if (edges.length === 0) {
|
|
65
|
+
return { content: [{ type: "text", text: "No relations found." }] };
|
|
66
|
+
}
|
|
67
|
+
const output = {
|
|
68
|
+
startNode: numericId,
|
|
69
|
+
nodes,
|
|
70
|
+
edges,
|
|
71
|
+
};
|
|
72
|
+
return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }] };
|
|
8
73
|
});
|
|
9
|
-
server.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
74
|
+
server.registerTool("set_memo_relations", {
|
|
75
|
+
description: [
|
|
76
|
+
"Add or remove REFERENCE relations for a memo.",
|
|
77
|
+
"- action=\"add\": add new references without affecting existing ones.",
|
|
78
|
+
"- action=\"remove\": remove specific references.",
|
|
79
|
+
"Note: COMMENT relations are managed by the system and cannot be modified here.",
|
|
80
|
+
].join(" "),
|
|
81
|
+
inputSchema: {
|
|
82
|
+
id: z.string().min(1).describe("Memo identifier. Numeric ID or UID string"),
|
|
83
|
+
action: z.enum(["add", "remove"]).describe("Whether to add or remove relations"),
|
|
84
|
+
targetIds: z.array(z.string().min(1)).min(1).describe("IDs of memos to add/remove as references. Numeric IDs or UID strings"),
|
|
85
|
+
},
|
|
86
|
+
annotations: { destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
87
|
+
}, async ({ id, action, targetIds }) => {
|
|
88
|
+
const numericId = await resolveToNumericId(client, id);
|
|
89
|
+
const resolvedTargets = await Promise.all(targetIds.map((t) => resolveToNumericId(client, t)));
|
|
90
|
+
const current = await client.get(`/api/v1/memos/${numericId}/relations`);
|
|
91
|
+
const existing = (current.relations || []).filter((r) => extractId(r.memo) === numericId && r.type === "REFERENCE");
|
|
92
|
+
let finalIds;
|
|
93
|
+
if (action === "add") {
|
|
94
|
+
const existingIds = new Set(existing.map((r) => extractId(r.relatedMemo)));
|
|
95
|
+
finalIds = [
|
|
96
|
+
...existing.map((r) => extractId(r.relatedMemo)),
|
|
97
|
+
...resolvedTargets.filter((t) => !existingIds.has(t)),
|
|
98
|
+
];
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
const removeSet = new Set(resolvedTargets);
|
|
102
|
+
finalIds = existing
|
|
103
|
+
.map((r) => extractId(r.relatedMemo))
|
|
104
|
+
.filter((rid) => !removeSet.has(rid));
|
|
105
|
+
}
|
|
18
106
|
const body = {
|
|
19
|
-
relations:
|
|
20
|
-
memo: `memos/${
|
|
21
|
-
relatedMemo: `memos/${
|
|
22
|
-
type:
|
|
107
|
+
relations: finalIds.map((targetId) => ({
|
|
108
|
+
memo: { name: `memos/${numericId}` },
|
|
109
|
+
relatedMemo: { name: `memos/${targetId}` },
|
|
110
|
+
type: "REFERENCE",
|
|
23
111
|
})),
|
|
24
112
|
};
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const remaining = (current.relations || []).filter((r) => !(r.relatedMemo === `memos/${relatedMemoId}` && r.type === type));
|
|
36
|
-
const result = await client.patch(`/api/v1/memos/${id}/relations`, { relations: remaining });
|
|
37
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
113
|
+
await client.patch(`/api/v1/memos/${numericId}/relations`, body);
|
|
114
|
+
const verb = action === "add" ? "added" : "removed";
|
|
115
|
+
return {
|
|
116
|
+
content: [
|
|
117
|
+
{
|
|
118
|
+
type: "text",
|
|
119
|
+
text: `${resolvedTargets.length} reference(s) ${verb}. Memo ${id} now has ${finalIds.length} outgoing reference(s).`,
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
};
|
|
38
123
|
});
|
|
39
124
|
};
|
|
40
125
|
//# sourceMappingURL=relations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relations.js","sourceRoot":"","sources":["../../src/tools/relations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,
|
|
1
|
+
{"version":3,"file":"relations.js","sourceRoot":"","sources":["../../src/tools/relations.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../src/tools/resources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../src/tools/resources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAkB3C,eAAO,MAAM,qBAAqB,GAAI,QAAQ,SAAS,EAAE,QAAQ,WAAW,SAiE3E,CAAC"}
|
package/dist/tools/resources.js
CHANGED
|
@@ -1,28 +1,89 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
function summarizeResource(res) {
|
|
3
|
+
const name = res.name;
|
|
4
|
+
const id = name?.match(/^resources\/(\d+)$/)?.[1];
|
|
5
|
+
const summary = {
|
|
6
|
+
id: id ? Number(id) : undefined,
|
|
7
|
+
uid: res.uid,
|
|
8
|
+
filename: res.filename,
|
|
9
|
+
type: res.type,
|
|
10
|
+
size: res.size,
|
|
11
|
+
};
|
|
12
|
+
if (res.externalLink)
|
|
13
|
+
summary.externalLink = res.externalLink;
|
|
14
|
+
if (res.memo)
|
|
15
|
+
summary.memo = res.memo;
|
|
16
|
+
return summary;
|
|
17
|
+
}
|
|
2
18
|
export const registerResourceTools = (server, client) => {
|
|
3
|
-
server.
|
|
19
|
+
server.registerTool("list_resources", {
|
|
20
|
+
description: "List all resources (attachments) owned by the current user.",
|
|
21
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
22
|
+
}, async () => {
|
|
4
23
|
const result = await client.get("/api/v1/resources");
|
|
5
|
-
|
|
24
|
+
const summaries = (result.resources || []).map((r) => summarizeResource(r));
|
|
25
|
+
return { content: [{ type: "text", text: JSON.stringify(summaries, null, 2) }] };
|
|
6
26
|
});
|
|
7
|
-
server.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
27
|
+
server.registerTool("upload_resource", {
|
|
28
|
+
description: "Upload a file as a resource. The file content must be base64 encoded. Optionally link it to a memo.",
|
|
29
|
+
inputSchema: {
|
|
30
|
+
filename: z.string().min(1).describe("File name with extension, e.g. \"photo.jpg\""),
|
|
31
|
+
contentBase64: z.string().min(1).describe("File content as a base64 encoded string"),
|
|
32
|
+
type: z.string().optional().describe("MIME type, e.g. \"image/jpeg\". Auto-detected from extension if omitted"),
|
|
33
|
+
memoId: z.number().int().optional().describe("Memo ID to link this resource to"),
|
|
34
|
+
},
|
|
35
|
+
annotations: { destructiveHint: false, openWorldHint: false },
|
|
36
|
+
}, async ({ filename, contentBase64, type, memoId }) => {
|
|
37
|
+
const mimeType = type ?? guessMimeType(filename);
|
|
38
|
+
const body = {
|
|
39
|
+
filename,
|
|
40
|
+
content: contentBase64,
|
|
41
|
+
type: mimeType,
|
|
42
|
+
};
|
|
43
|
+
if (memoId !== undefined) {
|
|
44
|
+
body.memo = `memos/${memoId}`;
|
|
45
|
+
}
|
|
46
|
+
const resource = await client.post("/api/v1/resources", body);
|
|
47
|
+
const id = resource.name?.match(/^resources\/(\d+)$/)?.[1];
|
|
48
|
+
return {
|
|
49
|
+
content: [
|
|
50
|
+
{
|
|
51
|
+
type: "text",
|
|
52
|
+
text: `Resource uploaded: id=${id}, filename="${resource.filename}"`,
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
};
|
|
12
56
|
});
|
|
13
|
-
server.
|
|
14
|
-
|
|
57
|
+
server.registerTool("delete_resource", {
|
|
58
|
+
description: "Delete a resource permanently.",
|
|
59
|
+
inputSchema: {
|
|
60
|
+
id: z.number().int().describe("Resource ID"),
|
|
61
|
+
},
|
|
62
|
+
annotations: { destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
15
63
|
}, async ({ id }) => {
|
|
16
64
|
await client.delete(`/api/v1/resources/${id}`);
|
|
17
65
|
return { content: [{ type: "text", text: `Resource ${id} deleted.` }] };
|
|
18
66
|
});
|
|
19
|
-
server.tool("link_resource_to_memo", "Link resources to a memo", {
|
|
20
|
-
memoId: z.number().int().describe("Memo ID"),
|
|
21
|
-
resourceIds: z.array(z.number().int()).min(1).describe("Resource IDs to link"),
|
|
22
|
-
}, async ({ memoId, resourceIds }) => {
|
|
23
|
-
const resources = resourceIds.map((id) => ({ name: `resources/${id}` }));
|
|
24
|
-
const result = await client.patch(`/api/v1/memos/${memoId}/resources`, { resources });
|
|
25
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
26
|
-
});
|
|
27
67
|
};
|
|
68
|
+
const MIME_MAP = {
|
|
69
|
+
jpg: "image/jpeg",
|
|
70
|
+
jpeg: "image/jpeg",
|
|
71
|
+
png: "image/png",
|
|
72
|
+
gif: "image/gif",
|
|
73
|
+
webp: "image/webp",
|
|
74
|
+
svg: "image/svg+xml",
|
|
75
|
+
pdf: "application/pdf",
|
|
76
|
+
mp3: "audio/mpeg",
|
|
77
|
+
mp4: "video/mp4",
|
|
78
|
+
webm: "video/webm",
|
|
79
|
+
txt: "text/plain",
|
|
80
|
+
md: "text/markdown",
|
|
81
|
+
json: "application/json",
|
|
82
|
+
csv: "text/csv",
|
|
83
|
+
zip: "application/zip",
|
|
84
|
+
};
|
|
85
|
+
function guessMimeType(filename) {
|
|
86
|
+
const ext = filename.split(".").pop()?.toLowerCase() ?? "";
|
|
87
|
+
return MIME_MAP[ext] ?? "application/octet-stream";
|
|
88
|
+
}
|
|
28
89
|
//# sourceMappingURL=resources.js.map
|