diff --git a/src/index.ts b/src/index.ts index b5942c6..4687b5f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -131,8 +131,12 @@ import { import { listContactsSchema, getContactSchema, + createContactSchema, + updateContactSchema, listContacts, getContact, + createContact, + updateContact, formatContactsList, formatContact, } from "./tools/contacts.js"; @@ -339,6 +343,30 @@ server.tool( } ); +server.tool( + "moco_create_contact", + "Create a new contact person in MOCO. Requires last name and gender. Optionally associate with a company.", + createContactSchema, + async (params) => { + const contact = await createContact(params); + return { + content: [{ type: "text", text: `Contact created successfully.\n\n${formatContact(contact)}` }], + }; + } +); + +server.tool( + "moco_update_contact", + "Update an existing contact person in MOCO by ID. All fields except ID are optional.", + updateContactSchema, + async (params) => { + const contact = await updateContact(params); + return { + content: [{ type: "text", text: `Contact updated successfully.\n\n${formatContact(contact)}` }], + }; + } +); + // ============ UNIT TOOLS ============ server.tool( diff --git a/src/tools/contacts.ts b/src/tools/contacts.ts index 0f39aab..7767c30 100644 --- a/src/tools/contacts.ts +++ b/src/tools/contacts.ts @@ -1,5 +1,5 @@ import { z } from "zod"; -import { mocoFetch } from "../api.js"; +import { mocoFetch, mocoPost, mocoPut } from "../api.js"; import type { Contact } from "../types.js"; // Schema for list contacts @@ -10,12 +10,77 @@ export const listContactsSchema = { per_page: z.number().optional().describe("Items per page (default: 100, max: 100)"), }; +// Schema for create contact +export const createContactSchema = { + lastname: z.string().describe("Last name"), + gender: z.enum(["F", "M", "U"]).describe('Gender: "F", "M", or "U"'), + firstname: z.string().optional().describe("First name"), + company_id: z.number().optional().describe("Associated company ID"), + user_id: z.number().optional().describe("Responsible user ID (defaults to current user)"), + title: z.string().optional().describe("Title, e.g. \"Dr. med.\""), + job_position: z.string().optional().describe("Job position"), + mobile_phone: z.string().optional().describe("Mobile phone number"), + work_fax: z.string().optional().describe("Work fax number"), + work_phone: z.string().optional().describe("Work phone number"), + work_email: z.string().optional().describe("Work email address"), + work_address: z.string().optional().describe("Work address"), + home_email: z.string().optional().describe("Home email address"), + home_address: z.string().optional().describe("Home address"), + birthday: z.string().optional().describe("Birthday in YYYY-MM-DD format"), + info: z.string().optional().describe("Additional information/notes"), + tags: z.array(z.string()).optional().describe("List of tags"), +}; + +// Schema for update contact +export const updateContactSchema = { + id: z.number().describe("Contact ID"), + lastname: z.string().optional().describe("Last name"), + gender: z.enum(["F", "M", "U"]).optional().describe('Gender: "F", "M", or "U"'), + firstname: z.string().optional().describe("First name"), + company_id: z.number().optional().describe("Associated company ID"), + user_id: z.number().optional().describe("Responsible user ID"), + title: z.string().optional().describe("Title"), + job_position: z.string().optional().describe("Job position"), + mobile_phone: z.string().optional().describe("Mobile phone number"), + work_fax: z.string().optional().describe("Work fax number"), + work_phone: z.string().optional().describe("Work phone number"), + work_email: z.string().optional().describe("Work email address"), + work_address: z.string().optional().describe("Work address"), + home_email: z.string().optional().describe("Home email address"), + home_address: z.string().optional().describe("Home address"), + birthday: z.string().optional().describe("Birthday in YYYY-MM-DD format"), + info: z.string().optional().describe("Additional information/notes"), + tags: z.array(z.string()).optional().describe("List of tags"), +}; + // Schema for get single contact export const getContactSchema = { id: z.number().describe("Contact ID"), }; // Types for parameters +export type CreateContactParams = { + lastname: string; + gender: "F" | "M" | "U"; + firstname?: string; + company_id?: number; + user_id?: number; + title?: string; + job_position?: string; + mobile_phone?: string; + work_fax?: string; + work_phone?: string; + work_email?: string; + work_address?: string; + home_email?: string; + home_address?: string; + birthday?: string; + info?: string; + tags?: string[]; +}; + +export type UpdateContactParams = Partial & { id: number }; + export type ListContactsParams = { tags?: string; term?: string; @@ -28,6 +93,14 @@ export type GetContactParams = { }; // API functions +export async function createContact(params: CreateContactParams): Promise { + return mocoPost("/contacts/people", params); +} + +export async function updateContact({ id, ...params }: UpdateContactParams): Promise { + return mocoPut(`/contacts/people/${id}`, params); +} + export async function listContacts(params: ListContactsParams): Promise { return mocoFetch("/contacts/people", params); }