imsg-mcp 1.18.0 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/cli.js +1 -1
- package/dist/index.js +60 -7
- package/dist/index.js.map +1 -1
- package/dist/{meta-CZmUZHTh.js → meta-CD2uvSHu.js} +2 -2
- package/dist/{meta-CZmUZHTh.js.map → meta-CD2uvSHu.js.map} +1 -1
- package/dist/tui.js +1 -1
- package/dist/{watchdog-CW2SEAmu.js → watchdog-D54vuRzh.js} +3 -2
- package/dist/{watchdog-CW2SEAmu.js.map → watchdog-D54vuRzh.js.map} +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and follows [Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
# [1.19.0](https://github.com/george43g/imsg-mcp/compare/v1.18.0...v1.19.0) (2026-07-25)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **contacts:** attach a normalized identity block to get_contact + resolve_handle ([99dfc72](https://github.com/george43g/imsg-mcp/commit/99dfc723e2a5bf8508f1b3940a63a0aeb684d120))
|
|
12
|
+
|
|
6
13
|
# [1.18.0](https://github.com/george43g/imsg-mcp/compare/v1.17.0...v1.18.0) (2026-07-25)
|
|
7
14
|
|
|
8
15
|
|
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createInterface } from "node:readline";
|
|
|
4
4
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
5
|
import { Command } from "commander";
|
|
6
6
|
import { d as checkLocalAccess, f as formatAccessReport, I as IMPLEMENTED_TYPES, A as ANALYTIC_INFO, i as installShutdownHandlers, r as registerCleanup, l as looksLikeThreadSlug } from "./shutdown-0TCv4XJB.js";
|
|
7
|
-
import { A as APP_VERSION, t as toYaml } from "./meta-
|
|
7
|
+
import { A as APP_VERSION, t as toYaml } from "./meta-CD2uvSHu.js";
|
|
8
8
|
import { spawn } from "node:child_process";
|
|
9
9
|
import { join, dirname } from "node:path";
|
|
10
10
|
function distRoot() {
|
package/dist/index.js
CHANGED
|
@@ -14,11 +14,11 @@ import { ensureAttachmentDownloaded } from "./attachment-sync-DMvlT8Zk.js";
|
|
|
14
14
|
import { n as normalizedPhoneVariants, h as hasNativeModule, I as IMessageDB, r as rankFuzzy } from "./imessage-db-CHbdUXk3.js";
|
|
15
15
|
import { parseUserDate } from "./date-parse-DJXMfq3a.js";
|
|
16
16
|
import { streamExport, ExportInterpretGuardError } from "./exportStream-BFxilSlL.js";
|
|
17
|
-
import {
|
|
17
|
+
import { n as normalizePhoneToE164, m as minMessageId, a as resolveRecipient, d as defaultCountryFromEnv, i as installWatchdog, b as noteActivity, r as readWatchdogState } from "./watchdog-D54vuRzh.js";
|
|
18
|
+
import { r as renderAnalyticText, A as APP_VERSION, a as APP_NAME } from "./meta-CD2uvSHu.js";
|
|
18
19
|
import { randomUUID } from "node:crypto";
|
|
19
20
|
import { z } from "zod";
|
|
20
21
|
import { a as applyInlineInterpretations, i as imageBlockFromFile, v as videoPosterFrame, m as mediaMetadata, b as refForAttachment, T as TRANSCRIBE_MAX_BYTES, g as getInterpretRuntime, t as transcriptSourceEnum, d as detectTranscriber } from "./media-intel-runtime-BkxG4bmW.js";
|
|
21
|
-
import { m as minMessageId, a as resolveRecipient, d as defaultCountryFromEnv, i as installWatchdog, n as noteActivity, r as readWatchdogState } from "./watchdog-CW2SEAmu.js";
|
|
22
22
|
const DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
23
23
|
let dbPath = join(homedir(), ".imsg-mcp", "analytics-cache.db");
|
|
24
24
|
let db = null;
|
|
@@ -323,6 +323,37 @@ function humansHintText(hint) {
|
|
|
323
323
|
_Relationship file(s): ${list}_
|
|
324
324
|
_${hint.guidance}_`;
|
|
325
325
|
}
|
|
326
|
+
function dedupe(items) {
|
|
327
|
+
const seen = /* @__PURE__ */ new Set();
|
|
328
|
+
const out = [];
|
|
329
|
+
for (const item of items) {
|
|
330
|
+
if (item && !seen.has(item)) {
|
|
331
|
+
seen.add(item);
|
|
332
|
+
out.push(item);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return out;
|
|
336
|
+
}
|
|
337
|
+
function normalizeEmail(email) {
|
|
338
|
+
return email.trim().toLowerCase();
|
|
339
|
+
}
|
|
340
|
+
function e164OrOriginal(phone, country) {
|
|
341
|
+
return normalizePhoneToE164(phone, country) ?? phone.trim();
|
|
342
|
+
}
|
|
343
|
+
function buildIdentity(canonicalName, phoneNumbers, emails, country) {
|
|
344
|
+
const phones = dedupe(phoneNumbers.map((p) => e164OrOriginal(p, country)));
|
|
345
|
+
const mails = dedupe(emails.map(normalizeEmail));
|
|
346
|
+
return {
|
|
347
|
+
canonicalName,
|
|
348
|
+
phones,
|
|
349
|
+
emails: mails,
|
|
350
|
+
handles: dedupe([...phones, ...mails])
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
function buildIdentityFromHandle(handle, name, country) {
|
|
354
|
+
const isEmail = handle.includes("@");
|
|
355
|
+
return buildIdentity(name ?? handle, isEmail ? [] : [handle], isEmail ? [handle] : [], country);
|
|
356
|
+
}
|
|
326
357
|
const INSTRUCTIONS_UUID = randomUUID();
|
|
327
358
|
function wrapUntrusted(text) {
|
|
328
359
|
if (text == null || text === "") return "";
|
|
@@ -2001,8 +2032,16 @@ const GetContactSchema = z.object({
|
|
|
2001
2032
|
}).refine((v) => v.handle !== void 0 || v.id !== void 0, {
|
|
2002
2033
|
message: "Provide either `handle` or `id`."
|
|
2003
2034
|
});
|
|
2035
|
+
const IdentitySchema = z.object({
|
|
2036
|
+
canonicalName: z.string().describe("Best display name for this person (or the handle itself)."),
|
|
2037
|
+
phones: z.array(z.string()).describe("Phone handles, E.164-normalized where derivable."),
|
|
2038
|
+
emails: z.array(z.string()).describe("Email handles, trimmed + lowercased."),
|
|
2039
|
+
handles: z.array(z.string()).describe("Every reachable handle, deduped — phones first, then emails.")
|
|
2040
|
+
});
|
|
2004
2041
|
const GetContactOutputSchema = z.object({
|
|
2005
2042
|
contact: ContactSchema.nullable(),
|
|
2043
|
+
/** Normalized cross-tool handle view (E.164 phones, lowercased emails). */
|
|
2044
|
+
identity: IdentitySchema.optional(),
|
|
2006
2045
|
/** Per-handle conversation mapping: which thread slug each handle chats under. */
|
|
2007
2046
|
threads: z.array(
|
|
2008
2047
|
z.object({
|
|
@@ -2041,7 +2080,9 @@ const ResolveHandleOutputSchema = z.object({
|
|
|
2041
2080
|
displayName: z.string(),
|
|
2042
2081
|
contactId: z.number().int().nullable(),
|
|
2043
2082
|
label: z.string().nullable(),
|
|
2044
|
-
resolved: z.boolean()
|
|
2083
|
+
resolved: z.boolean(),
|
|
2084
|
+
/** Normalized cross-tool handle view — populated even when unresolved. */
|
|
2085
|
+
identity: IdentitySchema.optional()
|
|
2045
2086
|
});
|
|
2046
2087
|
const CheckImessageAvailabilitySchema = z.object({
|
|
2047
2088
|
handle: nonEmptyString("Phone number or email to preflight-check for reachability.")
|
|
@@ -2439,7 +2480,7 @@ const TOOLS = [
|
|
|
2439
2480
|
},
|
|
2440
2481
|
{
|
|
2441
2482
|
name: "get_contact",
|
|
2442
|
-
description: "Fetch a single contact by handle (phone/email) or by numeric id, including each handle's thread slug (for send_message/get_messages). Returns null if not found. Includes `humansFile` — the path to this person's humans/v1 relationship file if one exists (read it for relationship context; init_human scaffolds one otherwise).",
|
|
2483
|
+
description: "Fetch a single contact by handle (phone/email) or by numeric id, including each handle's thread slug (for send_message/get_messages) and an `identity` block (canonicalName + E.164-normalized phones + lowercased emails + deduped handles). Returns null if not found. Includes `humansFile` — the path to this person's humans/v1 relationship file if one exists (read it for relationship context; init_human scaffolds one otherwise).",
|
|
2443
2484
|
annotations: annotations.read,
|
|
2444
2485
|
inputSchema: {
|
|
2445
2486
|
type: "object",
|
|
@@ -2469,7 +2510,7 @@ const TOOLS = [
|
|
|
2469
2510
|
},
|
|
2470
2511
|
{
|
|
2471
2512
|
name: "resolve_handle",
|
|
2472
|
-
description: "Resolve a phone number or email to its contact display name. Pass-through if unknown.",
|
|
2513
|
+
description: "Resolve a phone number or email to its contact display name. Pass-through if unknown. Always returns an `identity` block (canonicalName + E.164-normalized phones + lowercased emails + deduped handles) — even for an unknown handle, so you get it in canonical form.",
|
|
2473
2514
|
annotations: annotations.read,
|
|
2474
2515
|
inputSchema: {
|
|
2475
2516
|
type: "object",
|
|
@@ -3688,10 +3729,17 @@ ${withThreads.map((t) => ` ${t.handle} → ${t.threadSlug}`).join("\n")}` : "";
|
|
|
3688
3729
|
const humansLine = humansHint ? humansHintText(humansHint) : `
|
|
3689
3730
|
|
|
3690
3731
|
_${HUMANS_INIT_HINT}_`;
|
|
3732
|
+
const identity = buildIdentity(
|
|
3733
|
+
contact.displayName,
|
|
3734
|
+
contact.phoneNumbers,
|
|
3735
|
+
contact.emails,
|
|
3736
|
+
defaultCountryFromEnv()
|
|
3737
|
+
);
|
|
3691
3738
|
return toolText(
|
|
3692
3739
|
`${sanitizeUserText(contact.displayName)} (id ${contact.id})${phones}${emails}${org}${threadLines}${humansLine}`,
|
|
3693
3740
|
{
|
|
3694
3741
|
contact,
|
|
3742
|
+
identity,
|
|
3695
3743
|
threads,
|
|
3696
3744
|
humansFile,
|
|
3697
3745
|
humansGuidance: humansHint?.guidance ?? HUMANS_INIT_HINT
|
|
@@ -3749,13 +3797,17 @@ ${lines}${hint}`,
|
|
|
3749
3797
|
const selectorHit = resolveContactSelector(handle);
|
|
3750
3798
|
const effectiveHandle = selectorHit?.handle ?? handle;
|
|
3751
3799
|
const lookup = this.db.contacts.lookupContact(effectiveHandle);
|
|
3800
|
+
const country = defaultCountryFromEnv();
|
|
3752
3801
|
if (lookup) {
|
|
3802
|
+
const contact = this.db.contacts.getContact(lookup.contactId);
|
|
3803
|
+
const identity = contact ? buildIdentity(contact.displayName, contact.phoneNumbers, contact.emails, country) : buildIdentityFromHandle(effectiveHandle, lookup.displayName, country);
|
|
3753
3804
|
return toolText(`${handle} → ${sanitizeUserText(lookup.displayName)}`, {
|
|
3754
3805
|
handle,
|
|
3755
3806
|
displayName: lookup.displayName,
|
|
3756
3807
|
contactId: lookup.contactId,
|
|
3757
3808
|
label: lookup.label ?? null,
|
|
3758
|
-
resolved: true
|
|
3809
|
+
resolved: true,
|
|
3810
|
+
identity
|
|
3759
3811
|
});
|
|
3760
3812
|
}
|
|
3761
3813
|
return toolText(`No contact for ${handle}.`, {
|
|
@@ -3763,7 +3815,8 @@ ${lines}${hint}`,
|
|
|
3763
3815
|
displayName: handle,
|
|
3764
3816
|
contactId: null,
|
|
3765
3817
|
label: null,
|
|
3766
|
-
resolved: false
|
|
3818
|
+
resolved: false,
|
|
3819
|
+
identity: buildIdentityFromHandle(effectiveHandle, null, country)
|
|
3767
3820
|
});
|
|
3768
3821
|
}
|
|
3769
3822
|
async handleCheckImessageAvailability(args) {
|