Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

io.github.chrischall/ofw-mcp

NPM · OFW-MCP · SCANNED SEP 20

OurFamilyWizard co-parenting for Claude — messages, calendar, expenses, and journal

Available components

+1 this week 91 Trust /100
Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security100
  • No malware found by supply-chain analysis.Pass
  • No known CVEs affecting this package version or its production dependencies.Pass
  • No install/post-install scripts declared.Pass
  • 0 of 9 dependencies flagged as unhealthy. View diagnostics → Pass
Provenance & Transparency97
  • Source repository is publicly reachable at the declared URL. View diagnostics → Pass
  • Cryptographically verified build provenance (signed, bound to chrischall/ofw-mcp). View diagnostics → Pass
  • Clear OSI-approved license (MIT).Pass
  • Actively maintained (last published 0 days ago).Pass
  • Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability61
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 6615 tokens (~264/item across 25 items; 25 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management93
  • Stability observed for 28 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage97
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 90% of tool parameters carry a description.Partial
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • All 3 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
  • An AI judge read all 25 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a current MCP spec version (2026-07-28).Pass
Install

How do I install the io.github.chrischall/ofw-mcp server?

io.github.chrischall/ofw-mcp runs locally as an npm package, launched with npx -y ofw-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

npm · ofw-mcp

# add to Claude Code
claude mcp add chrischall-ofw-mcp -- npx -y ofw-mcp
// .cursor/mcp.json
{
  "mcpServers": {
    "chrischall-ofw-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "ofw-mcp"
      ]
    }
  }
}
// .vscode/mcp.json
{
  "servers": {
    "chrischall-ofw-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "ofw-mcp"
      ]
    }
  }
}
# add to Codex CLI
codex mcp add chrischall-ofw-mcp -- npx -y ofw-mcp
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "chrischall-ofw-mcp": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "ofw-mcp"
      ],
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add chrischall-ofw-mcp --command npx --arg -y --arg ofw-mcp
# ~/.hermes/config.yaml
mcp_servers:
  chrischall-ofw-mcp:
    command: "npx"
    args: ["-y", "ofw-mcp"]
// ~/.netclaw/config/netclaw.json
{
  "McpServers": {
    "chrischall-ofw-mcp": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "ofw-mcp"
      ]
    }
  }
}
# add to Vellum
assistant mcp add chrischall-ofw-mcp -t stdio -c npx -a -y ofw-mcp
// mcp.json
{
  "mcpServers": {
    "chrischall-ofw-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "ofw-mcp"
      ]
    }
  }
}
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 20 Sept 26 0
    • Stability: 0.90 → unverified security
    • Tool safety: pass → unverified security
    • Capabilities: pass → unverified functional
    • Tool coverage: 100 → unverified functional
    • Schema quality: Schema quality not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet. functional
    • MCP protocol: Implements a current MCP spec version (2026-07-28). functional
    • Package version: 2.17.0 → 2.19.0 functional
    • Package version: 2.17.0 → 2.18.0 functional
  • 19 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 87 to 90. That category is still filling its 30-day observation window: 26 days of observed history at the previous scan, 27 at this one. The score rises as the window fills, whether or not the server changes.

  • 18 Sept 26 +11
    • Known CVEs: unverified → pass security
    • Dependency health: unverified → 1.00 functional
  • 17 Sept 26 −13
    • Stability: pass → unverified security
    • Known CVEs: pass → unverified security
    • Tool safety: pass → unverified security
    • Capabilities: pass → unverified functional
    • Dependency health: 0.87 → unverified functional
    • Tool coverage: 100 → unverified functional
    • Schema quality: Schema quality not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet. functional
    • Stability: pass → 0.83 functional
    • Package version: 2.16.3 → 2.17.0 functional
  • 16 Sept 26 +16
    • Malware scan: unverified → pass security
    • Stability: 0.97 → pass security
    • Package version: 2.10.0 → 2.16.3 functional
  • 15 Sept 26 +11
    • Malware scan: unverified → pass security
    • Known CVEs: unverified → pass security
    • Dependency health: unverified → 0.87 functional
    • Package version: 2.16.2 → 2.16.3 functional
  • 14 Sept 26 −25
    • Stability: 0.90 → unverified security
    • Malware scan: pass → unverified security
    • Known CVEs: pass → unverified security
    • Tool safety: pass → unverified security
    • Capabilities: pass → unverified functional
    • Dependency health: 0.86 → unverified functional
    • Tool coverage: 100 → unverified functional
    • Schema quality: Schema quality not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet. functional
    • Package version: 2.16.1 → 2.16.2 functional
  • 12 Sept 26 +16
    • Malware scan: unverified → pass security
Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 20 Sept 2026 · Analysed npm/ofw-mcp@2.19.0

