Skip to main content
Glama

monica_manage_relationship

Manage and track relationships between contacts in Monica CRM. List, inspect, create, update, or delete connections to ensure accurate and organized contact networks.

Instructions

List, inspect, create, update, or delete relationships between contacts. Use this to confirm existing connections or link two contacts once you know the correct relationshipTypeId.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYes
contactIdNo
limitNo
pageNo
payloadNo
relationshipIdNo

Implementation Reference

  • The core handler function implementing the tool logic. It processes the 'action' parameter to perform CRUD operations on relationships using the MonicaClient, with error handling and structured responses.
    async ({ action, relationshipId, contactId, limit, page, payload }) => { switch (action) { case 'list': { if (!contactId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide contactId when listing relationships.' } ] }; } const response = await client.listRelationships({ contactId, limit, page }); const relationships = response.data.map(normalizeRelationship); const pagination = response.meta ? { currentPage: response.meta.current_page, lastPage: response.meta.last_page, perPage: response.meta.per_page, total: response.meta.total } : undefined; const text = relationships.length ? `Found ${relationships.length} relationship${relationships.length === 1 ? '' : 's'} for contact ${contactId}.` : `No relationships found for contact ${contactId}.`; const structuredContent: { action: typeof action; contactId: number; relationships: ReturnType<typeof normalizeRelationship>[]; pagination?: { currentPage: number; lastPage: number; perPage: number; total: number; }; } = { action, contactId, relationships }; if (pagination) { structuredContent.pagination = pagination; } return { content: [ { type: 'text' as const, text } ], structuredContent }; } case 'get': { if (!relationshipId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide relationshipId when retrieving a relationship.' } ] }; } const response = await client.getRelationship(relationshipId); const relationship = normalizeRelationship(response.data); return { content: [ { type: 'text' as const, text: `Relationship ${relationship.relationshipType.name} between ${relationship.contact.name} and ${relationship.relatedContact.name}.` } ], structuredContent: { action, relationshipId, relationship } }; } case 'create': { if (!payload) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide contactIsId, ofContactId, and relationshipTypeId or relationshipTypeName when creating a relationship.' } ] }; } const relationshipTypeId = await resolveRelationshipTypeId(client, { relationshipTypeId: payload.relationshipTypeId, relationshipTypeName: payload.relationshipTypeName }); const input = toRelationshipCreatePayload({ ...payload, relationshipTypeId }); const response = await client.createRelationship(input); const relationship = normalizeRelationship(response.data); logger.info({ relationshipId: relationship.id }, 'Created Monica relationship'); return { content: [ { type: 'text' as const, text: `Linked ${relationship.contact.name} and ${relationship.relatedContact.name} as ${relationship.relationshipType.name}.` } ], structuredContent: { action, relationship } }; } case 'update': { if (!relationshipId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide relationshipId when updating a relationship.' } ] }; } if (!payload) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide relationshipTypeId or relationshipTypeName when updating a relationship.' } ] }; } const relationshipTypeId = await resolveRelationshipTypeId(client, { relationshipTypeId: payload.relationshipTypeId, relationshipTypeName: payload.relationshipTypeName }); const input = toRelationshipUpdatePayload({ ...payload, relationshipTypeId }); const response = await client.updateRelationship(relationshipId, input); const relationship = normalizeRelationship(response.data); logger.info({ relationshipId }, 'Updated Monica relationship'); return { content: [ { type: 'text' as const, text: `Updated relationship ${relationshipId} to ${relationship.relationshipType.name}.` } ], structuredContent: { action, relationshipId, relationship } }; } case 'delete': { if (!relationshipId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide relationshipId when deleting a relationship.' } ] }; } const result = await client.deleteRelationship(relationshipId); logger.info({ relationshipId }, 'Deleted Monica relationship'); return { content: [ { type: 'text' as const, text: `Deleted relationship ID ${relationshipId}.` } ], structuredContent: { action, relationshipId, result } }; } default: return { isError: true as const, content: [ { type: 'text' as const, text: `Unsupported action: ${action}.` } ] }; } }
  • Direct registration of the 'monica_manage_relationship' tool using server.registerTool, including metadata, input schema, and handler reference.
    server.registerTool( 'monica_manage_relationship', { title: 'Manage Monica relationships', description: 'List, inspect, create, update, or delete relationships between contacts. Provide relationshipTypeId or relationshipTypeName to identify the connection.', inputSchema: { action: z.enum(['list', 'get', 'create', 'update', 'delete']), relationshipId: 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: relationshipPayloadSchema.optional() } }, async ({ action, relationshipId, contactId, limit, page, payload }) => { switch (action) { case 'list': { if (!contactId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide contactId when listing relationships.' } ] }; } const response = await client.listRelationships({ contactId, limit, page }); const relationships = response.data.map(normalizeRelationship); const pagination = response.meta ? { currentPage: response.meta.current_page, lastPage: response.meta.last_page, perPage: response.meta.per_page, total: response.meta.total } : undefined; const text = relationships.length ? `Found ${relationships.length} relationship${relationships.length === 1 ? '' : 's'} for contact ${contactId}.` : `No relationships found for contact ${contactId}.`; const structuredContent: { action: typeof action; contactId: number; relationships: ReturnType<typeof normalizeRelationship>[]; pagination?: { currentPage: number; lastPage: number; perPage: number; total: number; }; } = { action, contactId, relationships }; if (pagination) { structuredContent.pagination = pagination; } return { content: [ { type: 'text' as const, text } ], structuredContent }; } case 'get': { if (!relationshipId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide relationshipId when retrieving a relationship.' } ] }; } const response = await client.getRelationship(relationshipId); const relationship = normalizeRelationship(response.data); return { content: [ { type: 'text' as const, text: `Relationship ${relationship.relationshipType.name} between ${relationship.contact.name} and ${relationship.relatedContact.name}.` } ], structuredContent: { action, relationshipId, relationship } }; } case 'create': { if (!payload) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide contactIsId, ofContactId, and relationshipTypeId or relationshipTypeName when creating a relationship.' } ] }; } const relationshipTypeId = await resolveRelationshipTypeId(client, { relationshipTypeId: payload.relationshipTypeId, relationshipTypeName: payload.relationshipTypeName }); const input = toRelationshipCreatePayload({ ...payload, relationshipTypeId }); const response = await client.createRelationship(input); const relationship = normalizeRelationship(response.data); logger.info({ relationshipId: relationship.id }, 'Created Monica relationship'); return { content: [ { type: 'text' as const, text: `Linked ${relationship.contact.name} and ${relationship.relatedContact.name} as ${relationship.relationshipType.name}.` } ], structuredContent: { action, relationship } }; } case 'update': { if (!relationshipId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide relationshipId when updating a relationship.' } ] }; } if (!payload) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide relationshipTypeId or relationshipTypeName when updating a relationship.' } ] }; } const relationshipTypeId = await resolveRelationshipTypeId(client, { relationshipTypeId: payload.relationshipTypeId, relationshipTypeName: payload.relationshipTypeName }); const input = toRelationshipUpdatePayload({ ...payload, relationshipTypeId }); const response = await client.updateRelationship(relationshipId, input); const relationship = normalizeRelationship(response.data); logger.info({ relationshipId }, 'Updated Monica relationship'); return { content: [ { type: 'text' as const, text: `Updated relationship ${relationshipId} to ${relationship.relationshipType.name}.` } ], structuredContent: { action, relationshipId, relationship } }; } case 'delete': { if (!relationshipId) { return { isError: true as const, content: [ { type: 'text' as const, text: 'Provide relationshipId when deleting a relationship.' } ] }; } const result = await client.deleteRelationship(relationshipId); logger.info({ relationshipId }, 'Deleted Monica relationship'); return { content: [ { type: 'text' as const, text: `Deleted relationship ID ${relationshipId}.` } ], structuredContent: { action, relationshipId, result } }; } default: return { isError: true as const, content: [ { type: 'text' as const, text: `Unsupported action: ${action}.` } ] }; } } );
  • Invocation of the relationship tools registration within the main registerTools function, which orchestrates all tool registrations.
    registerRelationshipTools(context);
  • Zod schemas defining the input structure for the tool, including action enum and optional payload for relationship data.
    const relationshipPayloadSchema = z.object({ contactIsId: z.number().int().positive().optional(), ofContactId: z.number().int().positive().optional(), relationshipTypeId: z.number().int().positive().optional(), relationshipTypeName: z.string().min(1).max(255).optional() }); type RelationshipPayloadForm = z.infer<typeof relationshipPayloadSchema>; export function registerRelationshipTools(context: ToolRegistrationContext): void { const { server, client, logger } = context; server.registerTool( 'monica_manage_relationship', { title: 'Manage Monica relationships', description: 'List, inspect, create, update, or delete relationships between contacts. Provide relationshipTypeId or relationshipTypeName to identify the connection.', inputSchema: { action: z.enum(['list', 'get', 'create', 'update', 'delete']), relationshipId: 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: relationshipPayloadSchema.optional() }
  • Local helper functions that transform the tool's input payload into the exact formats required by MonicaClient's createRelationship and updateRelationship methods.
    function toRelationshipCreatePayload( payload: RelationshipPayloadForm & { relationshipTypeId: number } ): CreateRelationshipPayload { if ( typeof payload.contactIsId !== 'number' || typeof payload.ofContactId !== 'number' ) { throw new Error('contactIsId and ofContactId are required to create a relationship.'); } return { contactIsId: payload.contactIsId, ofContactId: payload.ofContactId, relationshipTypeId: payload.relationshipTypeId }; } function toRelationshipUpdatePayload( payload: RelationshipPayloadForm & { relationshipTypeId: number } ): UpdateRelationshipPayload { return { relationshipTypeId: payload.relationshipTypeId }; }

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