@zoobbe/cli 1.2.2 → 1.2.4

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
@@ -392,6 +392,10 @@ Once connected, Claude can read and manage your workspace through natural langua
392
392
  - "Move card abc123 to Done"
393
393
  - "What happened on the board this week?"
394
394
 
395
+ ### Source Attribution
396
+
397
+ All changes made through the MCP server are automatically tagged in activity logs as **(via AI Agent)**, and CLI commands are tagged as **(via CLI)**. This lets your team distinguish between manual and automated actions when reviewing card or board history.
398
+
395
399
  ### Available tools (28)
396
400
 
397
401
  | Category | Tools |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zoobbe/cli",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "description": "Zoobbe CLI - Manage boards, cards, and projects from the terminal",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -333,7 +333,7 @@ card
333
333
  .action(async (cardId) => {
334
334
  try {
335
335
  await withSpinner('Updating card...', () =>
336
- client.post(`/cards/update/${cardId}`, { isComplete: true })
336
+ client.post(`/cards/update/${cardId}`, { completed: true })
337
337
  );
338
338
 
339
339
  success(`Card ${cardId} marked as complete`);
@@ -658,7 +658,7 @@ card
658
658
  .action(async (cardId) => {
659
659
  try {
660
660
  await withSpinner('Updating card...', () =>
661
- client.post(`/cards/update/${cardId}`, { isComplete: false })
661
+ client.post(`/cards/update/${cardId}`, { completed: false })
662
662
  );
663
663
  success(`Card ${cardId} marked as incomplete`);
664
664
  } catch (err) {
package/src/index.js CHANGED
@@ -1,6 +1,10 @@
1
1
  const { Command } = require('commander');
2
2
  const chalk = require('chalk');
3
3
  const pkg = require('../package.json');
4
+ const client = require('./lib/client');
5
+
6
+ // Mark all requests from CLI as CLI actions
7
+ client.setSource('cli');
4
8
 
5
9
  const program = new Command();
6
10
 
package/src/lib/client.js CHANGED
@@ -1,6 +1,14 @@
1
1
  const config = require('./config');
2
2
 
3
3
  class ZoobbeClient {
4
+ constructor() {
5
+ this._source = null;
6
+ }
7
+
8
+ setSource(source) {
9
+ this._source = source;
10
+ }
11
+
4
12
  get baseUrl() {
5
13
  return config.get('apiUrl');
6
14
  }
@@ -10,11 +18,15 @@ class ZoobbeClient {
10
18
  }
11
19
 
12
20
  get headers() {
13
- return {
21
+ const h = {
14
22
  'Authorization': `Bearer ${this.apiKey}`,
15
23
  'Content-Type': 'application/json',
16
24
  'User-Agent': 'Zoobbe-CLI/1.0',
17
25
  };
26
+ if (this._source) {
27
+ h['X-Zoobbe-Source'] = this._source;
28
+ }
29
+ return h;
18
30
  }
19
31
 
20
32
  ensureAuth() {
@@ -96,13 +108,18 @@ class ZoobbeClient {
96
108
 
97
109
  const body = Buffer.concat([Buffer.from(header), fileBuffer, Buffer.from(footer)]);
98
110
 
111
+ const uploadHeaders = {
112
+ 'Authorization': `Bearer ${this.apiKey}`,
113
+ 'User-Agent': 'Zoobbe-CLI/1.0',
114
+ 'Content-Type': `multipart/form-data; boundary=${boundary}`,
115
+ };
116
+ if (this._source) {
117
+ uploadHeaders['X-Zoobbe-Source'] = this._source;
118
+ }
119
+
99
120
  const response = await fetch(url, {
100
121
  method: 'POST',
101
- headers: {
102
- 'Authorization': `Bearer ${this.apiKey}`,
103
- 'User-Agent': 'Zoobbe-CLI/1.0',
104
- 'Content-Type': `multipart/form-data; boundary=${boundary}`,
105
- },
122
+ headers: uploadHeaders,
106
123
  body,
107
124
  });
108
125
 
package/src/mcp-server.js CHANGED
@@ -16,6 +16,9 @@ const readline = require('readline');
16
16
  const client = require('./lib/client');
17
17
  const config = require('./lib/config');
18
18
 
19
+ // Mark all requests from MCP server as AI agent actions
20
+ client.setSource('mcp');
21
+
19
22
  // ── Tool Definitions ──
20
23
 
21
24
  const TOOLS = [
@@ -580,7 +583,7 @@ async function executeTool(name, args = {}) {
580
583
  await client.post(`/cards/${cardId}/priority`, { priority: args.priority });
581
584
  }
582
585
 
583
- return { created: true, title: args.title, id: cardId };
586
+ return { created: true, title: args.title, id: cardId, changed_by: 'AI Agent (via MCP)' };
584
587
  }
585
588
 
586
589
  case 'update_card': {
@@ -589,7 +592,7 @@ async function executeTool(name, args = {}) {
589
592
  if (args.description) body.description = args.description;
590
593
  if (Object.keys(body).length === 0) throw new Error('Provide title or description to update');
591
594
  await client.post(`/cards/update/${args.card_id}`, body);
592
- return { updated: true, card_id: args.card_id };
595
+ return { updated: true, card_id: args.card_id, changed_by: 'AI Agent (via MCP)' };
593
596
  }
594
597
 
595
598
  case 'move_card': {
@@ -617,12 +620,12 @@ async function executeTool(name, args = {}) {
617
620
  targetListId: targetList._id,
618
621
  targetPosition: 0,
619
622
  });
620
- return { moved: true, card_id: args.card_id, to: targetList.title };
623
+ return { moved: true, card_id: args.card_id, to: targetList.title, changed_by: 'AI Agent (via MCP)' };
621
624
  }
622
625
 
623
626
  case 'assign_card': {
624
627
  await client.post(`/cards/${args.card_id}/addMember`, { memberId: args.user_id });
625
- return { assigned: true, card_id: args.card_id, user_id: args.user_id };
628
+ return { assigned: true, card_id: args.card_id, user_id: args.user_id, changed_by: 'AI Agent (via MCP)' };
626
629
  }
627
630
 
628
631
  case 'add_comment': {
@@ -630,36 +633,36 @@ async function executeTool(name, args = {}) {
630
633
  await client.post(`/cards/${args.card_id}/comments`, {
631
634
  comment: args.comment, member: userId, mentionedIds: [],
632
635
  });
633
- return { commented: true, card_id: args.card_id };
636
+ return { commented: true, card_id: args.card_id, changed_by: 'AI Agent (via MCP)' };
634
637
  }
635
638
 
636
639
  case 'mark_card_done': {
637
- await client.post(`/cards/update/${args.card_id}`, { isComplete: true });
638
- return { done: true, card_id: args.card_id };
640
+ await client.post(`/cards/update/${args.card_id}`, { completed: true });
641
+ return { done: true, card_id: args.card_id, changed_by: 'AI Agent (via MCP)' };
639
642
  }
640
643
 
641
644
  case 'mark_card_undone': {
642
- await client.post(`/cards/update/${args.card_id}`, { isComplete: false });
643
- return { undone: true, card_id: args.card_id };
645
+ await client.post(`/cards/update/${args.card_id}`, { completed: false });
646
+ return { undone: true, card_id: args.card_id, changed_by: 'AI Agent (via MCP)' };
644
647
  }
645
648
 
646
649
  case 'set_due_date': {
647
650
  if (!args.due_date) {
648
651
  await client.delete(`/cards/${args.card_id}/duedate`);
649
- return { removed: true, card_id: args.card_id };
652
+ return { removed: true, card_id: args.card_id, changed_by: 'AI Agent (via MCP)' };
650
653
  }
651
654
  await client.post(`/cards/${args.card_id}/duedate`, { dueDate: args.due_date });
652
- return { set: true, card_id: args.card_id, due_date: args.due_date };
655
+ return { set: true, card_id: args.card_id, due_date: args.due_date, changed_by: 'AI Agent (via MCP)' };
653
656
  }
654
657
 
655
658
  case 'set_priority': {
656
659
  await client.post(`/cards/${args.card_id}/priority`, { priority: args.priority });
657
- return { set: true, card_id: args.card_id, priority: args.priority };
660
+ return { set: true, card_id: args.card_id, priority: args.priority, changed_by: 'AI Agent (via MCP)' };
658
661
  }
659
662
 
660
663
  case 'archive_card': {
661
664
  await client.post(`/cards/archive/${args.card_id}`);
662
- return { archived: true, card_id: args.card_id };
665
+ return { archived: true, card_id: args.card_id, changed_by: 'AI Agent (via MCP)' };
663
666
  }
664
667
 
665
668
  // ── Write: Board/List ──
@@ -675,13 +678,13 @@ async function executeTool(name, args = {}) {
675
678
  visibility: args.visibility || 'Private',
676
679
  });
677
680
  const b = data.board || data.data || data;
678
- return { created: true, name: args.name, id: b.shortId };
681
+ return { created: true, name: args.name, id: b.shortId, changed_by: 'AI Agent (via MCP)' };
679
682
  }
680
683
 
681
684
  case 'create_list': {
682
685
  const data = await client.post('/actionLists', { title: args.title, boardId: args.board_id });
683
686
  const l = data.actionList || data.data || data;
684
- return { created: true, title: args.title, id: l._id };
687
+ return { created: true, title: args.title, id: l._id, changed_by: 'AI Agent (via MCP)' };
685
688
  }
686
689
 
687
690
  case 'mark_notifications_read': {