feat(mcp): sprints, epics, backlog, trash, checklists and release notes
Thirty new tools (54 in all) for what the API gained since the MCP: create a project and read its public showcase; sprints (list, progress and burndown, plan, change, start, close with carry-over, delete, move a ticket in or out); epics and the backlog (list epics with progress, set a ticket's parent, rank); bulk edit of up to 100 tickets by key, saying which refused; the trash; checklists; following a ticket, removing a relation, editing and deleting comments; editing and archiving releases, drafting and saving their notes; notifications. Searching filters by epic, sprint and dates and sorts by backlog order; get_issue shows parent, checklist, commits and followers; create and update take parent and start date. API: `unreadOnly` and `dryRun` were documented as objects in the OpenAPI; they are booleans now. Chapter 9 lists every tool; Word and PDF regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -54,7 +54,7 @@ export class ReleasesResolver {
|
||||
@Tool({
|
||||
name: 'get_release',
|
||||
description:
|
||||
'A release with its progress (finished out of total), its tickets and, optionally, the day-by-day burnup.',
|
||||
'A release with its progress (finished out of total), its notes, its tickets and, optionally, the day-by-day burnup.',
|
||||
paramsSchema: z.object({
|
||||
releaseId,
|
||||
withBurnup: z.boolean().default(false),
|
||||
@@ -90,6 +90,7 @@ export class ReleasesResolver {
|
||||
return {
|
||||
...releaseLine(release),
|
||||
description: release.description,
|
||||
notes: release.notes,
|
||||
progress,
|
||||
issues: issues.items.map(issueLine),
|
||||
burnup,
|
||||
@@ -148,4 +149,104 @@ export class ReleasesResolver {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@Tool({
|
||||
name: 'update_release',
|
||||
description: 'Rename a release, describe it or move its target date.',
|
||||
paramsSchema: z.object({
|
||||
releaseId,
|
||||
name: z.string().min(1).max(60).optional(),
|
||||
description: z.string().max(5000).nullable().optional(),
|
||||
targetDate: z.string().nullable().optional().describe('ISO date'),
|
||||
}),
|
||||
annotations: {
|
||||
readOnlyHint: false,
|
||||
destructiveHint: false,
|
||||
idempotentHint: true,
|
||||
},
|
||||
})
|
||||
update(
|
||||
params: {
|
||||
releaseId: string;
|
||||
name?: string;
|
||||
description?: string | null;
|
||||
targetDate?: string | null;
|
||||
},
|
||||
ctx: McpContext,
|
||||
) {
|
||||
const { releaseId, ...body } = params;
|
||||
return toolResult(() =>
|
||||
this.api.data(
|
||||
this.api.as(ctx).PATCH('/api/releases/{releaseId}', {
|
||||
params: { path: { releaseId } },
|
||||
body,
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@Tool({
|
||||
name: 'archive_release',
|
||||
description:
|
||||
'Archive a planned release that will not ship; its tickets leave it.',
|
||||
paramsSchema: z.object({ releaseId }),
|
||||
annotations: { readOnlyHint: false, destructiveHint: true },
|
||||
})
|
||||
archive({ releaseId }: { releaseId: string }, ctx: McpContext) {
|
||||
return toolResult(() =>
|
||||
this.api.data(
|
||||
this.api.as(ctx).POST('/api/releases/{releaseId}/archive', {
|
||||
params: { path: { releaseId } },
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@Tool({
|
||||
name: 'draft_release_notes',
|
||||
description:
|
||||
"A Markdown draft of a release's notes from its finished tickets, grouped by type. Nothing is saved: polish it and save it with set_release_notes.",
|
||||
paramsSchema: z.object({ releaseId }),
|
||||
annotations: READ,
|
||||
})
|
||||
draftNotes({ releaseId }: { releaseId: string }, ctx: McpContext) {
|
||||
return toolResult(
|
||||
async () =>
|
||||
(
|
||||
await this.api.data(
|
||||
this.api.as(ctx).GET('/api/releases/{releaseId}/notes/draft', {
|
||||
params: { path: { releaseId } },
|
||||
}),
|
||||
)
|
||||
).markdown,
|
||||
);
|
||||
}
|
||||
|
||||
@Tool({
|
||||
name: 'set_release_notes',
|
||||
description:
|
||||
'Write the notes of a release (Markdown, for people: what shipped). null clears them.',
|
||||
paramsSchema: z.object({
|
||||
releaseId,
|
||||
notes: z.string().max(20000).nullable(),
|
||||
}),
|
||||
annotations: {
|
||||
readOnlyHint: false,
|
||||
destructiveHint: false,
|
||||
idempotentHint: true,
|
||||
},
|
||||
})
|
||||
setNotes(
|
||||
{ releaseId, notes }: { releaseId: string; notes: string | null },
|
||||
ctx: McpContext,
|
||||
) {
|
||||
return toolResult(() =>
|
||||
this.api.data(
|
||||
this.api.as(ctx).PUT('/api/releases/{releaseId}/notes', {
|
||||
params: { path: { releaseId } },
|
||||
body: { notes },
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user