keepsake-mcp 1.4.0 → 1.5.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 CHANGED
@@ -165,12 +165,12 @@ Add to `.cursor/mcp.json` in your project:
165
165
  ### Tags
166
166
  | Tool | Description |
167
167
  |------|-------------|
168
- | `list_tags` | List all tags |
169
- | `get_tag` | Get a tag by ID with all properties (color, icon, view mode, etc.) |
168
+ | `list_tags` | List tags (lightweight — ordering arrays omitted), with optional name search (`q`) |
169
+ | `get_tag` | Get a tag by ID with all properties, including `tasks_order` (section markers `h:<header_id>`) |
170
170
  | `create_tag` | Create a new tag |
171
171
  | `update_tag` | Update a tag (name, description, color, icon, view mode, favorite) |
172
172
  | `delete_tag` | Permanently delete a tag and all its links |
173
- | `get_tag_items` | Get everything linked to a tag |
173
+ | `get_tag_items` | Get items linked to a tag — filter by `types`/`status`, `summary` mode, task `sections` included |
174
174
  | `link_tag` | Link any entity to a tag |
175
175
  | `unlink_tag` | Remove a tag link |
176
176
 
package/build/tools.js CHANGED
@@ -488,17 +488,18 @@ export function registerAllTools(server, fetchApi) {
488
488
  // TAGS
489
489
  // ===========================================================================
490
490
  server.registerTool("list_tags", {
491
- description: "List all tags. Tags organize contacts, entries, tasks, notes, and companies.",
491
+ description: "List tags (lightweight: the manual tasks_order arrays are omitted — use get_tag for a tag's full ordering). Tags organize contacts, entries, tasks, notes, and companies. Use q to find a tag by name.",
492
492
  inputSchema: {
493
+ q: z.string().optional().describe("Filter by name (case-insensitive substring match)"),
493
494
  limit: z.number().int().positive().optional().describe("Max results (default 50)"),
494
495
  offset: z.number().int().nonnegative().optional().describe("Pagination offset"),
495
496
  },
496
497
  annotations: { title: "List tags", readOnlyHint: true, openWorldHint: false },
497
- }, async ({ limit, offset }) => {
498
- return toContent(await fetchApi(`/tags${qs({ limit, offset })}`));
498
+ }, async ({ q, limit, offset }) => {
499
+ return toContent(await fetchApi(`/tags${qs({ q, limit, offset })}`));
499
500
  });
500
501
  server.registerTool("get_tag", {
501
- description: "Get a single tag by ID with all its properties (name, description, color, icon, view mode, favorite status).",
502
+ description: "Get a single tag by ID with all its properties (name, description, color, icon, view mode, favorite status). Includes tasks_order, the manual ordering of the tag page's task list, where entries of the form \"h:<header_id>\" are section separators (see list_task_headers).",
502
503
  inputSchema: {
503
504
  id: z.string().uuid().describe("Tag UUID"),
504
505
  },
@@ -507,13 +508,22 @@ export function registerAllTools(server, fetchApi) {
507
508
  return toContent(await fetchApi(`/tags/${id}`));
508
509
  });
509
510
  server.registerTool("get_tag_items", {
510
- description: "Get all items linked to a specific tag: contacts, entries, tasks, notes, and companies with counts.",
511
+ description: "Get items linked to a tag. By default returns every type in full — on large tags that can be a huge response, so prefer types/status/summary to narrow it (e.g. types=['tasks'], status='pending', summary=true to review a project's open tasks). When tasks are included, the response also contains `sections`: the tag page's task sections with their task_ids (header_id null = tasks outside any section).",
511
512
  inputSchema: {
512
513
  id: z.string().uuid().describe("Tag UUID"),
514
+ types: z
515
+ .array(z.enum(["contacts", "entries", "tasks", "notes", "companies"]))
516
+ .optional()
517
+ .describe("Only fetch these item types (default: all)"),
518
+ status: z.enum(["pending", "completed"]).optional().describe("Filter tasks by status"),
519
+ summary: z
520
+ .boolean()
521
+ .optional()
522
+ .describe("Return lightweight items (ids, titles, excerpts) instead of full rows — recommended unless full content is needed"),
513
523
  },
514
524
  annotations: { title: "Get tag items", readOnlyHint: true, openWorldHint: false },
515
- }, async ({ id }) => {
516
- return toContent(await fetchApi(`/tags/${id}/items`));
525
+ }, async ({ id, types, status, summary }) => {
526
+ return toContent(await fetchApi(`/tags/${id}/items${qs({ types: types?.join(","), status, summary })}`));
517
527
  });
518
528
  server.registerTool("create_tag", {
519
529
  description: "A TAG is a thematic grouping space. Syntax: #name# or [[name]]. Groups notes, entries, tasks, and contacts.\n\nCreate a new tag. If a tag with the same name already exists, returns the existing tag.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keepsake-mcp",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "MCP server for Keepsake personal CRM — connect your AI agent to your contacts, tasks, notes, and more",
5
5
  "type": "module",
6
6
  "bin": {