wolfpack-mcp 1.0.0 → 1.0.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.
- package/dist/client.js +122 -30
- package/dist/index.js +30 -10
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { ApiClient } from './apiClient.js';
|
|
2
|
+
// Maximum number of items to fetch without confirmation
|
|
3
|
+
const MAX_ITEMS_THRESHOLD = 200;
|
|
4
|
+
// Page size for fetching all items
|
|
5
|
+
const PAGE_SIZE = 50;
|
|
2
6
|
export class WolfpackClient {
|
|
3
7
|
api;
|
|
4
8
|
teamId = null;
|
|
@@ -31,6 +35,48 @@ export class WolfpackClient {
|
|
|
31
35
|
async listTeams() {
|
|
32
36
|
return this.api.get('/teams');
|
|
33
37
|
}
|
|
38
|
+
// Helper to fetch all pages of a paginated endpoint
|
|
39
|
+
async fetchAllPages(endpoint, baseParams) {
|
|
40
|
+
// First request to get total count
|
|
41
|
+
const firstParams = new URLSearchParams(baseParams);
|
|
42
|
+
firstParams.set('limit', PAGE_SIZE.toString());
|
|
43
|
+
firstParams.set('offset', '0');
|
|
44
|
+
const firstQuery = firstParams.toString();
|
|
45
|
+
const firstPage = await this.api.get(`${endpoint}${firstQuery ? `?${firstQuery}` : ''}`);
|
|
46
|
+
// If total exceeds threshold, return first page with truncation warning
|
|
47
|
+
if (firstPage.total > MAX_ITEMS_THRESHOLD) {
|
|
48
|
+
return {
|
|
49
|
+
items: firstPage.items,
|
|
50
|
+
total: firstPage.total,
|
|
51
|
+
truncated: true,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// If all items fit in first page, return them
|
|
55
|
+
if (firstPage.items.length >= firstPage.total) {
|
|
56
|
+
return {
|
|
57
|
+
items: firstPage.items,
|
|
58
|
+
total: firstPage.total,
|
|
59
|
+
truncated: false,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// Fetch remaining pages
|
|
63
|
+
const allItems = [...firstPage.items];
|
|
64
|
+
let offset = PAGE_SIZE;
|
|
65
|
+
while (offset < firstPage.total) {
|
|
66
|
+
const params = new URLSearchParams(baseParams);
|
|
67
|
+
params.set('limit', PAGE_SIZE.toString());
|
|
68
|
+
params.set('offset', offset.toString());
|
|
69
|
+
const query = params.toString();
|
|
70
|
+
const page = await this.api.get(`${endpoint}${query ? `?${query}` : ''}`);
|
|
71
|
+
allItems.push(...page.items);
|
|
72
|
+
offset += PAGE_SIZE;
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
items: allItems,
|
|
76
|
+
total: firstPage.total,
|
|
77
|
+
truncated: false,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
34
80
|
// Work Item methods
|
|
35
81
|
async listWorkItems(options) {
|
|
36
82
|
const params = new URLSearchParams();
|
|
@@ -38,12 +84,22 @@ export class WolfpackClient {
|
|
|
38
84
|
params.append('teamId', options.teamId.toString());
|
|
39
85
|
if (options?.status)
|
|
40
86
|
params.append('status', options.status);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
87
|
+
// If explicit limit/offset provided, use single request (for manual pagination)
|
|
88
|
+
if (options?.limit !== undefined || options?.offset !== undefined) {
|
|
89
|
+
if (options?.limit)
|
|
90
|
+
params.append('limit', options.limit.toString());
|
|
91
|
+
if (options?.offset)
|
|
92
|
+
params.append('offset', options.offset.toString());
|
|
93
|
+
const query = params.toString();
|
|
94
|
+
const response = await this.api.get(`/work-items${query ? `?${query}` : ''}`);
|
|
95
|
+
return {
|
|
96
|
+
items: response.items,
|
|
97
|
+
total: response.total,
|
|
98
|
+
truncated: response.total > response.items.length,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// Otherwise, fetch all pages automatically
|
|
102
|
+
return this.fetchAllPages('/work-items', params);
|
|
47
103
|
}
|
|
48
104
|
async getWorkItem(workItemId, teamId) {
|
|
49
105
|
try {
|
|
@@ -91,12 +147,21 @@ export class WolfpackClient {
|
|
|
91
147
|
params.append('teamId', options.teamId.toString());
|
|
92
148
|
if (options?.stage)
|
|
93
149
|
params.append('stage', options.stage);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
150
|
+
// If explicit limit/offset provided, use single request
|
|
151
|
+
if (options?.limit !== undefined || options?.offset !== undefined) {
|
|
152
|
+
if (options?.limit)
|
|
153
|
+
params.append('limit', options.limit.toString());
|
|
154
|
+
if (options?.offset)
|
|
155
|
+
params.append('offset', options.offset.toString());
|
|
156
|
+
const query = params.toString();
|
|
157
|
+
const response = await this.api.get(`/radar-items${query ? `?${query}` : ''}`);
|
|
158
|
+
return {
|
|
159
|
+
items: response.items,
|
|
160
|
+
total: response.total,
|
|
161
|
+
truncated: response.total > response.items.length,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
return this.fetchAllPages('/radar-items', params);
|
|
100
165
|
}
|
|
101
166
|
async getRadarItem(itemId, teamId) {
|
|
102
167
|
try {
|
|
@@ -126,12 +191,21 @@ export class WolfpackClient {
|
|
|
126
191
|
params.append('type', options.type);
|
|
127
192
|
if (options?.assignedToId)
|
|
128
193
|
params.append('assignedToId', options.assignedToId);
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
194
|
+
// If explicit limit/offset provided, use single request
|
|
195
|
+
if (options?.limit !== undefined || options?.offset !== undefined) {
|
|
196
|
+
if (options?.limit)
|
|
197
|
+
params.append('limit', options.limit.toString());
|
|
198
|
+
if (options?.offset)
|
|
199
|
+
params.append('offset', options.offset.toString());
|
|
200
|
+
const query = params.toString();
|
|
201
|
+
const response = await this.api.get(`/issues${query ? `?${query}` : ''}`);
|
|
202
|
+
return {
|
|
203
|
+
items: response.items,
|
|
204
|
+
total: response.total,
|
|
205
|
+
truncated: response.total > response.items.length,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
return this.fetchAllPages('/issues', params);
|
|
135
209
|
}
|
|
136
210
|
async getIssue(issueId, teamId) {
|
|
137
211
|
try {
|
|
@@ -161,12 +235,21 @@ export class WolfpackClient {
|
|
|
161
235
|
// Wiki Page methods
|
|
162
236
|
async listWikiPages(options) {
|
|
163
237
|
const params = new URLSearchParams();
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
238
|
+
// If explicit limit/offset provided, use single request
|
|
239
|
+
if (options?.limit !== undefined || options?.offset !== undefined) {
|
|
240
|
+
if (options?.limit)
|
|
241
|
+
params.append('limit', options.limit.toString());
|
|
242
|
+
if (options?.offset)
|
|
243
|
+
params.append('offset', options.offset.toString());
|
|
244
|
+
const query = params.toString();
|
|
245
|
+
const response = await this.api.get(`/wiki-pages${query ? `?${query}` : ''}`);
|
|
246
|
+
return {
|
|
247
|
+
items: response.items,
|
|
248
|
+
total: response.total,
|
|
249
|
+
truncated: response.total > response.items.length,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
return this.fetchAllPages('/wiki-pages', params);
|
|
170
253
|
}
|
|
171
254
|
async getWikiPage(pageId) {
|
|
172
255
|
try {
|
|
@@ -188,12 +271,21 @@ export class WolfpackClient {
|
|
|
188
271
|
// Journal Entry methods
|
|
189
272
|
async listJournalEntries(options) {
|
|
190
273
|
const params = new URLSearchParams();
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
274
|
+
// If explicit limit/offset provided, use single request
|
|
275
|
+
if (options?.limit !== undefined || options?.offset !== undefined) {
|
|
276
|
+
if (options?.limit)
|
|
277
|
+
params.append('limit', options.limit.toString());
|
|
278
|
+
if (options?.offset)
|
|
279
|
+
params.append('offset', options.offset.toString());
|
|
280
|
+
const query = params.toString();
|
|
281
|
+
const response = await this.api.get(`/journal-entries${query ? `?${query}` : ''}`);
|
|
282
|
+
return {
|
|
283
|
+
items: response.items,
|
|
284
|
+
total: response.total,
|
|
285
|
+
truncated: response.total > response.items.length,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
return this.fetchAllPages('/journal-entries', params);
|
|
197
289
|
}
|
|
198
290
|
async getJournalEntry(entryId, teamId) {
|
|
199
291
|
try {
|
package/dist/index.js
CHANGED
|
@@ -573,14 +573,18 @@ class WolfpackMCPServer {
|
|
|
573
573
|
// Work Item handlers
|
|
574
574
|
case 'list_work_items': {
|
|
575
575
|
const parsed = ListWorkItemsSchema.parse(args);
|
|
576
|
-
const
|
|
576
|
+
const result = await this.client.listWorkItems({
|
|
577
577
|
teamId: parsed.team_id || this.client.getTeamId() || undefined,
|
|
578
578
|
status: parsed.status,
|
|
579
579
|
limit: parsed.limit,
|
|
580
580
|
offset: parsed.offset,
|
|
581
581
|
});
|
|
582
|
+
let text = JSON.stringify(result.items, null, 2);
|
|
583
|
+
if (result.truncated) {
|
|
584
|
+
text = `Note: Results truncated. Showing ${result.items.length} of ${result.total} items. Use status filter or limit/offset for pagination.\n\n${text}`;
|
|
585
|
+
}
|
|
582
586
|
return {
|
|
583
|
-
content: [{ type: 'text', text
|
|
587
|
+
content: [{ type: 'text', text }],
|
|
584
588
|
};
|
|
585
589
|
}
|
|
586
590
|
case 'get_work_item': {
|
|
@@ -632,14 +636,18 @@ class WolfpackMCPServer {
|
|
|
632
636
|
// Radar Item handlers
|
|
633
637
|
case 'list_radar_items': {
|
|
634
638
|
const parsed = ListRadarItemsSchema.parse(args);
|
|
635
|
-
const
|
|
639
|
+
const result = await this.client.listRadarItems({
|
|
636
640
|
teamId: parsed.team_id,
|
|
637
641
|
stage: parsed.stage,
|
|
638
642
|
limit: parsed.limit,
|
|
639
643
|
offset: parsed.offset,
|
|
640
644
|
});
|
|
645
|
+
let text = JSON.stringify(result.items, null, 2);
|
|
646
|
+
if (result.truncated) {
|
|
647
|
+
text = `Note: Results truncated. Showing ${result.items.length} of ${result.total} items. Use stage filter or limit/offset for pagination.\n\n${text}`;
|
|
648
|
+
}
|
|
641
649
|
return {
|
|
642
|
-
content: [{ type: 'text', text
|
|
650
|
+
content: [{ type: 'text', text }],
|
|
643
651
|
};
|
|
644
652
|
}
|
|
645
653
|
case 'get_radar_item': {
|
|
@@ -657,7 +665,7 @@ class WolfpackMCPServer {
|
|
|
657
665
|
// Issue handlers
|
|
658
666
|
case 'list_issues': {
|
|
659
667
|
const parsed = ListIssuesSchema.parse(args);
|
|
660
|
-
const
|
|
668
|
+
const result = await this.client.listIssues({
|
|
661
669
|
teamId: parsed.team_id,
|
|
662
670
|
status: parsed.status,
|
|
663
671
|
severity: parsed.severity,
|
|
@@ -666,8 +674,12 @@ class WolfpackMCPServer {
|
|
|
666
674
|
limit: parsed.limit,
|
|
667
675
|
offset: parsed.offset,
|
|
668
676
|
});
|
|
677
|
+
let text = JSON.stringify(result.items, null, 2);
|
|
678
|
+
if (result.truncated) {
|
|
679
|
+
text = `Note: Results truncated. Showing ${result.items.length} of ${result.total} items. Use filters or limit/offset for pagination.\n\n${text}`;
|
|
680
|
+
}
|
|
669
681
|
return {
|
|
670
|
-
content: [{ type: 'text', text
|
|
682
|
+
content: [{ type: 'text', text }],
|
|
671
683
|
};
|
|
672
684
|
}
|
|
673
685
|
case 'get_issue': {
|
|
@@ -747,12 +759,16 @@ class WolfpackMCPServer {
|
|
|
747
759
|
// Wiki Page handlers
|
|
748
760
|
case 'list_wiki_pages': {
|
|
749
761
|
const parsed = ListWikiPagesSchema.parse(args);
|
|
750
|
-
const
|
|
762
|
+
const result = await this.client.listWikiPages({
|
|
751
763
|
limit: parsed.limit,
|
|
752
764
|
offset: parsed.offset,
|
|
753
765
|
});
|
|
766
|
+
let text = JSON.stringify(result.items, null, 2);
|
|
767
|
+
if (result.truncated) {
|
|
768
|
+
text = `Note: Results truncated. Showing ${result.items.length} of ${result.total} pages. Use limit/offset for pagination.\n\n${text}`;
|
|
769
|
+
}
|
|
754
770
|
return {
|
|
755
|
-
content: [{ type: 'text', text
|
|
771
|
+
content: [{ type: 'text', text }],
|
|
756
772
|
};
|
|
757
773
|
}
|
|
758
774
|
case 'get_wiki_page': {
|
|
@@ -801,12 +817,16 @@ class WolfpackMCPServer {
|
|
|
801
817
|
// Journal Entry handlers
|
|
802
818
|
case 'list_journal_entries': {
|
|
803
819
|
const parsed = ListJournalEntriesSchema.parse(args);
|
|
804
|
-
const
|
|
820
|
+
const result = await this.client.listJournalEntries({
|
|
805
821
|
limit: parsed.limit,
|
|
806
822
|
offset: parsed.offset,
|
|
807
823
|
});
|
|
824
|
+
let text = JSON.stringify(result.items, null, 2);
|
|
825
|
+
if (result.truncated) {
|
|
826
|
+
text = `Note: Results truncated. Showing ${result.items.length} of ${result.total} entries. Use limit/offset for pagination.\n\n${text}`;
|
|
827
|
+
}
|
|
808
828
|
return {
|
|
809
|
-
content: [{ type: 'text', text
|
|
829
|
+
content: [{ type: 'text', text }],
|
|
810
830
|
};
|
|
811
831
|
}
|
|
812
832
|
case 'get_journal_entry': {
|