Skip to main content
Glama

monica_manage_task_reminder

Manage tasks and reminders in Monica CRM by creating, updating, deleting, listing, or viewing to-dos and stay-in-touch nudges for contacts.

Instructions

List, inspect, create, update, or delete Monica tasks and reminders. Choose itemType="task" for to-dos or itemType="reminder" for stay-in-touch nudges.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
itemTypeYes
actionYes
taskIdNo
reminderIdNo
contactIdNo
statusNo
limitNo
pageNo
taskPayloadNo
reminderPayloadNo

Implementation Reference

  • Main tool handler function: validates input and dispatches to task or reminder handler based on itemType.
    async (rawInput) => {
      const input = actionItemSchema.parse(rawInput);
    
      if (input.itemType === 'task') {
        return handleTaskAction({ input: input as TaskActionInput, client, logger });
      }
    
      return handleReminderAction({ input: input as ReminderActionInput, client, logger });
    }
  • Handler for task actions: list, get, create, update, delete tasks using Monica API.
    async function handleTaskAction({
      input,
      client,
      logger
    }: {
      input: TaskActionInput;
      client: ToolRegistrationContext['client'];
      logger: ToolRegistrationContext['logger'];
    }) {
      switch (input.action) {
        case 'list': {
          const response = await client.listTasks({
            contactId: input.contactId,
            status: input.status,
            limit: input.limit,
            page: input.page
          });
          const tasks = response.data.map(normalizeTask);
          const scope = input.contactId ? `contact ${input.contactId}` : 'your account';
          const summary = tasks.length
            ? `Fetched ${tasks.length} task${tasks.length === 1 ? '' : 's'} for ${scope}.`
            : `No tasks found for ${scope}.`;
    
          return {
            content: [
              {
                type: 'text' as const,
                text: summary
              }
            ],
            structuredContent: {
              itemType: input.itemType,
              action: input.action,
              contactId: input.contactId,
              status: input.status,
              tasks,
              pagination: {
                currentPage: response.meta.current_page,
                lastPage: response.meta.last_page,
                perPage: response.meta.per_page,
                total: response.meta.total
              }
            }
          };
        }
    
        case 'get': {
          const response = await client.getTask(input.taskId!);
          const task = normalizeTask(response.data);
    
          return {
            content: [
              {
                type: 'text' as const,
                text: `Task ${task.title} (ID ${task.id}).`
              }
            ],
            structuredContent: {
              itemType: input.itemType,
              action: input.action,
              task
            }
          };
        }
    
        case 'create': {
          const payload = input.taskPayload!;
          const result = await client.createTask(toTaskCreatePayload(payload));
          const task = normalizeTask(result.data);
          logger.info({ taskId: task.id }, 'Created Monica task');
    
          return {
            content: [
              {
                type: 'text' as const,
                text: `Created task ${task.title || `#${task.id}`} (ID ${task.id}).`
              }
            ],
            structuredContent: {
              itemType: input.itemType,
              action: input.action,
              task
            }
          };
        }
    
        case 'update': {
          const payload = input.taskPayload!;
          const result = await client.updateTask(input.taskId!, toTaskUpdatePayload(payload));
          const task = normalizeTask(result.data);
          logger.info({ taskId: input.taskId }, 'Updated Monica task');
    
          return {
            content: [
              {
                type: 'text' as const,
                text: `Updated task ${task.title || `#${task.id}`} (ID ${task.id}).`
              }
            ],
            structuredContent: {
              itemType: input.itemType,
              action: input.action,
              taskId: input.taskId,
              task
            }
          };
        }
    
        case 'delete': {
          const result = await client.deleteTask(input.taskId!);
          logger.info({ taskId: input.taskId }, 'Deleted Monica task');
    
          return {
            content: [
              {
                type: 'text' as const,
                text: `Deleted task ID ${input.taskId}.`
              }
            ],
            structuredContent: {
              itemType: input.itemType,
              action: input.action,
              taskId: input.taskId,
              result
            }
          };
        }
    
        default:
          return unreachable(input.action as never);
      }
    }
  • Handler for reminder actions: list, get, create, update, delete reminders using Monica API.
    async function handleReminderAction({
      input,
      client,
      logger
    }: {
      input: ReminderActionInput;
      client: ToolRegistrationContext['client'];
      logger: ToolRegistrationContext['logger'];
    }) {
      switch (input.action) {
        case 'list': {
          const response = await client.listReminders({
            contactId: input.contactId,
            limit: input.limit,
            page: input.page
          });
          const reminders = response.data.map(normalizeReminder);
          const scope = input.contactId ? `contact ${input.contactId}` : 'your account';
          const text = reminders.length
            ? `Found ${reminders.length} reminder${reminders.length === 1 ? '' : 's'} for ${scope}.`
            : `No reminders found for ${scope}.`;
    
          return {
            content: [
              {
                type: 'text' as const,
                text
              }
            ],
            structuredContent: {
              itemType: input.itemType,
              action: input.action,
              contactId: input.contactId,
              reminders,
              pagination: {
                currentPage: response.meta.current_page,
                lastPage: response.meta.last_page,
                perPage: response.meta.per_page,
                total: response.meta.total
              }
            }
          };
        }
    
        case 'get': {
          const response = await client.getReminder(input.reminderId!);
          const reminder = normalizeReminder(response.data);
          const contactName = reminder.contact?.name || `Contact ${reminder.contactId}`;
    
          return {
            content: [
              {
                type: 'text' as const,
                text: `Reminder "${reminder.title}" for ${contactName}. Next due ${reminder.nextExpectedDate ?? 'unknown'}.`
              }
            ],
            structuredContent: {
              itemType: input.itemType,
              action: input.action,
              reminder
            }
          };
        }
    
        case 'create': {
          const payload = input.reminderPayload!;
          let createPayload: CreateReminderPayload;
          try {
            createPayload = toReminderCreatePayload(payload);
          } catch (error) {
            return {
              isError: true as const,
              content: [
                { type: 'text' as const, text: (error as Error).message }
              ]
            };
          }
    
          try {
            const response = await client.createReminder(createPayload);
            const reminder = normalizeReminder(response.data);
            logger.info({ reminderId: reminder.id, contactId: reminder.contactId }, 'Created Monica reminder');
    
            return {
              content: [
                {
                  type: 'text' as const,
                  text: `Created reminder "${reminder.title}" for contact ${reminder.contactId}.`
                }
              ],
              structuredContent: {
                itemType: input.itemType,
                action: input.action,
                reminder
              }
            };
          } catch (error) {
            if (error instanceof MonicaApiError) {
              return buildErrorResponse(formatMonicaApiError(error));
            }
            throw error;
          }
        }
    
        case 'update': {
          const payload = input.reminderPayload!;
          let updatePayload: UpdateReminderPayload;
          try {
            updatePayload = toReminderUpdatePayload(payload);
          } catch (error) {
            return {
              isError: true as const,
              content: [
                { type: 'text' as const, text: (error as Error).message }
              ]
            };
          }
    
          try {
            const response = await client.updateReminder(input.reminderId!, updatePayload);
            const reminder = normalizeReminder(response.data);
            logger.info({ reminderId: input.reminderId }, 'Updated Monica reminder');
    
            return {
              content: [
                {
                  type: 'text' as const,
                  text: `Updated reminder "${reminder.title}" (ID ${reminder.id}).`
                }
              ],
              structuredContent: {
                itemType: input.itemType,
                action: input.action,
                reminderId: input.reminderId,
                reminder
              }
            };
          } catch (error) {
            if (error instanceof MonicaApiError) {
              return buildErrorResponse(formatMonicaApiError(error));
            }
            throw error;
          }
        }
    
        case 'delete': {
          try {
            const result = await client.deleteReminder(input.reminderId!);
            logger.info({ reminderId: input.reminderId }, 'Deleted Monica reminder');
    
            return {
              content: [
                {
                  type: 'text' as const,
                  text: `Deleted reminder ID ${input.reminderId}.`
                }
              ],
              structuredContent: {
                itemType: input.itemType,
                action: input.action,
                reminderId: input.reminderId,
                result
              }
            };
          } catch (error) {
            if (error instanceof MonicaApiError) {
              return buildErrorResponse(formatMonicaApiError(error));
            }
            throw error;
          }
        }
    
        default:
          return unreachable(input.action as never);
      }
    }
  • Zod schemas for tool input validation, including sub-schemas for task and reminder payloads and superRefine for action-specific checks.
    const actionItemInputShape = {
      itemType: z.enum(['task', 'reminder']),
      action: z.enum(['list', 'get', 'create', 'update', 'delete']),
      taskId: z.number().int().positive().optional(),
      reminderId: z.number().int().positive().optional(),
      contactId: z.number().int().positive().optional(),
      status: z.enum(['open', 'completed', 'all']).optional(),
      limit: z.number().int().min(1).max(100).optional(),
      page: z.number().int().min(1).optional(),
      taskPayload: taskPayloadSchema.optional(),
      reminderPayload: reminderPayloadSchema.optional()
    } as const;
    
    const actionItemSchema = z.object(actionItemInputShape).superRefine((data, ctx) => {
      if (data.itemType === 'task') {
        switch (data.action) {
          case 'list':
            break;
          case 'get':
          case 'delete':
            if (typeof data.taskId !== 'number') {
              ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Provide taskId for this action.' });
            }
            break;
          case 'create':
            if (!data.taskPayload) {
              ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Provide task details when creating a task.' });
            }
            break;
          case 'update':
            if (typeof data.taskId !== 'number') {
              ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Provide taskId when updating a task.' });
            }
            if (!data.taskPayload) {
              ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Provide task details when updating a task.' });
            }
            break;
          default:
            break;
        }
      } else {
        switch (data.action) {
          case 'list':
            break;
          case 'get':
          case 'delete':
            if (typeof data.reminderId !== 'number') {
              ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Provide reminderId for this action.' });
            }
            break;
          case 'create':
            if (!data.reminderPayload) {
              ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Provide reminder details when creating a reminder.' });
            }
            break;
          case 'update':
            if (typeof data.reminderId !== 'number') {
              ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Provide reminderId when updating a reminder.' });
            }
            if (!data.reminderPayload) {
              ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Provide reminder details when updating a reminder.' });
            }
            break;
          default:
            break;
        }
      }
    });
  • Registers the 'monica_manage_task_reminder' tool with the MCP server.
    server.registerTool(
      'monica_manage_task_reminder',
      {
        title: 'Manage Monica tasks and reminders',
        description:
          'List, inspect, create, update, or delete Monica tasks and reminders. Choose itemType="task" for to-dos or itemType="reminder" for stay-in-touch nudges.',
        inputSchema: actionItemInputShape
      },
      async (rawInput) => {
        const input = actionItemSchema.parse(rawInput);
    
        if (input.itemType === 'task') {
          return handleTaskAction({ input: input as TaskActionInput, client, logger });
        }
    
        return handleReminderAction({ input: input as ReminderActionInput, client, logger });
      }
    );

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Jacob-Stokes/monica-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server