This skill should be used when the user asks about OurFamilyWizard (OFW) co-parenting data. Triggers on phrases like "check OFW", "OurFamilyWizard inbox", "OFW messages", "OFW calendar", "OFW expenses", "what did my co-parent say", "log an expense in OFW", "OFW journal", or any request involving co-parenting messages, calendar events, shared expenses, or journal entries.
数据分析
Tmp.BcPQA7YzJI
试用让你的智能体读写 OurFamilyWizard 的消息、日程、费用和日志。
它能做什么
为 OurFamilyWizard 提供读写的 MCP 接口,可访问共同育儿数据:收件箱与发件箱消息、草稿、日程事件、共同费用与亲子日志。消息和草稿走本地缓存,每次返回都带 staleness、asOf、ageSeconds、serverConfirmed 等新鲜度信号,便于区分缓存结果与实时状态;无法在线核实时工具会以 UNVERIFIED_EMPTY 拒绝报告。发信、删除日程、读取收件箱消息都属于对具备法律效力的记录的不可逆副作用,操作前需用户明确确认。可通过 .mcp.json 或 mcporter 注册,凭据使用环境变量 OFW_USERNAME 与 OFW_PASSWORD。
什么时候用它
- 查看 OFW 收件箱与共同家长往来消息
- 按日期范围查询共享日程事件
- 登记一笔新的共同费用
- 审核后再发送草稿消息给共同家长
技能文档
ofw-mcp
MCP server for OurFamilyWizard — provides read/write access to messages, calendar, expenses, and journal.
- npm: npmjs.com/package/ofw-mcp
- Source: github.com/chrischall/ofw-mcp
Setup
Option A — Claude Code (direct MCP, no mcporter)
Add to .mcp.json in your project or ~/.claude/mcp.json:
{
"mcpServers": {
"ofw": {
"command": "npx",
"args": ["-y", "ofw-mcp"],
"env": {
"OFW_USERNAME": "you@example.com",
"OFW_PASSWORD": "yourpassword"
}
}
}
}
Option B — mcporter
1. Install
npm install -g ofw-mcp
Or from source:
git clone https://github.com/chrischall/ofw-mcp
cd ofw-mcp
npm install && npm run build
2. Configure credentials
cp .env.example .env
# Edit .env: set OFW_USERNAME and OFW_PASSWORD
3. Register with mcporter
mcporter config add ofw \
--command "ofw-mcp" \
--env "OFW_USERNAME=you@example.com" \
--env "OFW_PASSWORD=yourpassword" \
--config ~/.mcporter/mcporter.json
4. Verify
mcporter list --config ~/.mcporter/mcporter.json
mcporter call ofw.ofw_get_profile --config ~/.mcporter/mcporter.json
Calling tools (mcporter)
mcporter call ofw. [key=value ...] --config ~/.mcporter/mcporter.json
Always pass --config ~/.mcporter/mcporter.json unless a local config/mcporter.json exists.
Tools
User
| Tool | Description |
|---|---|
ofw_get_profile | Current user + co-parent info (IDs, contact details) |
ofw_get_notifications | Dashboard summary: unread count, upcoming events, outstanding expenses. ⚠️ Updates last-seen status. |
Messages
| Tool | Notes |
|---|---|
ofw_sync_messages(folders?, deep?, fetchUnreadBodies?) | Sync OFW → local cache. Call first if the cache might be stale. Returns unread inbox hints (bodies not fetched, to avoid mark-as-read). |
ofw_list_message_folders | List OFW folders with unread counts. Most reads use the cache; this is mainly for folder IDs and live unread counts. |
ofw_list_messages(folderId?, since?, until?, q?, page?, size?, autoRefresh?) | Cache-backed list. Supports folder ("inbox"/"sent"/"both"), date range, and substring search. Returns complete for the RESULT SET. An empty result from a non-fresh cache is refused (UNVERIFIED_EMPTY) — pass autoRefresh:true to sync and answer instead. |
ofw_get_message(messageId, allowMarkRead?) | Read a message OR draft body. Cache-first. Ids in the drafts cache return folder: "drafts". ⚠️ Falls through to OFW for unread inbox messages, which marks them read AND stamps a "First Viewed" time the co-parent can see — irreversible. Pass allowMarkRead:false to refuse that fetch instead; cached, sent and already-read messages are unaffected. |
ofw_send_message(draftId?, subject?, body?, recipientIds?, replyToId?, expectedRevision?, deleteDraftOnSuccess?, myFileIDs?, force?) | Send a message — the one irreversible operation. Preferred path: pass draftId (+ expectedRevision) to send an existing draft as it exists on the server — the tool re-reads it from OFW first and refuses if it changed since you read it (or was already sent/deleted); subject/body become optional overrides. recipientIds is usually still required: OFW does not store recipients on drafts. After a confirmed send the draft is auto-deleted (deleteDraftOnSuccess:false to keep it); on any failure or ambiguity it is retained and the response says why (draftRetained). Response leads with sentMessageId, draftKey, threaded, draftDeleted. Compose from scratch by passing subject/body/recipientIds with no draftId. |
ofw_get_unread_sent(page?, size?, autoRefresh?) | Sent messages your co-parent hasn't read yet (from cache). Reports scanned/total/complete; an empty sent cache that is not fresh is refused rather than reported as "nothing sent". |
ofw_list_drafts(page?, size?, verify?, autoRefresh?) | List saved drafts, auto-verified: when the cache is not verified-fresh a cheap drafts sync runs first (default verify:true), so one call answers server-confirmed. verify:false serves straight from cache. Each draft carries serverConfirmed, revision and draftKey. Returns complete — check it before saying "you have N drafts". See Freshness. |
ofw_save_draft(subject, body, recipientIds?, messageId?, replyToId?, myFileIDs?, expectedRevision?, force?) | Create a new draft. Pass messageId to replace an existing draft: the tool creates a fresh draft and deletes the old one (OFW's update-in-place endpoint silently no-ops). The returned id is the NEW id; the response leads with draftKey, which stays the same across every edit — track that, not the id. Note: OFW does not store recipients on drafts — recipientIds are accepted but come back empty (a one-line NOTE says so; supply them at send time instead). Threading warnings fire only on genuine drops — a draft echoing inReplyTo/showContext IS threaded. |
ofw_delete_draft(messageId) | Delete a draft. |
ofw_upload_attachment(path, shareClass?, label?, description?) | Upload a local file to My Files; returns a fileId to pass into myFileIDs. |
ofw_download_attachment(fileId, inline?, saveTo?, force?, extract?, maxChars?, parts?) | Download an attachment. Inline delivery returns the first rung that works: image → ImageContent; .xlsx/.csv/.pdf/.docx/.pptx/text → extracted content under extracted (per-sheet CSV, per-page/slide text); anything else → raw bytes. Default writes to ~/Downloads/ofw-mcp/ (add extract:true for content too). Use parts:"1-2" / a sheet name and maxChars on large files. |
ofw_check_freshness(folders?, messageIds?, allowMarkRead?) | Cheap live check that the cache still matches OFW — one request for folder counts plus one per id, no bodies, no sync. Each id gets a live state (draft/sent/received/deleted/unknown) plus folder and sentAt. Probes ids cached as drafts, as sent, or as already-read inbox messages freely; anything else needs allowMarkRead:true (it would mark an inbox message read). |
ofw_status(ids?, draftKeys?, includeDraftInventory?, allowMarkRead?) | The status call. One live round trip. With no arguments: the full, server-verified draft inventory. With ids/draftKeys: each one's live lifecycle state. Top-level complete is true only when every part was verified live. |
Calendar
| Tool | Notes |
|---|---|
ofw_list_events(startDate, endDate, detailed?) | Dates as YYYY-MM-DD |
ofw_create_event(title, startDate, endDate, ...) | startDate/endDate as ISO datetime |
ofw_update_event(eventId, ...) | Partial update — only pass fields to change |
ofw_delete_event(eventId) | Permanent delete |
Expenses
| Tool | Notes |
|---|---|
ofw_get_expense_totals | Summary of owed/paid totals |
ofw_list_expenses(start?, max?) | Paginated; default max 20 |
ofw_create_expense(amount, description) | Log a new expense |
Journal
| Tool | Notes |
|---|---|
ofw_list_journal_entries(start?, max?) | 1-based offset; default max 10 |
ofw_create_journal_entry(title, body) | Create a new entry |
Freshness, completeness, and lifecycle
Message and draft reads come from a local cache, so a result can be stale without looking stale. Three separate questions, three separate signals — do not substitute one for another:
| Question | Signal |
|---|---|
| How old is this data? | freshness — staleness (fresh/unverified/stale), asOf, ageSeconds, a quotable warning |
| Is this the WHOLE answer? | complete on ofw_list_messages / ofw_list_drafts / ofw_get_unread_sent / ofw_status |
| Is this entity still what I think it is? | state from ofw_status / ofw_check_freshness |
Rules:
- Verification is cheaper than recollection. Use it. Any status summary about drafts costs exactly one
ofw_status()call. There is no situation in which recalling an earlier tool result is the better option. - Never state current state from memory. A draft you saved earlier in the session is not evidence it still exists unsent now — the user may have sent, edited or deleted it in the web app since. This has gone wrong twice: drafts described as "still sitting unsent" that had already been sent.
existsOnServerdoes not mean "still a draft". A draft that was SENT still exists on the server. Onlystatedistinguishes them.- Check
completebefore quoting a count.complete: falsemeans the result set is a slice, or unverified, or both —completeNotesays which. "You have 3 drafts" requirescomplete: true. serverConfirmed: falsemeans "remembered, not known." Callofw_status/ofw_check_freshnessfirst, or say plainly that you are reporting cached state and give its age.- A refusal is a good outcome.
result: "UNVERIFIED_EMPTY"means the tool declined to report an absence it could not verify. Do theremedy— never re-report it as "nothing found". A wrong "no, that was never sent" is far costlier here than one extra call. state: "unknown"is not "fine". It means the question was not answered.- OFW does not bump a draft's timestamp when it is edited in the web app, which is why freshness is compared by content revision. "Nothing changed" and "we didn't look" are otherwise indistinguishable.
- A missing folder count in
ofw_sync_messagesoutput means that folder was not checked — it is never "no changes". ChecknotRefreshed.
Draft identity (draftKey)
Editing a draft mints a new OFW id every time — ofw_save_draft replaces by create-then-delete, so one message can burn through ten ids in a session. Track the draftKey it returns, not the id:
ofw_status(draftKeys: ["dk_…"])resolves the key to the chain's current id and state.- The key keeps resolving after the draft is sent:
state: "sent"withsentMessageIdandsentAt. draftKey: nullon a draft means it was authored outside this tool; it is adopted into a chain the first time you save over it.
Workflows
Check inbox:
ofw_list_message_folders→ find inbox folder IDofw_list_messages(folderId)→ list messagesofw_get_message(messageId)→ read a specific message
Send a message:
ofw_get_profile→ get co-parent's user IDofw_send_message(subject, body, [coParentId])
Reply to a message (with thread history):
ofw_get_message(messageId)→ read the message to reply toofw_send_message(subject, body, [coParentId], replyToId: messageId)— original message is included in the thread
Draft before sending (sensitive messages):
ofw_save_draft(subject, body)→ review with user; note the returneddraftKeyandrevisionofw_send_message(draftId, recipientIds, expectedRevision)after approval — sends the server's copy of the draft (no body re-supply), refuses if it changed since review, and deletes the draft only after the send is confirmed
Check what's coming up:
ofw_get_notificationsfor a quick summaryofw_list_events(today, +30days)for calendar detail
Caution
- Always confirm before sending messages or deleting anything — OFW is a legal co-parenting record.
ofw_get_notificationsupdates last-seen status — avoid calling silently in the background.ofw_get_messagemarks messages read — warn the user if they want to keep something unread.- Do not narrate cached state as present fact. Before saying what "is" true on OFW right now, call
ofw_status— one live round trip that answers drafts, ids and draft keys at once. Never assemble a status summary from earlier tool results in the conversation; re-read.
常见问题
- 消息读取是实时的还是缓存的?
- 消息和草稿走本地缓存。每次返回都带新鲜度字段(staleness、asOf、ageSeconds)和 serverConfirmed 标记;当结果无法在线核实时,工具会以 UNVERIFIED_EMPTY 拒绝报告,而不是返回空结果。
- 读取或发送会产生哪些副作用?
- ofw_get_message 会把收件箱消息标记为已读,并写入对方可见的 First Viewed 时间戳,可用 allowMarkRead:false 拒绝该读取。ofw_send_message 与 ofw_delete_event 不可逆,调用前需要用户明确确认。
- 如何安全地发送草稿?
- 先用 ofw_save_draft 保存草稿,记录返回的 draftKey 和 revision;审核后再调用 ofw_send_message(draftId, recipientIds, expectedRevision),工具会重新从 OFW 读取草稿,若与审核时不一致则拒绝发送,并在发送确认后才删除草稿。
相关技能
Access OurFamilyWizard (OFW) — messages, calendar, expenses, journal — from a shell with the fpx CLI (@fetchproxy/cli) instead of running the ofw-mcp server: capture the signed-in web app's Bearer token once via the browser bridge, then curl the REST API directly. Use when you want OFW data without the MCP, in a script, or on a machine where the MCP isn't installed.
让 OpenClaw 代理通过 Microsoft Graph API 接入个人微软账户,读写 Outlook 邮件、日历事件和 To Do 任务。
Let your AI assistant manage your Outlook calendar for you. Just say what you need — add, change, or delete events, set up repeating meetings, or ask when you're free — and it happens on your own calendar.
Read and manage your Skylight Calendar family hub — calendar events, chores and reward stars, shared lists (grocery/to-do), and meal plans. Triggers on phrases like "check Skylight", "what's on the family calendar", "add an event to Skylight", "what chores does [kid] have", "mark [chore] done", "add milk to the grocery list", "what's on our shopping list", "what's for dinner", "what's on the meal plan", "who's on the Skylight frame", or any request involving the Skylight frame, family calendar, chores, rewards, shared lists, or meals. Works against your own signed-in Skylight account via email + password.
Manage daily bills, expenses, and recurring payments with tracking, reminders, and analysis. Use when the user asks about bill management, expense tracking,...