ofw-mcp 2.3.2 → 2.4.1

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.
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Validate an OFW API response against a zod schema at the call site.
3
+ *
4
+ * Every OFW endpoint is reverse-engineered and undocumented, so a backend
5
+ * change on their side would otherwise flow `undefined` silently into the
6
+ * SQLite cache and persist (issue #83). Schemas are `.looseObject(...)`
7
+ * covering ONLY the fields the code actually reads — cosmetic API additions
8
+ * pass through untouched (and stay present in the parsed output, which
9
+ * matters for `listData`/`metadata` blobs cached verbatim).
10
+ *
11
+ * Two modes, chosen per call site:
12
+ * - `'lenient'` (default) — read/sync paths. On mismatch, log a structured
13
+ * warning to stderr naming the endpoint and fields, then return the RAW
14
+ * response unchanged so the existing `??` fallbacks keep the tool useful.
15
+ * - `'strict'` — write paths (send/save_draft verification, upload). On
16
+ * mismatch, throw: proceeding on an unverifiable response risks deleting
17
+ * a draft, mis-reporting a send, or caching an unusable fileId.
18
+ *
19
+ * The error/warning text is deliberately precise ("date.dateTime: expected
20
+ * string…") — it's the failure signal a maintainer (human or Claude) fixes
21
+ * in one session, vs. "some messages show the wrong date sometimes".
22
+ */
23
+ export function parseOFW(schema, raw, ctx, mode = 'lenient') {
24
+ const result = schema.safeParse(raw);
25
+ if (result.success)
26
+ return result.data;
27
+ const issues = result.error.issues
28
+ .map((i) => `${i.path.join('.') || '(root)'}: ${i.message}`)
29
+ .join('; ');
30
+ const message = `OFW response for ${ctx} failed validation: ${issues}`;
31
+ if (mode === 'strict')
32
+ throw new Error(message);
33
+ console.error(`[ofw-mcp] WARNING: ${message} — continuing with the raw response; fields derived from it may be missing or wrong.`);
34
+ return raw;
35
+ }
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "ofw-mcp",
3
- "version": "2.3.2",
3
+ "version": "2.4.1",
4
+ "license": "MIT",
4
5
  "mcpName": "io.github.chrischall/ofw-mcp",
5
6
  "description": "OurFamilyWizard MCP server for Claude — developed and maintained by AI (Claude Code)",
6
7
  "author": "Claude Code (AI) <https://www.anthropic.com/claude>",
@@ -9,6 +10,9 @@
9
10
  "url": "git+https://github.com/chrischall/ofw-mcp.git"
10
11
  },
11
12
  "type": "module",
13
+ "engines": {
14
+ "node": ">=22.5.0"
15
+ },
12
16
  "bin": {
13
17
  "ofw-mcp": "dist/index.js"
14
18
  },
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.3.2",
9
+ "version": "2.4.1",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "ofw-mcp",
14
- "version": "2.3.2",
14
+ "version": "2.4.1",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },
@@ -28,6 +28,12 @@
28
28
  "isRequired": false,
29
29
  "format": "string",
30
30
  "isSecret": true
31
+ },
32
+ {
33
+ "name": "OFW_WRITE_MODE",
34
+ "description": "Write-tool gate: \"none\" registers no write tools; \"drafts\" registers draft-level writes only (save/delete drafts, upload attachments); \"all\" registers everything (default). Unrecognized values fail closed to \"none\".",
35
+ "isRequired": false,
36
+ "format": "string"
31
37
  }
32
38
  ]
33
39
  }