automd-mcp 0.1.4 → 0.2.1

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.
Files changed (3) hide show
  1. package/dist/index.js +207 -204
  2. package/package.json +41 -40
  3. package/LICENSE.md +0 -60
package/dist/index.js CHANGED
@@ -40384,7 +40384,7 @@ var ApiError = class extends Error {
40384
40384
  hint = "Check that all required parameters are provided and correctly formatted.";
40385
40385
  break;
40386
40386
  case 404:
40387
- hint = "The requested resource does not exist. Use list_boards to see available board IDs.";
40387
+ hint = "The requested resource does not exist. Use list_items to see available item IDs.";
40388
40388
  break;
40389
40389
  case 409:
40390
40390
  hint = "The resource was modified by another client. Re-fetch the resource and retry your operation.";
@@ -40522,82 +40522,82 @@ function errorResponse(err) {
40522
40522
  return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
40523
40523
  }
40524
40524
  function registerTools(server2) {
40525
- server2.registerTool("list_boards", {
40526
- title: "List Boards",
40527
- description: "List all items (boards, checklists, and notes) with their task counts"
40525
+ server2.registerTool("list_items", {
40526
+ title: "List Items",
40527
+ description: "List all items (boards, checklists, pages, and knowledge bases) with their task counts. Returns array of {id, name, itemType, projectId, taskCount}."
40528
40528
  }, async () => {
40529
40529
  try {
40530
- const boards = await api.listFiles();
40531
- return json2(boards);
40530
+ const items = await api.listFiles();
40531
+ return json2(items);
40532
40532
  } catch (err) {
40533
40533
  return errorResponse(err);
40534
40534
  }
40535
40535
  });
40536
- server2.registerTool("get_board", {
40537
- title: "Get Board",
40538
- description: "Get a board, checklist, or note with its columns and tasks",
40539
- inputSchema: { boardId: external_exports.string().describe("The board ID") }
40540
- }, async ({ boardId }) => {
40536
+ server2.registerTool("get_item", {
40537
+ title: "Get Item",
40538
+ description: "Get an item (board, checklist, page, or knowledge base) with its columns and tasks",
40539
+ inputSchema: { itemId: external_exports.string().describe("The item ID (obtain from list_items)") }
40540
+ }, async ({ itemId }) => {
40541
40541
  try {
40542
- const board = await api.getFile(boardId);
40543
- return json2(board);
40542
+ const item = await api.getFile(itemId);
40543
+ return json2(item);
40544
40544
  } catch (err) {
40545
40545
  return errorResponse(err);
40546
40546
  }
40547
40547
  });
40548
- server2.registerTool("get_board_markdown", {
40549
- title: "Get Board Markdown",
40550
- description: "Get the raw markdown content of a board, checklist, or note",
40551
- inputSchema: { boardId: external_exports.string().describe("The board ID") }
40552
- }, async ({ boardId }) => {
40548
+ server2.registerTool("get_item_markdown", {
40549
+ title: "Get Item Markdown",
40550
+ description: "Get the raw markdown content of an item (board, checklist, or page)",
40551
+ inputSchema: { itemId: external_exports.string().describe("The item ID") }
40552
+ }, async ({ itemId }) => {
40553
40553
  try {
40554
- const board = await api.getFile(boardId);
40555
- return text(board.markdown);
40554
+ const item = await api.getFile(itemId);
40555
+ return text(item.markdown);
40556
40556
  } catch (err) {
40557
40557
  return errorResponse(err);
40558
40558
  }
40559
40559
  });
40560
- server2.registerTool("create_board", {
40561
- title: "Create Board",
40562
- description: "Create a new board, checklist, or note. Boards use # (H1) for columns and ## (H2) for tasks. Checklists use ## (H2) with [ ]/[x] prefixes. Notes are free-form markdown. All support YAML frontmatter, plain paragraphs (description), blockquotes (>) for acceptance criteria, and GFM checkboxes for subtasks.",
40560
+ server2.registerTool("create_item", {
40561
+ title: "Create Item",
40562
+ description: "Create a new board, checklist, page, or knowledge base. Boards use # (H1) for columns and ## (H2) for tasks. Checklists use ## (H2) with [ ]/[x] prefixes. Pages are free-form markdown. Knowledge bases are structured collections of entries (## H2) without checkboxes or progress \u2014 ideal for decisions, patterns, and reference material. All support YAML frontmatter, descriptions, blockquotes (>) for acceptance criteria, and GFM checkboxes for subtasks.",
40563
40563
  inputSchema: {
40564
- name: external_exports.string().describe("Name for the new board/checklist/note"),
40565
- itemType: external_exports.enum(["board", "checklist", "note"]).optional().describe("Type of item to create: board (kanban columns), checklist (task list with checkboxes), or note (free-form markdown). Defaults to board"),
40566
- markdown: external_exports.string().optional().describe("Initial markdown content. Start with YAML frontmatter (board:, description:). Use # for columns, ## for tasks. Paragraphs = description, blockquotes (>) = acceptance criteria, checkboxes = subtasks"),
40564
+ name: external_exports.string().describe("Name for the new item"),
40565
+ itemType: external_exports.enum(["board", "checklist", "page", "knowledge"]).optional().describe("Type of item to create: board (kanban columns), checklist (task list with checkboxes), page (free-form markdown), or knowledge (structured entries without checkboxes/progress). Defaults to board"),
40566
+ markdown: external_exports.string().optional().describe("Initial markdown content. Omit for an empty item. For boards: use # for columns, ## for tasks. For checklists: ## with [ ] prefix. For pages/knowledge: free-form markdown. All types support YAML frontmatter (board:, description:, vocabulary:)."),
40567
40567
  projectId: external_exports.string().optional().describe("Project ID to add the item to (optional)")
40568
40568
  }
40569
40569
  }, async ({ name, itemType, markdown, projectId }) => {
40570
40570
  try {
40571
- const board = await api.createFile(name, markdown, projectId, itemType);
40572
- return json2(board);
40571
+ const item = await api.createFile(name, markdown, projectId, itemType);
40572
+ return json2(item);
40573
40573
  } catch (err) {
40574
40574
  return errorResponse(err);
40575
40575
  }
40576
40576
  });
40577
- server2.registerTool("delete_board", {
40578
- title: "Delete Board",
40579
- description: "Permanently delete a board, checklist, or note and all its contents",
40577
+ server2.registerTool("delete_item", {
40578
+ title: "Delete Item",
40579
+ description: "Permanently delete an item (board, checklist, or page) and all its contents",
40580
40580
  inputSchema: {
40581
- boardId: external_exports.string().describe("The board ID to delete")
40581
+ itemId: external_exports.string().describe("The item ID to delete")
40582
40582
  }
40583
- }, async ({ boardId }) => {
40583
+ }, async ({ itemId }) => {
40584
40584
  try {
40585
- await api.deleteFile(boardId);
40586
- return text("Board deleted");
40585
+ await api.deleteFile(itemId);
40586
+ return text("Item deleted");
40587
40587
  } catch (err) {
40588
40588
  return errorResponse(err);
40589
40589
  }
40590
40590
  });
40591
- server2.registerTool("rename_board", {
40592
- title: "Rename Board",
40593
- description: "Rename an existing board, checklist, or note",
40591
+ server2.registerTool("rename_item", {
40592
+ title: "Rename Item",
40593
+ description: "Rename an existing item (board, checklist, or page)",
40594
40594
  inputSchema: {
40595
- boardId: external_exports.string().describe("The board ID"),
40596
- name: external_exports.string().describe("New name for the board")
40595
+ itemId: external_exports.string().describe("The item ID"),
40596
+ name: external_exports.string().describe("New name for the item")
40597
40597
  }
40598
- }, async ({ boardId, name }) => {
40598
+ }, async ({ itemId, name }) => {
40599
40599
  try {
40600
- const result = await api.updateFile(boardId, { name });
40600
+ const result = await api.updateFile(itemId, { name });
40601
40601
  return json2(result);
40602
40602
  } catch (err) {
40603
40603
  return errorResponse(err);
@@ -40605,17 +40605,17 @@ function registerTools(server2) {
40605
40605
  });
40606
40606
  server2.registerTool("add_task", {
40607
40607
  title: "Add Task",
40608
- description: "Add a new task (H2 heading) to a column. Content supports inline metadata like @user #label priority:high due:2025-03-20 est:4h",
40608
+ description: "Add a new task (## H2 heading) to a column. Content supports inline metadata: @user #label priority:high|medium|low due:YYYY-MM-DD est:4h knowledge:true. Do not include built-by: manually \u2014 use the agentName parameter.",
40609
40609
  inputSchema: {
40610
- boardId: external_exports.string().describe("The board ID"),
40611
- columnId: external_exports.string().describe("The column/heading ID to add the task to"),
40610
+ itemId: external_exports.string().describe("The item ID"),
40611
+ columnId: external_exports.string().describe("The column ID (found in get_item response columns[].id)"),
40612
40612
  content: external_exports.string().describe("Task content with optional inline metadata"),
40613
40613
  agentName: external_exports.string().regex(/^[\w-]+$/).optional().describe("Name of the agent making this change (tagged as built-by)")
40614
40614
  }
40615
- }, async ({ boardId, columnId, content, agentName }) => {
40615
+ }, async ({ itemId, columnId, content, agentName }) => {
40616
40616
  try {
40617
40617
  const finalContent = agentName ? `${content} built-by:${agentName}` : content;
40618
- const result = await api.addTask(boardId, columnId, finalContent);
40618
+ const result = await api.addTask(itemId, columnId, finalContent);
40619
40619
  return json2(result);
40620
40620
  } catch (err) {
40621
40621
  return errorResponse(err);
@@ -40623,20 +40623,20 @@ function registerTools(server2) {
40623
40623
  });
40624
40624
  server2.registerTool("update_task", {
40625
40625
  title: "Update Task",
40626
- description: "Update a task's content",
40626
+ description: "Update a task's title/content text only. For metadata use update_task_metadata, for completion use toggle_task, for position use move_task, for AC use update_acceptance_criteria, for learnings use update_learnings.",
40627
40627
  inputSchema: {
40628
- boardId: external_exports.string().describe("The board ID"),
40629
- taskId: external_exports.string().describe("The task ID"),
40628
+ itemId: external_exports.string().describe("The item ID"),
40629
+ taskId: external_exports.string().describe("The task ID (found in get_item response columns[].tasks[].id)"),
40630
40630
  content: external_exports.string().optional().describe("New task content"),
40631
40631
  agentName: external_exports.string().regex(/^[\w-]+$/).optional().describe("Name of the agent making this change (tagged as built-by)")
40632
40632
  }
40633
- }, async ({ boardId, taskId, content, agentName }) => {
40633
+ }, async ({ itemId, taskId, content, agentName }) => {
40634
40634
  try {
40635
40635
  let finalContent = content;
40636
40636
  if (agentName && finalContent) {
40637
40637
  finalContent = finalContent.replace(/\s*built-by:[\w-]+/gi, "") + ` built-by:${agentName}`;
40638
40638
  }
40639
- const result = await api.updateTask(boardId, taskId, {
40639
+ const result = await api.updateTask(itemId, taskId, {
40640
40640
  action: "updateContent",
40641
40641
  content: finalContent
40642
40642
  });
@@ -40647,14 +40647,14 @@ function registerTools(server2) {
40647
40647
  });
40648
40648
  server2.registerTool("toggle_task", {
40649
40649
  title: "Toggle Task",
40650
- description: "Toggle a task between checked and unchecked",
40650
+ description: "Toggle a task between checked [ ] and unchecked [x]. Only applies to tasks with checkbox prefixes. Sets completedAt on check, clears on uncheck.",
40651
40651
  inputSchema: {
40652
- boardId: external_exports.string().describe("The board ID"),
40652
+ itemId: external_exports.string().describe("The item ID"),
40653
40653
  taskId: external_exports.string().describe("The task ID")
40654
40654
  }
40655
- }, async ({ boardId, taskId }) => {
40655
+ }, async ({ itemId, taskId }) => {
40656
40656
  try {
40657
- const result = await api.updateTask(boardId, taskId, { action: "toggle" });
40657
+ const result = await api.updateTask(itemId, taskId, { action: "toggle" });
40658
40658
  return json2(result);
40659
40659
  } catch (err) {
40660
40660
  return errorResponse(err);
@@ -40664,14 +40664,14 @@ function registerTools(server2) {
40664
40664
  title: "Move Task",
40665
40665
  description: "Move a task to a different column at a specific position",
40666
40666
  inputSchema: {
40667
- boardId: external_exports.string().describe("The board ID"),
40667
+ itemId: external_exports.string().describe("The item ID"),
40668
40668
  taskId: external_exports.string().describe("The task ID"),
40669
40669
  targetColumnId: external_exports.string().describe("Target column ID"),
40670
- targetIndex: external_exports.number().describe("Position in the target column (0-based)")
40670
+ targetIndex: external_exports.number().describe("Position in target column (0-based). Use 0 to place at top. To append, use the column task count from get_item.")
40671
40671
  }
40672
- }, async ({ boardId, taskId, targetColumnId, targetIndex }) => {
40672
+ }, async ({ itemId, taskId, targetColumnId, targetIndex }) => {
40673
40673
  try {
40674
- const result = await api.updateTask(boardId, taskId, {
40674
+ const result = await api.updateTask(itemId, taskId, {
40675
40675
  action: "move",
40676
40676
  targetColumnId,
40677
40677
  targetIndex
@@ -40683,14 +40683,14 @@ function registerTools(server2) {
40683
40683
  });
40684
40684
  server2.registerTool("delete_task", {
40685
40685
  title: "Delete Task",
40686
- description: "Delete a task from a board",
40686
+ description: "Delete a task from an item",
40687
40687
  inputSchema: {
40688
- boardId: external_exports.string().describe("The board ID"),
40688
+ itemId: external_exports.string().describe("The item ID"),
40689
40689
  taskId: external_exports.string().describe("The task ID")
40690
40690
  }
40691
- }, async ({ boardId, taskId }) => {
40691
+ }, async ({ itemId, taskId }) => {
40692
40692
  try {
40693
- await api.deleteTask(boardId, taskId);
40693
+ await api.deleteTask(itemId, taskId);
40694
40694
  return text("Task deleted");
40695
40695
  } catch (err) {
40696
40696
  return errorResponse(err);
@@ -40698,20 +40698,20 @@ function registerTools(server2) {
40698
40698
  });
40699
40699
  server2.registerTool("add_column", {
40700
40700
  title: "Add Column",
40701
- description: "Add a new column (heading) to a board",
40701
+ description: 'Add a new column (# H1 heading) to a board or checklist. Columns group tasks into workflow stages like "To Do", "In Progress", "Done".',
40702
40702
  inputSchema: {
40703
- boardId: external_exports.string().describe("The board ID"),
40703
+ itemId: external_exports.string().describe("The item ID"),
40704
40704
  title: external_exports.string().describe("Column title")
40705
40705
  }
40706
- }, async ({ boardId, title }) => {
40706
+ }, async ({ itemId, title }) => {
40707
40707
  try {
40708
- const board = await api.getFile(boardId);
40709
- const newMarkdown = board.markdown.trimEnd() + `
40708
+ const item = await api.getFile(itemId);
40709
+ const newMarkdown = item.markdown.trimEnd() + `
40710
40710
 
40711
40711
  # ${title}
40712
40712
 
40713
40713
  `;
40714
- const result = await api.updateFile(boardId, { markdown: newMarkdown });
40714
+ const result = await api.updateFile(itemId, { markdown: newMarkdown });
40715
40715
  return json2(result);
40716
40716
  } catch (err) {
40717
40717
  return errorResponse(err);
@@ -40719,15 +40719,15 @@ function registerTools(server2) {
40719
40719
  });
40720
40720
  server2.registerTool("rename_column", {
40721
40721
  title: "Rename Column",
40722
- description: "Rename a column/heading on a board",
40722
+ description: "Rename a column/heading on an item",
40723
40723
  inputSchema: {
40724
- boardId: external_exports.string().describe("The board ID"),
40724
+ itemId: external_exports.string().describe("The item ID"),
40725
40725
  columnId: external_exports.string().describe("The column ID to rename"),
40726
40726
  title: external_exports.string().describe("New title for the column")
40727
40727
  }
40728
- }, async ({ boardId, columnId, title }) => {
40728
+ }, async ({ itemId, columnId, title }) => {
40729
40729
  try {
40730
- const result = await api.renameColumn(boardId, columnId, title);
40730
+ const result = await api.renameColumn(itemId, columnId, title);
40731
40731
  return json2(result);
40732
40732
  } catch (err) {
40733
40733
  return errorResponse(err);
@@ -40735,14 +40735,14 @@ function registerTools(server2) {
40735
40735
  });
40736
40736
  server2.registerTool("delete_column", {
40737
40737
  title: "Delete Column",
40738
- description: "Delete a column and all its tasks from a board",
40738
+ description: "Delete a column and all its tasks from an item",
40739
40739
  inputSchema: {
40740
- boardId: external_exports.string().describe("The board ID"),
40740
+ itemId: external_exports.string().describe("The item ID"),
40741
40741
  columnId: external_exports.string().describe("The column ID to delete")
40742
40742
  }
40743
- }, async ({ boardId, columnId }) => {
40743
+ }, async ({ itemId, columnId }) => {
40744
40744
  try {
40745
- await api.deleteColumn(boardId, columnId);
40745
+ await api.deleteColumn(itemId, columnId);
40746
40746
  return text("Column deleted");
40747
40747
  } catch (err) {
40748
40748
  return errorResponse(err);
@@ -40752,7 +40752,7 @@ function registerTools(server2) {
40752
40752
  title: "Update Task Metadata",
40753
40753
  description: "Update a task's metadata (priority, assignees, labels, due date, estimate) without rewriting its content",
40754
40754
  inputSchema: {
40755
- boardId: external_exports.string().describe("The board ID"),
40755
+ itemId: external_exports.string().describe("The item ID"),
40756
40756
  taskId: external_exports.string().describe("The task ID"),
40757
40757
  priority: external_exports.enum(["high", "medium", "low"]).nullable().optional().describe("Task priority"),
40758
40758
  assignees: external_exports.array(external_exports.string()).optional().describe("List of assignees (without @)"),
@@ -40761,10 +40761,10 @@ function registerTools(server2) {
40761
40761
  estimate: external_exports.number().nullable().optional().describe("Time estimate in hours"),
40762
40762
  agentName: external_exports.string().regex(/^[\w-]+$/).optional().describe("Name of the agent making this change (tagged as built-by)")
40763
40763
  }
40764
- }, async ({ boardId, taskId, priority, assignees, labels, dueDate, estimate, agentName }) => {
40764
+ }, async ({ itemId, taskId, priority, assignees, labels, dueDate, estimate, agentName }) => {
40765
40765
  try {
40766
- const board = await api.getFile(boardId);
40767
- const task = board.columns.flatMap((c) => c.tasks).find((t) => t.id === taskId);
40766
+ const item = await api.getFile(itemId);
40767
+ const task = item.columns.flatMap((c) => c.tasks).find((t) => t.id === taskId);
40768
40768
  if (!task) return text("Task not found");
40769
40769
  const metadata = { ...task.metadata };
40770
40770
  if (priority !== void 0) metadata.priority = priority;
@@ -40773,7 +40773,7 @@ function registerTools(server2) {
40773
40773
  if (dueDate !== void 0) metadata.dueDate = dueDate;
40774
40774
  if (estimate !== void 0) metadata.estimate = estimate;
40775
40775
  if (agentName) metadata.builtBy = agentName;
40776
- const result = await api.updateTask(boardId, taskId, {
40776
+ const result = await api.updateTask(itemId, taskId, {
40777
40777
  action: "updateMetadata",
40778
40778
  displayContent: task.displayContent,
40779
40779
  metadata
@@ -40787,13 +40787,13 @@ function registerTools(server2) {
40787
40787
  title: "Update Acceptance Criteria",
40788
40788
  description: `Update a task's acceptance criteria (rendered as blockquotes in markdown). These are testable conditions that define "done" for a task. Each line becomes a separate blockquote line.`,
40789
40789
  inputSchema: {
40790
- boardId: external_exports.string().describe("The board ID"),
40790
+ itemId: external_exports.string().describe("The item ID"),
40791
40791
  taskId: external_exports.string().describe("The task ID"),
40792
40792
  acceptanceCriteria: external_exports.string().nullable().describe("Acceptance criteria text. Each line becomes a blockquote entry. Pass null to remove AC.")
40793
40793
  }
40794
- }, async ({ boardId, taskId, acceptanceCriteria }) => {
40794
+ }, async ({ itemId, taskId, acceptanceCriteria }) => {
40795
40795
  try {
40796
- const result = await api.updateTask(boardId, taskId, {
40796
+ const result = await api.updateTask(itemId, taskId, {
40797
40797
  action: "updateAcceptanceCriteria",
40798
40798
  acceptanceCriteria
40799
40799
  });
@@ -40806,13 +40806,13 @@ function registerTools(server2) {
40806
40806
  title: "Update Learnings",
40807
40807
  description: "Update a completed task's learnings section (rendered as ### Learnings with a bullet list in markdown). Use this to record decisions, insights, and pitfalls discovered while completing a task. Supports #label tags for cross-referencing.",
40808
40808
  inputSchema: {
40809
- boardId: external_exports.string().describe("The board ID"),
40809
+ itemId: external_exports.string().describe("The item ID"),
40810
40810
  taskId: external_exports.string().describe("The task ID"),
40811
40811
  learnings: external_exports.string().nullable().describe('Learnings text. Each line becomes a bullet point under ### Learnings. Use #tags for keywords (e.g. "PKCE flow required for SPA #oauth #security"). Pass null to remove.')
40812
40812
  }
40813
- }, async ({ boardId, taskId, learnings }) => {
40813
+ }, async ({ itemId, taskId, learnings }) => {
40814
40814
  try {
40815
- const result = await api.updateTask(boardId, taskId, {
40815
+ const result = await api.updateTask(itemId, taskId, {
40816
40816
  action: "updateLearnings",
40817
40817
  learnings
40818
40818
  });
@@ -40825,7 +40825,7 @@ function registerTools(server2) {
40825
40825
  title: "Bulk Update Tasks",
40826
40826
  description: "Update multiple tasks at once. Each update can toggle, move, update content, or update metadata.",
40827
40827
  inputSchema: {
40828
- boardId: external_exports.string().describe("The board ID"),
40828
+ itemId: external_exports.string().describe("The item ID"),
40829
40829
  agentName: external_exports.string().regex(/^[\w-]+$/).optional().describe("Name of the agent making these changes (tagged as built-by)"),
40830
40830
  updates: external_exports.array(external_exports.object({
40831
40831
  taskId: external_exports.string().describe("The task ID"),
@@ -40834,10 +40834,12 @@ function registerTools(server2) {
40834
40834
  targetColumnId: external_exports.string().optional().describe("Target column (for move)"),
40835
40835
  targetIndex: external_exports.number().optional().describe("Target index (for move)"),
40836
40836
  displayContent: external_exports.string().optional().describe("Display content (for updateMetadata)"),
40837
- metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional().describe("Metadata fields (for updateMetadata)")
40837
+ metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional().describe("Metadata fields (for updateMetadata)"),
40838
+ acceptanceCriteria: external_exports.string().nullable().optional().describe("Acceptance criteria text (for updateAcceptanceCriteria). Pass null to remove."),
40839
+ learnings: external_exports.string().nullable().optional().describe("Learnings text (for updateLearnings). Pass null to remove.")
40838
40840
  })).describe("Array of task updates to apply")
40839
40841
  }
40840
- }, async ({ boardId, agentName, updates }) => {
40842
+ }, async ({ itemId, agentName, updates }) => {
40841
40843
  const results = [];
40842
40844
  for (const update of updates) {
40843
40845
  try {
@@ -40850,7 +40852,7 @@ function registerTools(server2) {
40850
40852
  data.metadata = { ...data.metadata, builtBy: agentName };
40851
40853
  }
40852
40854
  }
40853
- await api.updateTask(boardId, taskId, data);
40855
+ await api.updateTask(itemId, taskId, data);
40854
40856
  results.push({ taskId, ok: true });
40855
40857
  } catch (err) {
40856
40858
  results.push({
@@ -40869,7 +40871,7 @@ function registerTools(server2) {
40869
40871
  });
40870
40872
  server2.registerTool("search_tasks", {
40871
40873
  title: "Search Tasks",
40872
- description: "Search for tasks across all boards by text, assignee, label, or status",
40874
+ description: "Search for tasks across all items by text, assignee, label, or status",
40873
40875
  inputSchema: {
40874
40876
  query: external_exports.string().optional().describe("Text to search for in task content"),
40875
40877
  assignee: external_exports.string().optional().describe("Filter by assignee (without @)"),
@@ -40878,12 +40880,12 @@ function registerTools(server2) {
40878
40880
  }
40879
40881
  }, async ({ query, assignee, label, checked }) => {
40880
40882
  try {
40881
- const boards = await api.listFiles();
40883
+ const items = await api.listFiles();
40882
40884
  const results = [];
40883
- for (const boardSummary of boards) {
40885
+ for (const itemSummary of items) {
40884
40886
  try {
40885
- const board = await api.getFile(boardSummary.id);
40886
- for (const column of board.columns) {
40887
+ const item = await api.getFile(itemSummary.id);
40888
+ for (const column of item.columns) {
40887
40889
  for (const task of column.tasks) {
40888
40890
  let match = true;
40889
40891
  if (query && !task.content.toLowerCase().includes(query.toLowerCase())) match = false;
@@ -40892,8 +40894,8 @@ function registerTools(server2) {
40892
40894
  if (checked !== void 0 && task.checked !== checked) match = false;
40893
40895
  if (match) {
40894
40896
  results.push({
40895
- boardId: boardSummary.id,
40896
- boardName: boardSummary.name,
40897
+ itemId: itemSummary.id,
40898
+ itemName: itemSummary.name,
40897
40899
  taskId: task.id,
40898
40900
  content: task.content,
40899
40901
  column: column.title,
@@ -40903,7 +40905,7 @@ function registerTools(server2) {
40903
40905
  }
40904
40906
  }
40905
40907
  } catch (err) {
40906
- console.error(`[mcp] Failed to search board ${boardSummary.id}:`, err);
40908
+ console.error(`[mcp] Failed to search item ${itemSummary.id}:`, err);
40907
40909
  }
40908
40910
  }
40909
40911
  return json2({ count: results.length, results });
@@ -40913,7 +40915,7 @@ function registerTools(server2) {
40913
40915
  });
40914
40916
  server2.registerTool("search_context", {
40915
40917
  title: "Search Context",
40916
- description: 'Search for institutional knowledge across all boards. Searches task descriptions, acceptance criteria, and learnings \u2014 not just titles. Use this to find relevant context before starting work on a task (e.g. "what do we know about auth?" or "what was learned about pricing?").',
40918
+ description: "Search for contextual detail (descriptions, acceptance criteria, learnings) across all items. Returns any task with rich content \u2014 broader than find_knowledge which only returns knowledge:true items. Use this for finding implementation details, past decisions, and context before starting work.",
40917
40919
  inputSchema: {
40918
40920
  query: external_exports.string().optional().describe("Text to search for across descriptions, AC, learnings, and task content"),
40919
40921
  label: external_exports.string().optional().describe("Filter by label (without #). Also matches #tags inside learnings text."),
@@ -40921,13 +40923,13 @@ function registerTools(server2) {
40921
40923
  }
40922
40924
  }, async ({ query, label, completedOnly }) => {
40923
40925
  try {
40924
- const boards = await api.listFiles();
40926
+ const items = await api.listFiles();
40925
40927
  const results = [];
40926
40928
  const q = query?.toLowerCase();
40927
- for (const boardSummary of boards) {
40929
+ for (const itemSummary of items) {
40928
40930
  try {
40929
- const board = await api.getFile(boardSummary.id);
40930
- for (const column of board.columns) {
40931
+ const item = await api.getFile(itemSummary.id);
40932
+ for (const column of item.columns) {
40931
40933
  for (const task of column.tasks) {
40932
40934
  if (completedOnly && !task.checked) continue;
40933
40935
  const searchable = [
@@ -40947,8 +40949,8 @@ function registerTools(server2) {
40947
40949
  if (!hasContext) match = false;
40948
40950
  if (match) {
40949
40951
  results.push({
40950
- boardId: boardSummary.id,
40951
- boardName: boardSummary.name,
40952
+ itemId: itemSummary.id,
40953
+ itemName: itemSummary.name,
40952
40954
  taskId: task.id,
40953
40955
  taskTitle: task.displayContent,
40954
40956
  taskLabels: task.metadata.labels,
@@ -40962,7 +40964,7 @@ function registerTools(server2) {
40962
40964
  }
40963
40965
  }
40964
40966
  } catch (err) {
40965
- console.error(`[mcp] Failed to search board ${boardSummary.id}:`, err);
40967
+ console.error(`[mcp] Failed to search item ${itemSummary.id}:`, err);
40966
40968
  }
40967
40969
  }
40968
40970
  return json2({ count: results.length, results });
@@ -40972,7 +40974,7 @@ function registerTools(server2) {
40972
40974
  });
40973
40975
  server2.registerTool("list_projects", {
40974
40976
  title: "List Projects",
40975
- description: "List all projects"
40977
+ description: "List all projects. Returns array of {id, name, color}. Use project id as projectId in create_item or get_project_items."
40976
40978
  }, async () => {
40977
40979
  try {
40978
40980
  const projects = await api.listProjects();
@@ -40981,26 +40983,26 @@ function registerTools(server2) {
40981
40983
  return errorResponse(err);
40982
40984
  }
40983
40985
  });
40984
- server2.registerTool("get_project_boards", {
40985
- title: "Get Project Boards",
40986
- description: "List all items (boards, checklists, notes) belonging to a project",
40986
+ server2.registerTool("get_project_items", {
40987
+ title: "Get Project Items",
40988
+ description: "List all items (boards, checklists, pages) belonging to a project",
40987
40989
  inputSchema: {
40988
40990
  projectId: external_exports.string().describe("The project ID")
40989
40991
  }
40990
40992
  }, async ({ projectId }) => {
40991
40993
  try {
40992
- const allBoards = await api.listFiles();
40993
- const projectBoards = allBoards.filter(
40994
+ const allItems = await api.listFiles();
40995
+ const projectItems = allItems.filter(
40994
40996
  (b) => b.projectId === projectId
40995
40997
  );
40996
- return json2(projectBoards);
40998
+ return json2(projectItems);
40997
40999
  } catch (err) {
40998
41000
  return errorResponse(err);
40999
41001
  }
41000
41002
  });
41001
41003
  server2.registerTool("create_project", {
41002
41004
  title: "Create Project",
41003
- description: "Create a new project to organize boards",
41005
+ description: "Create a new project to organize items",
41004
41006
  inputSchema: {
41005
41007
  name: external_exports.string().describe("Name for the new project (max 200 characters)"),
41006
41008
  color: external_exports.string().optional().describe("Hex color for the project (default: #3b82f6)")
@@ -41015,9 +41017,9 @@ function registerTools(server2) {
41015
41017
  });
41016
41018
  server2.registerTool("add_knowledge", {
41017
41019
  title: "Add Knowledge",
41018
- description: "Add a knowledge item to a board. Knowledge items are tasks with knowledge:true \u2014 they store decisions, patterns, references, and institutional memory. They reuse the task infrastructure but skip the checkbox/completion workflow.",
41020
+ description: "Add a knowledge item. Knowledge items are tasks with knowledge:true \u2014 they store decisions, patterns, references, and institutional memory. They reuse the task infrastructure but skip the checkbox/completion workflow.",
41019
41021
  inputSchema: {
41020
- boardId: external_exports.string().describe("The board ID"),
41022
+ itemId: external_exports.string().describe("The item ID"),
41021
41023
  columnId: external_exports.string().describe("The column ID"),
41022
41024
  content: external_exports.string().describe('Knowledge item title (e.g. "Always use parameterized queries for SQL")'),
41023
41025
  description: external_exports.string().optional().describe("Detailed description/context for this knowledge item"),
@@ -41025,20 +41027,20 @@ function registerTools(server2) {
41025
41027
  labels: external_exports.array(external_exports.string()).optional().describe('Labels for categorization (e.g. ["security", "database"])'),
41026
41028
  agentName: external_exports.string().regex(/^[\w-]+$/).optional().describe("Agent name to tag with built-by:")
41027
41029
  }
41028
- }, async ({ boardId, columnId, content, description, learnings, labels, agentName }) => {
41030
+ }, async ({ itemId, columnId, content, description, learnings, labels, agentName }) => {
41029
41031
  try {
41030
41032
  let taskContent = `${content} knowledge:true`;
41031
41033
  if (labels?.length) taskContent += " " + labels.map((l) => `#${l}`).join(" ");
41032
41034
  if (agentName) taskContent += ` built-by:${agentName}`;
41033
- const result = await api.addTask(boardId, columnId, taskContent);
41035
+ const result = await api.addTask(itemId, columnId, taskContent);
41034
41036
  if (description && result?.taskId) {
41035
- await api.updateTask(boardId, result.taskId, {
41037
+ await api.updateTask(itemId, result.taskId, {
41036
41038
  action: "updateDescription",
41037
41039
  description
41038
41040
  });
41039
41041
  }
41040
41042
  if (learnings && result?.taskId) {
41041
- await api.updateTask(boardId, result.taskId, {
41043
+ await api.updateTask(itemId, result.taskId, {
41042
41044
  action: "updateLearnings",
41043
41045
  learnings
41044
41046
  });
@@ -41052,35 +41054,35 @@ function registerTools(server2) {
41052
41054
  title: "Update Knowledge",
41053
41055
  description: "Update an existing knowledge item's description, learnings, or labels.",
41054
41056
  inputSchema: {
41055
- boardId: external_exports.string().describe("The board ID"),
41057
+ itemId: external_exports.string().describe("The item ID"),
41056
41058
  taskId: external_exports.string().describe("The task/knowledge item ID"),
41057
41059
  description: external_exports.string().optional().describe("New description (replaces existing)"),
41058
41060
  learnings: external_exports.string().optional().describe("New learnings (replaces existing). Supports #tags."),
41059
41061
  labels: external_exports.array(external_exports.string()).optional().describe("New labels (replaces existing)")
41060
41062
  }
41061
- }, async ({ boardId, taskId, description, learnings, labels }) => {
41063
+ }, async ({ itemId, taskId, description, learnings, labels }) => {
41062
41064
  try {
41063
41065
  const results = [];
41064
41066
  if (description !== void 0) {
41065
- await api.updateTask(boardId, taskId, {
41067
+ await api.updateTask(itemId, taskId, {
41066
41068
  action: "updateDescription",
41067
41069
  description
41068
41070
  });
41069
41071
  results.push("description updated");
41070
41072
  }
41071
41073
  if (learnings !== void 0) {
41072
- await api.updateTask(boardId, taskId, {
41074
+ await api.updateTask(itemId, taskId, {
41073
41075
  action: "updateLearnings",
41074
41076
  learnings
41075
41077
  });
41076
41078
  results.push("learnings updated");
41077
41079
  }
41078
41080
  if (labels !== void 0) {
41079
- const board = await api.getFile(boardId);
41080
- const allTasks = board.columns.flatMap((c) => c.tasks);
41081
+ const item = await api.getFile(itemId);
41082
+ const allTasks = item.columns.flatMap((c) => c.tasks);
41081
41083
  const task = allTasks.find((t) => t.id === taskId);
41082
41084
  if (task) {
41083
- await api.updateTask(boardId, taskId, {
41085
+ await api.updateTask(itemId, taskId, {
41084
41086
  action: "updateMetadata",
41085
41087
  displayContent: task.displayContent,
41086
41088
  metadata: { ...task.metadata, labels }
@@ -41095,20 +41097,20 @@ function registerTools(server2) {
41095
41097
  });
41096
41098
  server2.registerTool("find_knowledge", {
41097
41099
  title: "Find Knowledge",
41098
- description: "Search for knowledge items across all boards. Returns tasks with knowledge:true OR tasks that have learnings. Use this to find institutional memory, past decisions, and patterns.",
41100
+ description: "Search specifically for curated knowledge items (knowledge:true) and tasks with captured learnings. Use for institutional decisions, patterns, and reference. For broader task history including descriptions, use search_context instead.",
41099
41101
  inputSchema: {
41100
41102
  query: external_exports.string().optional().describe("Text to search for in knowledge items"),
41101
41103
  label: external_exports.string().optional().describe("Filter by label (without #)")
41102
41104
  }
41103
41105
  }, async ({ query, label }) => {
41104
41106
  try {
41105
- const boards = await api.listFiles();
41107
+ const items = await api.listFiles();
41106
41108
  const results = [];
41107
41109
  const q = query?.toLowerCase();
41108
- for (const boardSummary of boards) {
41110
+ for (const itemSummary of items) {
41109
41111
  try {
41110
- const board = await api.getFile(boardSummary.id);
41111
- for (const column of board.columns) {
41112
+ const item = await api.getFile(itemSummary.id);
41113
+ for (const column of item.columns) {
41112
41114
  for (const task of column.tasks) {
41113
41115
  const isKnowledge = task.metadata?.knowledge === true;
41114
41116
  const hasLearnings = !!task.learnings;
@@ -41128,8 +41130,8 @@ function registerTools(server2) {
41128
41130
  if (!hasLabel && !hasInlineTag) continue;
41129
41131
  }
41130
41132
  results.push({
41131
- boardId: boardSummary.id,
41132
- boardName: boardSummary.name,
41133
+ itemId: itemSummary.id,
41134
+ itemName: itemSummary.name,
41133
41135
  taskId: task.id,
41134
41136
  title: task.displayContent,
41135
41137
  labels: task.metadata?.labels ?? [],
@@ -41140,7 +41142,7 @@ function registerTools(server2) {
41140
41142
  }
41141
41143
  }
41142
41144
  } catch (err) {
41143
- console.error(`[mcp] Failed to search board ${boardSummary.id}:`, err);
41145
+ console.error(`[mcp] Failed to search item ${itemSummary.id}:`, err);
41144
41146
  }
41145
41147
  }
41146
41148
  return json2({ count: results.length, results });
@@ -41153,7 +41155,7 @@ function registerTools(server2) {
41153
41155
  description: "Gather all knowledge about a topic and return a structured summary. This collects and organizes existing knowledge items \u2014 it does NOT generate AI content. Returns a paste-ready context brief.",
41154
41156
  inputSchema: {
41155
41157
  topic: external_exports.string().describe('Topic to synthesize knowledge about (e.g. "authentication", "pricing", "deployment")'),
41156
- labels: external_exports.string().optional().describe('Comma-separated labels to filter by (e.g. "backend,security")')
41158
+ labels: external_exports.string().optional().describe('Comma-separated labels to filter by (e.g. "backend,security"). Unlike label on other tools which takes a single value, this accepts multiple comma-separated.')
41157
41159
  }
41158
41160
  }, async ({ topic, labels }) => {
41159
41161
  try {
@@ -41167,7 +41169,7 @@ function registerTools(server2) {
41167
41169
  title: "Import Memories",
41168
41170
  description: "Bulk import knowledge items from external sources (AI conversation logs, meeting notes, etc.). Creates knowledge:true tasks for each item.",
41169
41171
  inputSchema: {
41170
- boardId: external_exports.string().describe("The board ID to import into"),
41172
+ itemId: external_exports.string().describe("The item ID to import into"),
41171
41173
  columnId: external_exports.string().describe("The column ID to add items to"),
41172
41174
  items: external_exports.array(external_exports.object({
41173
41175
  content: external_exports.string().describe("Knowledge item title"),
@@ -41177,7 +41179,7 @@ function registerTools(server2) {
41177
41179
  })).describe("Array of knowledge items to import"),
41178
41180
  agentName: external_exports.string().regex(/^[\w-]+$/).optional().describe("Agent name to tag imports with")
41179
41181
  }
41180
- }, async ({ boardId, columnId, items, agentName }) => {
41182
+ }, async ({ itemId, columnId, items, agentName }) => {
41181
41183
  try {
41182
41184
  const results = [];
41183
41185
  const errors = [];
@@ -41186,15 +41188,15 @@ function registerTools(server2) {
41186
41188
  let taskContent = `${item.content} knowledge:true`;
41187
41189
  if (item.labels?.length) taskContent += " " + item.labels.map((l) => `#${l}`).join(" ");
41188
41190
  if (agentName) taskContent += ` built-by:${agentName}`;
41189
- const result = await api.addTask(boardId, columnId, taskContent);
41191
+ const result = await api.addTask(itemId, columnId, taskContent);
41190
41192
  if (item.description && result?.taskId) {
41191
- await api.updateTask(boardId, result.taskId, {
41193
+ await api.updateTask(itemId, result.taskId, {
41192
41194
  action: "updateDescription",
41193
41195
  description: item.description
41194
41196
  });
41195
41197
  }
41196
41198
  if (item.learnings && result?.taskId) {
41197
- await api.updateTask(boardId, result.taskId, {
41199
+ await api.updateTask(itemId, result.taskId, {
41198
41200
  action: "updateLearnings",
41199
41201
  learnings: item.learnings
41200
41202
  });
@@ -41218,17 +41220,17 @@ function registerTools(server2) {
41218
41220
  title: "Archive Completed Tasks",
41219
41221
  description: "Bulk archive completed tasks. Optionally filter by age (days since completion) or column.",
41220
41222
  inputSchema: {
41221
- boardId: external_exports.string().describe("The board ID"),
41223
+ itemId: external_exports.string().describe("The item ID"),
41222
41224
  olderThanDays: external_exports.number().optional().describe("Only archive tasks completed more than N days ago"),
41223
41225
  columnId: external_exports.string().optional().describe("Only archive tasks in this column")
41224
41226
  }
41225
- }, async ({ boardId, olderThanDays, columnId }) => {
41227
+ }, async ({ itemId, olderThanDays, columnId }) => {
41226
41228
  try {
41227
- const board = await api.getFile(boardId);
41229
+ const item = await api.getFile(itemId);
41228
41230
  const now = /* @__PURE__ */ new Date();
41229
41231
  let archived = 0;
41230
41232
  const errors = [];
41231
- for (const column of board.columns) {
41233
+ for (const column of item.columns) {
41232
41234
  if (columnId && column.id !== columnId) continue;
41233
41235
  for (const task of column.tasks) {
41234
41236
  if (!task.checked) continue;
@@ -41241,7 +41243,7 @@ function registerTools(server2) {
41241
41243
  if (daysSince < olderThanDays) continue;
41242
41244
  }
41243
41245
  try {
41244
- await api.updateTask(boardId, task.id, {
41246
+ await api.updateTask(itemId, task.id, {
41245
41247
  action: "updateMetadata",
41246
41248
  displayContent: task.displayContent,
41247
41249
  metadata: { ...task.metadata, archived: true }
@@ -41264,47 +41266,47 @@ function registerTools(server2) {
41264
41266
 
41265
41267
  // src/resources.ts
41266
41268
  function registerResources(server2) {
41267
- server2.registerResource("boards", "automd://boards", {
41268
- description: "List of all AutoMD boards",
41269
+ server2.registerResource("items", "automd://items", {
41270
+ description: "List of all AutoMD items (boards, checklists, pages)",
41269
41271
  mimeType: "application/json"
41270
41272
  }, async () => {
41271
- const boards = await api.listFiles();
41273
+ const items = await api.listFiles();
41272
41274
  return {
41273
41275
  contents: [
41274
41276
  {
41275
- uri: "automd://boards",
41277
+ uri: "automd://items",
41276
41278
  mimeType: "application/json",
41277
- text: JSON.stringify(boards, null, 2)
41279
+ text: JSON.stringify(items, null, 2)
41278
41280
  }
41279
41281
  ]
41280
41282
  };
41281
41283
  });
41282
- server2.registerResource("board", new ResourceTemplate("automd://boards/{boardId}", { list: void 0 }), {
41283
- description: "A single AutoMD board with columns and tasks",
41284
+ server2.registerResource("item", new ResourceTemplate("automd://items/{itemId}", { list: void 0 }), {
41285
+ description: "A single AutoMD item (board, checklist, or page) with columns and tasks",
41284
41286
  mimeType: "application/json"
41285
- }, async (uri, { boardId }) => {
41286
- const board = await api.getFile(boardId);
41287
+ }, async (uri, { itemId }) => {
41288
+ const item = await api.getFile(itemId);
41287
41289
  return {
41288
41290
  contents: [
41289
41291
  {
41290
41292
  uri: uri.href,
41291
41293
  mimeType: "application/json",
41292
- text: JSON.stringify(board, null, 2)
41294
+ text: JSON.stringify(item, null, 2)
41293
41295
  }
41294
41296
  ]
41295
41297
  };
41296
41298
  });
41297
- server2.registerResource("board-markdown", new ResourceTemplate("automd://boards/{boardId}/markdown", { list: void 0 }), {
41298
- description: "Raw markdown content of a board",
41299
+ server2.registerResource("item-markdown", new ResourceTemplate("automd://items/{itemId}/markdown", { list: void 0 }), {
41300
+ description: "Raw markdown content of an item",
41299
41301
  mimeType: "text/markdown"
41300
- }, async (uri, { boardId }) => {
41301
- const board = await api.getFile(boardId);
41302
+ }, async (uri, { itemId }) => {
41303
+ const item = await api.getFile(itemId);
41302
41304
  return {
41303
41305
  contents: [
41304
41306
  {
41305
41307
  uri: uri.href,
41306
41308
  mimeType: "text/markdown",
41307
- text: board.markdown
41309
+ text: item.markdown
41308
41310
  }
41309
41311
  ]
41310
41312
  };
@@ -41340,16 +41342,17 @@ function registerSystemPrompts(server2) {
41340
41342
 
41341
41343
  ## Core Concepts
41342
41344
 
41343
- AutoMD has three item types:
41345
+ AutoMD has four item types:
41344
41346
  - **Boards** \u2014 Kanban-style markdown files with columns (H1) and tasks (H2). Each has YAML frontmatter with metadata.
41345
41347
  - **Checklists** \u2014 Task lists using ## (H2) headings with [ ]/[x] checkbox prefixes. Great for simple to-do lists and tracking.
41346
- - **Notes** \u2014 Free-form markdown documents for documentation, meeting notes, specs, etc.
41348
+ - **Pages** \u2014 Free-form markdown documents for specs, documentation, and reference material.
41349
+ - **Knowledge Bases** \u2014 Structured collections of knowledge entries (## H2) without checkboxes or progress tracking. Ideal for decisions, patterns, and institutional memory.
41347
41350
 
41348
- All three types support YAML frontmatter, descriptions, acceptance criteria, subtasks, and learnings.
41351
+ All four types support YAML frontmatter, descriptions, acceptance criteria, subtasks, and learnings.
41349
41352
 
41350
41353
  **Knowledge items** are tasks with \`knowledge:true\` \u2014 they store decisions, patterns, references, and institutional memory. They use the same task infrastructure but represent knowledge, not work to be done.
41351
41354
 
41352
- **Vocabulary** (optional YAML frontmatter) defines domain-specific label dimensions for a board:
41355
+ **Vocabulary** (optional YAML frontmatter) defines domain-specific label dimensions for an item:
41353
41356
  \`\`\`yaml
41354
41357
  vocabulary:
41355
41358
  technology: [react, node, python]
@@ -41389,13 +41392,13 @@ Description paragraph \u2014 background, context, the "why".
41389
41392
  - Use \`synthesize_topic\` to assemble context briefs about a topic
41390
41393
 
41391
41394
  ## Available Tools
41392
- - Board management: list_boards, get_board, create_board (supports board/checklist/note types), delete_board, rename_board
41395
+ - Item management: list_items, get_item, create_item (supports board/checklist/page/knowledge types), delete_item, rename_item
41393
41396
  - Task management: add_task, update_task, toggle_task, move_task, delete_task
41394
41397
  - Metadata: update_task_metadata, update_acceptance_criteria, update_learnings
41395
41398
  - Knowledge: add_knowledge, update_knowledge, find_knowledge, synthesize_topic, import_memories
41396
41399
  - Search: search_tasks, search_context
41397
41400
  - Bulk: bulk_update_tasks, archive_completed_tasks
41398
- - Projects: list_projects, get_project_boards, create_project
41401
+ - Projects: list_projects, get_project_items, create_project
41399
41402
 
41400
41403
  Always use the most specific tool for the job. Prefer knowledge tools for knowledge management over raw task tools.`
41401
41404
  }
@@ -41409,11 +41412,11 @@ function registerWorkflowPrompts(server2) {
41409
41412
  server2.registerPrompt("decompose_task", {
41410
41413
  description: "Break down a complex task into subtasks with estimates",
41411
41414
  argsSchema: {
41412
- boardId: external_exports.string().describe("The board ID"),
41415
+ itemId: external_exports.string().describe("The item ID"),
41413
41416
  taskId: external_exports.string().describe("The task ID to decompose")
41414
41417
  }
41415
- }, async ({ boardId, taskId }) => {
41416
- const board = await api.getFile(boardId);
41418
+ }, async ({ itemId, taskId }) => {
41419
+ const board = await api.getFile(itemId);
41417
41420
  const allTasks = board.columns.flatMap((c) => c.tasks);
41418
41421
  const task = allTasks.find((t) => t.id === taskId);
41419
41422
  const taskJson = JSON.stringify(task, null, 2);
@@ -41433,7 +41436,7 @@ Please:
41433
41436
  3. Identify any dependencies between subtasks
41434
41437
  4. Suggest which subtasks could be parallelized
41435
41438
 
41436
- Provide the specific add_subtask tool calls to create each subtask.`
41439
+ Subtasks are GFM checkboxes (\`- [ ] text\`) inside the parent task's content. Use update_task to add them to the parent task's body, or use add_task to create standalone tasks.`
41437
41440
  }
41438
41441
  }]
41439
41442
  };
@@ -41441,11 +41444,11 @@ Provide the specific add_subtask tool calls to create each subtask.`
41441
41444
  server2.registerPrompt("write_acceptance_criteria", {
41442
41445
  description: "Write acceptance criteria for a task",
41443
41446
  argsSchema: {
41444
- boardId: external_exports.string().describe("The board ID"),
41447
+ itemId: external_exports.string().describe("The item ID"),
41445
41448
  taskId: external_exports.string().describe("The task ID")
41446
41449
  }
41447
- }, async ({ boardId, taskId }) => {
41448
- const board = await api.getFile(boardId);
41450
+ }, async ({ itemId, taskId }) => {
41451
+ const board = await api.getFile(itemId);
41449
41452
  const allTasks = board.columns.flatMap((c) => c.tasks);
41450
41453
  const task = allTasks.find((t) => t.id === taskId);
41451
41454
  const taskJson = JSON.stringify(task, null, 2);
@@ -41492,7 +41495,7 @@ Please:
41492
41495
  3. Create initial tasks to get started (including knowledge items for key decisions)
41493
41496
  4. Set up a knowledge base board alongside the task board if the project would benefit from it
41494
41497
 
41495
- Use create_board with appropriate markdown including YAML frontmatter with vocabulary. Then add initial tasks with add_task and add_knowledge.`
41498
+ Use create_item with appropriate markdown including YAML frontmatter with vocabulary. Then add initial tasks with add_task and add_knowledge.`
41496
41499
  }
41497
41500
  }]
41498
41501
  };
@@ -41539,7 +41542,7 @@ I'll paste my notes/memories below. Please:
41539
41542
  1. Parse the content into individual knowledge items
41540
41543
  2. Categorize each with appropriate labels
41541
41544
  3. Use import_memories to bulk-create them on an appropriate board
41542
- 4. If no knowledge board exists, create one first with create_board
41545
+ 4. If no knowledge board exists, create one first with create_item
41543
41546
 
41544
41547
  Each imported item should have:
41545
41548
  - A clear, concise title
@@ -41559,11 +41562,11 @@ function registerPlanningPrompts(server2) {
41559
41562
  server2.registerPrompt("sprint_planning", {
41560
41563
  description: "Help plan next sprint from backlog",
41561
41564
  argsSchema: {
41562
- boardId: external_exports.string().describe("The board ID to plan from"),
41565
+ itemId: external_exports.string().describe("The item ID to plan from"),
41563
41566
  sprintCapacityHours: external_exports.number().optional().describe("Total sprint capacity in hours")
41564
41567
  }
41565
- }, async ({ boardId, sprintCapacityHours }) => {
41566
- const board = await api.getFile(boardId);
41568
+ }, async ({ itemId, sprintCapacityHours }) => {
41569
+ const board = await api.getFile(itemId);
41567
41570
  const boardJson = JSON.stringify(board, null, 2);
41568
41571
  const capacityNote = sprintCapacityHours ? `The team has ${sprintCapacityHours} hours of capacity for this sprint.` : "No specific capacity constraint was provided.";
41569
41572
  return {
@@ -41594,11 +41597,11 @@ Provide specific tool calls the agent can execute to move tasks into the sprint
41594
41597
  server2.registerPrompt("estimate_tasks", {
41595
41598
  description: "Estimate effort for unestimated tasks on a board",
41596
41599
  argsSchema: {
41597
- boardId: external_exports.string().describe("The board ID"),
41600
+ itemId: external_exports.string().describe("The item ID"),
41598
41601
  columnId: external_exports.string().optional().describe("Optional column ID to scope estimation")
41599
41602
  }
41600
- }, async ({ boardId, columnId }) => {
41601
- const board = await api.getFile(boardId);
41603
+ }, async ({ itemId, columnId }) => {
41604
+ const board = await api.getFile(itemId);
41602
41605
  const allTasks = board.columns.flatMap(
41603
41606
  (c) => columnId ? c.id === columnId ? c.tasks : [] : c.tasks
41604
41607
  );
@@ -41627,10 +41630,10 @@ Provide update_task_metadata tool calls to set estimates.`
41627
41630
  server2.registerPrompt("dependency_analysis", {
41628
41631
  description: "Analyze task dependencies and suggest ordering",
41629
41632
  argsSchema: {
41630
- boardId: external_exports.string().describe("The board ID to analyze")
41633
+ itemId: external_exports.string().describe("The item ID to analyze")
41631
41634
  }
41632
- }, async ({ boardId }) => {
41633
- const board = await api.getFile(boardId);
41635
+ }, async ({ itemId }) => {
41636
+ const board = await api.getFile(itemId);
41634
41637
  const boardJson = JSON.stringify(board, null, 2);
41635
41638
  return {
41636
41639
  messages: [{
@@ -41661,10 +41664,10 @@ function registerOperationsPrompts(server2) {
41661
41664
  server2.registerPrompt("triage_tasks", {
41662
41665
  description: "Review uncategorized tasks and suggest columns/priorities",
41663
41666
  argsSchema: {
41664
- boardId: external_exports.string().describe("The board ID to triage")
41667
+ itemId: external_exports.string().describe("The item ID to triage")
41665
41668
  }
41666
- }, async ({ boardId }) => {
41667
- const board = await api.getFile(boardId);
41669
+ }, async ({ itemId }) => {
41670
+ const board = await api.getFile(itemId);
41668
41671
  const boardJson = JSON.stringify(board, null, 2);
41669
41672
  return {
41670
41673
  messages: [{
@@ -41691,10 +41694,10 @@ For each suggestion, explain your reasoning and provide the specific tool calls
41691
41694
  server2.registerPrompt("daily_standup", {
41692
41695
  description: "Summarize progress: what's done, in progress, blocked",
41693
41696
  argsSchema: {
41694
- boardId: external_exports.string().describe("The board ID to summarize")
41697
+ itemId: external_exports.string().describe("The item ID to summarize")
41695
41698
  }
41696
- }, async ({ boardId }) => {
41697
- const board = await api.getFile(boardId);
41699
+ }, async ({ itemId }) => {
41700
+ const board = await api.getFile(itemId);
41698
41701
  const boardJson = JSON.stringify(board, null, 2);
41699
41702
  return {
41700
41703
  messages: [{
@@ -41720,10 +41723,10 @@ Format the summary in a way that would be useful for a quick team sync.`
41720
41723
  server2.registerPrompt("retrospective", {
41721
41724
  description: "Run a retrospective on completed work and extract learnings",
41722
41725
  argsSchema: {
41723
- boardId: external_exports.string().describe("The board ID to retrospect on")
41726
+ itemId: external_exports.string().describe("The item ID to retrospect on")
41724
41727
  }
41725
- }, async ({ boardId }) => {
41726
- const board = await api.getFile(boardId);
41728
+ }, async ({ itemId }) => {
41729
+ const board = await api.getFile(itemId);
41727
41730
  const boardJson = JSON.stringify(board, null, 2);
41728
41731
  return {
41729
41732
  messages: [{
@@ -41741,7 +41744,7 @@ Analyze completed tasks and the board state to provide:
41741
41744
  3. **Action Items** \u2014 Concrete improvements for next iteration
41742
41745
  4. **Learnings to Capture** \u2014 Key decisions and patterns worth preserving as knowledge items
41743
41746
 
41744
- For each learning worth capturing, provide add_knowledge or add_learning tool calls so they're preserved for future reference.`
41747
+ For each learning worth capturing, provide add_knowledge tool calls for new knowledge items, or update_learnings tool calls to attach learnings to existing tasks.`
41745
41748
  }
41746
41749
  }]
41747
41750
  };
@@ -41749,10 +41752,10 @@ For each learning worth capturing, provide add_knowledge or add_learning tool ca
41749
41752
  server2.registerPrompt("board_cleanup", {
41750
41753
  description: "Clean up stale tasks, duplicates, and organizational issues",
41751
41754
  argsSchema: {
41752
- boardId: external_exports.string().describe("The board ID to clean up")
41755
+ itemId: external_exports.string().describe("The item ID to clean up")
41753
41756
  }
41754
- }, async ({ boardId }) => {
41755
- const board = await api.getFile(boardId);
41757
+ }, async ({ itemId }) => {
41758
+ const board = await api.getFile(itemId);
41756
41759
  const boardJson = JSON.stringify(board, null, 2);
41757
41760
  return {
41758
41761
  messages: [{
@@ -41779,11 +41782,11 @@ Provide the specific tool calls to implement each cleanup action.`
41779
41782
  server2.registerPrompt("handoff_summary", {
41780
41783
  description: "Generate a handoff summary for transitioning work between people or AI agents",
41781
41784
  argsSchema: {
41782
- boardId: external_exports.string().describe("The board ID to summarize"),
41785
+ itemId: external_exports.string().describe("The item ID to summarize"),
41783
41786
  context: external_exports.string().optional().describe('What the handoff is for (e.g. "new team member", "agent sync")')
41784
41787
  }
41785
- }, async ({ boardId, context }) => {
41786
- const board = await api.getFile(boardId);
41788
+ }, async ({ itemId, context }) => {
41789
+ const board = await api.getFile(itemId);
41787
41790
  const boardJson = JSON.stringify(board, null, 2);
41788
41791
  return {
41789
41792
  messages: [{
package/package.json CHANGED
@@ -1,40 +1,41 @@
1
- {
2
- "name": "automd-mcp",
3
- "version": "0.1.4",
4
- "description": "MCP server for AutoMD — manage Kanban boards stored as markdown",
5
- "type": "module",
6
- "main": "./dist/index.js",
7
- "bin": {
8
- "automd-mcp": "./dist/index.js"
9
- },
10
- "files": [
11
- "dist"
12
- ],
13
- "keywords": [
14
- "mcp",
15
- "model-context-protocol",
16
- "kanban",
17
- "markdown",
18
- "automd",
19
- "task-management"
20
- ],
21
- "repository": {
22
- "type": "git",
23
- "url": "https://github.com/luka-zivkovic/automd"
24
- },
25
- "license": "SEE LICENSE IN LICENSE",
26
- "author": "Luka Zivkovic",
27
- "devDependencies": {
28
- "@modelcontextprotocol/sdk": "^1.26.0",
29
- "@types/mdast": "^4.0.4",
30
- "tsup": "^8.0.0",
31
- "tsx": "^4.19.0",
32
- "typescript": "^5.7.2",
33
- "zod": "^4.3.6"
34
- },
35
- "scripts": {
36
- "dev": "tsx watch src/index.ts",
37
- "start": "node dist/index.js",
38
- "build": "tsup"
39
- }
40
- }
1
+ {
2
+ "name": "automd-mcp",
3
+ "version": "0.2.1",
4
+ "description": "MCP server for AutoMD — manage boards, checklists, and pages stored as markdown",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "bin": {
8
+ "automd-mcp": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "dev": "tsx watch src/index.ts",
15
+ "start": "node dist/index.js",
16
+ "build": "tsup",
17
+ "prepublishOnly": "pnpm build"
18
+ },
19
+ "keywords": [
20
+ "mcp",
21
+ "model-context-protocol",
22
+ "kanban",
23
+ "markdown",
24
+ "automd",
25
+ "task-management"
26
+ ],
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/luka-zivkovic/automd"
30
+ },
31
+ "license": "SEE LICENSE IN LICENSE",
32
+ "author": "Luka Zivkovic",
33
+ "devDependencies": {
34
+ "@modelcontextprotocol/sdk": "^1.26.0",
35
+ "@types/mdast": "^4.0.4",
36
+ "tsup": "^8.0.0",
37
+ "tsx": "^4.19.0",
38
+ "typescript": "^5.7.2",
39
+ "zod": "^4.3.6"
40
+ }
41
+ }
package/LICENSE.md DELETED
@@ -1,60 +0,0 @@
1
- # License
2
-
3
- Portions of this software are licensed as follows:
4
-
5
- - Content of branches other than the main branch (i.e. "master") is not licensed.
6
- - Source code files that contain ".ee." in their filename or ".ee" in their dirname are NOT licensed under the Sustainable Use License. To use source code files that contain ".ee." in their filename or ".ee" in their dirname you must hold a valid AutoMD Enterprise License specifically allowing you access to such source code files, as defined in "LICENSE_EE.md".
7
- - All third party components incorporated into the AutoMD Software are licensed under the original license provided by the owner of the applicable component.
8
- - Content outside of the above mentioned files or restrictions is available under the "Sustainable Use License" as defined below.
9
-
10
- # Sustainable Use License
11
-
12
- Version 1.0
13
-
14
- ## Acceptance
15
-
16
- By using the software, you agree to all of the terms and conditions below.
17
-
18
- ## Copyright License
19
-
20
- The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations below.
21
-
22
- ## Limitations
23
-
24
- You may use or modify the software only for your own internal business purposes or for non-commercial or personal use. You may distribute the software or provide it to others only if you do so free of charge for non-commercial purposes. You may not provide the software to third parties as a hosted or managed service, where the service provides users with access to any substantial set of the features or functionality of the software. You may not move, change, disable, or circumvent the license key functionality in the software, and you may not remove or obscure any functionality in the software that is protected by the license key. You may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensor's trademarks is subject to applicable law.
25
-
26
- ## Patents
27
-
28
- The licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
29
-
30
- ## Notices
31
-
32
- You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms. If you modify the software, you must include in any modified copies of the software a prominent notice stating that you have modified the software.
33
-
34
- ## No Other Rights
35
-
36
- These terms do not imply any licenses other than those expressly granted in these terms.
37
-
38
- ## Termination
39
-
40
- If you use the software in violation of these terms, such use is not licensed, and your license will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violation of this license no later than 30 days after you receive that notice, your license will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your license to terminate automatically and permanently.
41
-
42
- ## No Liability
43
-
44
- As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.
45
-
46
- ## Definitions
47
-
48
- The **licensor** is the entity offering these terms, AutoMD (automd.io).
49
-
50
- The **software** is the software the licensor makes available under these terms, including any portion of it.
51
-
52
- **You** refers to the individual or entity agreeing to these terms.
53
-
54
- **Your company** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. Control means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
55
-
56
- **Your license** is the license granted to you for the software under these terms.
57
-
58
- **Use** means anything you do with the software requiring your license.
59
-
60
- **Trademark** means trademarks, service marks, and similar rights.