keepsake-mcp 1.6.0 → 1.7.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 +12 -1
- package/build/tools.js +62 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -100,7 +100,7 @@ Add to `.cursor/mcp.json` in your project:
|
|
|
100
100
|
}
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
## Available tools (
|
|
103
|
+
## Available tools (67)
|
|
104
104
|
|
|
105
105
|
### Contacts
|
|
106
106
|
| Tool | Description |
|
|
@@ -156,6 +156,17 @@ Add to `.cursor/mcp.json` in your project:
|
|
|
156
156
|
| `archive_note` | Archive a note |
|
|
157
157
|
| `restore_note` | Restore a deleted/archived note |
|
|
158
158
|
|
|
159
|
+
### Note comments (marginalia)
|
|
160
|
+
|
|
161
|
+
Material kept *alongside* a note without entering its text — an idea, a reference, an excerpt pasted to rewrite a passage later. Anchored to a passage by quoting it, or to the whole note. Never published, and temporary by design: anything worth keeping becomes a note or a linked task.
|
|
162
|
+
|
|
163
|
+
| Tool | Description |
|
|
164
|
+
|------|-------------|
|
|
165
|
+
| `list_note_comments` | List the marginalia attached to a note |
|
|
166
|
+
| `create_note_comment` | Attach a marginalia to a passage (pass `quote`) or to the whole note |
|
|
167
|
+
| `update_note_comment` | Edit the content of a marginalia |
|
|
168
|
+
| `delete_note_comment` | Permanently delete a marginalia |
|
|
169
|
+
|
|
159
170
|
### Daily Journal
|
|
160
171
|
| Tool | Description |
|
|
161
172
|
|------|-------------|
|
package/build/tools.js
CHANGED
|
@@ -823,6 +823,68 @@ export function registerAllTools(server, fetchApi) {
|
|
|
823
823
|
return toContent(await fetchApi(`/search${qs({ q, type, limit })}`));
|
|
824
824
|
});
|
|
825
825
|
// ---------------------------------------------------------------------------
|
|
826
|
+
// Note comments (marginalia)
|
|
827
|
+
// ---------------------------------------------------------------------------
|
|
828
|
+
server.registerTool("list_note_comments", {
|
|
829
|
+
description: "List the marginalia attached to a note. A marginalia is working material the user keeps ALONGSIDE a note without it entering the text: an idea, a reference, a link, an excerpt pasted to rewrite a passage later. They are never published, and they are meant to be TEMPORARY — anything worth keeping becomes a note or a linked task.\n\nEach one is either attached to a specific passage (`quote` is set) or to the whole note (`quote` is null).",
|
|
830
|
+
inputSchema: {
|
|
831
|
+
note_id: z.string().uuid().describe("Note UUID"),
|
|
832
|
+
},
|
|
833
|
+
annotations: { title: "List note comments", readOnlyHint: true, openWorldHint: false },
|
|
834
|
+
}, async ({ note_id }) => {
|
|
835
|
+
return toContent(await fetchApi(`/notes/${note_id}/comments`));
|
|
836
|
+
});
|
|
837
|
+
server.registerTool("create_note_comment", {
|
|
838
|
+
description: "Attach a marginalia to a note — material that must stay OUT of the note text.\n\nTo attach it to a passage, pass `quote` with that passage copied VERBATIM from the note content; the server locates it and stores the surrounding context so the comment survives later edits. Omit `quote` to comment on the note as a whole. If the quote is not found verbatim the call is refused rather than attached to the wrong place.\n\nDo not use this to suggest edits to the text — use update_note for that. And keep the number of comments low: a note peppered with them is a note the user abandons.",
|
|
839
|
+
inputSchema: {
|
|
840
|
+
note_id: z.string().uuid().describe("Note UUID"),
|
|
841
|
+
body: z.string().describe("The material itself (markdown, any length)"),
|
|
842
|
+
quote: z
|
|
843
|
+
.string()
|
|
844
|
+
.optional()
|
|
845
|
+
.describe("Passage to attach to, copied verbatim from the note content. Omit for a note-wide comment."),
|
|
846
|
+
},
|
|
847
|
+
annotations: {
|
|
848
|
+
title: "Create note comment",
|
|
849
|
+
destructiveHint: false,
|
|
850
|
+
idempotentHint: false,
|
|
851
|
+
openWorldHint: false,
|
|
852
|
+
},
|
|
853
|
+
}, async ({ note_id, ...params }) => {
|
|
854
|
+
return toContent(await fetchApi(`/notes/${note_id}/comments`, "POST", params));
|
|
855
|
+
});
|
|
856
|
+
server.registerTool("update_note_comment", {
|
|
857
|
+
description: "Edit the content of a marginalia. There is no intermediate state: a marginalia exists, or it is deleted. A remark that should outlive the note's revision becomes a note or a linked task instead.",
|
|
858
|
+
inputSchema: {
|
|
859
|
+
note_id: z.string().uuid().describe("Note UUID"),
|
|
860
|
+
comment_id: z.string().uuid().describe("Comment UUID"),
|
|
861
|
+
body: z.string().describe("New content (markdown)"),
|
|
862
|
+
},
|
|
863
|
+
annotations: {
|
|
864
|
+
title: "Update note comment",
|
|
865
|
+
destructiveHint: false,
|
|
866
|
+
idempotentHint: true,
|
|
867
|
+
openWorldHint: false,
|
|
868
|
+
},
|
|
869
|
+
}, async ({ note_id, comment_id, ...params }) => {
|
|
870
|
+
return toContent(await fetchApi(`/notes/${note_id}/comments/${comment_id}`, "PATCH", params));
|
|
871
|
+
});
|
|
872
|
+
server.registerTool("delete_note_comment", {
|
|
873
|
+
description: "Delete a marginalia. Marginalia are temporary by design, so this is the normal way to retire one — there is no recoverable middle state.",
|
|
874
|
+
inputSchema: {
|
|
875
|
+
note_id: z.string().uuid().describe("Note UUID"),
|
|
876
|
+
comment_id: z.string().uuid().describe("Comment UUID"),
|
|
877
|
+
},
|
|
878
|
+
annotations: {
|
|
879
|
+
title: "Delete note comment",
|
|
880
|
+
destructiveHint: true,
|
|
881
|
+
idempotentHint: true,
|
|
882
|
+
openWorldHint: false,
|
|
883
|
+
},
|
|
884
|
+
}, async ({ note_id, comment_id }) => {
|
|
885
|
+
return toContent(await fetchApi(`/notes/${note_id}/comments/${comment_id}`, "DELETE"));
|
|
886
|
+
});
|
|
887
|
+
// ---------------------------------------------------------------------------
|
|
826
888
|
// Agent instructions
|
|
827
889
|
// ---------------------------------------------------------------------------
|
|
828
890
|
server.registerTool("get_agent_instructions", {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "keepsake-mcp",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "MCP server for Keepsake personal CRM
|
|
3
|
+
"version": "1.7.0",
|
|
4
|
+
"description": "MCP server for Keepsake personal CRM \u2014 connect your AI agent to your contacts, tasks, notes, and more",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"keepsake-mcp": "build/index.js"
|