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.
- package/README.md +334 -0
- package/dist/client.d.ts +15 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +155 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +18 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +27 -0
- package/dist/config.js.map +1 -0
- package/dist/http.d.ts +4 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +342 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +79 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/index.d.ts +3 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +68 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/resources/index.d.ts +4 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +52 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +40 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/memos.d.ts +9 -0
- package/dist/tools/memos.d.ts.map +1 -0
- package/dist/tools/memos.js +137 -0
- package/dist/tools/memos.js.map +1 -0
- package/dist/tools/relations.d.ts +4 -0
- package/dist/tools/relations.d.ts.map +1 -0
- package/dist/tools/relations.js +108 -0
- package/dist/tools/relations.js.map +1 -0
- package/dist/tools/resources.d.ts +4 -0
- package/dist/tools/resources.d.ts.map +1 -0
- package/dist/tools/resources.js +90 -0
- package/dist/tools/resources.js.map +1 -0
- package/dist/tools/review.d.ts +4 -0
- package/dist/tools/review.d.ts.map +1 -0
- package/dist/tools/review.js +208 -0
- package/dist/tools/review.js.map +1 -0
- package/dist/tools/tags.d.ts +4 -0
- package/dist/tools/tags.d.ts.map +1 -0
- package/dist/tools/tags.js +164 -0
- package/dist/tools/tags.js.map +1 -0
- package/dist/tools/utils.d.ts +6 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +68 -0
- package/dist/tools/utils.js.map +1 -0
- package/dist/types.d.ts +36 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +49 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { MemosClient } from "./client.js";
|
|
3
|
+
import { registerMemoTools } from "./tools/memos.js";
|
|
4
|
+
import { registerTagTools } from "./tools/tags.js";
|
|
5
|
+
import { registerSearchTool } from "./tools/review.js";
|
|
6
|
+
import { registerPrompts } from "./prompts/index.js";
|
|
7
|
+
import { VALID_VISIBILITIES } from "./types.js";
|
|
8
|
+
// Crear servidor con cliente inyectado (para HTTP multi-tenant)
|
|
9
|
+
export const createServerWithClient = (client, options = {}) => {
|
|
10
|
+
const defaultVisibility = options.defaultVisibility ?? "PRIVATE";
|
|
11
|
+
const server = new McpServer({
|
|
12
|
+
name: "memos-mcp",
|
|
13
|
+
version: "3.0.0",
|
|
14
|
+
});
|
|
15
|
+
registerMemoTools(server, client, { defaultVisibility });
|
|
16
|
+
registerTagTools(server, client);
|
|
17
|
+
registerSearchTool(server, client);
|
|
18
|
+
registerPrompts(server);
|
|
19
|
+
return server;
|
|
20
|
+
};
|
|
21
|
+
// Crear servidor con env vars (para stdio mode)
|
|
22
|
+
export const createServer = () => {
|
|
23
|
+
const memosUrl = process.env.MEMOS_URL;
|
|
24
|
+
const memosToken = process.env.MEMOS_TOKEN;
|
|
25
|
+
if (!memosUrl) {
|
|
26
|
+
console.error("Error: MEMOS_URL environment variable is required");
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
if (!memosToken) {
|
|
30
|
+
console.error("Error: MEMOS_TOKEN environment variable is required");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
const rawVisibility = process.env.MEMOS_DEFAULT_VISIBILITY?.toUpperCase();
|
|
34
|
+
const defaultVisibility = rawVisibility && VALID_VISIBILITIES.includes(rawVisibility)
|
|
35
|
+
? rawVisibility
|
|
36
|
+
: "PRIVATE";
|
|
37
|
+
const client = new MemosClient(memosUrl, memosToken);
|
|
38
|
+
return createServerWithClient(client, { defaultVisibility });
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAmB,MAAM,YAAY,CAAC;AAMjE,gEAAgE;AAChE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,MAAmB,EACnB,UAAyB,EAAE,EAC3B,EAAE;IACF,MAAM,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,IAAI,SAAS,CAAC;IAEjE,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,iBAAiB,EAAE,CAAC,CAAC;IACzD,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,eAAe,CAAC,MAAM,CAAC,CAAC;IAExB,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,gDAAgD;AAChD,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,EAAE;IAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;IACvC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IAE3C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,WAAW,EAAE,CAAC;IAC1E,MAAM,iBAAiB,GACrB,aAAa,IAAI,kBAAkB,CAAC,QAAQ,CAAC,aAA2B,CAAC;QACvE,CAAC,CAAE,aAA4B;QAC/B,CAAC,CAAC,SAAS,CAAC;IAEhB,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACrD,OAAO,sBAAsB,CAAC,MAAM,EAAE,EAAE,iBAAiB,EAAE,CAAC,CAAC;AAC/D,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { MemosClient } from "../client.js";
|
|
3
|
+
import type { Visibility } from "../types.js";
|
|
4
|
+
interface MemoToolsOptions {
|
|
5
|
+
defaultVisibility: Visibility;
|
|
6
|
+
}
|
|
7
|
+
export declare const registerMemoTools: (server: McpServer, client: MemosClient, options: MemoToolsOptions) => void;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=memos.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memos.d.ts","sourceRoot":"","sources":["../../src/tools/memos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAQ,UAAU,EAAE,MAAM,aAAa,CAAC;AAmCpD,UAAU,gBAAgB;IACxB,iBAAiB,EAAE,UAAU,CAAC;CAC/B;AAED,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,SAAS,EACjB,QAAQ,WAAW,EACnB,SAAS,gBAAgB,SA6G1B,CAAC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { resolveToMemoId } from "./utils.js";
|
|
3
|
+
function parseToRFC3339(isoString, paramName) {
|
|
4
|
+
const date = new Date(isoString);
|
|
5
|
+
if (isNaN(date.getTime())) {
|
|
6
|
+
throw new Error(`Invalid date for ${paramName}. Use ISO 8601 (e.g. "2025-01-01").`);
|
|
7
|
+
}
|
|
8
|
+
return date.toISOString();
|
|
9
|
+
}
|
|
10
|
+
function cleanMemo(memo, baseUrl) {
|
|
11
|
+
const { nodes, snippet, creator, attachments, ...rest } = memo;
|
|
12
|
+
// Transform attachments with only useful fields
|
|
13
|
+
if (Array.isArray(attachments) && attachments.length > 0) {
|
|
14
|
+
rest.attachments = attachments.map((r) => {
|
|
15
|
+
const uid = r.name?.match(/^attachments\/(.+)$/)?.[1] || "";
|
|
16
|
+
const filename = r.filename;
|
|
17
|
+
const result = {
|
|
18
|
+
filename,
|
|
19
|
+
type: r.type || r.mime,
|
|
20
|
+
size: Number(r.size) || 0,
|
|
21
|
+
createTime: r.createTime,
|
|
22
|
+
};
|
|
23
|
+
if (uid && filename && baseUrl) {
|
|
24
|
+
result.url = `${baseUrl}/file/attachments/${uid}/${filename}`;
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return rest;
|
|
30
|
+
}
|
|
31
|
+
export const registerMemoTools = (server, client, options) => {
|
|
32
|
+
const visibilityEnum = z.enum(["PRIVATE", "PROTECTED", "PUBLIC"]);
|
|
33
|
+
// get — retrieve a single memo
|
|
34
|
+
server.registerTool("get", {
|
|
35
|
+
description: "Get a single memo by ID or UID.",
|
|
36
|
+
inputSchema: {
|
|
37
|
+
id: z.string().min(1).describe("Memo ID or UID"),
|
|
38
|
+
},
|
|
39
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
40
|
+
}, async ({ id }) => {
|
|
41
|
+
const memo = await client.get(`/api/v1/memos/${id}`);
|
|
42
|
+
const cleaned = cleanMemo(memo, client.baseUrl);
|
|
43
|
+
return { content: [{ type: "text", text: JSON.stringify(cleaned, null, 2) }] };
|
|
44
|
+
});
|
|
45
|
+
// create — create a new memo
|
|
46
|
+
server.registerTool("create", {
|
|
47
|
+
description: "Create a memo with markdown content. Use #hashtags for tags. CRITICAL LIMIT: Each memo MUST NOT exceed 13,000 characters. The Memos server enforces a hard limit of ~18K but to avoid errors always stay under 13K. If you need to write more, split into multiple memos with a shared tag (e.g. #project/my-post) and add part numbers.",
|
|
48
|
+
inputSchema: {
|
|
49
|
+
content: z.string().min(1).max(13000).describe("Markdown content with #tags. CRITICAL: MUST NOT exceed 13,000 chars. Server hard limit is ~18K but stay under 13K to avoid errors. Split longer content into multiple memos sharing a #parent-tag."),
|
|
50
|
+
visibility: visibilityEnum.optional().describe("Visibility (default: configured default)"),
|
|
51
|
+
createTime: z.string().optional().describe("Backdate. ISO 8601."),
|
|
52
|
+
},
|
|
53
|
+
annotations: { destructiveHint: false, openWorldHint: false },
|
|
54
|
+
}, async ({ content, visibility, createTime }) => {
|
|
55
|
+
const body = {
|
|
56
|
+
content,
|
|
57
|
+
visibility: visibility ?? options.defaultVisibility,
|
|
58
|
+
};
|
|
59
|
+
if (createTime)
|
|
60
|
+
body.createTime = parseToRFC3339(createTime, "createTime");
|
|
61
|
+
const memo = await client.post("/api/v1/memos", body);
|
|
62
|
+
const name = memo.name;
|
|
63
|
+
if (!name)
|
|
64
|
+
throw new Error("Create failed: no memo name in response");
|
|
65
|
+
const match = name.match(/^memos\/(.+)$/);
|
|
66
|
+
const memoId = match?.[1];
|
|
67
|
+
if (!memoId)
|
|
68
|
+
throw new Error(`Create failed: unexpected name format: ${name}`);
|
|
69
|
+
return { content: [{ type: "text", text: JSON.stringify({ name: memo.name, visibility: memo.visibility, url: `${client.baseUrl}/memos/${memoId}` }) }] };
|
|
70
|
+
});
|
|
71
|
+
// update — modify an existing memo
|
|
72
|
+
server.registerTool("update", {
|
|
73
|
+
description: "Update memo fields. Only provided fields are changed.",
|
|
74
|
+
inputSchema: {
|
|
75
|
+
id: z.string().min(1).describe("Memo ID or UID"),
|
|
76
|
+
content: z.string().max(13000).optional().describe("New markdown content. CRITICAL: MUST NOT exceed 13,000 chars. Server hard limit is ~18K but stay under 13K."),
|
|
77
|
+
visibility: visibilityEnum.optional().describe("New visibility"),
|
|
78
|
+
pinned: z.boolean().optional().describe("Pin/unpin"),
|
|
79
|
+
state: z.enum(["NORMAL", "ARCHIVED"]).optional().describe("Archive/restore"),
|
|
80
|
+
createTime: z.string().optional().describe("Override creation time. ISO 8601."),
|
|
81
|
+
updateTime: z.string().optional().describe("Override update time. ISO 8601."),
|
|
82
|
+
preserveUpdateTime: z.boolean().optional().describe("Don't change update time"),
|
|
83
|
+
},
|
|
84
|
+
annotations: { destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
85
|
+
}, async ({ id, content, visibility, pinned, state, createTime, updateTime, preserveUpdateTime }) => {
|
|
86
|
+
const memoId = await resolveToMemoId(client, id);
|
|
87
|
+
const body = {};
|
|
88
|
+
const mask = [];
|
|
89
|
+
if (content !== undefined) {
|
|
90
|
+
body.content = content;
|
|
91
|
+
mask.push("content");
|
|
92
|
+
}
|
|
93
|
+
if (visibility !== undefined) {
|
|
94
|
+
body.visibility = visibility;
|
|
95
|
+
mask.push("visibility");
|
|
96
|
+
}
|
|
97
|
+
if (pinned !== undefined) {
|
|
98
|
+
body.pinned = pinned;
|
|
99
|
+
mask.push("pinned");
|
|
100
|
+
}
|
|
101
|
+
if (state !== undefined) {
|
|
102
|
+
body.rowStatus = state === "ARCHIVED" ? "ARCHIVED" : "ACTIVE";
|
|
103
|
+
mask.push("row_status");
|
|
104
|
+
}
|
|
105
|
+
if (createTime !== undefined) {
|
|
106
|
+
body.createTime = parseToRFC3339(createTime, "createTime");
|
|
107
|
+
mask.push("create_time");
|
|
108
|
+
}
|
|
109
|
+
if (updateTime !== undefined) {
|
|
110
|
+
body.updateTime = parseToRFC3339(updateTime, "updateTime");
|
|
111
|
+
mask.push("update_time");
|
|
112
|
+
}
|
|
113
|
+
if (mask.length === 0)
|
|
114
|
+
return { content: [{ type: "text", text: "No fields to update." }] };
|
|
115
|
+
const params = { updateMask: mask.join(",") };
|
|
116
|
+
if (preserveUpdateTime)
|
|
117
|
+
params.preserveUpdateTime = "true";
|
|
118
|
+
await client.patch(`/api/v1/memos/${memoId}`, body, params);
|
|
119
|
+
const updatedMemo = await client.get(`/api/v1/memos/${memoId}`);
|
|
120
|
+
const cleaned = cleanMemo(updatedMemo, client.baseUrl);
|
|
121
|
+
return { content: [{ type: "text", text: JSON.stringify(cleaned, null, 2) }] };
|
|
122
|
+
});
|
|
123
|
+
// delete — remove a memo
|
|
124
|
+
server.registerTool("delete", {
|
|
125
|
+
description: "Permanently delete a memo. Cannot be undone.",
|
|
126
|
+
inputSchema: {
|
|
127
|
+
id: z.string().min(1).describe("Memo ID or UID"),
|
|
128
|
+
},
|
|
129
|
+
annotations: { destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
130
|
+
}, async ({ id }) => {
|
|
131
|
+
const memo = await client.get(`/api/v1/memos/${id}`);
|
|
132
|
+
const memoId = await resolveToMemoId(client, id);
|
|
133
|
+
await client.delete(`/api/v1/memos/${memoId}`);
|
|
134
|
+
return { content: [{ type: "text", text: JSON.stringify({ deleted: true, name: memo.name, snippet: memo.snippet?.substring(0, 100) }) }] };
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
//# sourceMappingURL=memos.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memos.js","sourceRoot":"","sources":["../../src/tools/memos.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +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;AAwD3C,eAAO,MAAM,qBAAqB,GAAI,QAAQ,SAAS,EAAE,QAAQ,WAAW,SA2F3E,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { resolveToMemoId } from "./utils.js";
|
|
3
|
+
function extractId(memoRef) {
|
|
4
|
+
const name = typeof memoRef === "string" ? memoRef : memoRef?.name;
|
|
5
|
+
if (!name || typeof name !== "string")
|
|
6
|
+
return undefined;
|
|
7
|
+
const match = name.match(/^memos\/(.+)$/);
|
|
8
|
+
return match ? match[1] : undefined;
|
|
9
|
+
}
|
|
10
|
+
async function buildRelationGraph(client, startId, maxDepth) {
|
|
11
|
+
const visited = new Set();
|
|
12
|
+
const edges = [];
|
|
13
|
+
const edgeSet = new Set();
|
|
14
|
+
const queue = [{ id: startId, depth: 0 }];
|
|
15
|
+
while (queue.length > 0) {
|
|
16
|
+
const { id, depth } = queue.shift();
|
|
17
|
+
if (visited.has(id))
|
|
18
|
+
continue;
|
|
19
|
+
visited.add(id);
|
|
20
|
+
const result = await client.get(`/api/v1/memos/${id}/relations`);
|
|
21
|
+
for (const r of result.relations || []) {
|
|
22
|
+
const fromId = extractId(r.memo);
|
|
23
|
+
const toId = extractId(r.relatedMemo);
|
|
24
|
+
if (fromId === undefined || toId === undefined)
|
|
25
|
+
continue;
|
|
26
|
+
const edgeKey = `${fromId}->${toId}:${r.type}`;
|
|
27
|
+
if (edgeSet.has(edgeKey))
|
|
28
|
+
continue;
|
|
29
|
+
edgeSet.add(edgeKey);
|
|
30
|
+
edges.push({ from: fromId, to: toId, type: r.type });
|
|
31
|
+
const neighborId = fromId === id ? toId : fromId;
|
|
32
|
+
if (depth < maxDepth && !visited.has(neighborId)) {
|
|
33
|
+
queue.push({ id: neighborId, depth: depth + 1 });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { nodes: [...visited], edges };
|
|
38
|
+
}
|
|
39
|
+
export const registerRelationTools = (server, client) => {
|
|
40
|
+
server.registerTool("list_memo_relations", {
|
|
41
|
+
description: [
|
|
42
|
+
"List relations of a memo. Returns edges with direction (from → to) and type.",
|
|
43
|
+
"- depth=1 (default): direct relations only.",
|
|
44
|
+
"- depth=2+: recursively expand related memos to build a relation graph.",
|
|
45
|
+
"Each edge shows {from, to, type}. Use get_memo to inspect specific nodes.",
|
|
46
|
+
].join(" "),
|
|
47
|
+
inputSchema: {
|
|
48
|
+
id: z.string().min(1).describe("Memo identifier. Numeric ID or UID string"),
|
|
49
|
+
depth: z.number().int().min(1).max(5).default(1).describe("How many levels deep to traverse. 1 = direct relations, 2+ = recursive graph"),
|
|
50
|
+
},
|
|
51
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
52
|
+
}, async ({ id, depth }) => {
|
|
53
|
+
const memoId = await resolveToMemoId(client, id);
|
|
54
|
+
const { nodes, edges } = await buildRelationGraph(client, memoId, depth);
|
|
55
|
+
if (edges.length === 0) {
|
|
56
|
+
return { content: [{ type: "text", text: "No relations found." }] };
|
|
57
|
+
}
|
|
58
|
+
const output = { startNode: memoId, nodes, edges };
|
|
59
|
+
return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }] };
|
|
60
|
+
});
|
|
61
|
+
server.registerTool("set_memo_relations", {
|
|
62
|
+
description: [
|
|
63
|
+
"Add or remove REFERENCE relations for a memo.",
|
|
64
|
+
"- action=\"add\": add new references without affecting existing ones.",
|
|
65
|
+
"- action=\"remove\": remove specific references.",
|
|
66
|
+
"Note: COMMENT relations are managed by the system and cannot be modified here.",
|
|
67
|
+
].join(" "),
|
|
68
|
+
inputSchema: {
|
|
69
|
+
id: z.string().min(1).describe("Memo identifier. Numeric ID or UID string"),
|
|
70
|
+
action: z.enum(["add", "remove"]).describe("Whether to add or remove relations"),
|
|
71
|
+
targetIds: z.array(z.string().min(1)).min(1).describe("IDs of memos to add/remove as references. Numeric IDs or UID strings"),
|
|
72
|
+
},
|
|
73
|
+
annotations: { destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
74
|
+
}, async ({ id, action, targetIds }) => {
|
|
75
|
+
const memoId = await resolveToMemoId(client, id);
|
|
76
|
+
const resolvedTargets = await Promise.all(targetIds.map((t) => resolveToMemoId(client, t)));
|
|
77
|
+
const current = await client.get(`/api/v1/memos/${memoId}/relations`);
|
|
78
|
+
const existing = (current.relations || []).filter((r) => extractId(r.memo) === memoId && r.type === "REFERENCE");
|
|
79
|
+
let finalIds;
|
|
80
|
+
if (action === "add") {
|
|
81
|
+
const existingIds = new Set(existing.map((r) => extractId(r.relatedMemo)).filter((id) => id !== undefined));
|
|
82
|
+
finalIds = [
|
|
83
|
+
...existing.map((r) => extractId(r.relatedMemo)).filter((id) => id !== undefined),
|
|
84
|
+
...resolvedTargets.filter((t) => !existingIds.has(t)),
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
const removeSet = new Set(resolvedTargets);
|
|
89
|
+
finalIds = existing
|
|
90
|
+
.map((r) => extractId(r.relatedMemo))
|
|
91
|
+
.filter((id) => id !== undefined)
|
|
92
|
+
.filter((rid) => !removeSet.has(rid));
|
|
93
|
+
}
|
|
94
|
+
const body = {
|
|
95
|
+
relations: finalIds.map((targetId) => ({
|
|
96
|
+
memo: { name: `memos/${memoId}` },
|
|
97
|
+
relatedMemo: { name: `memos/${targetId}` },
|
|
98
|
+
type: "REFERENCE",
|
|
99
|
+
})),
|
|
100
|
+
};
|
|
101
|
+
await client.patch(`/api/v1/memos/${memoId}/relations`, body);
|
|
102
|
+
const verb = action === "add" ? "added" : "removed";
|
|
103
|
+
return {
|
|
104
|
+
content: [{ type: "text", text: `${resolvedTargets.length} reference(s) ${verb}. Memo ${id} now has ${finalIds.length} outgoing reference(s).` }],
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=relations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relations.js","sourceRoot":"","sources":["../../src/tools/relations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,SAAS,SAAS,CAAC,OAAgB;IACjC,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,OAAmC,EAAE,IAAc,CAAC;IAC1G,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACxD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAC1C,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACtC,CAAC;AAQD,KAAK,UAAU,kBAAkB,CAC/B,MAAmB,EACnB,OAAe,EACf,QAAgB;IAEhB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,KAAK,GAAW,EAAE,CAAC;IACzB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,KAAK,GAAoC,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAE3E,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;QACrC,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,SAAS;QAC9B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEhB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAC7B,iBAAiB,EAAE,YAAY,CAChC,CAAC;QAEF,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACjC,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;YACtC,IAAI,MAAM,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS;gBAAE,SAAS;YAEzD,MAAM,OAAO,GAAG,GAAG,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YAC/C,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;gBAAE,SAAS;YACnC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAErD,MAAM,UAAU,GAAG,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;YACjD,IAAI,KAAK,GAAG,QAAQ,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;gBACjD,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,MAAiB,EAAE,MAAmB,EAAE,EAAE;IAC9E,MAAM,CAAC,YAAY,CACjB,qBAAqB,EACrB;QACE,WAAW,EAAE;YACX,8EAA8E;YAC9E,6CAA6C;YAC7C,yEAAyE;YACzE,2EAA2E;SAC5E,CAAC,IAAI,CAAC,GAAG,CAAC;QACX,WAAW,EAAE;YACX,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,2CAA2C,CAAC;YAC3E,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,8EAA8E,CAAC;SAC1I;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KAC1D,EACD,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;QACtB,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACjD,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QAEzE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC,EAAE,CAAC;QAC/E,CAAC;QAED,MAAM,MAAM,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QACnD,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;IAEF,MAAM,CAAC,YAAY,CACjB,oBAAoB,EACpB;QACE,WAAW,EAAE;YACX,+CAA+C;YAC/C,uEAAuE;YACvE,kDAAkD;YAClD,gFAAgF;SACjF,CAAC,IAAI,CAAC,GAAG,CAAC;QACX,WAAW,EAAE;YACX,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,2CAA2C,CAAC;YAC3E,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,oCAAoC,CAAC;YAChF,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,sEAAsE,CAAC;SAC9H;QACD,WAAW,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KACpF,EACD,KAAK,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE;QAClC,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAEjD,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,GAAG,CACvC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CACjD,CAAC;QAEF,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,GAAG,CAC9B,iBAAiB,MAAM,YAAY,CACpC,CAAC;QACF,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM,CAC/C,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,CAC9D,CAAC;QAEF,IAAI,QAAkB,CAAC;QACvB,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YACrB,MAAM,WAAW,GAAG,IAAI,GAAG,CACzB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAgB,EAAE,CAAC,EAAE,KAAK,SAAS,CAAC,CAC7F,CAAC;YACF,QAAQ,GAAG;gBACT,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAgB,EAAE,CAAC,EAAE,KAAK,SAAS,CAAC;gBAC/F,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;aACtD,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,CAAC;YAC3C,QAAQ,GAAG,QAAQ;iBAChB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;iBACpC,MAAM,CAAC,CAAC,EAAE,EAAgB,EAAE,CAAC,EAAE,KAAK,SAAS,CAAC;iBAC9C,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1C,CAAC;QAED,MAAM,IAAI,GAAG;YACX,SAAS,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBACrC,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE;gBACjC,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,QAAQ,EAAE,EAAE;gBAC1C,IAAI,EAAE,WAAW;aAClB,CAAC,CAAC;SACJ,CAAC;QACF,MAAM,MAAM,CAAC,KAAK,CAAC,iBAAiB,MAAM,YAAY,EAAE,IAAI,CAAC,CAAC;QAE9D,MAAM,IAAI,GAAG,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QACpD,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC,MAAM,iBAAiB,IAAI,UAAU,EAAE,YAAY,QAAQ,CAAC,MAAM,yBAAyB,EAAE,CAAC;SAC3J,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +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;AAkB3C,eAAO,MAAM,qBAAqB,GAAI,QAAQ,SAAS,EAAE,QAAQ,WAAW,SAkE3E,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
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
|
+
}
|
|
18
|
+
export const registerResourceTools = (server, client) => {
|
|
19
|
+
server.registerTool("list_resources", {
|
|
20
|
+
description: "List all resources (attachments) owned by the current user.",
|
|
21
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
22
|
+
}, async () => {
|
|
23
|
+
const result = await client.get("/api/v1/resources");
|
|
24
|
+
const summaries = (result.resources || []).map((r) => summarizeResource(r));
|
|
25
|
+
return { content: [{ type: "text", text: JSON.stringify(summaries, null, 2) }] };
|
|
26
|
+
});
|
|
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\/(.+)$/)?.[1];
|
|
48
|
+
const resFilename = resource.filename || "unknown";
|
|
49
|
+
return {
|
|
50
|
+
content: [
|
|
51
|
+
{
|
|
52
|
+
type: "text",
|
|
53
|
+
text: `Resource uploaded: id=${id || "unknown"}, filename="${resFilename}"`,
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
server.registerTool("delete_resource", {
|
|
59
|
+
description: "Delete a resource permanently.",
|
|
60
|
+
inputSchema: {
|
|
61
|
+
id: z.number().int().describe("Resource ID"),
|
|
62
|
+
},
|
|
63
|
+
annotations: { destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
64
|
+
}, async ({ id }) => {
|
|
65
|
+
await client.delete(`/api/v1/resources/${id}`);
|
|
66
|
+
return { content: [{ type: "text", text: `Resource ${id} deleted.` }] };
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
const MIME_MAP = {
|
|
70
|
+
jpg: "image/jpeg",
|
|
71
|
+
jpeg: "image/jpeg",
|
|
72
|
+
png: "image/png",
|
|
73
|
+
gif: "image/gif",
|
|
74
|
+
webp: "image/webp",
|
|
75
|
+
svg: "image/svg+xml",
|
|
76
|
+
pdf: "application/pdf",
|
|
77
|
+
mp3: "audio/mpeg",
|
|
78
|
+
mp4: "video/mp4",
|
|
79
|
+
webm: "video/webm",
|
|
80
|
+
txt: "text/plain",
|
|
81
|
+
md: "text/markdown",
|
|
82
|
+
json: "application/json",
|
|
83
|
+
csv: "text/csv",
|
|
84
|
+
zip: "application/zip",
|
|
85
|
+
};
|
|
86
|
+
function guessMimeType(filename) {
|
|
87
|
+
const ext = filename.split(".").pop()?.toLowerCase() ?? "";
|
|
88
|
+
return MIME_MAP[ext] ?? "application/octet-stream";
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../../src/tools/resources.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../src/tools/review.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAkE3C,eAAO,MAAM,kBAAkB,GAAI,QAAQ,SAAS,EAAE,QAAQ,WAAW,SA4GxE,CAAC"}
|