@zoobbe/cli 1.2.2 → 1.2.3
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 +4 -0
- package/package.json +1 -1
- package/src/index.js +4 -0
- package/src/lib/client.js +23 -6
- package/src/mcp-server.js +16 -13
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
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
|
-
|
|
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
640
|
await client.post(`/cards/update/${args.card_id}`, { isComplete: true });
|
|
638
|
-
return { done: true, card_id: args.card_id };
|
|
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
645
|
await client.post(`/cards/update/${args.card_id}`, { isComplete: false });
|
|
643
|
-
return { undone: true, card_id: args.card_id };
|
|
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': {
|