OurFamilyWizard MCP
This server provides natural-language access to OurFamilyWizard for co-parenting data and actions:
Messages: List, search, and read messages; send new messages, replies, and drafts with conflict detection; sync cache; check unread sent messages; manage drafts.
Calendar: List, create, update, and delete events with full details.
Expenses: Get totals, list history, and log new expenses.
Journal: List and create journal entries.
Attachments: Upload to My Files; download and extract content from attachments.
Profile & Notifications: View profile, co-parent info, and dashboard summaries.
Status & Safety: Check cache freshness, live status; write protection modes; prevent accidental read markings.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@OurFamilyWizard MCPShow me my recent OFW messages"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
OurFamilyWizard MCP
A Model Context Protocol server that connects Claude to OurFamilyWizard, giving you natural-language access to your co-parenting messages, calendar, expenses, and journal.
AI-developed project. This codebase was entirely built and is actively maintained by Claude Sonnet 4.6. No human has audited the implementation. Review all code and tool permissions before use.
What you can do
Ask Claude things like:
"Show me my recent OFW messages"
"What's on the kids' calendar next week?"
"List recent expenses and tell me what I owe"
"Add a journal entry about today's pickup"
"Draft a reply to the last message from my co-parent"
Related MCP server: whoop-mcp
Requirements
Node.js 22.5 or later (
node:sqliteis the cache backend)An active OurFamilyWizard account
Acknowledgement of Terms
By using this MCP server, you acknowledge and agree to the following:
1. This server accesses your own OurFamilyWizard account. Auth happens via your own credentials. It does not — and cannot — access your co-parent's account, your children's accounts, or anyone else's.
2. OurFamilyWizard's Terms govern your use of this server, just as they govern your direct use of OFW. There is no explicit anti-scraping clause; the governing language is broader:
Users may not obtain or attempt to obtain any materials or information through any means not intentionally made available.
And on credentials: "You are solely responsible for (1) maintaining the strict confidentiality of assigned Authentication Methods, (2) instructing any individual to whom the assigned Authentication Method is shared ('Authorized User') to not allow another person to use the Authentication Method." OFW does contemplate "Authorized Users" and third-party-enabled integrations — but the account holder remains responsible.
You are agreeing to those terms — read by the maintainer 2026-05-23 — every time you invoke a tool in this server.
3. Personal, family use only. This project is not affiliated with, endorsed by, sponsored by, or in partnership with OurFamilyWizard, LLC or its parent. It is a personal automation tool for the named account holder. Do not use it on behalf of a co-parent without their consent, do not share credentials with anyone, and do not use it to bulk-extract another family's data.
4. OFW is a court-of-record platform. Messages, expenses, calendar entries, and journal entries on OFW may be entered into legal proceedings — including custody, divorce, and parenting-plan-modification cases. Anything this server writes to OFW (drafts you save, events you create, expenses you log) will appear with the same legal weight as if you had typed it yourself. Do not let this MCP send a message, create an event, or log an expense that you have not read and approved. Review every write operation before confirming.
5. You accept full responsibility for any consequences — both technical (account warnings, suspension) and legal (anything OFW records about your account activity). The MCP author is not your attorney; if you're using OFW in connection with an active legal matter, talk to your actual attorney before automating anything.
This section is the maintainer's good-faith summary of the terms — it is not legal advice and does not modify or supersede OurFamilyWizard's actual ToS.
Installation
1. Clone and build
git clone https://github.com/chrischall/ofw-mcp.git
cd ofw-mcp
npm install
npm run build2. Add to Claude Desktop
Edit your Claude Desktop config file:
Mac:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
Add the ofw entry inside "mcpServers" (create the key if it doesn't exist):
{
"mcpServers": {
"ofw": {
"command": "node",
"args": ["/absolute/path/to/ofw-mcp/dist/index.js"],
"env": {
"OFW_USERNAME": "your-email@example.com",
"OFW_PASSWORD": "your-ofw-password"
}
}
}
}Replace /absolute/path/to/ofw-mcp with the actual path where you cloned the repo. On Mac, run pwd inside the cloned directory to get it.
3. Restart Claude Desktop
Quit completely (Cmd+Q on Mac, not just close the window) and relaunch.
4. Verify
Ask Claude: "What does my OFW dashboard look like?" — it should show your unread message count, upcoming events, and outstanding expenses.
Authentication
ofw-mcp tries three auth paths in order; whichever succeeds first is used. Existing setups keep working unchanged.
Env-var credentials (legacy, recommended for Claude Desktop). Set
OFW_USERNAME+OFW_PASSWORDand the server logs in via OFW's form endpoint. This is the path shown in the Claude Desktop config above.fetchproxy fallback (no env vars needed). When the credentials are absent, the server reads
localStorage["auth"]once at startup from your already-signed-inourfamilywizard.comtab via the fetchproxy browser extension. After that one read, all OFW API calls go directly from Node — the extension is not in the request hot path. Install the fetchproxy extension (Chrome Web Store / Safari.dmg), sign into OurFamilyWizard once, and the MCP just works. If you have multiple OFW accounts and want them to use separate caches, setOFW_CACHE_IDENTITYto a label per profile.Error. If neither path is available, the server tells you exactly which fix to apply. Set
OFW_DISABLE_FETCHPROXY=1to skip the fetchproxy fallback entirely (turns missing credentials into a hard error — useful in headless CI).
Credential options (env-var path)
Option A — env block in Claude Desktop config (shown above, recommended):
"env": {
"OFW_USERNAME": "your-email@example.com",
"OFW_PASSWORD": "your-ofw-password"
}Option B — .env file in the project directory:
cp .env.example .env
# edit .env and fill in your credentialsEnvironment variables always take priority over the .env file. You can also pass them directly on the command line:
OFW_USERNAME=you@example.com OFW_PASSWORD=yourpass node dist/index.jsAvailable tools
Read-only tools run automatically. Write tools ask for your confirmation first. The Write mode column shows the minimum OFW_WRITE_MODE a tool needs to be available at all — see Write protection below.
Tool | What it does | Permission | Write mode |
| Your profile and co-parent info | Auto | any |
| Dashboard counts (unread messages, upcoming events, outstanding expenses) | Auto | any |
| Folders with unread counts — get folder IDs here before listing messages | Auto | any |
| Messages in a folder | Auto | any |
| Full content of a single message | Auto | any |
| Sync messages into the local cache (unread bodies left unfetched to avoid read receipts) | Auto | any |
| Sent messages a recipient hasn't read yet (from local cache) | Auto | any |
| Cheap live check that the cache still matches OFW — per id, whether it is still a | Auto | any |
| One live call for "where does everything stand?" — the full verified draft inventory, and the current state of any ids or draft keys | Auto | any |
| Download a message attachment to disk, or inline as extracted content / bytes | Auto | any |
| Send a message | Confirm |
|
| Draft messages | Auto | any |
| Create or update a draft | Confirm |
|
| Delete a draft | Confirm |
|
| Upload a local file to My Files; returns a fileId to attach via | Auto |
|
| Calendar events in a date range | Auto | any |
| Create a calendar event | Confirm |
|
| Update a calendar event | Confirm |
|
| Delete a calendar event | Confirm |
|
| Expense summary totals | Auto | any |
| Expense history | Auto | any |
| Log a new expense | Confirm |
|
| Journal entries | Auto | any |
| Create a journal entry | Confirm |
|
Data freshness (OFW_FRESHNESS_TTL_SECONDS)
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.
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:
"freshness": {
"source": "cache",
"asOf": "2026-07-20T12:40:00.000Z",
"ageSeconds": 5231,
"staleness": "unverified",
"lastServerSyncAt": "2026-07-20T13:59:00.000Z",
"syncComplete": false,
"historyComplete": true,
"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."
}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.
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.
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. It probes ids that are cached as drafts, as sent messages, or as already-read inbox messages freely, because none of those can change anything; 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.
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.
Is it still what I think it is? (ofw_status)
Freshness answers how old is this data. It does not answer is this entity still what I think it is — and that is a different failure. A draft that has been sent still exists on the server, so "does this id exist?" comes back true for the one case where the answer matters most.
ofw_status is the call that should back any status summary:
{
"checkedAt": "2026-07-28T09:12:00.000Z",
"requested": [
{ "id": 538279699, "state": "sent", "sentAt": "2026-07-27T23:31:09", "inSync": false },
{ "id": 538086428, "state": "draft", "inSync": true }
],
"complete": true
}stateisdraft,sent,received,deletedorunknown, read live from OFW.unknownmeans the question was not answered — it is not a synonym for "fine".With no arguments it returns the full draft inventory, verified against OFW first.
complete: truemeans every part of the snapshot was confirmed live. If it is false,incompleteReasonssays what wasn't, and the payload is not a basis for stating a count.
Draft keys. Editing a draft mints a new OFW id every time (ofw_save_draft replaces by create-then-delete, because OFW's update-in-place endpoint silently no-ops). ofw_save_draft therefore also returns a draftKey that stays constant across every edit and follows the message into Sent. ofw_status(draftKeys: ["dk_…"]) resolves it to the current id and state — including state: "sent" with sentMessageId — so "what happened to the draft I was working on?" is one call, not a guess about which id is current.
Absence is never reported from a stale cache
A cached read that comes back empty is shaped identically to a verified "nothing there". ofw_list_messages, ofw_list_drafts and ofw_get_unread_sent therefore refuse rather than answer when the result is empty and the backing cache is not fresh:
{
"result": "UNVERIFIED_EMPTY",
"reason": "No drafts were found, but the backing cache is \"unverified\" — it was last verified 207 min ago. Refusing to report absence from unverified data…",
"remedy": "Call ofw_sync_messages(folders:[\"drafts\"]) and retry, re-call with autoRefresh:true, or use ofw_status(includeDraftInventory:true) for a single live answer.",
"complete": false
}A false negative ("no, that was never sent") is more dangerous than a refusal, because it reads as a definitive answer. Non-empty results are never withheld — a stale cache that did find something is still evidence of presence, labelled with its age as before. Pass autoRefresh: true (or set OFW_AUTO_REFRESH=true) to have the tool sync and answer instead of refusing; a refresh that still cannot make the read verifiable refuses anyway.
Every list read also carries an explicit complete boolean describing the result set — "this is every matching item on OurFamilyWizard as of asOf" — with a completeNote naming what is missing when it is false. Check it before stating a count.
Write protection (OFW_WRITE_MODE)
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.
| What's available |
| Read/sync/search only. No write tools exist. |
| Adds draft-level writes: |
| Everything (the default — fully backward compatible). |
Unrecognized values fail closed to none, with a warning on stderr — a typo never silently grants write access.
Reading is a write, too (OFW_ALLOW_MARK_READ)
Fetching a message body for the first time marks it read on OurFamilyWizard and stamps a "First Viewed" timestamp your co-parent can see. That is part of the record and cannot be undone — and it happens as a side effect of an ordinary read, so OFW_WRITE_MODE does not govern it.
By default nothing changes: reads behave exactly as they always have. Two controls exist if you want them:
Setting | Effect |
| Refuses a fetch that would stamp an unread inbox message, returning a structured |
| Deployment-wide ceiling. No tool may stamp: |
OFW_FETCH_UNREAD_BODIES=true flips ofw_sync_messages to fetch unread bodies by default (off unless set) — useful where read receipts are routine. It is capped by OFW_ALLOW_MARK_READ.
Calendar opt-in (OFW_CALENDAR_WRITES)
Calendar events sit between the two message tiers: they have no draft stage (a created event is immediately visible on the shared record), but unlike a sent message they are reversible — an event can be edited or deleted afterward. If you run in drafts mode but are comfortable with direct calendar writes, set OFW_CALENDAR_WRITES=true to additionally register ofw_create_event, ofw_update_event, and ofw_delete_event. The flag is redundant in all mode and never overrides none.
Troubleshooting
"0 messages" — Claude may have read the notification counts rather than the actual messages. Ask explicitly: "List the messages in my OFW inbox" or "Use ofw_list_message_folders then ofw_list_messages".
"OFW auth: set OFW_USERNAME + OFW_PASSWORD, or install the fetchproxy extension…" — neither auth path is configured. Either fill in the env block in your Claude Desktop config, or install the fetchproxy extension and sign into ourfamilywizard.com in your browser.
"fetchproxy fallback failed" — the env-var path wasn't configured and the extension couldn't be reached. Confirm the fetchproxy extension is installed, signed into OFW, and that it's running (open the extension popup). If you want to disable the fallback entirely, set OFW_DISABLE_FETCHPROXY=1.
403 Forbidden — wrong credentials. Verify your username/password at ofw.ourfamilywizard.com.
Tools not appearing in Claude — go to Claude Desktop → Settings → Developer to see connected servers and any error output. Make sure you fully quit and relaunched after editing the config.
Can't find the config file on Mac — in Finder press Cmd+Shift+G and paste ~/Library/Application Support/Claude/.
Security
Credentials live only in your local config file or
.envThey are passed to the server as environment variables and never logged
The server authenticates with OFW using the same login flow as the web app
Use a strong, unique OFW password
Development
npm test # tsc typecheck, then the vitest suite
npm run build # tsc → dist/, then esbuild bundle → dist/bundle.js
npm run dev # node --env-file=.env dist/index.js (requires built dist)Main is protected. All changes land via PR — open with gh pr create --label <release-notes-label> and add ready-to-merge once you're satisfied with the auto-review feedback. See CLAUDE.md for the full PR + release flow.
Project structure
src/
index.ts MCP server entry (McpServer + StdioServerTransport)
client.ts OFW HTTP client with Bearer token + 401/429 retry
auth.ts resolveAuth(): env-var creds → fetchproxy → error
auth-password.ts Spring Security form login (legacy env-var path)
cache.ts SQLite cache (messages, drafts, attachments, sync state)
sync.ts Folder ID resolution + per-folder sync logic
config.ts Cache dir, attachment dir, env parsing
tools/
_shared.ts Recipient mapping, response helpers, path expansion
user.ts ofw_get_profile, ofw_get_notifications
messages.ts Folders, list, get, send, drafts, sync, attachments
calendar.ts List, create, update, delete events
expenses.ts Totals, list, create
journal.ts List, create entries
tests/ Mirrors src/; mocks OFWClient.request via vi.spyOnAuth flow
Auth resolution lives in src/auth.ts. Three paths, in priority order:
Env vars present →
src/auth-password.tsdoes the legacy OFW Spring Security form login:GET /ofw/login.form— establishes a session cookiePOST /ofw/login— submits credentials, returns{ auth: "<token>" }
Env vars absent (and
OFW_DISABLE_FETCHPROXYunset) →@fetchproxy/bootstrapreadslocalStorage["auth"]+localStorage["tokenExpiry"]once from the user's signed-inourfamilywizard.comtab, then closes the bridge.Nothing configured → throws with both fixes spelled out.
Either path returns a Bearer token to OFWClient, which then operates from Node with Authorization: Bearer <token> — fetchproxy is not in the request hot path. On 401 the client re-resolves auth and replays once. Tokens are cached for 6h (env-var path) or until tokenExpiry (fetchproxy path).
Also see the fetchproxy README for extension install instructions.
License
MIT
Available Tools
25 toolsofw_check_freshnessA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| folders | No | Folders to compare cached vs live counts for. Defaults to all three when messageIds is not given. Must be non-empty if given. | |
| messageIds | No | Specific 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 — see allowMarkRead. | |
| allowMarkRead | No | Default 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 Viewed" time — irreversible. Such ids are skipped (reason:"WOULD_MARK_READ") unless you set this to true. The server-wide OFW_ALLOW_MARK_READ=false is a ceiling this cannot raise. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses costs ('one OFW request per folder plus one per messageId'), explains return fields (live state, revision hash comparison), clarifies that drafts edited in web app don't change timestamps, and warns about allowMarkRead marking messages read irreversibly. Annotations show readOnlyHint=false, which is consistent with the potential write effect of allowMarkRead=true. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single dense paragraph but efficiently front-loads purpose and cost. Every sentence adds value, no redundancy. It reads naturally while packing in behavioral details. Ideal length for this complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and three parameters with edge cases, the description fully covers what the tool does, when to use it, costs, side effects, output fields, and distinguishes from similar tools. Leaves no obvious gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but description adds significant meaning: for folders it explains default behavior when messageIds omitted; for messageIds it details which cached states can be probed without marking read; for allowMarkRead it explains the irreversible consequence and server ceiling. This goes well beyond the schema's enum descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Cheaply confirm whether the local cache still matches OurFamilyWizard, WITHOUT running a full sync.' It specifies a use case ('draft X is still sitting unsent') and distinguishes from siblings like ofw_status and full sync.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance: 'Use this before asserting anything about current state' and 'For draftKeys, or a full live draft inventory, use ofw_status.' Also explains when not to use (if mark read side effect is undesirable) and provides alternative sibling tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_create_eventA
Create a calendar event in OurFamilyWizard. Unless privateEvent is true, the event is immediately visible to the co-parent — there is no draft stage.
| Name | Required | Description | Default |
|---|---|---|---|
| notes | No | ||
| title | Yes | ||
| allDay | No | ||
| endDate | No | End date YYYY-MM-DD (default: startDate) | |
| endTime | No | End time HH:mm, 24-hour (required unless allDay) | |
| children | No | Child userIds to tag (see ofw_get_profile) | |
| location | No | ||
| startDate | Yes | Start date YYYY-MM-DD | |
| startTime | No | Start time HH:mm, 24-hour (required unless allDay) | |
| privateEvent | No | true = visible only to you; default false = shared with co-parent | |
| eventParentId | No | userId of the parent the event is 'for' | |
| pickUpParentId | No | userId of the pick-up parent | |
| dropOffParentId | No | userId of the drop-off parent | |
| reminderMinutes | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the minimal annotation (destructiveHint: false), the description discloses key behavior: events are immediately visible to the co-parent unless privateEvent is set, and there is no draft stage. This adds valuable context for an agent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, no waste, and the most critical behavioral detail (visibility and draft stage) is front-loaded. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite 14 parameters and no output schema, the description only covers visibility and draft behavior. It lacks explanation of return values, error cases, or interactions among parameters like children, eventParentId, or reminders. The complexity of the tool demands more.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 64% schema description coverage, the baseline is 3. The description does not add new meaning to parameters beyond what the schema already provides, but it does not detract either. No parameter-specific elaboration is given.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Create a calendar event in OurFamilyWizard' with a specific verb and resource. It distinguishes from siblings by highlighting the immediate visibility to co-parent and absence of a draft stage, which sets it apart from update/delete tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides guidance on when to use privateEvent (to control visibility), and implies this is for new events given the sibling tools for update and delete. However, it does not explicitly state when not to use it or mention alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_create_expenseB
Log a new expense in OurFamilyWizard
| Name | Required | Description | Default |
|---|---|---|---|
| amount | Yes | Expense amount | |
| description | Yes | Expense description |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide destructiveHint=false, indicating non-destructive action. Description does not add behavioral details such as whether it creates a new record, what it returns, or any side effects. The agent may need more context about the operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, front-loaded with verb and object. Every word earns its place; no unnecessary fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Simple tool with two required params and no output schema. Description is minimal but covers the core action. However, it lacks details on return value or post-creation behavior, which could be useful for a new expense action.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with descriptions for both parameters. Description does not add additional meaning beyond the schema, so baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states verb 'Log' and resource 'expense' clearly. However, it does not differentiate from sibling tools like ofw_list_expenses or ofw_get_expense_totals, missing a chance to clarify its unique action.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives like updating or deleting expenses. No prerequisites or context provided, leaving the agent to infer usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_create_journal_entryB
Create a new journal entry in OurFamilyWizard
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | Entry text content | |
| title | Yes | Entry title |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only provide destructiveHint=false. Description adds no additional behavioral info such as permissions, side effects, or what happens on success. Minimal disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single concise sentence with no wasted words. Perfectly sized for the tool's simplicity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple create tool with no output schema and fully described parameters, the description is adequate but does not mention what the tool returns (e.g., created entry ID). Missing return value information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with descriptions for both 'title' and 'body'. Description does not add extra meaning beyond what the schema already provides. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'Create a new journal entry' with specific verb and resource. Distinct from sibling 'ofw_list_journal_entries' which is a read operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool vs alternatives. There are no similar create tools among siblings, but no explicit usage context is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_delete_draftADestructive
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.
| Name | Required | Description | Default |
|---|---|---|---|
| force | No | Default false. Delete even if the draft changed on OurFamilyWizard since you read it. The discarded server version is echoed back in the response. | |
| messageId | Yes | Draft message ID to delete | |
| expectedRevision | No | The `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. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations give destructiveHint: true. Description details the safety mechanism (re-read and refuse on change), local cache removal, and behavior of force parameter. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: first states the core action, second elaborates behavior. No fluff, front-loaded, each word contributes meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive tool with 3 parameters, no output schema, the description covers concurrency, safety, force option, and cache side effect. Comprehensive and sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers all 3 parameters with descriptions (100% coverage). The description reinforces the meaning of expectedRevision and force, explaining their interplay, adding workflow context beyond bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'Delete a draft message from OurFamilyWizard. Also removes the draft from the local cache.' It identifies the specific verb and resource, distinguishing it from siblings like ofw_save_draft and ofw_list_drafts.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides guidance on when to use: deletion of drafts. Explains the re-read-and-refuse logic, expectedRevision, and force:true. Does not explicitly name alternatives like ofw_save_draft for modifications, but the usage context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_delete_eventADestructive
Delete an OurFamilyWizard calendar event
| Name | Required | Description | Default |
|---|---|---|---|
| eventId | Yes | Event id — the `id` from ofw_list_events / eventRecurrenceId from ofw_create_event | |
| includeFuture | No | For repeating events: also delete future occurrences (default false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotation already indicates destructiveHint=true, so the description's 'Delete' is consistent but adds no new behavioral context (e.g., permanence, cascading effects on recurring events). It meets the minimum bar but does not exceed it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with no wasted words. It is appropriately front-loaded and easy to parse quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple delete tool with no output schema, the description is mostly complete. However, it could briefly note that the action is irreversible or that includeFuture affects recurring events, which would improve completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Both parameters are fully described in the input schema (100% coverage). The description adds no additional meaning beyond the schema, so the score is baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Delete' and the resource 'OurFamilyWizard calendar event'. It is distinct from sibling tools like ofw_create_event and ofw_update_event, making it easy for an agent to select this tool when deletion is needed.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives, such as ofw_update_event for modifications. It does not mention prerequisites or conditions under which deletion should not be performed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_download_attachmentA
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).
| Name | Required | Description | Default |
|---|---|---|---|
| force | No | Re-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). | |
| parts | No | Which 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 listed in `extracted.omitted`. | |
| fileId | Yes | Attachment file id (from ofw_get_message → attachments[].fileId) | |
| inline | No | If 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 (forcedInline:true) so the content is still returned. If omitted, falls back to the OFW_INLINE_ATTACHMENTS env var (default: false = disk). | |
| saveTo | No | Absolute 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. | |
| extract | No | Whether 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 hash or re-upload the file); set true in disk mode to get both the saved path and the extracted content. | |
| maxChars | No | Ceiling 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`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses all behavioral traits beyond the annotations: it explains the inline delivery ladder, disk saving behavior, no-op on re-download, mime type normalization, and forced inline on hosted deployments. Annotations only indicate readOnlyHint=false, so the description fully covers the mutation and side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the main purpose and each sentence adds value. However, it is lengthy and could be slightly more concise; still, the complexity of the tool justifies the detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 7 parameters and no output schema, the description fully covers all aspects: behavior, response structure (meta block, extracted content), parameter defaults, edge cases, and context from sibling tools. It is complete and leaves no gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All 7 parameters are described in the schema (100% coverage), but the description adds significant meaning: e.g., the ladder for inline delivery, default extract behavior, relationship between inline and env var, and edge cases like force being ignored when inline:true. This greatly enriches understanding beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool downloads an OFW message attachment by fileId and returns readable content. It specifies the inline delivery ladder for different file types, distinguishing it from sibling tools like ofw_get_message which provides the fileId but not the download.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance on when to use inline vs disk mode, the OFW_INLINE_ATTACHMENTS env var, and the source of fileId (from ofw_get_message). Also explains when to set extract, force, and saveTo, and notes edge cases like hosted deployments where disk mode is unavailable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_get_expense_totalsARead-only
Get OurFamilyWizard expense summary totals (owed/paid)
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true. The description adds context about output type (owed/paid totals) but does not disclose additional traits like time period scope.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence with no wasted words. Front-loaded with verb and resource.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters and no output schema, description sufficiently conveys purpose. Could specify time period scope but not critical for basic functionality.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist; schema coverage is 100%. Description adds value by clarifying output content. Baseline 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Get' and resource 'expense summary totals (owed/paid)', distinguishing it from sibling tool 'ofw_list_expenses' which likely lists individual expenses.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives like 'ofw_list_expenses'. No explicit context for usage or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_get_messageA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| view | No | Response 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 duplicates this record's own id, subject, sentAt, recipients and read flag; the sender is promoted to `from`, and `files`/`replied` are kept. Pass "full" for the echo. | |
| messageId | Yes | Message ID (also accepts draft IDs — drafts are routed via the drafts cache) | |
| allowMarkRead | No | Default 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. Reads that cannot stamp anything (a cached body, a sent message, an already-read message) still succeed. The server-wide OFW_ALLOW_MARK_READ=false is a ceiling this argument cannot raise. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond the readOnlyHint:false annotation by disclosing the irreversible, co-parent-visible mark-read side effect, the First Viewed timestamp, and the exact conditions under which it happens. It also explains cache versus fetch behavior and draft-specific response differences, giving the agent a precise mental model of side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core action is front-loaded, and each subsequent sentence adds a distinct behavioral fact rather than repeating flourishes. The length is justified by the tool's side-effect complexity and the absence of an output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-message getter with a subtle write-behavior trap, the description is complete: it covers cache reads, irreversible marking, the opt-out flag, draft routing, and folder values for each message category. There is no output schema, but the behavioral and routing details an agent needs are all present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, giving the baseline of 3, but the description adds meaningful semantics for messageId: supplying a draft ID yields folder=drafts and draft-cache values, including no fromUser and modifiedAt-mirrored timestamps. allowMarkRead semantics are also reinforced, though largely restating the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb-plus-resource statement: Get a single OurFamilyWizard message OR draft by ID. This clearly differentiates the tool from sibling list and draft utilities and states the exact unit of work.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives strong situational context: when a cache read is possible no stamping occurs, and when a fetch of an unread inbox message would mark it read, with allowMarkRead:false as an opt-out. However, it never explicitly names when to prefer this over a sibling such as ofw_list_messages or ofw_list_drafts, so the routing is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_get_notificationsA
Get OurFamilyWizard dashboard summary: unread message count, upcoming events, outstanding expenses. Note: updates your last-seen status.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Explicitly discloses side effect of updating last-seen status, which annotations (readOnlyHint=false) only hint at. This adds critical behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with purpose, behavioral note in second sentence. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with no output schema, the description adequately states return content and side effect, making it fully actionable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, so no parameter information is needed. The description properly omits any parameter discussion.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the tool retrieves a dashboard summary with specific items (unread count, events, expenses), distinguishing it from sibling tools that target individual data types.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage for a general overview but does not explicitly differentiate from siblings or provide when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_get_profileARead-only
Get current user and co-parent profile information from OurFamilyWizard
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description correctly indicates a read operation, consistent with the readOnlyHint annotation. It adds no extra behavioral details beyond what the annotation already provides.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, concise sentence that directly conveys the tool's purpose without unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple nature of the tool (no parameters, readOnlyHint annotation), the description is complete. No output schema is needed for such a straightforward retrieval.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters, so the baseline is 4 as per guidelines. The description does not need to elaborate on parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (get) and the resource (current user and co-parent profile information). It implicitly distinguishes from sibling tools that handle notifications, messages, events, expenses, and journal entries.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool should be used when profile information is needed but provides no explicit guidance on when not to use it or alternatives. With zero parameters and no sibling profile tools, this is adequate but minimal.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_get_unread_sentA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page (default 1) | |
| size | No | Per page (default 50) | |
| autoRefresh | No | If 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 var (false unless set), in which case the call refuses with result:"UNVERIFIED_EMPTY" and names the remedy. Costs OFW requests when it fires. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses key behaviors: reads from local cache, returns a 'complete' flag, and refusal with UNVERIFIED_EMPTY when cache is not fresh. Explains autoRefresh side effect, aligning with readOnlyHint=false annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four-sentence paragraph is front-loaded with purpose, every sentence adds value, no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even without an output schema, the description explains the 'complete' return field and special refusal result. All necessary details for using the tool are present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the description adds significant context for autoRefresh, including default behavior and cost implications, exceeding raw schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool lists sent messages that are unread by recipients, with specific verb and resource. Distinguishes from sibling tools like ofw_list_messages by specifying unread sent messages and local cache usage.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides guidance on using autoRefresh to avoid refusal, explaining when it's needed. Does not explicitly contrast with alternatives, but the tool name and context imply its specific use case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_healthcheckVerify credentials and upstream reachabilityARead-onlyIdempotent
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'. Call this when a real tool fails and you want to know which hop broke. Read-only; never returns the credential itself.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, and the description adds meaningful behavioral detail: it never returns the credential itself, makes exactly one authenticated request, reports the credential source, round-trip time, and distinguishes failure categories. This goes beyond the safety hints already encoded in annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is tightly written in three sentences: mechanism, outputs, and usage trigger. Every sentence adds distinct value, and the most decision-relevant information appears early.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema present, the description compensates by enumerating exactly what the tool reports: credential source, acceptance by ourfamilywizard.com, round-trip time, and a plain-English failure hint. It also explains the diagnostic purpose and the safety guarantee about not returning the credential, making it complete for an agent selecting and invoking the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there is nothing for the description to clarify beyond the schema. The baseline for no-parameter tools is 4, and the description does not need to elaborate on inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific diagnostic action: resolve credentials exactly as real tools do, make one authenticated request to ourfamilywizard.com, and report the outcome. It clearly distinguishes this health-check tool from the data-oriented sibling tools by focusing on broken-hop diagnosis rather than domain operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit trigger: 'Call this when a real tool fails and you want to know which hop broke.' It implies the alternative is failing sibling tools, but it does not explicitly name a sibling or list when-not-to-use scenarios. Still, the usage context is clear enough for an agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_list_draftsA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number (default 1) | |
| size | No | Drafts per page (default 50) | |
| view | No | Response 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 duplicates this draft's own id, subject, modifiedAt and recipients. `revision`, `draftKey` and `cacheStatus` are kept on both rungs. | |
| verify | No | Default 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 serve straight from the local cache with no OFW requests. | |
| autoRefresh | No | If 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 var (false unless set), in which case the call refuses with result:"UNVERIFIED_EMPTY" and names the remedy. Costs OFW requests when it fires. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description fully discloses that this appears to be a list operation but may trigger a drafts sync, make OFW requests, and refuse empty results from a stale cache. It explains the semantic meaning of `complete`, `draftKey`, and UNVERIFIED_EMPTY, going well beyond the annotation readOnlyHint:false. There is no contradiction and no hidden side effect is glossed over.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but front-loaded, leading with the main purpose and then layering essential caveats. Some content repeats the schema's verify and autoRefresh explanations, but the behavioral warnings about `complete` and UNVERIFIED_EMPTY are crucial enough to justify the length. A bulleted structure would improve scannability but the current form is efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there is no output schema, the description compensates well by explaining the crucial return semantics: the `complete` boolean, the `draftKey` stability, and the UNVERIFIED_EMPTY refusal path. It also covers pagination and response-shape parameters through the input schema. Nothing essential for invoking this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already explains verify, autoRefresh, view, page, and size. The main description adds no new parameter-level meaning beyond reinforcing the verify/autoRefresh workflow, which the schema already covers. This meets the baseline for fully documented parameters without adding extra value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List draft messages'. It distinguishes this from sibling messaging tools by focusing on drafts and adds a distinctive guarantee: results are 'verified against OurFamilyWizard in ONE call'. This makes the tool's purpose immediately identifiable even without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives concrete guidance on when to use each mode: verify:true for server-confirmed answers, verify:false for cache-only answers, and autoRefresh:true to resolve UNVERIFIED_EMPTY. It does not explicitly name sibling tools as alternatives for non-draft listing, but the context of draft messages and the explicit flag guidance make the usage conditions clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_list_eventsARead-only
List OurFamilyWizard calendar events in a date range
| Name | Required | Description | Default |
|---|---|---|---|
| endDate | Yes | End date YYYY-MM-DD | |
| detailed | No | Return full event details (default false) | |
| startDate | Yes | Start date YYYY-MM-DD |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true. Description adds that it lists events in a date range but no further behavioral traits (e.g., no pagination info, rate limits, or data freshness). Minimal added value beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single front-loaded sentence that efficiently conveys the tool's purpose. No unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with full schema coverage and readOnlyHint annotation, the description is complete enough. No output schema required.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 100% coverage with descriptions for all 3 parameters. Description doesn't add additional meaning beyond the schema, so baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it lists calendar events from OurFamilyWizard within a date range. The verb 'List' and resource 'calendar events' are specific, and it distinguishes from create/update/delete siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives. It doesn't mention when not to use it or suggest other tools like ofw_create_event for adding events.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_list_expensesARead-only
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.
| Name | Required | Description | Default |
|---|---|---|---|
| max | No | Max results (default 20) | |
| start | No | Start offset, 0-based (default 0). To continue a listing, pass the `nextStart` from the previous response. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint=true annotation, the description discloses a non-obvious response trait: paging state (hasMore, nextStart) precedes the records, so truncated reads still convey whether more remain. This plus the total/absence guardrail adds real behavioral context that an agent could not infer from annotations or the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, all earning their place: purpose, paging mechanism, response ordering with its implication, and an anti-hallucination guardrail. It is front-loaded with the core purpose and contains zero filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with two optional, fully documented parameters and no output schema, the description covers purpose, pagination mechanics, response shape, and interpretation rules. The only small gap is not naming ofw_get_expense_totals as the explicit alternative for totals, relying instead on an implied prohibition.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with both max and start fully documented including defaults, ranges, and the nextStart continuation contract. The description adds the offset-paging framing but does not materially extend what the schema already provides, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'List OurFamilyWizard expenses' — a specific verb and resource that precisely identifies the operation. It cleanly distinguishes itself from sibling tools like ofw_get_expense_totals (totals) and ofw_create_expense (creation), reinforced by the closing guardrail 'Never state an expense total'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description establishes clear use context: listing expenses with offset paging via start/max, and continuing via nextStart. The directive 'Never state an expense total or an absence from one page' functions as an implicit exclusion for the totals sibling, but it does not name the alternative explicitly, which would have earned a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_list_journal_entriesARead-only
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.
| Name | Required | Description | Default |
|---|---|---|---|
| max | No | Max results (default 10) | |
| start | No | Start offset, 1-based (default 1). To continue a listing, pass the `nextStart` from the previous response. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the readOnlyHint annotation by detailing the paging contract: offset paging with 1-based start/max, response shape with hasMore and nextStart before records, the null meaning of nextStart, and the warning never to state an entry count or absence from a single page. This is substantial non-obvious behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three tightly packed sentences with no filler. It front-loads the core purpose, then communicates the paging behavior and the critical agent-facing caveat, so every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list tool with two optional parameters, the description is complete: it identifies the resource, the paging mechanism, the response paging fields, and the key interpretation pitfall. The schema covers parameter defaults and continuation, and the annotation covers safety, so an agent can invoke and interpret the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description mentions 'start/max' and '1-based' but the input schema already documents defaults, ranges, and how to continue with nextStart. The additional paging-state information is response behavior rather than new parameter-level meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List OurFamilyWizard journal entries.' This clearly distinguishes it from sibling tools that list events, messages, expenses, or drafts, and it is not a tautology.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The resource-scoped purpose makes the selection context clear, and sibling tools target different resources, so an agent can choose this tool without much ambiguity. However, it does not explicitly name alternative tools or state when not to use this tool, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_list_message_foldersARead-only
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide readOnlyHint=true, so the description does not need to repeat that. It adds valuable behavioral context: 'Fetched LIVE from OFW, so the counts are current.' This goes beyond the annotation by explaining the data freshness.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three concise sentences, each adding value. The first sentence states the core purpose, the second adds behavioral detail, and the third clarifies what is not returned. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (no parameters, no output schema), the description is complete. It explains the action, the output (folder IDs and counts), the distinction from message content, and the live nature of the data.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters, so the baseline is 4. The description does not need to add parameter details, and it correctly focuses on the tool's purpose and output.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'List', the resource 'OurFamilyWizard message folders', and specifies that it returns folder IDs and unread counts. It distinguishes itself from sibling tools like ofw_list_messages by explicitly noting that it does not return message content.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a clear usage hint: 'Returns folder IDs needed to call ofw_list_messages', implying the tool is a prerequisite. It also warns that it does not return message content, preventing misuse. However, it does not explicitly list when not to use or mention alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_list_messagesA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Substring match on subject AND body (case-insensitive). Use to find messages on a specific topic. | |
| page | No | Page number (default 1) | |
| size | No | Messages per page (default 50) | |
| sort | No | Result 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 "oldest" its earliest. Use "oldest" to start at the old end of a range instead of paging to it. | |
| view | No | Response 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 duplicates this record's own id, subject, sentAt, recipients and read flag; the sender is promoted to `from`, and `files`/`replied` are kept. Pass "full" for the echo. | |
| since | No | ISO date or datetime — only messages with sent_at >= since (inclusive) | |
| until | No | ISO date or datetime — only messages with sent_at < until (exclusive) | |
| folderId | No | Folder name: "inbox", "sent", or "both" (default "both") | |
| autoRefresh | No | If 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 var (false unless set), in which case the call refuses with result:"UNVERIFIED_EMPTY" and names the remedy. Costs OFW requests when it fires. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only include readOnlyHint=false, so the description carries the behavioral burden, and it delivers richly: result ordering, inclusive vs exclusive date semantics, the `complete` boolean's meaning, the UNVERIFIED_EMPTY refusal behavior, and the autoRefresh fallback are all disclosed. No annotation contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence earns its place: it front-loads the core resource, then packs decision-relevant behavior (pagination semantics, sort behavior, complete flag, unverified-empty behavior) in a tight block. No filler or repetition of schema entries.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex 9-parameter, no-output-schema tool, the description covers the operational guardrails needed to call it correctly: freshness, empty-refusal, autoRefresh cost, and result completeness. The one gap is that it does not describe the record fields or response envelope, but with no output schema, a bit more detail about the result payload would round it out; still, the coverage is strong.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already has 100% coverage, so the baseline is 3, and the description adds meaningful semantics beyond schema: the `sort` field's effect on which end of a truncated page is kept, the cache-size motivation for filters vs page-walking, and the precise meaning of `complete` relative to freshness.asOf. It does not restate every schema field, but the added strategic context is substantial.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List messages from the local OurFamilyWizard cache,' then immediately names filtering dimensions (folder, date range, substring on subject+body). This clearly distinguishes it from sibling tools like ofw_get_message (single message) and ofw_sync_messages (sync operation).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent when to prefer filters over pagination ('if you know what you want (a date range, a topic), prefer the filters over walking pages'), and there is an explicit 'instead of paging to it' alternative. Although sibling alternatives are not named by name, the guidance about cache size and filter-vs-page tradeoff is actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_save_draftA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | Message body text | |
| force | No | Default 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. | |
| subject | Yes | Message subject | |
| messageId | No | ID of an existing draft to replace (the new draft will have a new id; the old is deleted) | |
| myFileIDs | No | Attachment file ids (from ofw_upload_attachment) | |
| replyToId | No | ID of the message this draft replies to | |
| recipientIds | No | Array of recipient user IDs (optional for drafts) | |
| expectedRevision | No | With 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 current server body is returned. Omit and the tool compares the server against the local cache instead — omitting never means "overwrite anyway". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes far beyond the readOnlyHint=false annotation, disclosing mutation consequences (replacement deletes the old draft, id changes on every edit), recipient non-persistence, replyToId normalization, conflict refusal behavior, and force semantics. The agent is fully warned about irreversible and surprising behaviors.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Long but exceptionally dense and organized with clear section labels (RECIPIENTS, IDENTITY, THREADING, SAFETY). Every sentence carries non-obvious operational information; no filler is present, and the core action is stated first.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a high-complexity mutation tool with no output schema, this description is remarkably complete. It covers returned identity fields (draftKey, id, revision), conflict response (serverBody), threading verdict fields, and failure recovery, so an agent can call and interpret it correctly without additional documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema already has 100% descriptive coverage, the description adds crucial semantics: recipientIds are not persisted, messageId leads to a new id and deletion, expectedRevision asserts a specific version, replyToId may be rewritten, and myFileIDs should come from ofw_upload_attachment. It substantially enhances the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ('Save a message as a draft in OurFamilyWizard') and clarifies scope by distinguishing create from replace ('Pass messageId to replace an existing draft'). It is clearly distinct from sibling tools such as ofw_send_message, ofw_list_drafts, and ofw_delete_draft.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit routing cues: supply recipientIds at send time instead, pass messageId to replace, attach files via myFileIDs from ofw_upload_attachment, and retry with expectedRevision after a conflict. It also explains why the OFW update-in-place endpoint is never used. This is concrete when-to-use and alternative guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_send_messageADestructive
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.
| Name | Required | Description | Default |
|---|---|---|---|
| body | No | Message 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). | |
| force | No | Default 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. | |
| draftId | No | ID 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 that was already sent/deleted, refuses rather than sending blind. | |
| subject | No | Message subject. Required unless draftId/messageId is given (then it overrides the server draft's subject). | |
| messageId | No | Synonym for draftId (if both are passed they must be equal). | |
| myFileIDs | No | Attachment 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. | |
| replyToId | No | ID of the message being replied to. Defaults to the draft's stored reply target when sending by draftId. | |
| recipientIds | No | Array of recipient user IDs (get from ofw_get_profile). Usually required even when sending a draft: OurFamilyWizard does not persist recipients on drafts. | |
| expectedRevision | No | With 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 and the current server content returned. Omit and the tool compares the server against the local cache instead — omitting never means "send whatever is there now". | |
| deleteDraftOnSuccess | No | Default 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 unverifiable send the draft is ALWAYS kept, regardless of this flag. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructiveHint annotation, the description reveals critical runtime behaviors: the tool re-reads the server version, refuses on revision mismatch or already-sent draft, deletes the source draft only after confirmation, always retains it on failure, and may rewrite replyToId from cache. This is exactly the kind of consequence disclosure an agent needs before invoking an irreversible operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The text is long but tightly organized with SCREAMING-header segments for draft sending, recipients, post-send behavior, fresh compose, and attachments. The irreversibility warning is front-loaded, and every sentence conveys a behavioral rule or condition rather than padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 10-parameter, zero-required-parameter mutation tool with only destructiveHint and no output schema, this definition is exceptionally complete. It describes the response fields (sentMessageId, draftKey, threaded, draftDeleted, draftRetained), success/failure handling, attachment behavior, and the draft deletion guarantee, so an agent has enough context to call it safely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though schema coverage is 100%, the description adds cross-parameter meaning that the schema alone does not carry: draftId and messageId are synonyms, subject/body override only when provided, myFileIDs overrides draft attachments when sending by draftId, and expectedRevision asserts the exact version being sent. It clarifies the interaction between parameters and the guard mechanics, not just individual field types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb and object — 'Send a message via OurFamilyWizard' — and immediately distinguishes this from drafting/saving by framing it as the irreversible, guarded operation. It then lays out two concrete modes (send existing draft vs compose from scratch), so an agent can tell exactly what the tool accomplishes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit usage branches: use draftId/messageId to send an existing draft, no draftId to compose fresh, and states when recipientIds is still required because OFW does not persist recipients. It also explains when to keep the draft via deleteDraftOnSuccess:false and when the send is refused, giving clear conditions for invocation without relying on inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_statusA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | No | Message/draft ids to resolve to a live state (combined with draftKeys, max 25 probes per call). | |
| draftKeys | No | Stable draft keys (from ofw_save_draft / ofw_list_drafts) to resolve to their CURRENT id and state. | |
| allowMarkRead | No | Default 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. Those are skipped unless this is true. Cached drafts, sent messages and already-read messages are always probed. Capped by OFW_ALLOW_MARK_READ. | |
| includeDraftInventory | No | Return 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 false. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description thoroughly discloses behavioral traits: it is a live call that may mutate state (marking messages as read via allowMarkRead, irreversible and co-parent-visible). It explains the verification logic and the meaning of the `complete` flag. This exceeds the annotation's false readOnlyHint by providing concrete details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is comprehensive and front-loaded with purpose, but it is relatively long. However, every sentence adds valuable information without redundancy, so its length is justified. Could be slightly more concise, but it remains efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description adequately explains return fields: state, sentAt, viewedAt, sentMessageId, and the top-level `complete` flag with its condition. It also clarifies edge cases (e.g., draftKeys resolving after sent). This covers all necessary behavioral context for an AI agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the description adds significant meaning beyond schema: it explains the stable identity of draftKeys, why they are needed (OFW creates new IDs on edit), and how they resolve to states. It also clarifies the default behavior of includeDraftInventory and the implications of allowMarkRead.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'ONE live call that answers "where does everything stand?"' and specifies it returns the full current draft inventory verified against OurFamilyWizard, distinguishing it from session memory or cached reads. It also explains the behavior with optional parameters like ids and draftKeys.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context: 'This is the call that should back any status summary about drafts or specific messages — never session memory, and never a cached read alone.' It also explains when to use draftKeys and the allowMarkRead parameter. However, it does not explicitly contrast with sibling tools like ofw_list_drafts or ofw_get_message, which would strengthen the guidelines.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_sync_messagesA
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).
| Name | Required | Description | Default |
|---|---|---|---|
| deep | No | If true, walk every OFW page until empty regardless of cache state. Use to backfill gaps. Default false. | |
| folders | No | Folders to sync (default: all three). Must be non-empty if given — an empty list would sync nothing while reporting success. | |
| maxRequests | No | Maximum 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_REQUESTS, or unbounded on local installs). | |
| fetchUnreadBodies | No | If 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_UNREAD_BODIES env var (false unless set), and is forced off entirely when OFW_ALLOW_MARK_READ=false. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses critical behavioral traits beyond the readOnlyHint annotation: every call re-checks the newest page first, budget-based pausing and resumption, local vs. hosted unbounded behavior, and the irreversible mark-as-read effect of fetchUnreadBodies. This fully informs the agent of side effects and operational constraints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is comprehensive but somewhat verbose for the complexity of the tool. Every sentence is meaningful and well-organized, but some lines could be tightened without losing clarity. Overall, it balances detail with readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers all essential aspects: return values (counts, unread list), budget/resume mechanism, deep parameter for backfilling, mark-as-read implications, and local vs. hosted differences. Missing only minor details like error handling, but the complexity is well-addressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema descriptions cover 100% of parameters, the tool description adds significant context: it explains the budget mechanism for maxRequests, the backfill logic for deep, the mark-as-read implication for fetchUnreadBodies, and the default behavior for folders. This enhances understanding beyond the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool syncs messages from OurFamilyWizard into a local cache and returns counts per folder and a list of unread inbox messages without fetched bodies. It is distinct from sibling tools like ofw_get_message (fetches a specific message) and ofw_list_messages (lists messages), making its purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use this tool versus alternatives (e.g., call ofw_get_message on unread messages not fetched). It explains the bounded and resumable sync behavior, how to handle done:false responses, and the effect of the deep parameter for backfilling. It also warns that done:false does not mean recent messages are missing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_update_eventADestructive
Update an existing OurFamilyWizard calendar event. Fetches the event, applies the given changes, and writes the merged result back (OFW has no partial update).
| Name | Required | Description | Default |
|---|---|---|---|
| notes | No | ||
| title | No | ||
| allDay | No | ||
| endDate | No | End date YYYY-MM-DD (default: startDate) | |
| endTime | No | End time HH:mm, 24-hour (required unless allDay) | |
| eventId | Yes | Event id — the `id` from ofw_list_events / eventRecurrenceId from ofw_create_event | |
| children | No | Child userIds to tag; pass [] to remove all child tags (omit to keep current tags) | |
| location | No | ||
| startDate | No | Start date YYYY-MM-DD | |
| startTime | No | Start time HH:mm, 24-hour (required unless allDay) | |
| privateEvent | No | true = visible only to you; default false = shared with co-parent | |
| eventParentId | No | userId of the parent the event is 'for' | |
| pickUpParentId | No | userId of the pick-up parent | |
| dropOffParentId | No | userId of the drop-off parent | |
| reminderMinutes | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds behavioral context beyond the destructiveHint annotation: it reveals the merge strategy (fetch, apply changes, write back). It does not contradict annotations. It lacks explicit disclosure of required permissions or irreversibility details, but the annotation covers general destructiveness.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences: first states the purpose, second explains the merge behavior. No redundancy, efficient, and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description explains the crucial merge strategy, which is key for correct usage. However, it does not explicitly state that omitted fields retain their current values, nor does it describe the return value (no output schema). For a tool with 15 parameters, this is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 67% schema description coverage, the schema already documents most parameters. The description adds overall context about the merge operation but does not elaborate on individual parameters beyond what's in the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Update an existing OurFamilyWizard calendar event.' It also explains the merge strategy, distinguishing it from create (ofw_create_event) and delete (ofw_delete_event) siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains the fetch-merge-write approach and notes that OFW has no partial update, implying how to use parameters. However, it does not explicitly state when to use this tool versus create or delete, though the context with sibling tools makes it clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ofw_upload_attachmentA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Absolute path to the local file to upload. Tilde (~) is expanded. | |
| label | No | Display label for the file in OFW (default: filename) | |
| shareClass | No | Share class (default PRIVATE) | |
| description | No | Description shown in OFW My Files (default: filename) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses default privacy (PRIVATE), the ability to share via shareClass, and the return value (fileId). Annotations only include destructiveHint: false, so the description adds useful behavioral context, though it omits details like file size limits or synchronous behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the core action and return value. Every sentence adds essential information without redundancy or wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 4 parameters, no output schema, and minimal annotations, the description adequately explains the upload purpose, return value usage, and key parameter behavior. It connects to sibling tools for downstream attachment use. Missing details like error handling or prerequisites are acceptable for this scope.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with clear parameter descriptions, so baseline is 3. The description adds value by noting tilde expansion for path and reinforcing the default shareClass, providing extra semantic guidance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool uploads a local file to OurFamilyWizard's 'My Files' for message attachment, specifies the returned fileId, and distinguishes from sibling tools like ofw_send_message and ofw_save_draft by explaining how the fileId is used.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description tells when to use the tool (before sending or drafting a message) and explains optional parameters like shareClass for sharing with co-parents. It does not list explicit when-not-to-use scenarios, but the context is sufficient given the sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
3 tool updates
v2.15.1- Changed
ofw_get_message1 field changed- added
Input schema / properties / viewAdded value: +{ + "description": "Response 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 duplicates this record's own id, subject, sentAt, recipients and read flag; the sender is promoted to `from`, and `files`/`replied` are kept. Pass \"full\" for the echo.", + "enum": [ + "compact", + "full" + ], + "type": "string" +}
- Changed
ofw_list_drafts1 field changed- added
Input schema / properties / viewAdded value: +{ + "description": "Response 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 duplicates this draft's own id, subject, modifiedAt and recipients. `revision`, `draftKey` and `cacheStatus` are kept on both rungs.", + "enum": [ + "compact", + "full" + ], + "type": "string" +}
- Changed
ofw_list_messages1 field changed- added
Input schema / properties / viewAdded value: +{ + "description": "Response 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 duplicates this record's own id, subject, sentAt, recipients and read flag; the sender is promoted to `from`, and `files`/`replied` are kept. Pass \"full\" for the echo.", + "enum": [ + "compact", + "full" + ], + "type": "string" +}
6 tool updates
v2.14.0- Added
ofw_healthcheck - Changed
ofw_list_drafts1 field changed- added
Input schema / properties / verifyAdded value: +{ + "description": "Default 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 serve straight from the local cache with no OFW requests.", + "type": "boolean" +}
- Changed
ofw_list_expenses1 field changed- changed
Input schema / properties / start / descriptionPrevious value: -"Start offset (default 0)"New value: +"Start offset, 0-based (default 0). To continue a listing, pass the `nextStart` from the previous response."
- Changed
ofw_list_journal_entries1 field changed- changed
Input schema / properties / start / descriptionPrevious value: -"Start offset (default 1)"New value: +"Start offset, 1-based (default 1). To continue a listing, pass the `nextStart` from the previous response."
- Changed
ofw_list_messages1 field changed- added
Input schema / properties / sortAdded value: +{ + "description": "Result 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 \"oldest\" its earliest. Use \"oldest\" to start at the old end of a range instead of paging to it.", + "enum": [ + "newest", + "oldest" + ], + "type": "string" +}
- Changed
ofw_send_message10 fields changed- changed
Input schema / properties / body / descriptionPrevious value: -"Message body text. Required unless messageId/draftId references a cached draft."New value: +"Message 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)." - added
Input schema / properties / deleteDraftOnSuccessAdded value: +{ + "description": "Default 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 unverifiable send the draft is ALWAYS kept, regardless of this flag.", + "type": "boolean" +} - changed
Input schema / properties / draftId / descriptionPrevious value: -"Legacy synonym for messageId. If both are passed they must be equal."New value: +"ID 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 that was already sent/deleted, refuses rather than sending blind." - added
Input schema / properties / expectedRevisionAdded value: +{ + "description": "With 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 and the current server content returned. Omit and the tool compares the server against the local cache instead — omitting never means \"send whatever is there now\".", + "type": "string" +} - added
Input schema / properties / forceAdded value: +{ + "description": "Default 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.", + "type": "boolean" +} - changed
Input schema / properties / messageId / descriptionPrevious value: -"ID of an existing draft to send. When set, missing subject/body/recipientIds default to the draft's cached values, and the draft is deleted after sending."New value: +"Synonym for draftId (if both are passed they must be equal)." - changed
Input schema / properties / myFileIDs / descriptionPrevious value: -"Attachment file ids (from ofw_upload_attachment) to attach to the message"New value: +"Attachment 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." - changed
Input schema / properties / recipientIds / descriptionPrevious value: -"Array of recipient user IDs (get from ofw_get_profile). Required unless messageId/draftId references a cached draft."New value: +"Array of recipient user IDs (get from ofw_get_profile). Usually required even when sending a draft: OurFamilyWizard does not persist recipients on drafts." - changed
Input schema / properties / replyToId / descriptionPrevious value: -"ID of the message being replied to"New value: +"ID of the message being replied to. Defaults to the draft's stored reply target when sending by draftId." - changed
Input schema / properties / subject / descriptionPrevious value: -"Message subject. Required unless messageId/draftId references a cached draft."New value: +"Message subject. Required unless draftId/messageId is given (then it overrides the server draft's subject)."
5 tool updates
v2.9.2- Changed
ofw_check_freshness2 fields changed- changed
Input schema / properties / allowMarkRead / descriptionPrevious value: -"Default false. Probing an id that is NOT a cached draft requires fetching its detail, which marks an unread inbox message as READ on OurFamilyWizard — an irreversible change to the record. Such ids are skipped unless you set this to true."New value: +"Default 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 Viewed\" time — irreversible. Such ids are skipped (reason:\"WOULD_MARK_READ\") unless you set this to true. The server-wide OFW_ALLOW_MARK_READ=false is a ceiling this cannot raise." - changed
Input schema / properties / messageIds / descriptionPrevious value: -"Specific ids to verify against OFW (max 25). By default only ids present in the drafts cache are probed — see allowMarkRead."New value: +"Specific 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 — see allowMarkRead."
- Changed
ofw_get_unread_sent1 field changed- added
Input schema / properties / autoRefreshAdded value: +{ + "description": "If 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 var (false unless set), in which case the call refuses with result:\"UNVERIFIED_EMPTY\" and names the remedy. Costs OFW requests when it fires.", + "type": "boolean" +}
- Changed
ofw_list_drafts1 field changed- added
Input schema / properties / autoRefreshAdded value: +{ + "description": "If 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 var (false unless set), in which case the call refuses with result:\"UNVERIFIED_EMPTY\" and names the remedy. Costs OFW requests when it fires.", + "type": "boolean" +}
- Changed
ofw_list_messages1 field changed- added
Input schema / properties / autoRefreshAdded value: +{ + "description": "If 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 var (false unless set), in which case the call refuses with result:\"UNVERIFIED_EMPTY\" and names the remedy. Costs OFW requests when it fires.", + "type": "boolean" +}
- Added
ofw_status
23 tool updates
v2.8.0- First observed
ofw_check_freshness - First observed
ofw_create_event - First observed
ofw_create_expense - First observed
ofw_create_journal_entry - First observed
ofw_delete_draft - First observed
ofw_delete_event - First observed
ofw_download_attachment - First observed
ofw_get_expense_totals - First observed
ofw_get_message - First observed
ofw_get_notifications - First observed
ofw_get_profile - First observed
ofw_get_unread_sent - First observed
ofw_list_drafts - First observed
ofw_list_events - First observed
ofw_list_expenses - First observed
ofw_list_journal_entries - First observed
ofw_list_message_folders - First observed
ofw_list_messages - First observed
ofw_save_draft - First observed
ofw_send_message - First observed
ofw_sync_messages - First observed
ofw_update_event - First observed
ofw_upload_attachment
TDQS
Most tools target a distinct resource+action pair (events, messages, drafts, expenses, journal), so an agent can usually tell them apart. The small cluster of status/freshness/notification tools overlaps conceptually, but the descriptions differentiate their roles clearly enough.
All tools share the ofw_ prefix and nearly all follow a readable verb_noun pattern such as list_messages, create_event, and save_draft. A few outliers like ofw_status, ofw_healthcheck, and ofw_check_freshness deviate from the pattern, but they are still consistent in style and easy to parse.
25 tools is at the heavy end of the borderline range, though the broad domain—calendar, messages, expenses, journal, profile, and attachments—helps justify the count. The sync/status/freshness helper tools inflate the surface area beyond what the core workflows alone would require.
Calendar events have complete CRUD coverage and the message lifecycle is thoroughly handled, including drafts, sends, sync, and freshness checking. However, expenses and journal entries only support list/create, with no update, delete, or single-get operations, leaving notable lifecycle gaps.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
- QuallaaOAuthcom.quallaa
Talk to your public-facing AI from any MCP client — Claude, ChatGPT, Cursor, Cline, Windsurf.
MCP server unifying ERPs, CRMs, APIs and knowledge base for Claude, ChatGPT and Gemini.
Hosted MCP server for Cliniko — patients, appointments, availability, and invoices for AI agents.
Related MCP Servers
- AlicenseAqualityAmaintenanceA Model Context Protocol server that integrates Google Calendar with Claude Desktop, enabling users to manage calendar events (view, create, update, delete) through natural language.511458MIT
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol (MCP) server that gives Claude access to your WHOOP biometric data — recovery, sleep, strain, and workouts.47MIT
- AlicenseNot gradedqualityAmaintenanceA Model Context Protocol (MCP) server that brings your Withings health data into Claude, allowing natural conversation access to sleep patterns, body measurements, workouts, heart data, and more.41MIT
- AlicenseNot gradedqualityCmaintenanceA Model Context Protocol (MCP) server that connects to ActivityWatch, allowing LLMs like Claude to interact with your time tracking data.4MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/chrischall/ofw-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server