Spaces:
Sleeping
Sleeping
File size: 3,248 Bytes
57a889c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | import { McpServer } from '@modelcontextprotocol/sdk/server/mcp';
import { z } from 'zod';
import { isDemoUser } from '../../services/authService';
import {
getNotifications, getUnreadCount,
markRead as markNotificationRead, markUnread as markNotificationUnread,
markAllRead,
} from '../../services/inAppNotifications';
import {
TOOL_ANNOTATIONS_READONLY, TOOL_ANNOTATIONS_WRITE,
TOOL_ANNOTATIONS_DELETE, TOOL_ANNOTATIONS_NON_IDEMPOTENT,
demoDenied, ok,
} from './_shared';
import { canRead, canWrite } from '../scopes';
export function registerNotificationTools(server: McpServer, userId: number, scopes: string[] | null): void {
const R = canRead(scopes, 'notifications');
const W = canWrite(scopes, 'notifications');
// --- NOTIFICATIONS ---
if (R) server.registerTool(
'list_notifications',
{
description: 'List in-app notifications for the current user.',
inputSchema: {
limit: z.number().int().positive().optional().default(20),
offset: z.number().int().min(0).optional().default(0),
unread_only: z.boolean().optional().default(false),
},
annotations: TOOL_ANNOTATIONS_READONLY,
},
async ({ limit, offset, unread_only }) => {
const result = getNotifications(userId, { limit: limit ?? 20, offset: offset ?? 0, unreadOnly: unread_only ?? false });
return ok(result);
}
);
if (R) server.registerTool(
'get_unread_notification_count',
{
description: 'Get the number of unread in-app notifications.',
inputSchema: {},
annotations: TOOL_ANNOTATIONS_READONLY,
},
async () => {
const count = getUnreadCount(userId);
return ok({ count });
}
);
if (W) server.registerTool(
'mark_notification_read',
{
description: 'Mark a single notification as read.',
inputSchema: {
notificationId: z.number().int().positive(),
},
annotations: TOOL_ANNOTATIONS_WRITE,
},
async ({ notificationId }) => {
if (isDemoUser(userId)) return demoDenied();
const success = markNotificationRead(notificationId, userId);
if (!success) return { content: [{ type: 'text' as const, text: 'Notification not found.' }], isError: true };
return ok({ success: true });
}
);
if (W) server.registerTool(
'mark_notification_unread',
{
description: 'Mark a single notification as unread.',
inputSchema: {
notificationId: z.number().int().positive(),
},
annotations: TOOL_ANNOTATIONS_WRITE,
},
async ({ notificationId }) => {
if (isDemoUser(userId)) return demoDenied();
const success = markNotificationUnread(notificationId, userId);
if (!success) return { content: [{ type: 'text' as const, text: 'Notification not found.' }], isError: true };
return ok({ success: true });
}
);
if (W) server.registerTool(
'mark_all_notifications_read',
{
description: "Mark all of the current user's notifications as read.",
inputSchema: {},
annotations: TOOL_ANNOTATIONS_WRITE,
},
async () => {
if (isDemoUser(userId)) return demoDenied();
const count = markAllRead(userId);
return ok({ success: true, count });
}
);
}
|