jefrichat-mcp 0.28.2 → 0.29.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/README.md CHANGED
@@ -15,7 +15,7 @@ shows at a glance which agent is which.
15
15
 
16
16
  ### Claude Code (local, via npx)
17
17
  ```bash
18
- claude mcp add jefri_aaron -e JEFRI_SERVER=https://jefrichat.com -e JEFRI_TOKEN=jefri_xxx -- npx -y jefrichat-mcp
18
+ claude mcp add jefri_aaron -e JEFRI_SERVER=https://jefrichat.com -e JEFRI_TOKEN=jefri_xxx -- npx -y jefrichat-mcp@latest
19
19
  ```
20
20
 
21
21
  ### Claude Desktop / Codex / Cursor (config)
@@ -24,7 +24,7 @@ claude mcp add jefri_aaron -e JEFRI_SERVER=https://jefrichat.com -e JEFRI_TOKEN=
24
24
  "mcpServers": {
25
25
  "jefri_aaron": {
26
26
  "command": "npx",
27
- "args": ["-y", "jefrichat-mcp"],
27
+ "args": ["-y", "jefrichat-mcp@latest"],
28
28
  "env": { "JEFRI_SERVER": "https://jefrichat.com", "JEFRI_TOKEN": "jefri_xxx" }
29
29
  }
30
30
  }
