@taiga-ai/mcp-server 0.2.3-dev.290 → 0.2.3-dev.292
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/index.js
CHANGED
|
@@ -47,14 +47,14 @@ var TaigaClient = class {
|
|
|
47
47
|
}
|
|
48
48
|
async listProjects(opts) {
|
|
49
49
|
const params = new URLSearchParams();
|
|
50
|
-
if (opts?.teamId) params.set("
|
|
50
|
+
if (opts?.teamId) params.set("factoryId", opts.teamId);
|
|
51
51
|
if (opts?.status) params.set("status", opts.status);
|
|
52
52
|
if (opts?.limit) params.set("limit", String(opts.limit));
|
|
53
53
|
const qs = params.toString();
|
|
54
|
-
return this.request("GET", `/
|
|
54
|
+
return this.request("GET", `/products${qs ? `?${qs}` : ""}`);
|
|
55
55
|
}
|
|
56
56
|
async getProject(id) {
|
|
57
|
-
return this.request("GET", `/
|
|
57
|
+
return this.request("GET", `/products/${id}`);
|
|
58
58
|
}
|
|
59
59
|
async listTenantDocuments(opts) {
|
|
60
60
|
const params = new URLSearchParams();
|
|
@@ -72,22 +72,22 @@ var TaigaClient = class {
|
|
|
72
72
|
const params = new URLSearchParams();
|
|
73
73
|
if (opts?.limit) params.set("limit", String(opts.limit));
|
|
74
74
|
const qs = params.toString();
|
|
75
|
-
return this.request("GET", `/
|
|
75
|
+
return this.request("GET", `/factories/${teamId}/documents${qs ? `?${qs}` : ""}`);
|
|
76
76
|
}
|
|
77
77
|
async getTeamDocument(teamId, type) {
|
|
78
|
-
return this.request("GET", `/
|
|
78
|
+
return this.request("GET", `/factories/${teamId}/documents/${type}`);
|
|
79
79
|
}
|
|
80
80
|
async saveTeamDocumentDraft(teamId, type, body) {
|
|
81
|
-
return this.request("PUT", `/
|
|
81
|
+
return this.request("PUT", `/factories/${teamId}/documents/${type}/draft`, body);
|
|
82
82
|
}
|
|
83
83
|
async listProjectDocuments(projectId, opts) {
|
|
84
84
|
const params = new URLSearchParams();
|
|
85
85
|
if (opts?.limit) params.set("limit", String(opts.limit));
|
|
86
86
|
const qs = params.toString();
|
|
87
|
-
return this.request("GET", `/
|
|
87
|
+
return this.request("GET", `/products/${projectId}/documents${qs ? `?${qs}` : ""}`);
|
|
88
88
|
}
|
|
89
89
|
async getProjectDocument(projectId, type) {
|
|
90
|
-
return this.request("GET", `/
|
|
90
|
+
return this.request("GET", `/products/${projectId}/documents/${type}`);
|
|
91
91
|
}
|
|
92
92
|
/**
|
|
93
93
|
* Fetch the full context for a project in parallel: project metadata,
|
|
@@ -95,8 +95,8 @@ var TaigaClient = class {
|
|
|
95
95
|
* Returns a structured bundle optimized for coding agent consumption.
|
|
96
96
|
*/
|
|
97
97
|
async getProjectContext(projectId) {
|
|
98
|
-
const project = await this.request("GET", `/
|
|
99
|
-
const teamId = project.data.
|
|
98
|
+
const project = await this.request("GET", `/products/${projectId}`);
|
|
99
|
+
const teamId = project.data.factoryId;
|
|
100
100
|
const [projectDocs, teamDocs] = await Promise.all([this.listProjectDocuments(projectId, { limit: 20 }).catch(() => ({ data: [] })), teamId ? this.listTeamDocuments(teamId, { limit: 20 }).catch(() => ({ data: [] })) : Promise.resolve({ data: [] })]);
|
|
101
101
|
const keyProjectDocTypes = [
|
|
102
102
|
"specification",
|
|
@@ -156,19 +156,19 @@ var TaigaClient = class {
|
|
|
156
156
|
const params = new URLSearchParams();
|
|
157
157
|
if (opts?.limit) params.set("limit", String(opts.limit));
|
|
158
158
|
const qs = params.toString();
|
|
159
|
-
return this.request("GET", `/
|
|
159
|
+
return this.request("GET", `/products/${projectId}/backlog${qs ? `?${qs}` : ""}`);
|
|
160
160
|
}
|
|
161
161
|
async getBacklogItem(itemId) {
|
|
162
162
|
return this.request("GET", `/backlog/${itemId}`);
|
|
163
163
|
}
|
|
164
164
|
async listEnvironments(projectId) {
|
|
165
|
-
return this.request("GET", `/
|
|
165
|
+
return this.request("GET", `/products/${projectId}/environments`);
|
|
166
166
|
}
|
|
167
167
|
async listTeams(opts) {
|
|
168
168
|
const params = new URLSearchParams();
|
|
169
169
|
if (opts?.limit) params.set("limit", String(opts.limit));
|
|
170
170
|
const qs = params.toString();
|
|
171
|
-
return this.request("GET", `/
|
|
171
|
+
return this.request("GET", `/factories${qs ? `?${qs}` : ""}`);
|
|
172
172
|
}
|
|
173
173
|
};
|
|
174
174
|
//#endregion
|
package/package.json
CHANGED
package/src/client.test.ts
CHANGED
|
@@ -109,7 +109,7 @@ describe('TaigaClient', () => {
|
|
|
109
109
|
|
|
110
110
|
await client.listProjects();
|
|
111
111
|
|
|
112
|
-
expect(spy.mock.calls[0][0]).toBe('https://api.test.com/v1/
|
|
112
|
+
expect(spy.mock.calls[0][0]).toBe('https://api.test.com/v1/products');
|
|
113
113
|
});
|
|
114
114
|
|
|
115
115
|
it('should omit query string when no optional params are provided', async () => {
|
|
@@ -117,7 +117,7 @@ describe('TaigaClient', () => {
|
|
|
117
117
|
|
|
118
118
|
await makeClient().listProjects();
|
|
119
119
|
|
|
120
|
-
expect(spy.mock.calls[0][0]).toBe('https://api.test.com/v1/
|
|
120
|
+
expect(spy.mock.calls[0][0]).toBe('https://api.test.com/v1/products');
|
|
121
121
|
});
|
|
122
122
|
|
|
123
123
|
it('should include all optional filters as query params', async () => {
|
|
@@ -126,7 +126,7 @@ describe('TaigaClient', () => {
|
|
|
126
126
|
await makeClient().listProjects({ teamId: 't1', status: 'active', limit: 10 });
|
|
127
127
|
|
|
128
128
|
const url = spy.mock.calls[0][0] as string;
|
|
129
|
-
expect(url).toContain('
|
|
129
|
+
expect(url).toContain('factoryId=t1');
|
|
130
130
|
expect(url).toContain('status=active');
|
|
131
131
|
expect(url).toContain('limit=10');
|
|
132
132
|
});
|
|
@@ -137,7 +137,7 @@ describe('TaigaClient', () => {
|
|
|
137
137
|
await makeClient().listBacklogItems('proj-1', { limit: 20 });
|
|
138
138
|
|
|
139
139
|
const url = spy.mock.calls[0][0] as string;
|
|
140
|
-
expect(url).toContain('/v1/
|
|
140
|
+
expect(url).toContain('/v1/products/proj-1/backlog');
|
|
141
141
|
expect(url).toContain('limit=20');
|
|
142
142
|
});
|
|
143
143
|
|
|
@@ -146,7 +146,7 @@ describe('TaigaClient', () => {
|
|
|
146
146
|
|
|
147
147
|
await makeClient().listEnvironments('proj-1');
|
|
148
148
|
|
|
149
|
-
expect(spy.mock.calls[0][0]).toBe('https://api.test.com/v1/
|
|
149
|
+
expect(spy.mock.calls[0][0]).toBe('https://api.test.com/v1/products/proj-1/environments');
|
|
150
150
|
});
|
|
151
151
|
});
|
|
152
152
|
|
|
@@ -207,7 +207,7 @@ describe('TaigaClient', () => {
|
|
|
207
207
|
|
|
208
208
|
const result = await makeClient().getProject('p1');
|
|
209
209
|
|
|
210
|
-
expect(spy.mock.calls[0][0]).toBe('https://api.test.com/v1/
|
|
210
|
+
expect(spy.mock.calls[0][0]).toBe('https://api.test.com/v1/products/p1');
|
|
211
211
|
expect(result.data).toEqual({ id: 'p1', name: 'Alpha' });
|
|
212
212
|
});
|
|
213
213
|
|
|
@@ -244,7 +244,7 @@ describe('TaigaClient', () => {
|
|
|
244
244
|
|
|
245
245
|
await makeClient().listTeams({ limit: 50 });
|
|
246
246
|
|
|
247
|
-
expect(spy.mock.calls[0][0]).toContain('/v1/
|
|
247
|
+
expect(spy.mock.calls[0][0]).toContain('/v1/factories?limit=50');
|
|
248
248
|
});
|
|
249
249
|
|
|
250
250
|
it('should GET documents from tenant path with optional limit', async () => {
|
package/src/client.ts
CHANGED
|
@@ -61,15 +61,15 @@ export class TaigaClient {
|
|
|
61
61
|
|
|
62
62
|
async listProjects(opts?: { teamId?: string; status?: string; limit?: number }) {
|
|
63
63
|
const params = new URLSearchParams();
|
|
64
|
-
if (opts?.teamId) params.set('
|
|
64
|
+
if (opts?.teamId) params.set('factoryId', opts.teamId);
|
|
65
65
|
if (opts?.status) params.set('status', opts.status);
|
|
66
66
|
if (opts?.limit) params.set('limit', String(opts.limit));
|
|
67
67
|
const qs = params.toString();
|
|
68
|
-
return this.request<{ data: unknown[]; nextCursor: string | null }>('GET', `/
|
|
68
|
+
return this.request<{ data: unknown[]; nextCursor: string | null }>('GET', `/products${qs ? `?${qs}` : ''}`);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
async getProject(id: string) {
|
|
72
|
-
return this.request<{ data: unknown }>('GET', `/
|
|
72
|
+
return this.request<{ data: unknown }>('GET', `/products/${id}`);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
// ---------------------------------------------------------------------------
|
|
@@ -104,16 +104,16 @@ export class TaigaClient {
|
|
|
104
104
|
const qs = params.toString();
|
|
105
105
|
return this.request<{ data: unknown[]; nextCursor: string | null }>(
|
|
106
106
|
'GET',
|
|
107
|
-
`/
|
|
107
|
+
`/factories/${teamId}/documents${qs ? `?${qs}` : ''}`
|
|
108
108
|
);
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
async getTeamDocument(teamId: string, type: string) {
|
|
112
|
-
return this.request<{ data: unknown }>('GET', `/
|
|
112
|
+
return this.request<{ data: unknown }>('GET', `/factories/${teamId}/documents/${type}`);
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
async saveTeamDocumentDraft(teamId: string, type: string, body: { data: Record<string, unknown> }) {
|
|
116
|
-
return this.request<{ data: unknown }>('PUT', `/
|
|
116
|
+
return this.request<{ data: unknown }>('PUT', `/factories/${teamId}/documents/${type}/draft`, body);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
// ---------------------------------------------------------------------------
|
|
@@ -126,12 +126,12 @@ export class TaigaClient {
|
|
|
126
126
|
const qs = params.toString();
|
|
127
127
|
return this.request<{ data: unknown[]; nextCursor: string | null }>(
|
|
128
128
|
'GET',
|
|
129
|
-
`/
|
|
129
|
+
`/products/${projectId}/documents${qs ? `?${qs}` : ''}`
|
|
130
130
|
);
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
async getProjectDocument(projectId: string, type: string) {
|
|
134
|
-
return this.request<{ data: unknown }>('GET', `/
|
|
134
|
+
return this.request<{ data: unknown }>('GET', `/products/${projectId}/documents/${type}`);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
// ---------------------------------------------------------------------------
|
|
@@ -144,9 +144,9 @@ export class TaigaClient {
|
|
|
144
144
|
* Returns a structured bundle optimized for coding agent consumption.
|
|
145
145
|
*/
|
|
146
146
|
async getProjectContext(projectId: string): Promise<Record<string, unknown>> {
|
|
147
|
-
// First fetch the project to get the
|
|
148
|
-
const project = await this.request<{ data: Record<string, unknown> }>('GET', `/
|
|
149
|
-
const teamId = project.data.
|
|
147
|
+
// First fetch the project to get its factory (the API's name for a team since PRO-1668)
|
|
148
|
+
const project = await this.request<{ data: Record<string, unknown> }>('GET', `/products/${projectId}`);
|
|
149
|
+
const teamId = project.data.factoryId as string | undefined;
|
|
150
150
|
|
|
151
151
|
// Fetch the document lists in parallel.
|
|
152
152
|
const [projectDocs, teamDocs] = await Promise.all([
|
|
@@ -226,7 +226,7 @@ export class TaigaClient {
|
|
|
226
226
|
const qs = params.toString();
|
|
227
227
|
return this.request<{ data: unknown[]; nextCursor: string | null }>(
|
|
228
228
|
'GET',
|
|
229
|
-
`/
|
|
229
|
+
`/products/${projectId}/backlog${qs ? `?${qs}` : ''}`
|
|
230
230
|
);
|
|
231
231
|
}
|
|
232
232
|
|
|
@@ -239,7 +239,7 @@ export class TaigaClient {
|
|
|
239
239
|
// ---------------------------------------------------------------------------
|
|
240
240
|
|
|
241
241
|
async listEnvironments(projectId: string) {
|
|
242
|
-
return this.request<{ data: unknown[] }>('GET', `/
|
|
242
|
+
return this.request<{ data: unknown[] }>('GET', `/products/${projectId}/environments`);
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
// ---------------------------------------------------------------------------
|
|
@@ -250,6 +250,6 @@ export class TaigaClient {
|
|
|
250
250
|
const params = new URLSearchParams();
|
|
251
251
|
if (opts?.limit) params.set('limit', String(opts.limit));
|
|
252
252
|
const qs = params.toString();
|
|
253
|
-
return this.request<{ data: unknown[]; nextCursor: string | null }>('GET', `/
|
|
253
|
+
return this.request<{ data: unknown[]; nextCursor: string | null }>('GET', `/factories${qs ? `?${qs}` : ''}`);
|
|
254
254
|
}
|
|
255
255
|
}
|
|
@@ -266,7 +266,7 @@ describe('MCP server integration', () => {
|
|
|
266
266
|
|
|
267
267
|
const { client } = await bootMcpPair({
|
|
268
268
|
capabilities: ALL_CAPABILITIES,
|
|
269
|
-
routes: { 'GET /v1/
|
|
269
|
+
routes: { 'GET /v1/factories': { data: teams, nextCursor: null } },
|
|
270
270
|
});
|
|
271
271
|
|
|
272
272
|
const result = await client.callTool({ name: 'taiga_list_teams', arguments: {} });
|
|
@@ -314,7 +314,7 @@ describe('MCP server integration', () => {
|
|
|
314
314
|
|
|
315
315
|
const { client, fetchSpy } = await bootMcpPair({
|
|
316
316
|
capabilities: ALL_CAPABILITIES,
|
|
317
|
-
routes: { [`PUT /v1/
|
|
317
|
+
routes: { [`PUT /v1/factories/${teamId}/documents/${docType}/draft`]: { data: updated } },
|
|
318
318
|
});
|
|
319
319
|
|
|
320
320
|
await client.callTool({
|
|
@@ -323,10 +323,10 @@ describe('MCP server integration', () => {
|
|
|
323
323
|
});
|
|
324
324
|
|
|
325
325
|
const putCall = fetchSpy.mock.calls.find(
|
|
326
|
-
(c: unknown[]) => (c[1] as RequestInit)?.method === 'PUT' && (c[0] as string).includes('/
|
|
326
|
+
(c: unknown[]) => (c[1] as RequestInit)?.method === 'PUT' && (c[0] as string).includes('/factories/')
|
|
327
327
|
);
|
|
328
328
|
expect(putCall).toBeDefined();
|
|
329
|
-
expect(putCall![0]).toContain(`/v1/
|
|
329
|
+
expect(putCall![0]).toContain(`/v1/factories/${teamId}/documents/${docType}/draft`);
|
|
330
330
|
});
|
|
331
331
|
|
|
332
332
|
it('should return teams through MCP protocol', async () => {
|
|
@@ -334,7 +334,7 @@ describe('MCP server integration', () => {
|
|
|
334
334
|
|
|
335
335
|
const { client } = await bootMcpPair({
|
|
336
336
|
capabilities: ALL_CAPABILITIES,
|
|
337
|
-
routes: { 'GET /v1/
|
|
337
|
+
routes: { 'GET /v1/factories': { data: teams, nextCursor: null } },
|
|
338
338
|
});
|
|
339
339
|
|
|
340
340
|
const result = await client.callTool({ name: 'taiga_list_teams', arguments: {} });
|
|
Binary file
|
|
Binary file
|