monica_manage_note
Manage notes for contacts in Monica CRM by listing, viewing, creating, updating, or deleting journal entries and snippets attached to contact profiles.
Instructions
List, inspect, create, update, or delete notes attached to a contact. Use this to capture or revise journal snippets.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | ||
| noteId | No | ||
| contactId | No | ||
| limit | No | ||
| page | No | ||
| payload | No |
Implementation Reference
- src/tools/modules/notes.ts:32-204 (handler)Core handler implementing CRUD operations for Monica notes: list notes for contact, get note, create/update/delete note with validation and structured responses.async ({ action, noteId, contactId, limit, page, payload }) => { if (action === 'list') { if (!contactId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide contactId when listing notes.' } ] }; } const response = await client.fetchContactNotes(contactId, limit, page); const notes = response.data.map(normalizeNote); const summary = notes.length ? `Fetched ${notes.length} note${notes.length === 1 ? '' : 's'} for contact ${contactId}.` : `No notes found for contact ${contactId}.`; return { content: [ { type: 'text' as const, text: summary } ], structuredContent: { action, contactId, notes, pagination: { currentPage: response.meta.current_page, lastPage: response.meta.last_page, perPage: response.meta.per_page, total: response.meta.total } } }; } if (action === 'get') { if (!noteId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide noteId when retrieving a note.' } ] }; } const response = await client.getNote(noteId); const note = normalizeNote(response.data); return { content: [ { type: 'text' as const, text: `Note ${note.id} for contact ${note.contact.name}.` } ], structuredContent: { action, note } }; } if (action === 'create') { if (!payload || typeof payload.contactId !== 'number' || !payload.body) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide contactId and body when creating a note.' } ] }; } const result = await client.createNote(toNoteCreatePayload(payload)); const note = normalizeNote(result.data); logger.info({ noteId: note.id }, 'Created Monica note'); return { content: [ { type: 'text' as const, text: `Created note ${note.id} for contact ${note.contact.name}.` } ], structuredContent: { action, note } }; } if (action === 'update') { if (!noteId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide noteId when updating a note.' } ] }; } if (!payload) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide note details when updating a note.' } ] }; } const result = await client.updateNote(noteId, toNoteUpdatePayload(payload)); const note = normalizeNote(result.data); logger.info({ noteId }, 'Updated Monica note'); return { content: [ { type: 'text' as const, text: `Updated note ${note.id} for contact ${note.contact.name}.` } ], structuredContent: { action, noteId, note } }; } if (action === 'delete') { if (!noteId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide noteId when deleting a note.' } ] }; } await client.deleteNote(noteId); logger.info({ noteId }, 'Deleted Monica note'); return { content: [ { type: 'text' as const, text: `Deleted note ID ${noteId}.` } ], structuredContent: { action, noteId, deleted: true } }; } return { isError: true as const, content: [ { type: 'text' as const, text: `Unsupported action: ${action}.` } ] }; }
- src/tools/modules/notes.ts:6-30 (schema)Zod schemas defining input validation for tool parameters including action types and optional note payload.const notePayloadSchema = z.object({ body: z.string().max(1_000_000).optional(), contactId: z.number().int().positive().optional(), isFavorited: z.boolean().optional() }); type NotePayloadForm = z.infer<typeof notePayloadSchema>; export function registerNoteTools(context: ToolRegistrationContext): void { const { server, client, logger } = context; server.registerTool( 'monica_manage_note', { title: 'Manage Monica notes', description: 'List, inspect, create, update, or delete notes attached to a contact. Use this to capture or revise journal snippets.', inputSchema: { action: z.enum(['list', 'get', 'create', 'update', 'delete']), noteId: z.number().int().positive().optional(), contactId: z.number().int().positive().optional(), limit: z.number().int().min(1).max(100).optional(), page: z.number().int().min(1).optional(), payload: notePayloadSchema.optional() }
- src/tools/modules/notes.ts:17-205 (registration)Direct registration of the 'monica_manage_note' tool via server.registerTool within registerNoteTools function.server.registerTool( 'monica_manage_note', { title: 'Manage Monica notes', description: 'List, inspect, create, update, or delete notes attached to a contact. Use this to capture or revise journal snippets.', inputSchema: { action: z.enum(['list', 'get', 'create', 'update', 'delete']), noteId: z.number().int().positive().optional(), contactId: z.number().int().positive().optional(), limit: z.number().int().min(1).max(100).optional(), page: z.number().int().min(1).optional(), payload: notePayloadSchema.optional() } }, async ({ action, noteId, contactId, limit, page, payload }) => { if (action === 'list') { if (!contactId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide contactId when listing notes.' } ] }; } const response = await client.fetchContactNotes(contactId, limit, page); const notes = response.data.map(normalizeNote); const summary = notes.length ? `Fetched ${notes.length} note${notes.length === 1 ? '' : 's'} for contact ${contactId}.` : `No notes found for contact ${contactId}.`; return { content: [ { type: 'text' as const, text: summary } ], structuredContent: { action, contactId, notes, pagination: { currentPage: response.meta.current_page, lastPage: response.meta.last_page, perPage: response.meta.per_page, total: response.meta.total } } }; } if (action === 'get') { if (!noteId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide noteId when retrieving a note.' } ] }; } const response = await client.getNote(noteId); const note = normalizeNote(response.data); return { content: [ { type: 'text' as const, text: `Note ${note.id} for contact ${note.contact.name}.` } ], structuredContent: { action, note } }; } if (action === 'create') { if (!payload || typeof payload.contactId !== 'number' || !payload.body) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide contactId and body when creating a note.' } ] }; } const result = await client.createNote(toNoteCreatePayload(payload)); const note = normalizeNote(result.data); logger.info({ noteId: note.id }, 'Created Monica note'); return { content: [ { type: 'text' as const, text: `Created note ${note.id} for contact ${note.contact.name}.` } ], structuredContent: { action, note } }; } if (action === 'update') { if (!noteId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide noteId when updating a note.' } ] }; } if (!payload) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide note details when updating a note.' } ] }; } const result = await client.updateNote(noteId, toNoteUpdatePayload(payload)); const note = normalizeNote(result.data); logger.info({ noteId }, 'Updated Monica note'); return { content: [ { type: 'text' as const, text: `Updated note ${note.id} for contact ${note.contact.name}.` } ], structuredContent: { action, noteId, note } }; } if (action === 'delete') { if (!noteId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide noteId when deleting a note.' } ] }; } await client.deleteNote(noteId); logger.info({ noteId }, 'Deleted Monica note'); return { content: [ { type: 'text' as const, text: `Deleted note ID ${noteId}.` } ], structuredContent: { action, noteId, deleted: true } }; } return { isError: true as const, content: [ { type: 'text' as const, text: `Unsupported action: ${action}.` } ] }; } );
- src/tools/registerTools.ts:37-37 (registration)Invocation of registerNoteTools as part of the overall tool registration sequence in registerTools.registerNoteTools(context);
- src/utils/formatters.ts:124-135 (helper)Helper function to normalize raw Monica API note data to a consistent structured format, used in handler responses.export function normalizeNote(note: MonicaNote) { return { id: note.id, body: note.body, isFavorited: note.is_favorited, favoritedAt: note.favorited_at ?? undefined, contactId: note.contact.id, contact: normalizeContactSummary(note.contact), createdAt: note.created_at, updatedAt: note.updated_at }; }