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:
70
apps/mcp/src/app/tools/notifications.resolver.ts
Normal file
70
apps/mcp/src/app/tools/notifications.resolver.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { McpContext, Resolver, Tool } from '@nestjs-mcp/server';
|
||||
import { z } from 'zod';
|
||||
import { TaskStreamApi } from '../api/taskstream-api';
|
||||
import { limit } from './params';
|
||||
import { toolResult } from './tool-result';
|
||||
|
||||
@Resolver()
|
||||
export class NotificationsResolver {
|
||||
constructor(private readonly api: TaskStreamApi) {}
|
||||
|
||||
@Tool({
|
||||
name: 'my_notifications',
|
||||
description:
|
||||
"The user's notifications, newest first: assignments, status changes, failed QA, comments, mentions, followed tickets, reminders.",
|
||||
paramsSchema: z.object({
|
||||
unreadOnly: z.boolean().default(true),
|
||||
limit: limit(100, 30),
|
||||
}),
|
||||
annotations: { readOnlyHint: true, openWorldHint: false },
|
||||
})
|
||||
mine(
|
||||
{ unreadOnly, limit }: { unreadOnly: boolean; limit: number },
|
||||
ctx: McpContext,
|
||||
) {
|
||||
return toolResult(async () => {
|
||||
const page = await this.api.data(
|
||||
this.api.as(ctx).GET('/api/me/notifications', {
|
||||
params: { query: { unreadOnly, limit } },
|
||||
}),
|
||||
);
|
||||
return {
|
||||
unread: page.unread,
|
||||
items: page.items.map((n) => ({
|
||||
id: n.id,
|
||||
kind: n.kind,
|
||||
project: n.projectKey,
|
||||
issue: n.issueKey,
|
||||
who: n.actor?.name ?? null,
|
||||
summary: n.summary,
|
||||
read: n.readAt !== null,
|
||||
at: n.createdAt,
|
||||
})),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@Tool({
|
||||
name: 'mark_notifications_read',
|
||||
description: 'Mark notifications as read: these ids, or all of them.',
|
||||
paramsSchema: z.object({
|
||||
ids: z
|
||||
.array(z.string())
|
||||
.optional()
|
||||
.describe('Notification ids; absent: all'),
|
||||
}),
|
||||
annotations: {
|
||||
readOnlyHint: false,
|
||||
destructiveHint: false,
|
||||
idempotentHint: true,
|
||||
openWorldHint: false,
|
||||
},
|
||||
})
|
||||
markRead({ ids }: { ids?: string[] }, ctx: McpContext) {
|
||||
return toolResult(() =>
|
||||
this.api.data(
|
||||
this.api.as(ctx).POST('/api/me/notifications/read', { body: { ids } }),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user