Provenance Verified

A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.

Result Verified
Ecosystem npm
Reason Verified
Discovered via Registry attestation endpoint
Source repo chrischall/ofw-mcp
Certificate issuer https://token.actions.githubusercontent.com
Certificate SAN https://github.com/chrischall/ofw-mcp/.github/workflows/release-please.yml@refs/heads/main
Rekor log index 2902181909
Predicate type https://slsa.dev/provenance/v1
Subject digest sha512:839b5b19bcfbf0156f48772a7d7219afa290805a65109114d00bb854e421aafe2606f215e49bf26a454d1b378074b6b1d8d36b586b8f66ee186fa55be

Background: How many MCP packages publish verified provenance →

Dependencies 9 packages
Packages resolved 9
Tree resolution Complete

Background: SBOMs and build attestations, explained →

MCP tools · 25 exposed · ~6,615 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
ofw_check_freshness ~434

Cheaply confirm whether the local cache still matches OurFamilyWizard, WITHOUT running a full sync. Use this before asserting anything about current state — especially "draft X is still sitting unsent". Costs one OFW request for the folder check plus one per messageId. For each folder it returns the live server count next to the cached count. For each id it returns a LIVE lifecycle `state` — "draft" | "sent" | "received" | "deleted" | "unknown" — alongside `folder`, `sentAt`, `existsOnServer` and a content comparison. `state` is the field that answers "is this still a draft?": a draft that has been SENT still exists on the server, so existsOnServer:true never distinguished the two. A cached draft whose state is no longer "draft" reports inSync:false even when its text is byte-identical. Content is compared by revision hash, because OFW draft timestamps do NOT change when a draft is edited in the web app. Does not fetch bodies into the cache, does not touch attachments, and does not depend on sync state. For draftKeys, or a full live draft inventory, use ofw_status.

NameTypeReqDescription
allowMarkReadbooleanDefault false. Probing an id whose cached state cannot rule out an unread INBOX message requires fetching its detail, which marks it READ on OurFamilyWizard and stamps a co-parent-visible "First View…
foldersarrayFolders to compare cached vs live counts for. Defaults to all three when messageIds is not given. Must be non-empty if given.
messageIdsarraySpecific ids to verify against OFW (max 25). Ids cached as drafts, as sent messages, or as already-read inbox messages are probed freely — none of those can stamp the record. Anything else is skipped…

No output schema declared.

No examples provided.

ofw_create_event ~244

Create a calendar event in OurFamilyWizard. Unless privateEvent is true, the event is immediately visible to the co-parent — there is no draft stage.

NameTypeReqDescription
allDayboolean
childrenarrayChild userIds to tag (see ofw_get_profile)
dropOffParentIdnumberuserId of the drop-off parent
endDatestringEnd date YYYY-MM-DD (default: startDate)
endTimestringEnd time HH:mm, 24-hour (required unless allDay)
eventParentIdnumberuserId of the parent the event is 'for'
locationstring
notesstring
pickUpParentIdnumberuserId of the pick-up parent
privateEventbooleantrue = visible only to you; default false = shared with co-parent
reminderMinutesinteger
startDatestringyesStart date YYYY-MM-DD
startTimestringStart time HH:mm, 24-hour (required unless allDay)
titlestringyes

