+58
-13
packages/mcp/server.ts
+58
-13
packages/mcp/server.ts
···
1
1
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
import { getLogger } from "@logtape/logtape";
3
3
import { z } from "zod";
4
-
import type { Consumer } from "@cistern/consumer";
4
+
import type { Consumer, DecryptedMemo } from "@cistern/consumer";
5
5
6
6
export function createServer(consumer: Consumer) {
7
7
const logger = getLogger("cistern-mcp");
···
10
10
version: "1.0.0",
11
11
});
12
12
13
+
let iterator:
14
+
| AsyncGenerator<DecryptedMemo, void, "stop" | undefined>
15
+
| undefined;
16
+
13
17
server.registerTool(
14
-
"add",
18
+
"next_memo",
19
+
{
20
+
title: "Next memo",
21
+
description: "Retrieve the next outstanding memo",
22
+
outputSchema: { tid: z.string(), text: z.string() },
23
+
},
24
+
async () => {
25
+
if (!iterator) {
26
+
logger.trace("creating iterator");
27
+
iterator ??= consumer.listMemos();
28
+
}
29
+
30
+
const res = await iterator.next();
31
+
32
+
if (res.done) {
33
+
logger.trace("iterator done; cleaning up");
34
+
iterator = undefined;
35
+
}
36
+
37
+
return {
38
+
content: [{
39
+
type: "text",
40
+
text: res.value?.text ?? "no memos remaining",
41
+
}],
42
+
structuredContent: {
43
+
tid: res.value?.tid ?? "",
44
+
text: res.value?.text ?? "no memos remaining",
45
+
},
46
+
};
47
+
},
48
+
);
49
+
50
+
server.registerTool(
51
+
"delete_memo",
15
52
{
16
-
title: "Addition Tool",
17
-
description: "Add two numbers",
18
-
inputSchema: { a: z.number(), b: z.number() },
19
-
outputSchema: { result: z.number() },
53
+
title: "Delete memo",
54
+
description:
55
+
"Delete a memo by record key, after it has been handled as instructed by the user",
56
+
inputSchema: { key: z.string() },
57
+
outputSchema: { success: z.boolean() },
20
58
},
21
-
({ a, b }) => {
22
-
logger.trace("Addition Tool called", { a, b });
59
+
async ({ key }) => {
60
+
try {
61
+
await consumer.deleteMemo(key);
23
62
24
-
const output = { result: a + b };
63
+
return {
64
+
content: [{ type: "text", text: "delete successful" }],
65
+
structuredContent: { success: true },
66
+
};
67
+
} catch (error) {
68
+
logger.error("failed to delete memo: {error}", { error });
25
69
26
-
return Promise.resolve({
27
-
content: [{ type: "text", text: JSON.stringify(output) }],
28
-
structuredContent: output,
29
-
});
70
+
return {
71
+
content: [{ type: "text", text: "delete unsuccessful" }],
72
+
structuredContent: { success: false },
73
+
};
74
+
}
30
75
},
31
76
);
32
77