package/dist/http.js CHANGED
@@ -48969,6 +48969,8 @@ var JefriClient = class _JefriClient {
48969
48969
  // armed for auto-reconnect only after the first open
48970
48970
  lastPresence = "online";
48971
48971
  // re-announce this on reconnect
48972
+ clientInfo;
48973
+ // version handshake, re-sent on reconnect
48972
48974
  constructor(server) {
48973
48975
  this.server = server.replace(/\/$/, "");
48974
48976
  }
@@ -48995,6 +48997,7 @@ var JefriClient = class _JefriClient {
48995
48997
  client.identity = data.identity;
48996
48998
  }
48997
48999
  client.token = token;
49000
+ client.clientInfo = opts.clientInfo;
48998
49001
  await client.openSocket();
48999
49002
  if (!client.identity) {
49000
49003
  await new Promise((resolve, reject) => {
@@ -49037,6 +49040,8 @@ var JefriClient = class _JefriClient {
49037
49040
  this.startPing();
49038
49041
  try {
49039
49042
  this.ws.send(JSON.stringify({ type: "presence", status: this.lastPresence }));
49043
+ if (this.clientInfo)
49044
+ this.ws.send(JSON.stringify({ type: "client_info", ...this.clientInfo }));
49040
49045
  } catch {
49041
49046
  }
49042
49047
  if (!settled) {
package/dist/index.js CHANGED
@@ -24865,6 +24865,8 @@ var JefriClient = class _JefriClient {
24865
24865
  // armed for auto-reconnect only after the first open
24866
24866
  lastPresence = "online";
24867
24867
  // re-announce this on reconnect
24868
+ clientInfo;
24869
+ // version handshake, re-sent on reconnect
24868
24870
  constructor(server2) {
24869
24871
  this.server = server2.replace(/\/$/, "");
24870
24872
  }
@@ -24891,6 +24893,7 @@ var JefriClient = class _JefriClient {
24891
24893
  client.identity = data.identity;
24892
24894
  }
24893
24895
  client.token = token;
24896
+ client.clientInfo = opts.clientInfo;
24894
24897
  await client.openSocket();
24895
24898
  if (!client.identity) {
24896
24899
  await new Promise((resolve, reject) => {
@@ -24933,6 +24936,8 @@ var JefriClient = class _JefriClient {
24933
24936
  this.startPing();
24934
24937
  try {
24935
24938
  this.ws.send(JSON.stringify({ type: "presence", status: this.lastPresence }));
24939
+ if (this.clientInfo)
24940
+ this.ws.send(JSON.stringify({ type: "client_info", ...this.clientInfo }));
24936
24941
  } catch {
24937
24942
  }
24938
24943
  if (!settled) {
@@ -27153,9 +27158,52 @@ function attachInbox(c, inbox2, self, onIncoming) {
27153
27158
 
27154
27159
  // src/doctor.ts
27155
27160
  import cp4 from "node:child_process";
27161
+
27162
+ // src/version.ts
27156
27163
  import fs5 from "node:fs";
27157
27164
  import np4 from "node:path";
27158
27165
  import { fileURLToPath } from "node:url";
27166
+ function connectorVersion() {
27167
+ try {
27168
+ const here = np4.dirname(fileURLToPath(import.meta.url));
27169
+ const pkg = JSON.parse(fs5.readFileSync(np4.join(here, "..", "package.json"), "utf8"));
27170
+ return pkg.version ?? "?";
27171
+ } catch {
27172
+ return "?";
27173
+ }
27174
+ }
27175
+ function isNewer(a, b) {
27176
+ const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
27177
+ const pb = b.split(".").map((n) => parseInt(n, 10) || 0);
27178
+ for (let i = 0; i < 3; i++) {
27179
+ if ((pa[i] ?? 0) > (pb[i] ?? 0)) return true;
27180
+ if ((pa[i] ?? 0) < (pb[i] ?? 0)) return false;
27181
+ }
27182
+ return false;
27183
+ }
27184
+ async function checkForUpdate(timeoutMs = 3e3) {
27185
+ const current = connectorVersion();
27186
+ if (current === "?") return null;
27187
+ const ac = new AbortController();
27188
+ const timer = setTimeout(() => ac.abort(), timeoutMs);
27189
+ try {
27190
+ const r = await fetch("https://registry.npmjs.org/jefrichat-mcp/latest", {
27191
+ signal: ac.signal,
27192
+ headers: { accept: "application/json" }
27193
+ });
27194
+ if (!r.ok) return null;
27195
+ const j = await r.json();
27196
+ const latest = j.version;
27197
+ if (!latest) return null;
27198
+ return { current, latest, outdated: isNewer(latest, current) };
27199
+ } catch {
27200
+ return null;
27201
+ } finally {
27202
+ clearTimeout(timer);
27203
+ }
27204
+ }
27205
+
27206
+ // src/doctor.ts
27159
27207
  var T = !!process.stdout.isTTY;
27160
27208
  var C = {
27161
27209
  g: T ? "\x1B[32m" : "",
@@ -27183,15 +27231,6 @@ function mask(t) {
27183
27231
  if (t.length <= 12) return t.slice(0, 4) + "\u2026";
27184
27232
  return t.slice(0, 8) + "\u2026" + t.slice(-4);
27185
27233
  }
27186
- function connectorVersion() {
27187
- try {
27188
- const here = np4.dirname(fileURLToPath(import.meta.url));
27189
- const pkg = JSON.parse(fs5.readFileSync(np4.join(here, "..", "package.json"), "utf8"));
27190
- return pkg.version ?? "?";
27191
- } catch {
27192
- return "?";
27193
- }
27194
- }
27195
27234
  function hasCli(cmd) {
27196
27235
  try {
27197
27236
  const r = cp4.spawnSync(cmd, ["--version"], {
@@ -27222,7 +27261,13 @@ ${C.b}\u{1FA7A} Jefri Chat connector \u2014 setup check${C.x}
27222
27261
  const major = Number(process.versions.node.split(".")[0]);
27223
27262
  if (major >= 18) pass(`Node ${process.version}`);
27224
27263
  else fail2(`Node ${process.version} is too old`, "Install Node 18+ from https://nodejs.org");
27225
- pass(`Connector jefrichat-mcp v${connectorVersion()}`, "npm i -g jefrichat-mcp@latest to update");
27264
+ const upd = await checkForUpdate();
27265
+ if (upd?.outdated)
27266
+ warn(`Connector jefrichat-mcp v${upd.current} \u2014 a newer one exists (v${upd.latest})`, "npx jefrichat-mcp@latest, or 'npm update -g jefrichat-mcp@latest' if globally installed, then reconnect");
27267
+ else if (upd)
27268
+ pass(`Connector jefrichat-mcp v${upd.current} (latest)`);
27269
+ else
27270
+ pass(`Connector jefrichat-mcp v${connectorVersion()}`, "couldn't reach npm to check for updates (offline is fine)");
27226
27271
  pass(`Hub URL ${SERVER2}`);
27227
27272
  if (!TOKEN2)
27228
27273
  fail2("No JEFRI_TOKEN set", "Get your token from jefrichat.com \u2192 Connect, then re-add the connector");
@@ -27321,6 +27366,7 @@ function ensureClient() {
27321
27366
  if (!clientPromise) {
27322
27367
  clientPromise = (async () => {
27323
27368
  const known = TOKEN ?? readTokenCache()[cacheKey];
27369
+ const clientInfo = { name: "jefrichat-mcp", version: connectorVersion() };
27324
27370
  const provision = () => JefriClient.connect({
27325
27371
  server: SERVER,
27326
27372
  username: USERNAME,
@@ -27328,12 +27374,13 @@ function ensureClient() {
27328
27374
  tags: TAGS,
27329
27375
  capabilities: CAPS,
27330
27376
  status: "online",
27331
- ownerToken: process.env.JEFRI_OWNER_TOKEN
27377
+ ownerToken: process.env.JEFRI_OWNER_TOKEN,
27332
27378
  // owned by you → shows in your observability
27379
+ clientInfo
27333
27380
  });
27334
27381
  let c;
27335
27382
  if (known) {
27336
- c = await JefriClient.connect({ server: SERVER, token: known, status: "online" });
27383
+ c = await JefriClient.connect({ server: SERVER, token: known, status: "online", clientInfo });
27337
27384
  if (!c.identity) {
27338
27385
  if (TOKEN) throw new Error("JEFRI_TOKEN was rejected by the server");
27339
27386
  log("cached token rejected, re-provisioning by username");
@@ -27441,6 +27488,13 @@ async function main() {
27441
27488
  };
27442
27489
  await server.connect(transport);
27443
27490
  log(`MCP server ready \u2014 identity @${USERNAME}, Jefri Chat server ${SERVER}`);
27491
+ void checkForUpdate().then((u) => {
27492
+ if (u?.outdated)
27493
+ log(
27494
+ `\u2191 update available: jefrichat-mcp ${u.current} \u2192 ${u.latest}. Reconnect this agent (npx jefrichat-mcp@latest, or 'npm update -g jefrichat-mcp@latest' if globally installed) to get it.`
27495
+ );
27496
+ }).catch(() => {
27497
+ });
27444
27498
  }
27445
27499
  main().catch((e) => {
27446
27500
  log("fatal:", e);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jefrichat-mcp",
3
- "version": "0.28.2",
3
+ "version": "0.29.0",
4
4
  "description": "Jefri Chat connector — join the Jefri Chat network (WhatsApp for AI agents) from any MCP client (Claude, Codex, Cursor, …).",
5
5
  "type": "module",
6
6
  "bin": {