ofw-mcp 2.20.2 → 2.20.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/README.md +2 -1
- package/dist/bundle.js +89 -7
- package/dist/index.js +1 -1
- package/mint.yaml +7 -0
- package/package.json +3 -3
- 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.20.
|
|
9
|
+
"version": "2.20.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.20.
|
|
17
|
+
"version": "2.20.3",
|
|
18
18
|
"author": {
|
|
19
19
|
"name": "Chris Chall"
|
|
20
20
|
},
|
package/README.md
CHANGED
|
@@ -227,13 +227,14 @@ Every list read also carries an explicit **`complete`** boolean describing the *
|
|
|
227
227
|
|
|
228
228
|
### Server-side confirmation (`MCP_CONFIRM_MODE`)
|
|
229
229
|
|
|
230
|
-
The writes marked **Confirm (server)** above — sending a message, logging an expense, creating/updating/deleting a *shared* calendar event, and uploading a file as `SHARED` — are confirmed by this server, not left to the host. A client that can show a confirmation prompt (Claude Code) gets one, with a preview of exactly what would happen
|
|
230
|
+
The writes marked **Confirm (server)** above — sending a message, logging an expense, creating/updating/deleting a *shared* calendar event, and uploading a file as `SHARED` — are confirmed by this server, not left to the host. A client that can show a confirmation prompt (Claude Code) gets one, with a preview of exactly what would happen, unless `MCP_CONFIRM_ELICITATION=off`. A client that cannot (claude.ai, Claude Desktop) gets two steps: the first call writes **nothing** and returns that preview plus a `confirmToken`, and only a repeat call with the same arguments and that token proceeds.
|
|
231
231
|
|
|
232
232
|
Previews name what you are approving — recipients by name, subject and full body, the reply target, attachment file names; the expense amount and description; the event's title, date, time, visibility and (for an update) before and after. The token is bound to exactly that: a different body, amount or recipient is refused, and so is a draft or event that changed on OurFamilyWizard after the preview (say, the co-parent edited the event), even with `force: true`. A token works once and expires.
|
|
233
233
|
|
|
234
234
|
| Variable | Default | |
|
|
235
235
|
|---|---|---|
|
|
236
236
|
| `MCP_CONFIRM_MODE` | `ask-user` | What a gated write does on a client that cannot show a prompt. `ask-user`: two steps, and the model must get your approval in chat before using the token. `auto`: two steps, but the model may use the token after reviewing the preview itself. `refuse`: such writes are refused (do them on ourfamilywizard.com). An unrecognised value is treated as `refuse`. |
|
|
237
|
+
| `MCP_CONFIRM_ELICITATION` | `on` | `off` never shows a confirmation prompt, so every client gets the `MCP_CONFIRM_MODE` path. Set it for a client that claims to support prompts but never shows one (the gated write hangs — opencode 2.0.x). Any other value stays `on`, with a warning on stderr. |
|
|
237
238
|
| `MCP_CONFIRM_TTL_SECONDS` | `600` | How long a token stays valid. |
|
|
238
239
|
| `MCP_CONFIRM_SECRET` | random per process | Signing key; set it only if tokens must survive a server restart. On mcp-host the host supplies a stable per-child key (`MCP_HOST_CONFIRM_SECRET`) and spent tokens are recorded under `MCP_DATA_DIR`, so an approval survives an idle restart. |
|
|
239
240
|
|
package/dist/bundle.js
CHANGED
|
@@ -38459,6 +38459,7 @@ function escapeKey(key) {
|
|
|
38459
38459
|
var DEFAULT_REQUEST_KEY = "confirmation";
|
|
38460
38460
|
var DEFAULT_CONFIRMATION_LABEL = "Confirm this action should proceed.";
|
|
38461
38461
|
var UNSUPPORTED_NOTE = "Nothing was done because this client cannot show a confirmation prompt (it declares no MCP elicitation capability), and this action is never taken without one";
|
|
38462
|
+
var DISABLED_NOTE = "Nothing was done because confirmation prompts are turned off for this server, and this action is never taken without one";
|
|
38462
38463
|
var STATE_PREFIX = "mcpu.confirm.v1.";
|
|
38463
38464
|
function bindingKey(binding) {
|
|
38464
38465
|
if (binding.ttlSeconds !== void 0 && !(Number.isFinite(binding.ttlSeconds) && binding.ttlSeconds > 0)) {
|
|
@@ -38531,6 +38532,15 @@ ${JSON.stringify(preview, null, 2)}`,
|
|
|
38531
38532
|
};
|
|
38532
38533
|
const response = inputResponse(ctx.mcpReq.inputResponses, requestKey);
|
|
38533
38534
|
const accepted = acceptedContent(ctx.mcpReq.inputResponses, requestKey, confirmationSchema);
|
|
38535
|
+
if (options.elicitation === false) {
|
|
38536
|
+
return textResult({
|
|
38537
|
+
confirmed: false,
|
|
38538
|
+
dispatched: false,
|
|
38539
|
+
action: options.action,
|
|
38540
|
+
reason: "confirmation-unsupported",
|
|
38541
|
+
note: options.unsupportedNote ? `${DISABLED_NOTE}. ${options.unsupportedNote}` : `${DISABLED_NOTE}.`
|
|
38542
|
+
});
|
|
38543
|
+
}
|
|
38534
38544
|
if (response.kind === "missing") {
|
|
38535
38545
|
if (callerAcceptsFormElicitation(ctx) === false) {
|
|
38536
38546
|
return textResult({
|
|
@@ -38725,7 +38735,7 @@ async function tokenConfirmation(action, fb) {
|
|
|
38725
38735
|
}
|
|
38726
38736
|
async function requireConfirmationWithFallback(ctx, options) {
|
|
38727
38737
|
const { tokenFallback, ...confirmation } = options;
|
|
38728
|
-
if (tokenFallback && callerAcceptsFormElicitation(ctx) === false) {
|
|
38738
|
+
if (tokenFallback && (options.elicitation === false || callerAcceptsFormElicitation(ctx) === false)) {
|
|
38729
38739
|
return tokenConfirmation(options.action, tokenFallback);
|
|
38730
38740
|
}
|
|
38731
38741
|
return requireConfirmation(ctx, confirmation);
|
|
@@ -38887,6 +38897,20 @@ function readConfirmMode(env = process.env) {
|
|
|
38887
38897
|
}
|
|
38888
38898
|
return "refuse";
|
|
38889
38899
|
}
|
|
38900
|
+
function readConfirmElicitation(env = process.env) {
|
|
38901
|
+
const raw = readEnvVar("MCP_CONFIRM_ELICITATION", { env })?.trim().toLowerCase();
|
|
38902
|
+
if (!raw || raw === "on")
|
|
38903
|
+
return "on";
|
|
38904
|
+
if (raw === "off")
|
|
38905
|
+
return "off";
|
|
38906
|
+
const key = `elicitation:${raw}`;
|
|
38907
|
+
if (!warned.has(key)) {
|
|
38908
|
+
warned.add(key);
|
|
38909
|
+
process.stderr.write(`MCP_CONFIRM_ELICITATION="${raw}" is not one of on, off; treating it as on.
|
|
38910
|
+
`);
|
|
38911
|
+
}
|
|
38912
|
+
return "on";
|
|
38913
|
+
}
|
|
38890
38914
|
function readConfirmTtl(env) {
|
|
38891
38915
|
const raw = readEnvVar("MCP_CONFIRM_TTL_SECONDS", { env })?.trim();
|
|
38892
38916
|
if (!raw)
|
|
@@ -38931,6 +38955,7 @@ function spentTokenStoreFromEnv(env = process.env) {
|
|
|
38931
38955
|
}
|
|
38932
38956
|
var CONFIRM_TOKEN_AUTO_INSTRUCTION = "Nothing has been done yet. Review this preview; if it is what was intended, call again with the same arguments plus confirmToken. (This server runs with MCP_CONFIRM_MODE=auto, so the user's approval in chat is not required.)";
|
|
38933
38957
|
var REFUSE_HINT = "Set MCP_CONFIRM_MODE=ask-user on the server to allow two-step confirmation instead.";
|
|
38958
|
+
var ELICITATION_OFF_HINT = "MCP_CONFIRM_ELICITATION=off on the server turns confirmation prompts off.";
|
|
38934
38959
|
var BAD_TTL_HINT = "MCP_CONFIRM_TTL_SECONDS on the server is not a positive whole number of seconds; fix it to allow two-step confirmation.";
|
|
38935
38960
|
function boundArgs(args) {
|
|
38936
38961
|
if (args === null || typeof args !== "object" || Array.isArray(args) || !("confirmToken" in args))
|
|
@@ -38944,10 +38969,13 @@ function confirmationFromEnv(options) {
|
|
|
38944
38969
|
const spent = callerSpent ?? spentTokenStoreFromEnv(env);
|
|
38945
38970
|
const mode = readConfirmMode(env);
|
|
38946
38971
|
const ttlSeconds = readConfirmTtl(env);
|
|
38972
|
+
const elicitationOff = readConfirmElicitation(env) === "off";
|
|
38947
38973
|
const bound = args === void 0 ? void 0 : boundArgs(args);
|
|
38948
|
-
const
|
|
38974
|
+
const bindingAdded = bound === void 0 || rest.binding ? rest : { ...rest, binding: { key: confirmKeyFromEnv(env), args: bound, ttlSeconds: ttlSeconds ?? DEFAULT_TTL_SECONDS2 } };
|
|
38975
|
+
const confirmation = elicitationOff ? { ...bindingAdded, elicitation: false } : bindingAdded;
|
|
38949
38976
|
if (mode === "refuse" || ttlSeconds === void 0) {
|
|
38950
|
-
const
|
|
38977
|
+
const reason = mode === "refuse" ? REFUSE_HINT : BAD_TTL_HINT;
|
|
38978
|
+
const hint = elicitationOff ? `${ELICITATION_OFF_HINT} ${reason}` : reason;
|
|
38951
38979
|
return {
|
|
38952
38980
|
...confirmation,
|
|
38953
38981
|
unsupportedNote: confirmation.unsupportedNote ? `${confirmation.unsupportedNote} ${hint}` : hint
|
|
@@ -40389,6 +40417,17 @@ var KNOWN_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
|
40389
40417
|
]);
|
|
40390
40418
|
var ACCOUNT_KEY_FRAME = "account-key";
|
|
40391
40419
|
var ACCOUNT_ATTEST_FRAME = "account-attest";
|
|
40420
|
+
var BRIDGE_ROLE_FRAME = "bridge-role";
|
|
40421
|
+
var BRIDGE_SERVE_FRAME = "bridge-serve";
|
|
40422
|
+
var ROOM_PING_FRAME = "room-ping";
|
|
40423
|
+
var ROOM_PONG_FRAME = "room-pong";
|
|
40424
|
+
var BRIDGE_ROLE_LABEL_MAX = 64;
|
|
40425
|
+
var ROOM_FRAME_ACCEPTS = Object.freeze({
|
|
40426
|
+
[BRIDGE_ROLE_FRAME]: BRIDGE_ROLE_FRAME,
|
|
40427
|
+
[BRIDGE_SERVE_FRAME]: BRIDGE_SERVE_FRAME,
|
|
40428
|
+
[ROOM_PING_FRAME]: ROOM_PING_FRAME,
|
|
40429
|
+
[ROOM_PONG_FRAME]: ROOM_PING_FRAME
|
|
40430
|
+
});
|
|
40392
40431
|
|
|
40393
40432
|
// node_modules/@fetchproxy/protocol/dist/mcp-id.js
|
|
40394
40433
|
var ID_RE = /^([^:]+):([^:]+):([0-9a-f]{16})$/;
|
|
@@ -41054,6 +41093,12 @@ function validateFrame(raw) {
|
|
|
41054
41093
|
return validateAccountKey(raw);
|
|
41055
41094
|
if (t === ACCOUNT_ATTEST_FRAME)
|
|
41056
41095
|
return validateAccountAttest(raw);
|
|
41096
|
+
if (t === BRIDGE_ROLE_FRAME)
|
|
41097
|
+
return validateBridgeRole(raw);
|
|
41098
|
+
if (t === BRIDGE_SERVE_FRAME || t === ROOM_PING_FRAME || t === ROOM_PONG_FRAME) {
|
|
41099
|
+
assertExactFields(raw, TYPE_ONLY_FIELDS, t);
|
|
41100
|
+
return { type: t };
|
|
41101
|
+
}
|
|
41057
41102
|
throw new ProtocolError3(`unknown frame type: ${String(t)}`);
|
|
41058
41103
|
}
|
|
41059
41104
|
function validateHello(raw) {
|
|
@@ -41379,6 +41424,43 @@ function validateAccountAttest(raw) {
|
|
|
41379
41424
|
sig: raw.sig
|
|
41380
41425
|
};
|
|
41381
41426
|
}
|
|
41427
|
+
var TYPE_ONLY_FIELDS = ["type"];
|
|
41428
|
+
var BRIDGE_ROLE_FIELDS = ["type", "role", "canServe", "serving"];
|
|
41429
|
+
var BRIDGE_ROLE_SERVING_FIELDS = ["label", "since"];
|
|
41430
|
+
function validateBridgeRole(raw) {
|
|
41431
|
+
const L = BRIDGE_ROLE_FRAME;
|
|
41432
|
+
const role = raw.role;
|
|
41433
|
+
if (role !== "serving" && role !== "standby") {
|
|
41434
|
+
throw new ProtocolError3(`${L}.role: must be one of serving, standby`);
|
|
41435
|
+
}
|
|
41436
|
+
const canServe = raw.canServe;
|
|
41437
|
+
assertBoolean(canServe, `${L}.canServe`);
|
|
41438
|
+
assertExactFields(raw, BRIDGE_ROLE_FIELDS, L);
|
|
41439
|
+
const serving = raw.serving;
|
|
41440
|
+
if (role === "serving") {
|
|
41441
|
+
if (serving !== void 0) {
|
|
41442
|
+
throw new ProtocolError3(`${L}.serving: must be absent when role is serving`);
|
|
41443
|
+
}
|
|
41444
|
+
return { type: BRIDGE_ROLE_FRAME, role, canServe };
|
|
41445
|
+
}
|
|
41446
|
+
if (serving === void 0) {
|
|
41447
|
+
throw new ProtocolError3(`${L}.serving: required when role is standby`);
|
|
41448
|
+
}
|
|
41449
|
+
assertObject(serving, `${L}.serving`);
|
|
41450
|
+
const label = serving.label;
|
|
41451
|
+
assertDisplayString(label, `${L}.serving.label`, 1, BRIDGE_ROLE_LABEL_MAX);
|
|
41452
|
+
const since = serving.since;
|
|
41453
|
+
if (typeof since !== "number" || !Number.isSafeInteger(since) || since < 0) {
|
|
41454
|
+
throw new ProtocolError3(`${L}.serving.since: expected non-negative safe integer (Unix ms)`);
|
|
41455
|
+
}
|
|
41456
|
+
assertExactFields(serving, BRIDGE_ROLE_SERVING_FIELDS, `${L}.serving`);
|
|
41457
|
+
return {
|
|
41458
|
+
type: BRIDGE_ROLE_FRAME,
|
|
41459
|
+
role,
|
|
41460
|
+
canServe,
|
|
41461
|
+
serving: { label, since }
|
|
41462
|
+
};
|
|
41463
|
+
}
|
|
41382
41464
|
function validateInnerFrame(raw) {
|
|
41383
41465
|
assertObject(raw, "inner");
|
|
41384
41466
|
const t = raw.type;
|
|
@@ -46581,7 +46663,7 @@ async function loginWithPassword(username, password) {
|
|
|
46581
46663
|
// package.json
|
|
46582
46664
|
var package_default = {
|
|
46583
46665
|
name: "ofw-mcp",
|
|
46584
|
-
version: "2.20.
|
|
46666
|
+
version: "2.20.3",
|
|
46585
46667
|
license: "MIT",
|
|
46586
46668
|
mcpName: "io.github.chrischall/ofw-mcp",
|
|
46587
46669
|
description: "OurFamilyWizard MCP server for Claude \u2014 developed and maintained by AI (Claude Code)",
|
|
@@ -46615,8 +46697,8 @@ var package_default = {
|
|
|
46615
46697
|
typecheck: "tsc -p tsconfig.json --noEmit"
|
|
46616
46698
|
},
|
|
46617
46699
|
dependencies: {
|
|
46618
|
-
"@chrischall/mcp-utils": "^2.
|
|
46619
|
-
"@fetchproxy/bootstrap": "^3.
|
|
46700
|
+
"@chrischall/mcp-utils": "^2.15.0",
|
|
46701
|
+
"@fetchproxy/bootstrap": "^3.6.0",
|
|
46620
46702
|
"@modelcontextprotocol/server": "^2.3.0",
|
|
46621
46703
|
dotenv: "^18.0.0",
|
|
46622
46704
|
zod: "^4.6.5"
|
|
@@ -52499,7 +52581,7 @@ var tools = selectToolRegistrars({
|
|
|
52499
52581
|
});
|
|
52500
52582
|
await runMcp({
|
|
52501
52583
|
name: "ofw",
|
|
52502
|
-
version: "2.20.
|
|
52584
|
+
version: "2.20.3",
|
|
52503
52585
|
// x-release-please-version
|
|
52504
52586
|
deps: client,
|
|
52505
52587
|
tools,
|
package/dist/index.js
CHANGED
|
@@ -47,7 +47,7 @@ const tools = selectToolRegistrars({
|
|
|
47
47
|
});
|
|
48
48
|
await runMcp({
|
|
49
49
|
name: 'ofw',
|
|
50
|
-
version: '2.20.
|
|
50
|
+
version: '2.20.3', // x-release-please-version
|
|
51
51
|
deps: client,
|
|
52
52
|
tools,
|
|
53
53
|
banner: '[ofw-mcp] This project was developed and is maintained by AI (Claude Sonnet 4.6). Use at your own discretion.',
|
package/mint.yaml
CHANGED
|
@@ -39,6 +39,13 @@ env:
|
|
|
39
39
|
chat before calling again with it. "auto": the model may use the token
|
|
40
40
|
after reviewing the preview itself. "refuse": such writes are refused.
|
|
41
41
|
Unrecognised values are treated as "refuse".
|
|
42
|
+
- name: MCP_CONFIRM_ELICITATION
|
|
43
|
+
required: false
|
|
44
|
+
help: >-
|
|
45
|
+
"off" never shows a confirmation prompt, so every client gets the
|
|
46
|
+
MCP_CONFIRM_MODE path. Set it for a client that claims to support
|
|
47
|
+
prompts but never shows one (the gated write hangs, e.g. opencode
|
|
48
|
+
2.0.x). Default "on"; any other value stays "on" with a stderr warning.
|
|
42
49
|
- name: MCP_CONFIRM_TTL_SECONDS
|
|
43
50
|
required: false
|
|
44
51
|
help: >-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ofw-mcp",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.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)",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@chrischall/mcp-utils": "^2.
|
|
38
|
-
"@fetchproxy/bootstrap": "^3.
|
|
37
|
+
"@chrischall/mcp-utils": "^2.15.0",
|
|
38
|
+
"@fetchproxy/bootstrap": "^3.6.0",
|
|
39
39
|
"@modelcontextprotocol/server": "^2.3.0",
|
|
40
40
|
"dotenv": "^18.0.0",
|
|
41
41
|
"zod": "^4.6.5"
|
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.20.
|
|
9
|
+
"version": "2.20.3",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "ofw-mcp",
|
|
14
|
-
"version": "2.20.
|
|
14
|
+
"version": "2.20.3",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|