No output schema declared.

No examples provided.

ofw_create_expense ~38

Log a new expense in OurFamilyWizard

NameTypeReqDescription
amountnumberyesExpense amount
descriptionstringyesExpense description

No output schema declared.

No examples provided.

ofw_create_journal_entry ~41

Create a new journal entry in OurFamilyWizard

NameTypeReqDescription
bodystringyesEntry text content
titlestringyesEntry title

No output schema declared.

No examples provided.

ofw_delete_draft ~184

Delete a draft message from OurFamilyWizard. Also removes the draft from the local cache. Before deleting, the draft is re-read from OFW and the delete is REFUSED if it changed since you last read it (the current server body is returned so nothing is lost) — pass expectedRevision to assert which version you mean, or force:true to delete regardless.

NameTypeReqDescription
expectedRevisionstringThe `revision` you got from ofw_list_drafts/ofw_get_message. Asserts you are deleting THAT version; if the draft changed on OFW since, the delete is refused and the current server body returned.
forcebooleanDefault false. Delete even if the draft changed on OurFamilyWizard since you read it. The discarded server version is echoed back in the response.
messageIdnumberyesDraft message ID to delete

No output schema declared.

No examples provided.

ofw_delete_event ~67

Delete an OurFamilyWizard calendar event

NameTypeReqDescription
eventIdstringyesEvent id — the `id` from ofw_list_events / eventRecurrenceId from ofw_create_event
includeFuturebooleanFor repeating events: also delete future occurrences (default false)

No output schema declared.

No examples provided.

ofw_download_attachment ~698

Download an OFW message attachment by fileId and return content you can actually read. Inline delivery walks a ladder and returns the first rung that works: (1) host-renderable images (PNG/JPEG/GIF/WEBP) come back as ImageContent; (2) .xlsx/.csv/.tsv, .pdf, .docx, .pptx and text files come back as EXTRACTED CONTENT — per-sheet CSV, per-page/slide text, document text — in the response JSON under `extracted`; (3) anything else comes back as an EmbeddedResource blob of the raw bytes. The meta block names the rung as `deliveredVia` and, when it falls through to bytes, lists what was tried in `deliveryAttempts`. Reported mime types are always normalized to a bare media type (no charset/name parameters). In disk mode the bytes are saved to ~/Downloads/ofw-mcp/ and the response carries the absolute path; pass extract:true to ALSO get the extracted content in that response. The default for `inline` can be flipped server-side via the OFW_INLINE_ATTACHMENTS env var. On a hosted deployment with no filesystem, disk mode is unavailable, so inline is forced (forcedInline:true) rather than failing — a saveTo path never costs you the content. fileId comes from attachments[].fileId on ofw_get_message. Override disk destination with OFW_ATTACHMENTS_DIR or saveTo. Re-downloading to the same path is a no-op (disk mode only).

