fix(contacts): persist all documented fields on create (fixes #716)

create_contact previously read only fn/email/tel from contact_data and
silently dropped org, organization, note, title, nickname, bday,
categories, url — and didn't accept phone as an alias for tel, so the
reporter's exact call lost every field except fn and email. Introduce
_build_contact_from_data, share it with update_contact's fallback, and
normalise str→list inputs so pythonvCard4 doesn't iterate bare strings
character-by-character for list-typed properties.

Closes #716

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-04-23 07:28:05 +02:00
co-authored by Claude Opus 4.7
parent d766f3c014
commit 723aee9134
4 changed files with 174 additions and 16 deletions
+17 -1
View File
@@ -191,7 +191,23 @@ def configure_contacts_tools(mcp: FastMCP):
not the display name. Use nc_contacts_list_addressbooks to
find available URI slugs.
uid: The unique ID for the contact.
contact_data: A dictionary with the contact's details, e.g. {"fn": "John Doe", "email": "john.doe@example.com"}.
contact_data: A dictionary with the contact's details. Supported keys:
- ``fn`` (str, required): Formatted full name.
- ``email`` (str or list of str/dicts): Email address(es).
- ``tel`` / ``phone`` (str or list): Phone number(s).
- ``org`` / ``organization`` (str or list of str): Organization.
Lists become semicolon-separated ORG components per RFC 6350.
- ``title`` (str): Job title.
- ``note`` (str): Free-form note.
- ``nickname`` (str or list of str).
- ``bday`` (ISO date str ``"YYYY-MM-DD"`` or ``datetime.date``).
- ``categories`` (list of str, or comma-separated str).
- ``url`` (str or list of str).
Unknown keys are ignored. Example:
``{"fn": "John Doe", "email": "john@example.com",
"organization": "Acme", "note": "Met at conference"}``.
"""
client = await get_client(ctx)
return await client.contacts.create_contact(