ofw-mcp 2.6.7 → 2.7.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.
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "OurFamilyWizard tools for Claude Code",
9
- "version": "2.6.7"
9
+ "version": "2.7.0"
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.6.7",
17
+ "version": "2.7.0",
18
18
  "author": {
19
19
  "name": "Chris Chall"
20
20
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ofw",
3
3
  "displayName": "OurFamilyWizard",
4
- "version": "2.6.7",
4
+ "version": "2.7.0",
5
5
  "description": "OurFamilyWizard co-parenting tools for Claude — messages, calendar, expenses, and journal via MCP",
6
6
  "author": {
7
7
  "name": "Chris Chall"
package/README.md CHANGED
@@ -133,7 +133,7 @@ Instead of running `ofw-mcp` locally, you can add it to [claude.ai](https://clau
133
133
  - **Write mode defaults to `all`.** The hosted connector registers every tool by default, configurable per deployment via `OFW_WRITE_MODE` / `OFW_CALENDAR_WRITES` in `wrangler.jsonc` — see [Write protection](#write-protection-ofw_write_mode).
134
134
  - **Message sync is bounded and resumable.** To stay under Cloudflare's per-request subrequest cap, `ofw_sync_messages` on the hosted connector caps how many OFW requests one call makes (`OFW_SYNC_MAX_REQUESTS` in `wrangler.jsonc`, default `40`) and resumes across calls, so a large mailbox backfills over multiple `ofw_sync_messages` calls rather than one; the local stdio server is unbounded. See [`docs/DEPLOY-CONNECTOR.md`](docs/DEPLOY-CONNECTOR.md#sync--the-subrequest-limit).
135
135
 
136
- Standing this up requires a Cloudflare account and is a manual, one-time process for whoever hosts it (there is no CI/CD path for it) — see [`docs/DEPLOY-CONNECTOR.md`](docs/DEPLOY-CONNECTOR.md) for the full runbook. `wrangler.jsonc` serves the Worker at a custom domain (`https://connector.ofw.nullnet.app/mcp`) plus the account's `*.workers.dev` URL; whoever hosts it uses their own domain. The local stdio / `.mcpb` install above remains the desktop-only alternative if you'd rather run it against just your own account.
136
+ Standing this up requires a Cloudflare account and is a one-time setup for whoever hosts it; after that the `deploy-connector` job in `release-please.yml` deploys each release automatically (and **Actions deploy-connector Run workflow** deploys any ref on demand) — see [`docs/DEPLOY-CONNECTOR.md`](docs/DEPLOY-CONNECTOR.md) for the full runbook. `wrangler.jsonc` serves the Worker at a custom domain (`https://connector.ofw.nullnet.app/mcp`) plus the account's `*.workers.dev` URL; whoever hosts it uses their own domain. The local stdio / `.mcpb` install above remains the desktop-only alternative if you'd rather run it against just your own account.
137
137
 
138
138
  ## Available tools
139
139
 
@@ -148,6 +148,7 @@ Read-only tools run automatically. Write tools ask for your confirmation first.
148
148
  | `ofw_get_message` | Full content of a single message | Auto | any |
149
149
  | `ofw_sync_messages` | Sync messages into the local cache (unread bodies left unfetched to avoid read receipts) | Auto | any |
150
150
  | `ofw_get_unread_sent` | Sent messages a recipient hasn't read yet (from local cache) | Auto | any |
151
+ | `ofw_check_freshness` | Cheap live check that the cache still matches OFW — confirm a draft still exists unsent, without a full sync | Auto | any |
151
152
  | `ofw_download_attachment` | Download a message attachment to disk (or inline as MCP content) | Auto | any |
152
153
  | `ofw_send_message` | Send a message | Confirm | `all` |
153
154
  | `ofw_list_drafts` | Draft messages | Auto | any |
@@ -164,6 +165,33 @@ Read-only tools run automatically. Write tools ask for your confirmation first.
164
165
  | `ofw_list_journal_entries` | Journal entries | Auto | any |
165
166
  | `ofw_create_journal_entry` | Create a journal entry | Confirm | `all` |
166
167
 
168
+ ### Data freshness (`OFW_FRESHNESS_TTL_SECONDS`)
169
+
170
+ Message and draft reads are served from the local cache, which means a result can look authoritative while being minutes or months out of date. The cache also cannot detect some changes on its own: **editing a draft in the OFW web app bumps no timestamp at all**, so "nothing changed" and "we didn't look" are indistinguishable unless the server says which happened.
171
+
172
+ So every read tool (`ofw_list_messages`, `ofw_list_drafts`, `ofw_get_message`, `ofw_list_message_folders`, `ofw_sync_messages`) returns a `freshness` block alongside its data:
173
+
174
+ ```json
175
+ "freshness": {
176
+ "source": "cache",
177
+ "asOf": "2026-07-20T12:40:00.000Z",
178
+ "ageSeconds": 5231,
179
+ "staleness": "unverified",
180
+ "lastServerSyncAt": "2026-07-20T13:59:00.000Z",
181
+ "syncComplete": false,
182
+ "historyComplete": true,
183
+ "warning": "Served from cache last verified 87 min ago; the last sync did not finish checking drafts. Re-read before asserting current state — call ofw_check_freshness for a cheap live confirmation, or ofw_sync_messages to refresh."
184
+ }
185
+ ```
186
+
187
+ `staleness` is `fresh` only when the data was fetched live in that call, or verified against OFW within the threshold by a sync that actually reached that folder. It degrades to `unverified` when it ages out or a sync skipped the folder, and `stale` when the folder has never been checked at all. Anything other than `fresh` always carries a human-readable `warning` stating the age and the reason. The bias is deliberate and one-directional: a false `unverified` costs one extra call, whereas a false `fresh` lets remembered state be narrated as present fact.
188
+
189
+ Drafts additionally carry per-item `cacheStatus`, `asOf`, and **`serverConfirmed`** — true only when a completed drafts walk verified them inside the threshold. `serverConfirmed: false` means a draft's existence and unsent status are *remembered*, not known, and should not be stated as current fact without calling `ofw_check_freshness` first.
190
+
191
+ `ofw_check_freshness` is the cheap way to re-verify: one request for a folder count comparison plus one per message id, no bodies, no full sync. Draft ids are compared by **content revision**, not timestamp, for the reason above. By default it only probes ids that are in the drafts cache — fetching any other id would mark an unread inbox message as read on OurFamilyWizard, an irreversible change to a court-visible record, so those are skipped unless you pass `allowMarkRead: true`.
192
+
193
+ Set `OFW_FRESHNESS_TTL_SECONDS` to tune the threshold (default `300`, i.e. 5 minutes). Unusable values fall back to the default rather than widening the window.
194
+
167
195
  ### Write protection (`OFW_WRITE_MODE`)
168
196
 
169
197
  The "Confirm" permission above is a *hint* to the MCP host — a host configured to auto-approve tools (or a user who clicked "always allow" once) would leave nothing between model output and a sent message. Because OurFamilyWizard is a court-of-record platform, the server also supports a structural gate: set `OFW_WRITE_MODE` in the server's `env` block and tools above your chosen level are **never registered**, so no host setting or prompt-injected instruction can invoke them.