@taiga-ai/mcp-server 0.12.0-dev.421 → 0.13.0-dev.422
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 +348 -85
- package/package.json +1 -1
- package/src/client.ts +34 -21
- package/src/server.integration.test.ts +295 -92
- package/src/tools/annotations.ts +6 -0
- package/src/tools/backlogs.ts +118 -58
- package/src/tools/builds.ts +13 -29
- package/src/tools/index.ts +2 -0
- package/src/tools/instructions.ts +19 -13
- package/src/tools/jobs.ts +89 -0
- package/src/tools/queue.ts +61 -4
- package/src/tools/request-prompt.test.ts +32 -0
- package/src/tools/request-prompt.ts +28 -0
- package/src/tools/wait.ts +38 -0
- package/taiga-ai-mcp-server-0.13.0-dev.422.tgz +0 -0
- package/taiga-ai-mcp-server-0.12.0-dev.421.tgz +0 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The planner's prompt for an initiative request, built as the web builds it
|
|
3
|
+
* (apps/web/src/features/loops/delivery/components/planning/generateBacklogJob.ts):
|
|
4
|
+
* title and description trimmed, the description's inline-image markdown
|
|
5
|
+
* removed and the blank lines it leaves collapsed, joined by a blank line.
|
|
6
|
+
* The planner reads `userPrompt` and nothing else of the request, so the same
|
|
7
|
+
* words must make the same prompt from either surface.
|
|
8
|
+
*
|
|
9
|
+
* The image pattern is the web's (inline-image-doc-ids.ts), which keeps it in
|
|
10
|
+
* lockstep with the API's `extractInlineImageDocIds`: the `` form,
|
|
11
|
+
* an exact UUID, and a terminator after `/image`.
|
|
12
|
+
*/
|
|
13
|
+
const INLINE_IMAGE_RE =
|
|
14
|
+
/!\[(?:[^\]\\]|\\.)*\]\([^)]*?\/custom-documents\/([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})\/image(?=[)?#\s])[^)]*\)/g;
|
|
15
|
+
|
|
16
|
+
/** The description without its inline images, as the web strips it. */
|
|
17
|
+
export function stripInlineImages(markdown: string): string {
|
|
18
|
+
return markdown
|
|
19
|
+
.replace(INLINE_IMAGE_RE, '')
|
|
20
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
21
|
+
.trim();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** The prompt for a title and a description; undefined when both are empty, which asks for a suggestion. */
|
|
25
|
+
export function requestPrompt(title: string | undefined, description: string | undefined): string | undefined {
|
|
26
|
+
const body = stripInlineImages((description ?? '').trim());
|
|
27
|
+
return [(title ?? '').trim(), body].filter(Boolean).join('\n\n') || undefined;
|
|
28
|
+
}
|
package/src/tools/wait.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { z } from 'zod';
|
|
|
4
4
|
import { TaigaApiError, type TaigaClient } from '../client.js';
|
|
5
5
|
import { READ_ONLY } from './annotations.js';
|
|
6
6
|
import { isNetworkFailure, runTool, toolResult } from './errors.js';
|
|
7
|
+
import { SETTLED_JOB_STATUSES, jobReport } from './jobs.js';
|
|
7
8
|
import { criteriaCounts, pickFields } from './summarize.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
@@ -176,6 +177,8 @@ function itemSignature(item: Row): string {
|
|
|
176
177
|
item.state,
|
|
177
178
|
item.planningStatus,
|
|
178
179
|
item.needsHumanCause,
|
|
180
|
+
// The review gate decides whose turn a landed plan is, while the lifecycle reads the same either way.
|
|
181
|
+
item.autoBuild,
|
|
179
182
|
lifecycle.stage,
|
|
180
183
|
lifecycle.turn,
|
|
181
184
|
lifecycle.cta,
|
|
@@ -442,4 +445,39 @@ export function registerWaitTools(server: McpServer, client: TaigaClient, option
|
|
|
442
445
|
})
|
|
443
446
|
);
|
|
444
447
|
}
|
|
448
|
+
|
|
449
|
+
if (client.hasCapability('products:read')) {
|
|
450
|
+
server.registerTool(
|
|
451
|
+
'taiga_wait_for_job',
|
|
452
|
+
{
|
|
453
|
+
title: 'Wait for an agent job',
|
|
454
|
+
description:
|
|
455
|
+
'Wait until an agent job finishes (completed, failed or cancelled): an initiative request, a document, ' +
|
|
456
|
+
'a refresh. Returns the job as taiga_get_job reads it, with what came of an initiative request, as soon ' +
|
|
457
|
+
'as it settles (reached: true), or at the timeout with reached: false: call again to keep waiting. Most ' +
|
|
458
|
+
'jobs take a few minutes.',
|
|
459
|
+
inputSchema: {
|
|
460
|
+
jobId: z.string().uuid().describe('Agent job ID -- a request tool returns it'),
|
|
461
|
+
timeoutSeconds,
|
|
462
|
+
},
|
|
463
|
+
annotations: READ_ONLY,
|
|
464
|
+
},
|
|
465
|
+
(params, extra) =>
|
|
466
|
+
runTool(async () => {
|
|
467
|
+
const result = await waitFor(
|
|
468
|
+
async (signal) => (await client.getAgentJob(params.jobId, signal)).data as Row,
|
|
469
|
+
(job) => (SETTLED_JOB_STATUSES.has(String(job.status)) ? { reached: true } : null),
|
|
470
|
+
(params.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS) * 1000,
|
|
471
|
+
options,
|
|
472
|
+
{
|
|
473
|
+
progressToken: extra._meta?.progressToken,
|
|
474
|
+
sendNotification: extra.sendNotification,
|
|
475
|
+
signal: extra.signal,
|
|
476
|
+
}
|
|
477
|
+
);
|
|
478
|
+
const { now, ...outcome } = result;
|
|
479
|
+
return toolResult({ ...outcome, job: now ? jobReport(now) : null });
|
|
480
|
+
})
|
|
481
|
+
);
|
|
482
|
+
}
|
|
445
483
|
}
|
|
Binary file
|
|
Binary file
|