NameTypeReqDescription
extractbooleanWhether to extract readable content from the file. Default: on for inline delivery of any non-image type, off in disk mode. Set false to get the raw bytes inline instead of extracted text (e.g. to ha…
fileIdnumberyesAttachment file id (from ofw_get_message → attachments[].fileId)
forcebooleanRe-download even if already on disk. Default false. Ignored when inline:true (inline always fetches fresh bytes, or reuses an on-disk copy if present).
inlinebooleanIf true, return content inline as MCP content blocks and skip the disk write. If false, write to disk and return the path — except on a hosted deployment with no filesystem, where inline is forced (f…
maxCharsintegerCeiling on extracted characters (default 50000). Over it, content is clipped on a row/line boundary, `truncated` is set, and anything dropped whole is listed in `extracted.omitted`.
partsstringWhich sheets / slides / pages to extract, e.g. "1-3,5" (1-based positions) or a sheet name like "2026". A bare number matches either a position or a name. Omit for everything. Unselected parts are li…
saveTostringAbsolute path or directory to write to. If a directory, the OFW filename is used. Default: ~/Downloads/ofw-mcp/<fileId>-<filename>. Ignored when inline is in effect.

No output schema declared.

No examples provided.

ofw_get_expense_totals ~25

Get OurFamilyWizard expense summary totals (owed/paid)

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

ofw_get_message ~396

Get a single OurFamilyWizard message OR draft by ID. Reads from local cache when available; otherwise fetches from OFW — and for an UNREAD INBOX message that fetch marks it read and stamps a "First Viewed" time the co-parent can see, which is part of the record and cannot be undone. Pass allowMarkRead:false to refuse such a fetch instead (cached bodies, sent messages and already-read messages are unaffected, because none of them stamp anything). For ids that match a draft (in the drafts cache), the response carries folder="drafts" and the body/subject/recipients reflect the drafts cache (which ofw_sync_messages keeps fresh) — drafts have no `fromUser`, and `sentAt`/`fetchedBodyAt` mirror the draft's `modifiedAt`. For inbox/sent messages, folder is "inbox" or "sent" as before.

NameTypeReqDescription
allowMarkReadbooleanDefault true (the long-standing behaviour). Set false to refuse a fetch that would mark an unread INBOX message as READ on OurFamilyWizard — an irreversible, co-parent-visible change to the record. R…
messageIdstringyesMessage ID (also accepts draft IDs — drafts are routed via the drafts cache)
viewstringResponse shape: "compact" (default) drops fields the response already carries elsewhere; "full" returns every field this server understands. compact omits OurFamilyWizard's raw `listData` echo, which…

No output schema declared.

No examples provided.

ofw_get_notifications ~36

Get OurFamilyWizard dashboard summary: unread message count, upcoming events, outstanding expenses. Note: updates your last-seen status.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

ofw_get_profile ~23

Get current user and co-parent profile information from OurFamilyWizard

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

ofw_get_unread_sent ~186

List sent messages that have not been read by one or more recipients. Reads from local cache. Returns `complete` describing whether every sent message was scanned. An empty SENT cache that is not verified-fresh is REFUSED (result:"UNVERIFIED_EMPTY") rather than reported as "nothing sent"; pass autoRefresh:true to sync and answer instead.

NameTypeReqDescription
autoRefreshbooleanIf the result comes back EMPTY from a cache that is not verified-fresh, sync the backing folders first and answer from the refreshed cache instead of refusing. Defaults to the OFW_AUTO_REFRESH env va…
pageintegerPage (default 1)
sizeintegerPer page (default 50)

No output schema declared.

No examples provided.

ofw_healthcheck ~101

Resolves the credential the way real tools do, then makes one authenticated request to ourfamilywizard.com. Reports which source supplied the credential, whether ourfamilywizard.com accepted it, the round-trip time, and a plain-English hint distinguishing 'no credential' from 'credential rejected' from 'a ourfamilywizard.com-side problem'. Read-only; never returns the credential itself. Call this when a real tool fails and you want to know which hop broke.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

ofw_list_drafts ~423

List draft messages, verified against OurFamilyWizard in ONE call: when the local drafts cache is not verified-fresh, a cheap drafts sync runs first by default (verify:true), so the answer is server-confirmed without a second call. Pass verify:false to answer purely from the cache (no OFW requests). Returns an explicit `complete` boolean describing the RESULT SET: true means "these are ALL the drafts on OurFamilyWizard as of freshness.asOf" — check it before saying "you have N drafts". Each draft carries its `draftKey` (stable across the create-then-delete churn of editing) when one is known. An empty result from a cache that is not verified-fresh is REFUSED (result:"UNVERIFIED_EMPTY"); pass autoRefresh:true to sync and answer instead.

NameTypeReqDescription
autoRefreshbooleanIf the result comes back EMPTY from a cache that is not verified-fresh, sync the backing folders first and answer from the refreshed cache instead of refusing. Defaults to the OFW_AUTO_REFRESH env va…
pageintegerPage number (default 1)
sizeintegerDrafts per page (default 50)
verifybooleanDefault true: when the drafts cache is not verified-fresh, run a drafts sync first (cheap — one list page plus one detail per draft) so the response is server-confirmed in one call. Set false to serv…
viewstringResponse shape: "compact" (default) drops fields the response already carries elsewhere; "full" returns every field this server understands. compact omits OurFamilyWizard's raw `listData` echo, which…

No output schema declared.

No examples provided.

ofw_list_events ~61

List OurFamilyWizard calendar events in a date range

NameTypeReqDescription
detailedbooleanReturn full event details (default false)
endDatestringyesEnd date YYYY-MM-DD
startDatestringyesStart date YYYY-MM-DD

No output schema declared.

No examples provided.

ofw_list_expenses ~125

List OurFamilyWizard expenses. Offset-paged via start/max. The response leads with its paging state — `hasMore` and `nextStart` (null when the list is exhausted) — BEFORE the records, so a truncated or partially-read response still says whether more remain. Never state an expense total or an absence from one page.

NameTypeReqDescription
maxintegerMax results (default 20)
startintegerStart offset, 0-based (default 0). To continue a listing, pass the `nextStart` from the previous response.

No output schema declared.

No examples provided.

ofw_list_journal_entries ~130

List OurFamilyWizard journal entries. Offset-paged via start/max (1-based). The response leads with its paging state — `hasMore` and `nextStart` (null when the list is exhausted) — BEFORE the records, so a truncated or partially-read response still says whether more remain. Never state an entry count or an absence from one page.

NameTypeReqDescription
maxintegerMax results (default 10)
startintegerStart offset, 1-based (default 1). To continue a listing, pass the `nextStart` from the previous response.

No output schema declared.

No examples provided.

ofw_list_message_folders ~61

List OurFamilyWizard message folders (inbox, sent, etc.) and their unread counts. Fetched LIVE from OFW, so the counts are current. Returns folder IDs needed to call ofw_list_messages. Does NOT return message content.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

ofw_list_messages ~566

List messages from the local OurFamilyWizard cache. Supports filtering by folder, date range, and a substring query on subject+body. Pagination is offset-based (1-based `page`) but if you know what you want (a date range, a topic), prefer the filters over walking pages — the cache may have 1000+ messages. Results are newest-first by default; `sort:"oldest"` starts at the old end of a range instead of paging to it. Returns an explicit `complete` boolean describing the RESULT SET: true means "this is every message on OurFamilyWizard matching these filters as of freshness.asOf" — check it before asserting a count. An empty result from a cache that is not verified-fresh is REFUSED (result:"UNVERIFIED_EMPTY") rather than reported as an absence; pass autoRefresh:true to sync and answer instead.

NameTypeReqDescription
autoRefreshbooleanIf the result comes back EMPTY from a cache that is not verified-fresh, sync the backing folders first and answer from the refreshed cache instead of refusing. Defaults to the OFW_AUTO_REFRESH env va…
folderIdstringFolder name: "inbox", "sent", or "both" (default "both")
pageintegerPage number (default 1)
qstringSubstring match on subject AND body (case-insensitive). Use to find messages on a specific topic.
sincestringISO date or datetime — only messages with sent_at >= since (inclusive)
sizeintegerMessages per page (default 50)
sortstringResult order: "newest" (default, newest first) or "oldest" (oldest first). This decides which end a truncated page keeps — with "newest" page 1 of a wide date range holds its most RECENT slice, with…
untilstringISO date or datetime — only messages with sent_at < until (exclusive)
viewstringResponse shape: "compact" (default) drops fields the response already carries elsewhere; "full" returns every field this server understands. compact omits OurFamilyWizard's raw `listData` echo, which…

No output schema declared.

No examples provided.

ofw_save_draft ~634

Save a message as a draft in OurFamilyWizard. RECIPIENTS: OurFamilyWizard does NOT persist recipients on drafts — recipientIds are accepted but the saved draft comes back with none (documented OFW behavior, noted once in the response, not warned about; supply recipientIds at send time instead). IDENTITY: the response leads with `draftKey`, the stable identity that survives editing — key off it, because the `id` changes on EVERY edit (replacing a draft creates a NEW draft and deletes the old one; OFW's update-in-place endpoint silently no-ops, so we never use it). Pass messageId to replace an existing draft; the response.id will be the NEW id, and a transparency NOTE documents the swap and which fields were carried over. THREADING: if replyToId is provided, the cache may rewrite it to the latest reply in the thread (note included). The threading verdict is read from OFW's full echo (replyToId/inReplyTo/showContext) — a warning appears ONLY when the reply linkage was genuinely dropped or re-targeted, and the response's top-level replyToId/inReplyTo always agree with its listData. Attach files via myFileIDs (from ofw_upload_attachment). After saving, the tool re-fetches the draft from OFW, and the returned `revision` reflects that authoritative state (so it will match on your next edit). SAFETY: because replacing DESTROYS the old draft rather than merging, passing messageId first re-reads that draft from OFW and REFUSES the write if its subject/body/recipients changed since you read it (drafts edited in the OFW web app do not bump any timestamp, so the local cache can be silently behind). A pure replyToId normalization by OFW is NOT treated as a conflict. The refusal returns the current server body under serverBody — merge your edit into it and retry with expectedRevision.

NameTypeReqDescription
bodystringyesMessage body text
expectedRevisionstringWith messageId: the `revision` you got from ofw_list_drafts/ofw_get_message for that draft. Asserts you are replacing THAT version. If the draft changed on OFW since, the write is refused and the cur…
forcebooleanDefault false. Overwrite even when the draft changed on OurFamilyWizard since you read it. The discarded server version is echoed back in the response. Only use after showing the user the conflict.
messageIdnumberID of an existing draft to replace (the new draft will have a new id; the old is deleted)
myFileIDsarrayAttachment file ids (from ofw_upload_attachment)
recipientIdsarrayArray of recipient user IDs (optional for drafts)
replyToIdnumberID of the message this draft replies to
subjectstringyesMessage subject

No output schema declared.

No examples provided.

ofw_send_message ~848

Send a message via OurFamilyWizard — the ONE irreversible operation here, so it carries the strongest guard. TO SEND AN EXISTING DRAFT (the safe default): pass draftId (or messageId — same thing). The tool re-reads the draft from OFW and sends the SERVER'S version, so what goes out is what is on OurFamilyWizard, not what this session remembers — subject/body act only as explicit overrides. It is guarded exactly like ofw_save_draft: pass expectedRevision to assert which version you are sending; if the draft changed on OFW since you read it — or no longer exists (it may already have been SENT) — the send is REFUSED with the current server content echoed back, and nothing goes out. RECIPIENTS: OurFamilyWizard does not persist recipients on drafts, so recipientIds is usually still required at send time (ids from ofw_get_profile). After the send is CONFIRMED (OFW returned the new message id and the re-fetched sent record matches what was posted), the source draft is deleted automatically; pass deleteDraftOnSuccess:false to keep it. On ANY failure or ambiguity the draft is never deleted — the response carries draftRetained:true with the reason. TO COMPOSE FROM SCRATCH: supply subject/body/recipientIds with no draftId. If replyToId is provided (or inherited from the draft), the cache may rewrite it to the latest reply in the same thread (a note is included when this happens). ATTACHMENTS: when sending by draftId, the server draft's own attachments carry over automatically; myFileIDs (from ofw_upload_attachment) overrides or attaches files on a fresh compose. The response leads with sentMessageId and the stable draftKey, and reports threaded (whether OFW actually linked the reply) and draftDeleted.

NameTypeReqDescription
bodystringMessage body text. Required unless draftId/messageId is given (then it overrides the server draft's body — omit it to send exactly what is on OurFamilyWizard).
deleteDraftOnSuccessbooleanDefault true. Delete the source draft after — and ONLY after — the send is confirmed (new message id returned and the re-fetched sent record checks out). Set false to keep the draft. On a failed or u…
draftIdnumberID of an existing draft to send. The draft is re-read from OurFamilyWizard and its SERVER content is sent; missing subject/body default from it. Guarded: a draft that changed since you read it, or th…
expectedRevisionstringWith draftId: the `revision` from ofw_list_drafts / ofw_get_message / ofw_check_freshness for that draft. Asserts you are sending THAT version; if the draft changed on OFW since, the send is refused…
forcebooleanDefault false. Send even when the draft changed on OurFamilyWizard since you read it, or its current state could not be read. Only use after showing the user the conflict.
messageIdnumberSynonym for draftId (if both are passed they must be equal).
myFileIDsarrayAttachment file ids (from ofw_upload_attachment) to attach to the message. When sending by draftId, omit it to carry the server draft's own attachments over; passing it overrides them.
recipientIdsarrayArray of recipient user IDs (get from ofw_get_profile). Usually required even when sending a draft: OurFamilyWizard does not persist recipients on drafts.
replyToIdnumberID of the message being replied to. Defaults to the draft's stored reply target when sending by draftId.
subjectstringMessage subject. Required unless draftId/messageId is given (then it overrides the server draft's subject).

No output schema declared.

No examples provided.

ofw_status ~418

ONE live call that answers "where does everything stand?". This is the call that should back any status summary about drafts or specific messages — never session memory, and never a cached read alone. With no arguments it returns the FULL current draft inventory, verified against OurFamilyWizard. Pass ids and/or draftKeys to get each one's live lifecycle `state` ("draft" | "sent" | "received" | "deleted" | "unknown") with `sentAt` and `viewedAt`. A draftKey is the stable identity ofw_save_draft returns: editing a draft mints a new OFW id every time (create-then-delete), so the key is the only way to ask "what happened to the thing I was working on?" — it resolves to the chain's current id and keeps resolving after the draft is SENT (state:"sent" with sentMessageId). The top-level `complete` is true ONLY when every part of this snapshot was verified live; if it is false, do not state a draft count or a lifecycle claim from this payload.

NameTypeReqDescription
allowMarkReadbooleanDefault false. An id whose cached state cannot rule out an unread INBOX message can only be probed by fetching its detail, which marks it READ on OurFamilyWizard — irreversible and co-parent-visible.…
draftKeysarrayStable draft keys (from ofw_save_draft / ofw_list_drafts) to resolve to their CURRENT id and state.
idsarrayMessage/draft ids to resolve to a live state (combined with draftKeys, max 25 probes per call).
includeDraftInventorybooleanReturn the full current draft list, verified against OurFamilyWizard first. Defaults to TRUE when neither ids nor draftKeys is given (so a bare ofw_status() is a complete status snapshot), otherwise…

No output schema declared.

No examples provided.

ofw_sync_messages ~427

Sync messages from OurFamilyWizard into the local cache. Returns counts per folder and a list of unread inbox messages whose bodies were NOT fetched (to avoid mark-as-read on OFW). Call ofw_get_message(id) on those to read them. EVERY call re-checks the newest page first, so new messages are picked up promptly even while an old-history backfill is still running; only then does it spend what is left of its budget advancing that backfill. Pass deep:true to walk all OFW pages instead of stopping at the first all-cached page (use to backfill suspected gaps). Sync is BOUNDED and RESUMABLE: on hosted deployments a per-call OFW-request budget (env OFW_SYNC_MAX_REQUESTS, or the maxRequests argument) caps how far one call walks; when the budget is hit the response reports done:false with a note — call again with the SAME arguments to resume. done:false means older history is still being backfilled; it does NOT mean recent messages are missing. Local installs are unbounded by default (done is always true).

NameTypeReqDescription
deepbooleanIf true, walk every OFW page until empty regardless of cache state. Use to backfill gaps. Default false.
fetchUnreadBodiesbooleanIf true, also fetch bodies for unread inbox messages — which marks each one READ on OurFamilyWizard and stamps a co-parent-visible "First Viewed" time that cannot be undone. Defaults to the OFW_FETCH…
foldersarrayFolders to sync (default: all three). Must be non-empty if given — an empty list would sync nothing while reporting success.
maxRequestsintegerMaximum OFW requests this single call may make before pausing. When hit, the response reports done:false — call again with the same arguments to continue. Omit to use the server default (OFW_SYNC_MAX…

No output schema declared.

No examples provided.

ofw_update_event ~284

Update an existing OurFamilyWizard calendar event. Fetches the event, applies the given changes, and writes the merged result back (OFW has no partial update).

NameTypeReqDescription
allDayboolean
childrenarrayChild userIds to tag; pass [] to remove all child tags (omit to keep current tags)
dropOffParentIdnumberuserId of the drop-off parent
endDatestringEnd date YYYY-MM-DD (default: startDate)
endTimestringEnd time HH:mm, 24-hour (required unless allDay)
eventIdstringyesEvent id — the `id` from ofw_list_events / eventRecurrenceId from ofw_create_event
eventParentIdnumberuserId of the parent the event is 'for'
locationstring
notesstring
pickUpParentIdnumberuserId of the pick-up parent
privateEventbooleantrue = visible only to you; default false = shared with co-parent
reminderMinutesinteger
startDatestringStart date YYYY-MM-DD
startTimestringStart time HH:mm, 24-hour (required unless allDay)
titlestring

No output schema declared.

No examples provided.

ofw_upload_attachment ~165

Upload a local file to OurFamilyWizard's "My Files" so it can be attached to a message. Returns the fileId — pass that to ofw_send_message or ofw_save_draft in myFileIDs to attach it. The file is uploaded as PRIVATE (visible only to you) by default; pass shareClass:"SHARED" to share with co-parents directly via the My Files area.

NameTypeReqDescription
descriptionstringDescription shown in OFW My Files (default: filename)
labelstringDisplay label for the file in OFW (default: filename)
pathstringyesAbsolute path to the local file to upload. Tilde (~) is expanded.
shareClassstringShare class (default PRIVATE)

No output schema declared.

No examples provided.

Common questions

What is the io.github.chrischall/ofw-mcp server?

io.github.chrischall/ofw-mcp is listed in the public MCP registry as io.github.chrischall/ofw-mcp. OurFamilyWizard co-parenting for Claude, messages, calendar, expenses, and journal. This page covers its npm package (ofw-mcp).

Is the io.github.chrischall/ofw-mcp server safe to use?

io.github.chrischall/ofw-mcp scores 91 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 20 September 2026. It declares no install or post-install scripts. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the io.github.chrischall/ofw-mcp server expose?

io.github.chrischall/ofw-mcp exposes 25 tools: ofw_healthcheck, ofw_get_profile, ofw_get_notifications, ofw_list_message_folders, ofw_list_messages, and 20 more. Their descriptions and schemas cost roughly 6,615 tokens of context every time the server is loaded.

Is the io.github.chrischall/ofw-mcp server still maintained?

io.github.chrischall/ofw-mcp is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

What licence is the io.github.chrischall/ofw-mcp server under?

io.github.chrischall/ofw-mcp declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.