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:
2026-10-09 10:17:10 +02:00
parent 58fe5e8301
commit e6ac02d328
16 changed files with 1129 additions and 54 deletions

View File

@@ -37,6 +37,59 @@ export class ProjectsResolver {
);
}
@Tool({
name: 'create_project',
description:
'Create a project; the user becomes its owner. The key prefixes its tickets (WEB → WEB-1) and cannot change later.',
paramsSchema: z.object({
key: z
.string()
.regex(/^[A-Za-z][A-Za-z0-9]{1,9}$/)
.describe('2-10 letters or digits, starting with a letter; unique'),
name: z.string().min(1).max(120),
description: z.string().max(5000).optional(),
isPublic: z
.boolean()
.default(false)
.describe('Anyone can read it, also without signing in'),
}),
annotations: { readOnlyHint: false, destructiveHint: false },
})
create(
params: {
key: string;
name: string;
description?: string;
isPublic: boolean;
},
ctx: McpContext,
) {
return toolResult(() =>
this.api.data(
this.api.as(ctx).POST('/api/projects', {
body: { ...params, key: params.key.toUpperCase() },
}),
),
);
}
@Tool({
name: 'get_project_showcase',
description:
'The public summary of a public project: epics on the roadmap with dates and progress, latest releases (notes of shipped ones), the sprint under way and open good-first-issue tickets. Paths point into the web app.',
paramsSchema: z.object({ project: projectRef }),
annotations: READ,
})
showcase({ project }: { project: string }, ctx: McpContext) {
return toolResult(() =>
this.api.data(
this.api.as(ctx).GET('/api/explore/projects/{project}/showcase', {
params: { path: { project } },
}),
),
);
}
@Tool({
name: 'get_project',
description:
@@ -72,6 +125,7 @@ export class ProjectsResolver {
assigneeId: z.string().optional().describe('Only this person (user id)'),
releaseId: z.string().optional().describe('Only this release'),
area: z.string().optional().describe('Only this area id'),
sprintId: z.string().optional().describe('Only this sprint'),
perColumn: limit(200, 25),
}),
annotations: READ,
@@ -82,6 +136,7 @@ export class ProjectsResolver {
assigneeId?: string;
releaseId?: string;
area?: string;
sprintId?: string;
perColumn: number;
},
ctx: McpContext,