ofw-mcp 2.4.2 → 2.4.3
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/bundle.js +187 -48
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/server.json +2 -2
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "OurFamilyWizard tools for Claude Code",
|
|
9
|
-
"version": "2.4.
|
|
9
|
+
"version": "2.4.3"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"displayName": "OurFamilyWizard",
|
|
15
15
|
"source": "./",
|
|
16
16
|
"description": "OurFamilyWizard co-parenting tools for Claude — messages, calendar, expenses, and journal via MCP",
|
|
17
|
-
"version": "2.4.
|
|
17
|
+
"version": "2.4.3",
|
|
18
18
|
"author": {
|
|
19
19
|
"name": "Chris Chall"
|
|
20
20
|
},
|
package/dist/bundle.js
CHANGED
|
@@ -35837,10 +35837,20 @@ async function openEncryptedFrame(sessionKey, frame) {
|
|
|
35837
35837
|
|
|
35838
35838
|
// node_modules/@fetchproxy/server/dist/election.js
|
|
35839
35839
|
import { createServer, Server as HttpServer } from "node:http";
|
|
35840
|
+
var DEFAULT_BIND_TIMEOUT_MS = 5e3;
|
|
35840
35841
|
async function electRole(opts) {
|
|
35841
35842
|
const server = createServer();
|
|
35843
|
+
const bindTimeoutMs = opts.bindTimeoutMs ?? DEFAULT_BIND_TIMEOUT_MS;
|
|
35842
35844
|
return new Promise((resolve2, reject) => {
|
|
35845
|
+
let timer;
|
|
35846
|
+
const clearBindTimer = () => {
|
|
35847
|
+
if (timer) {
|
|
35848
|
+
clearTimeout(timer);
|
|
35849
|
+
timer = void 0;
|
|
35850
|
+
}
|
|
35851
|
+
};
|
|
35843
35852
|
const onError = (e) => {
|
|
35853
|
+
clearBindTimer();
|
|
35844
35854
|
server.removeListener("listening", onListening);
|
|
35845
35855
|
if (e.code === "EADDRINUSE") {
|
|
35846
35856
|
try {
|
|
@@ -35853,11 +35863,25 @@ async function electRole(opts) {
|
|
|
35853
35863
|
}
|
|
35854
35864
|
};
|
|
35855
35865
|
const onListening = () => {
|
|
35866
|
+
clearBindTimer();
|
|
35856
35867
|
server.removeListener("error", onError);
|
|
35857
35868
|
resolve2({ role: "host", server });
|
|
35858
35869
|
};
|
|
35859
35870
|
server.once("error", onError);
|
|
35860
35871
|
server.once("listening", onListening);
|
|
35872
|
+
if (bindTimeoutMs > 0) {
|
|
35873
|
+
timer = setTimeout(() => {
|
|
35874
|
+
server.removeListener("error", onError);
|
|
35875
|
+
server.removeListener("listening", onListening);
|
|
35876
|
+
try {
|
|
35877
|
+
server.close();
|
|
35878
|
+
} catch {
|
|
35879
|
+
}
|
|
35880
|
+
reject(new Error(`fetchproxy: bind to ${opts.host}:${opts.port} timed out after ${bindTimeoutMs}ms (port may be in a bad state)`));
|
|
35881
|
+
}, bindTimeoutMs);
|
|
35882
|
+
if (typeof timer.unref === "function")
|
|
35883
|
+
timer.unref();
|
|
35884
|
+
}
|
|
35861
35885
|
server.listen(opts.port, opts.host);
|
|
35862
35886
|
});
|
|
35863
35887
|
}
|
|
@@ -35950,6 +35974,44 @@ var SessionState = class {
|
|
|
35950
35974
|
}
|
|
35951
35975
|
};
|
|
35952
35976
|
|
|
35977
|
+
// node_modules/@fetchproxy/server/dist/session-ready.js
|
|
35978
|
+
var SESSION_READY_TIMEOUT_MS = 3e4;
|
|
35979
|
+
var FetchproxySessionNotReadyError = class extends Error {
|
|
35980
|
+
reason;
|
|
35981
|
+
pairCode;
|
|
35982
|
+
mcpId;
|
|
35983
|
+
hint;
|
|
35984
|
+
constructor(info) {
|
|
35985
|
+
const pairing = info.pairCode !== null && info.pairCode !== "";
|
|
35986
|
+
const hint = pairing ? `Open the Transporter extension popup and approve pair code ${info.pairCode} for "${info.mcpId}", then retry.` : `The extension is connected but hasn't confirmed a session for "${info.mcpId}" \u2014 sign in to the target site in that browser (and approve the requested scope if it changed), then retry.`;
|
|
35987
|
+
super(`fetchproxy: ${pairing ? "pairing not yet approved" : "no confirmed browser session"} for "${info.mcpId}". ${hint}`);
|
|
35988
|
+
this.name = "FetchproxySessionNotReadyError";
|
|
35989
|
+
this.reason = pairing ? "pair-required" : "not-ready";
|
|
35990
|
+
this.pairCode = pairing ? info.pairCode : null;
|
|
35991
|
+
this.mcpId = info.mcpId;
|
|
35992
|
+
this.hint = hint;
|
|
35993
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
35994
|
+
}
|
|
35995
|
+
};
|
|
35996
|
+
async function awaitSessionReady(ready, opts) {
|
|
35997
|
+
const ms = opts.timeoutMs ?? SESSION_READY_TIMEOUT_MS;
|
|
35998
|
+
if (ms <= 0)
|
|
35999
|
+
return ready;
|
|
36000
|
+
let timer;
|
|
36001
|
+
const timeout = new Promise((_, reject) => {
|
|
36002
|
+
timer = setTimeout(() => {
|
|
36003
|
+
reject(new FetchproxySessionNotReadyError({ mcpId: opts.mcpId, pairCode: opts.pendingPairCode() }));
|
|
36004
|
+
}, ms);
|
|
36005
|
+
timer.unref?.();
|
|
36006
|
+
});
|
|
36007
|
+
try {
|
|
36008
|
+
return await Promise.race([ready, timeout]);
|
|
36009
|
+
} finally {
|
|
36010
|
+
if (timer)
|
|
36011
|
+
clearTimeout(timer);
|
|
36012
|
+
}
|
|
36013
|
+
}
|
|
36014
|
+
|
|
35953
36015
|
// node_modules/@fetchproxy/server/dist/host.js
|
|
35954
36016
|
var PUBLIC_ORIGIN_RE = /^https?:\/\/(?!(127\.0\.0\.1|localhost)(:|$))/i;
|
|
35955
36017
|
var enc2 = new TextEncoder();
|
|
@@ -36037,6 +36099,29 @@ async function startHost(opts) {
|
|
|
36037
36099
|
return;
|
|
36038
36100
|
}
|
|
36039
36101
|
if (frame.type === "hello" && frame.role === "server") {
|
|
36102
|
+
const peerEdPub = fromB64(frame.identityEd25519Pub);
|
|
36103
|
+
const peerSigMsg = concatBytes(enc2.encode(frame.mcpId), fromB64(frame.sessionNonce));
|
|
36104
|
+
const peerSig = fromB64(frame.sessionSig);
|
|
36105
|
+
let peerSigOk = false;
|
|
36106
|
+
try {
|
|
36107
|
+
peerSigOk = await ed25519Verify(peerEdPub, peerSigMsg, peerSig);
|
|
36108
|
+
} catch {
|
|
36109
|
+
peerSigOk = false;
|
|
36110
|
+
}
|
|
36111
|
+
if (!peerSigOk) {
|
|
36112
|
+
console.warn("[fetchproxy] peer hello signature invalid \u2014 refusing registration (possible squatter)");
|
|
36113
|
+
ws.close(1008, "peer hello signature invalid");
|
|
36114
|
+
return;
|
|
36115
|
+
}
|
|
36116
|
+
const existing = peers.get(frame.mcpId);
|
|
36117
|
+
if (existing && existing.ws !== ws) {
|
|
36118
|
+
const existingEdPub = existing.helloFrame.identityEd25519Pub;
|
|
36119
|
+
if (existingEdPub !== frame.identityEd25519Pub) {
|
|
36120
|
+
console.warn("[fetchproxy] peer mcpId already mapped to a different identity \u2014 refusing (mcpId squatting)");
|
|
36121
|
+
ws.close(1008, "mcpId already registered to another identity");
|
|
36122
|
+
return;
|
|
36123
|
+
}
|
|
36124
|
+
}
|
|
36040
36125
|
identified = "peer";
|
|
36041
36126
|
peerMcpId = frame.mcpId;
|
|
36042
36127
|
peers.set(frame.mcpId, { ws, helloFrame: frame });
|
|
@@ -36129,8 +36214,10 @@ async function startHost(opts) {
|
|
|
36129
36214
|
resetSessionPromise();
|
|
36130
36215
|
disconnectListeners.forEach((cb) => cb());
|
|
36131
36216
|
}
|
|
36132
|
-
if (identified === "peer" && peerMcpId)
|
|
36133
|
-
peers.
|
|
36217
|
+
if (identified === "peer" && peerMcpId) {
|
|
36218
|
+
if (peers.get(peerMcpId)?.ws === ws)
|
|
36219
|
+
peers.delete(peerMcpId);
|
|
36220
|
+
}
|
|
36134
36221
|
});
|
|
36135
36222
|
});
|
|
36136
36223
|
return {
|
|
@@ -36146,7 +36233,10 @@ async function startHost(opts) {
|
|
|
36146
36233
|
});
|
|
36147
36234
|
}),
|
|
36148
36235
|
sendOwnInner: async (inner) => {
|
|
36149
|
-
const session = await ownSessionReady
|
|
36236
|
+
const session = await awaitSessionReady(ownSessionReady, {
|
|
36237
|
+
mcpId: opts.ownMcpId,
|
|
36238
|
+
pendingPairCode: () => ownPendingPairCode
|
|
36239
|
+
});
|
|
36150
36240
|
if (!extensionWs)
|
|
36151
36241
|
throw new Error("host: no extension connected");
|
|
36152
36242
|
const sealed = await sealInnerFrame(session.sessionKey, opts.ownMcpId, session.nextOutboundSeq(), inner);
|
|
@@ -36251,7 +36341,10 @@ async function startPeer(opts) {
|
|
|
36251
36341
|
ws,
|
|
36252
36342
|
session: sessionPromise,
|
|
36253
36343
|
sendInner: async (inner) => {
|
|
36254
|
-
await sessionPromise
|
|
36344
|
+
await awaitSessionReady(sessionPromise, {
|
|
36345
|
+
mcpId: opts.mcpId,
|
|
36346
|
+
pendingPairCode: () => pendingPairCode
|
|
36347
|
+
});
|
|
36255
36348
|
const s = session;
|
|
36256
36349
|
const sealed = await sealInnerFrame(s.sessionKey, opts.mcpId, s.nextOutboundSeq(), inner);
|
|
36257
36350
|
ws.send(JSON.stringify(sealed));
|
|
@@ -36917,6 +37010,35 @@ var FetchproxyServer = class {
|
|
|
36917
37010
|
this.keepAliveTimer = null;
|
|
36918
37011
|
}
|
|
36919
37012
|
}
|
|
37013
|
+
/**
|
|
37014
|
+
* Send an inner request frame via whichever bridge handle is active. If the
|
|
37015
|
+
* send throws (e.g. `FetchproxySessionNotReadyError` — the session never
|
|
37016
|
+
* confirmed), the frame never reached the bridge, so no reply will arrive:
|
|
37017
|
+
* drop the just-registered pending resolver for this id (it lives in exactly
|
|
37018
|
+
* one of the op maps — request ids are unique) so it doesn't leak until the
|
|
37019
|
+
* server closes, then rethrow.
|
|
37020
|
+
*/
|
|
37021
|
+
async sendInnerFrame(inner) {
|
|
37022
|
+
try {
|
|
37023
|
+
if (this.hostHandle) {
|
|
37024
|
+
await this.hostHandle.sendOwnInner(inner);
|
|
37025
|
+
} else if (this.peerHandle) {
|
|
37026
|
+
await this.peerHandle.sendInner(inner);
|
|
37027
|
+
}
|
|
37028
|
+
} catch (err) {
|
|
37029
|
+
if ("id" in inner && typeof inner.id === "number") {
|
|
37030
|
+
const { id } = inner;
|
|
37031
|
+
this.pending.delete(id);
|
|
37032
|
+
this.pendingReadCookies.delete(id);
|
|
37033
|
+
this.pendingStorage.delete(id);
|
|
37034
|
+
this.pendingCapture.delete(id);
|
|
37035
|
+
this.pendingRedirect.delete(id);
|
|
37036
|
+
this.pendingDownload.delete(id);
|
|
37037
|
+
this.pendingIdb.delete(id);
|
|
37038
|
+
}
|
|
37039
|
+
throw err;
|
|
37040
|
+
}
|
|
37041
|
+
}
|
|
36920
37042
|
/**
|
|
36921
37043
|
* Single bridge round-trip, wrapped by `fetchTimeoutMs` when set.
|
|
36922
37044
|
* On timeout returns the `{ok:false, kind:'timeout'}` envelope —
|
|
@@ -36928,11 +37050,7 @@ var FetchproxyServer = class {
|
|
|
36928
37050
|
const pending = new Promise((resolve2) => {
|
|
36929
37051
|
this.pending.set(id, resolve2);
|
|
36930
37052
|
});
|
|
36931
|
-
|
|
36932
|
-
await this.hostHandle.sendOwnInner(inner);
|
|
36933
|
-
} else if (this.peerHandle) {
|
|
36934
|
-
await this.peerHandle.sendInner(inner);
|
|
36935
|
-
}
|
|
37053
|
+
await this.sendInnerFrame(inner);
|
|
36936
37054
|
const timeoutMs = this.opts.fetchTimeoutMs;
|
|
36937
37055
|
if (timeoutMs === void 0 || timeoutMs <= 0)
|
|
36938
37056
|
return pending;
|
|
@@ -36961,6 +37079,51 @@ var FetchproxyServer = class {
|
|
|
36961
37079
|
clearTimeout(timer);
|
|
36962
37080
|
}
|
|
36963
37081
|
}
|
|
37082
|
+
/**
|
|
37083
|
+
* FP-B2: bound a non-`fetch` verb's reply wait by `fetchTimeoutMs`.
|
|
37084
|
+
*
|
|
37085
|
+
* Before this, only `fetch()` raced its `pending` reply against a timer
|
|
37086
|
+
* (`_fetchOnceWithTimeout`); `readCookies`, the storage reads,
|
|
37087
|
+
* `capture_request_header`, `capture_redirect`, `download`, and
|
|
37088
|
+
* `read_indexed_db` awaited their `pending` promise with no race, so a
|
|
37089
|
+
* wedged extension hung the tool call indefinitely.
|
|
37090
|
+
*
|
|
37091
|
+
* `pending` is the already-registered reply promise. `pendingMap`/`id`
|
|
37092
|
+
* point at the op-specific map entry so we can drop it on expiry exactly
|
|
37093
|
+
* as `_fetchOnceWithTimeout` does — otherwise a late bridge reply would
|
|
37094
|
+
* resolve into a stale resolver / leak. On timeout we reject with a
|
|
37095
|
+
* `FetchproxyTimeoutError` (the same throwable the convenience methods
|
|
37096
|
+
* already surface for fetch timeouts). `0`/unset opts out (unbounded),
|
|
37097
|
+
* matching the fetch path.
|
|
37098
|
+
*/
|
|
37099
|
+
async _withVerbTimeout(pending, pendingMap, id, url2) {
|
|
37100
|
+
const timeoutMs = this.opts.fetchTimeoutMs;
|
|
37101
|
+
if (timeoutMs === void 0 || timeoutMs <= 0)
|
|
37102
|
+
return pending;
|
|
37103
|
+
let timer;
|
|
37104
|
+
const start = Date.now();
|
|
37105
|
+
try {
|
|
37106
|
+
return await Promise.race([
|
|
37107
|
+
pending,
|
|
37108
|
+
new Promise((_resolve, reject) => {
|
|
37109
|
+
timer = setTimeout(() => {
|
|
37110
|
+
pendingMap.delete(id);
|
|
37111
|
+
reject(new FetchproxyTimeoutError({
|
|
37112
|
+
url: url2,
|
|
37113
|
+
timeoutMs,
|
|
37114
|
+
role: this.role,
|
|
37115
|
+
port: this.opts.port,
|
|
37116
|
+
elapsedMs: Date.now() - start,
|
|
37117
|
+
retryAttempted: false
|
|
37118
|
+
}));
|
|
37119
|
+
}, timeoutMs);
|
|
37120
|
+
})
|
|
37121
|
+
]);
|
|
37122
|
+
} finally {
|
|
37123
|
+
if (timer)
|
|
37124
|
+
clearTimeout(timer);
|
|
37125
|
+
}
|
|
37126
|
+
}
|
|
36964
37127
|
/**
|
|
36965
37128
|
* Map an `ok:false` fetch result to its typed throwable. Centralizes
|
|
36966
37129
|
* the kind-to-error-class switch so `request()` and (via the same
|
|
@@ -37251,12 +37414,8 @@ var FetchproxyServer = class {
|
|
|
37251
37414
|
const pending = new Promise((resolve2) => {
|
|
37252
37415
|
this.pendingReadCookies.set(id, resolve2);
|
|
37253
37416
|
});
|
|
37254
|
-
|
|
37255
|
-
|
|
37256
|
-
} else if (this.peerHandle) {
|
|
37257
|
-
await this.peerHandle.sendInner(inner);
|
|
37258
|
-
}
|
|
37259
|
-
const result = await pending;
|
|
37417
|
+
await this.sendInnerFrame(inner);
|
|
37418
|
+
const result = await this._withVerbTimeout(pending, this.pendingReadCookies, id, `https://${host}`);
|
|
37260
37419
|
if (!result.ok) {
|
|
37261
37420
|
throw new FetchproxyProtocolError(result.error);
|
|
37262
37421
|
}
|
|
@@ -37322,12 +37481,8 @@ var FetchproxyServer = class {
|
|
|
37322
37481
|
const pending = new Promise((resolve2, reject) => {
|
|
37323
37482
|
this.pendingStorage.set(id, { resolve: resolve2, reject });
|
|
37324
37483
|
});
|
|
37325
|
-
|
|
37326
|
-
|
|
37327
|
-
} else if (this.peerHandle) {
|
|
37328
|
-
await this.peerHandle.sendInner(inner);
|
|
37329
|
-
}
|
|
37330
|
-
return pending;
|
|
37484
|
+
await this.sendInnerFrame(inner);
|
|
37485
|
+
return this._withVerbTimeout(pending, this.pendingStorage, id, `https://${host}`);
|
|
37331
37486
|
}
|
|
37332
37487
|
/**
|
|
37333
37488
|
* 0.3.0+: snapshot the next outgoing request's named header. Single-
|
|
@@ -37431,12 +37586,8 @@ var FetchproxyServer = class {
|
|
|
37431
37586
|
const pending = new Promise((resolve2, reject) => {
|
|
37432
37587
|
this.pendingCapture.set(id, { resolve: resolve2, reject });
|
|
37433
37588
|
});
|
|
37434
|
-
|
|
37435
|
-
|
|
37436
|
-
} else if (this.peerHandle) {
|
|
37437
|
-
await this.peerHandle.sendInner(inner);
|
|
37438
|
-
}
|
|
37439
|
-
return pending;
|
|
37589
|
+
await this.sendInnerFrame(inner);
|
|
37590
|
+
return this._withVerbTimeout(pending, this.pendingCapture, id, `https://${opts.host}${opts.path ?? "/*"}`);
|
|
37440
37591
|
}
|
|
37441
37592
|
/**
|
|
37442
37593
|
* Snapshot the redirect target URL of the next request the browser
|
|
@@ -37520,12 +37671,8 @@ var FetchproxyServer = class {
|
|
|
37520
37671
|
const pending = new Promise((resolve2, reject) => {
|
|
37521
37672
|
this.pendingRedirect.set(id, { resolve: resolve2, reject });
|
|
37522
37673
|
});
|
|
37523
|
-
|
|
37524
|
-
|
|
37525
|
-
} else if (this.peerHandle) {
|
|
37526
|
-
await this.peerHandle.sendInner(inner);
|
|
37527
|
-
}
|
|
37528
|
-
return pending;
|
|
37674
|
+
await this.sendInnerFrame(inner);
|
|
37675
|
+
return this._withVerbTimeout(pending, this.pendingRedirect, id, `https://${opts.host}${opts.path ?? "/*"}`);
|
|
37529
37676
|
}
|
|
37530
37677
|
/**
|
|
37531
37678
|
* Download `url` through the BROWSER's own network stack via
|
|
@@ -37606,12 +37753,8 @@ var FetchproxyServer = class {
|
|
|
37606
37753
|
const pending = new Promise((resolve2, reject) => {
|
|
37607
37754
|
this.pendingDownload.set(id, { resolve: resolve2, reject });
|
|
37608
37755
|
});
|
|
37609
|
-
|
|
37610
|
-
|
|
37611
|
-
} else if (this.peerHandle) {
|
|
37612
|
-
await this.peerHandle.sendInner(inner);
|
|
37613
|
-
}
|
|
37614
|
-
return pending;
|
|
37756
|
+
await this.sendInnerFrame(inner);
|
|
37757
|
+
return this._withVerbTimeout(pending, this.pendingDownload, id, opts.url);
|
|
37615
37758
|
}
|
|
37616
37759
|
/**
|
|
37617
37760
|
* 0.4.0+: read declared IndexedDB keys from the user's signed-in
|
|
@@ -37658,12 +37801,8 @@ var FetchproxyServer = class {
|
|
|
37658
37801
|
const pending = new Promise((resolve2, reject) => {
|
|
37659
37802
|
this.pendingIdb.set(id, { resolve: resolve2, reject });
|
|
37660
37803
|
});
|
|
37661
|
-
|
|
37662
|
-
|
|
37663
|
-
} else if (this.peerHandle) {
|
|
37664
|
-
await this.peerHandle.sendInner(inner);
|
|
37665
|
-
}
|
|
37666
|
-
return pending;
|
|
37804
|
+
await this.sendInnerFrame(inner);
|
|
37805
|
+
return this._withVerbTimeout(pending, this.pendingIdb, id, origin);
|
|
37667
37806
|
}
|
|
37668
37807
|
assertScopeSubset(requested, declared, label) {
|
|
37669
37808
|
const undeclared = undeclaredKeys(requested, declared);
|
|
@@ -38150,7 +38289,7 @@ function getDefaultInlineAttachments() {
|
|
|
38150
38289
|
// package.json
|
|
38151
38290
|
var package_default = {
|
|
38152
38291
|
name: "ofw-mcp",
|
|
38153
|
-
version: "2.4.
|
|
38292
|
+
version: "2.4.3",
|
|
38154
38293
|
license: "MIT",
|
|
38155
38294
|
mcpName: "io.github.chrischall/ofw-mcp",
|
|
38156
38295
|
description: "OurFamilyWizard MCP server for Claude \u2014 developed and maintained by AI (Claude Code)",
|
|
@@ -38182,7 +38321,7 @@ var package_default = {
|
|
|
38182
38321
|
"test:watch": "vitest"
|
|
38183
38322
|
},
|
|
38184
38323
|
dependencies: {
|
|
38185
|
-
"@chrischall/mcp-utils": "^0.
|
|
38324
|
+
"@chrischall/mcp-utils": "^0.10.3",
|
|
38186
38325
|
"@fetchproxy/bootstrap": "^1.3.0",
|
|
38187
38326
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
38188
38327
|
dotenv: "^17.4.2",
|
|
@@ -39787,7 +39926,7 @@ process.emit = function(event, ...args) {
|
|
|
39787
39926
|
};
|
|
39788
39927
|
await runMcp({
|
|
39789
39928
|
name: "ofw",
|
|
39790
|
-
version: "2.4.
|
|
39929
|
+
version: "2.4.3",
|
|
39791
39930
|
// x-release-please-version
|
|
39792
39931
|
deps: client,
|
|
39793
39932
|
tools: [
|
package/dist/index.js
CHANGED
|
@@ -24,7 +24,7 @@ import { registerJournalTools } from './tools/journal.js';
|
|
|
24
24
|
// always succeeds before any credential check runs.
|
|
25
25
|
await runMcp({
|
|
26
26
|
name: 'ofw',
|
|
27
|
-
version: '2.4.
|
|
27
|
+
version: '2.4.3', // x-release-please-version
|
|
28
28
|
deps: client,
|
|
29
29
|
tools: [
|
|
30
30
|
registerUserTools,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ofw-mcp",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"mcpName": "io.github.chrischall/ofw-mcp",
|
|
6
6
|
"description": "OurFamilyWizard MCP server for Claude — developed and maintained by AI (Claude Code)",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"test:watch": "vitest"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@chrischall/mcp-utils": "^0.
|
|
35
|
+
"@chrischall/mcp-utils": "^0.10.3",
|
|
36
36
|
"@fetchproxy/bootstrap": "^1.3.0",
|
|
37
37
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
38
38
|
"dotenv": "^17.4.2",
|
package/server.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/chrischall/ofw-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "2.4.
|
|
9
|
+
"version": "2.4.3",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "ofw-mcp",
|
|
14
|
-
"version": "2.4.
|
|
14
|
+
"version": "2.4.3",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|