Skip to content

feat: return contact relations and omit binary vCard payloads - #4

Open
janbaer wants to merge 2 commits into
dominik1001:claude/beautiful-carson-4lqy46from
janbaer:feat/get-contact-relations
Open

feat: return contact relations and omit binary vCard payloads#4
janbaer wants to merge 2 commits into
dominik1001:claude/beautiful-carson-4lqy46from
janbaer:feat/get-contact-relations

Conversation

@janbaer

@janbaer janbaer commented Aug 16, 2026

Copy link
Copy Markdown

Two changes to what get-contact returns.

Binary payloads. The stored vCard was echoed verbatim. A card with an inline portrait carries PHOTO;ENCODING=b with tens of thousands of base64 characters; on one real card that was 57 KB of a 60 KB result, and the tool result exceeded my client's response limit. PHOTO, LOGO, SOUND and KEY are now reported as <57312 bytes omitted>. A photo referenced by URI is left alone.

Relations. Added a relations object keyed by role, e.g. {"Spouse": "Ada Lovelace"}. Clients store these as a pair sharing a property group (itemN.X-ABLABEL holds the role, itemN.X-ABRELATEDNAMES the person, the role wrapped in Apple's _$!<...>!$_ form), which every caller would otherwise reassemble from raw vCard text.

Four unit tests added, README tool docs regenerated.

get-contact echoed the stored vCard verbatim. A card holding an inline
portrait carries PHOTO;ENCODING=b with tens of thousands of base64
characters; on one real card that was 57 KB of a 60 KB result. For an MCP
client this is context spent on bytes no model can use, and it can push a
single tool result past the response limit. Embedded binary values (PHOTO,
LOGO, SOUND, KEY) are now reported as a size marker instead. A photo
referenced by URI is untouched.

Relations are surfaced as a `relations` object keyed by role, e.g.
{"Spouse": "Ada Lovelace"}. Clients record them as a pair sharing a property
group - itemN.X-ABLABEL carries the role, itemN.X-ABRELATEDNAMES the person,
with the role wrapped in Apple's _$!<...>!$_ form - which every caller would
otherwise have to reassemble from raw vCard text.
@janbaer
janbaer marked this pull request as draft August 16, 2026 15:39
`relations` mapped a role to a single name, so a card recording two children
under the same label kept only the last one and dropped the other without any
signal. Children, siblings and friends are exactly the roles that repeat, so
this is the ordinary case rather than a contrived one. Each role now carries a
list, and a person reached twice — as X-SPOUSE and an item pair usually do —
is recorded once.

Also spells out in the tool description that the returned vCard is normalised
rather than byte-for-byte, so nobody mistakes it for the stored copy.
@janbaer

janbaer commented Aug 16, 2026

Copy link
Copy Markdown
Author

Pushed one follow-up: relations mapped a role to a single name, so a card recording two children under the same label kept only the last one and dropped the other without any signal. Children, siblings and friends are exactly the roles that repeat, so that is the ordinary case rather than a contrived one. Each role now carries a list, and a person reached twice — as X-SPOUSE and an item pair usually do — is recorded once.

Also spelled out in the tool description that the returned vcard is normalised rather than byte-for-byte: continuation lines are unfolded and line endings rewritten, so it should not be mistaken for the stored copy.

@janbaer
janbaer marked this pull request as ready for review August 16, 2026 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant