ofw-mcp 2.19.5 → 2.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +24 -1
- package/dist/bundle.js +479 -49
- package/dist/client.js +4 -1
- package/dist/config.js +37 -0
- package/dist/index.js +13 -9
- package/dist/tool-surface.js +14 -0
- package/dist/tools/_shared.js +5 -1
- package/dist/tools/expenses.js +563 -56
- package/package.json +1 -1
- package/server.json +14 -2
- package/skills/ofw/SKILL.md +10 -3
- package/skills/ofw-fpx/references/requests.md +58 -4
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/chrischall/ofw-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.20.0",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "ofw-mcp",
|
|
14
|
-
"version": "2.
|
|
14
|
+
"version": "2.20.0",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|
|
@@ -64,6 +64,18 @@
|
|
|
64
64
|
"description": "Absolute path for the session cache file. Defaults to $MCP_DATA_DIR/.ofw-mcp/session.json.",
|
|
65
65
|
"isRequired": false,
|
|
66
66
|
"format": "string"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "OFW_EXPENSE_ONLY",
|
|
70
|
+
"description": "Set true to register only healthcheck plus expense tools. All profile/dashboard, message, calendar, and journal tools are structurally absent.",
|
|
71
|
+
"isRequired": false,
|
|
72
|
+
"format": "string"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "OFW_EXPENSE_UPLOAD_ONLY",
|
|
76
|
+
"description": "Set true for strict reimbursement upload mode: only healthcheck, ofw_upload_expense_pdf, ofw_create_expense, and ofw_update_expense register. Implies OFW_EXPENSE_ONLY.",
|
|
77
|
+
"isRequired": false,
|
|
78
|
+
"format": "string"
|
|
67
79
|
}
|
|
68
80
|
]
|
|
69
81
|
}
|
package/skills/ofw/SKILL.md
CHANGED
|
@@ -112,12 +112,19 @@ Always pass `--config ~/.mcporter/mcporter.json` unless a local `config/mcporter
|
|
|
112
112
|
| `ofw_update_event(eventId, ...)` | Partial update — only pass fields to change |
|
|
113
113
|
| `ofw_delete_event(eventId)` | Permanent delete |
|
|
114
114
|
|
|
115
|
+
### Restricted expense deployments
|
|
116
|
+
|
|
117
|
+
When `OFW_EXPENSE_ONLY=true`, only the healthcheck and expense tools exist. When `OFW_EXPENSE_UPLOAD_ONLY=true`, only `ofw_healthcheck`, `ofw_upload_expense_pdf`, `ofw_create_expense`, and `ofw_update_expense` exist. Do not suggest message/calendar/journal/profile tools in those deployments; they are structurally unregistered.
|
|
118
|
+
|
|
115
119
|
### Expenses
|
|
116
120
|
| Tool | Notes |
|
|
117
121
|
|------|-------|
|
|
118
122
|
| `ofw_get_expense_totals` | Summary of owed/paid totals |
|
|
119
|
-
| `ofw_list_expenses(
|
|
120
|
-
| `
|
|
123
|
+
| `ofw_list_expenses(page?, size?)` | Paginated (1-based page); default size 20; follow `nextPage` |
|
|
124
|
+
| `ofw_list_expense_categories` | Category ids and split metadata (use the id in create/update) |
|
|
125
|
+
| `ofw_upload_expense_pdf(path \| url, fileName?, label?, description?)` | Upload one receipt PDF to My Files (SHARED, co-parent-visible even on a private expense) for later attachment; confirm-gated; mode `all` only |
|
|
126
|
+
| `ofw_create_expense(title, amount, purchaseDate, categoryId, payerId, children, description?, privateExpense?, receiptFileId?)` | Log a new expense; confirm-gated; optionally private with one receipt |
|
|
127
|
+
| `ofw_update_expense(expenseId, …only the fields to change…)` | Reads the expense and keeps every field you omit; `privateExpense:false` publishes a private expense; `receiptFileId` replaces all receipts, `null` clears it or `description`; refuses as `EXPENSE_FIELDS_UNREADABLE` (naming the fields) rather than erase one it can't read; confirm-gated |
|
|
121
128
|
|
|
122
129
|
### Journal
|
|
123
130
|
| Tool | Notes |
|
|
@@ -166,7 +173,7 @@ Message and draft reads come from a local cache, so **a result can be stale with
|
|
|
166
173
|
|---|---|
|
|
167
174
|
| How old is this data? | `freshness` — `staleness` (`fresh`/`unverified`/`stale`), `asOf`, `ageSeconds`, a quotable `warning` |
|
|
168
175
|
| Is this the WHOLE answer? | `complete` on `ofw_list_messages` / `ofw_list_drafts` / `ofw_get_unread_sent` / `ofw_status` |
|
|
169
|
-
| If not, how do I get the rest? | `nextPage` (message tools) or `nextStart` (`
|
|
176
|
+
| If not, how do I get the rest? | `nextPage` (message tools and `ofw_list_expenses`) or `nextStart` (`ofw_list_journal_entries`) — null means there is no more |
|
|
170
177
|
| Is this entity still what I think it is? | `state` from `ofw_status` / `ofw_check_freshness` |
|
|
171
178
|
|
|
172
179
|
Rules:
|
|
@@ -197,18 +197,72 @@ curl -s -X DELETE "https://ofw.ourfamilywizard.com/pub/v1/calendar/events/${EVEN
|
|
|
197
197
|
curl -s 'https://ofw.ourfamilywizard.com/pub/v2/expense/expenses/totals' "${AUTH_HEADERS[@]}" | jq .
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
-
**List expenses** (
|
|
200
|
+
**List expenses** (page-based, 1-indexed `page`):
|
|
201
|
+
|
|
202
|
+
OFW currently ignores the legacy `start`/`max` query parameters and returns
|
|
203
|
+
page 1 repeatedly. Use `page`/`size` and follow the response metadata's
|
|
204
|
+
`last` flag / `currentPage`.
|
|
205
|
+
|
|
206
|
+
```sh
|
|
207
|
+
curl -s 'https://ofw.ourfamilywizard.com/pub/v2/expense/expenses?page=1&size=20' "${AUTH_HEADERS[@]}" | jq .
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Upload a receipt PDF** (write to My Files). It must be `SHARED` — that is the
|
|
211
|
+
share class OFW accepts in an expense's `fileIds` — and a SHARED file is
|
|
212
|
+
visible to the co-parent in My Files as soon as it lands:
|
|
201
213
|
|
|
202
214
|
```sh
|
|
203
|
-
curl -s 'https://ofw.ourfamilywizard.com/pub/
|
|
215
|
+
curl -s -X POST 'https://ofw.ourfamilywizard.com/pub/v3/myfiles/multipart' \
|
|
216
|
+
"${AUTH_HEADERS[@]}" \
|
|
217
|
+
-F "file=@/path/to/receipt.pdf;type=application/pdf" \
|
|
218
|
+
-F 'source=expense' \
|
|
219
|
+
-F 'description=receipt.pdf' \
|
|
220
|
+
-F 'label=receipt.pdf' \
|
|
221
|
+
-F 'fileName=receipt.pdf' \
|
|
222
|
+
-F 'shared=true' \
|
|
223
|
+
-F 'shareClass=SHARED' | jq .
|
|
204
224
|
```
|
|
205
225
|
|
|
226
|
+
Use the returned `fileId` as `receiptFileId` when creating the expense.
|
|
227
|
+
|
|
206
228
|
**Create an expense** (write):
|
|
207
229
|
|
|
230
|
+
The current OFW expense form requires a complete expense record. In addition to
|
|
231
|
+
the amount, send the expense title, purchase date, category id, parent who owes
|
|
232
|
+
(`payerId`), and at least one child user id. Description, visibility, and a
|
|
233
|
+
single receipt file are optional.
|
|
234
|
+
|
|
235
|
+
```sh
|
|
236
|
+
curl -s -X POST 'https://ofw.ourfamilywizard.com/pub/v2/expense' \
|
|
237
|
+
"${AUTH_HEADERS[@]}" -H 'Content-Type: application/json' \
|
|
238
|
+
--data '{
|
|
239
|
+
"title":"Soccer cleats",
|
|
240
|
+
"amount":45.00,
|
|
241
|
+
"purchaseDate":"2026-09-28",
|
|
242
|
+
"categoryId":1,
|
|
243
|
+
"payerId":<PAYER_USER_ID>,
|
|
244
|
+
"children":[<CHILD_USER_ID>],
|
|
245
|
+
"description":"Cleats for soccer",
|
|
246
|
+
"isPrivate":false,
|
|
247
|
+
"fileIds":[<RECEIPT_FILE_ID>]
|
|
248
|
+
}' | jq .
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Use OFW numeric ids, not display labels, for `categoryId`, `payerId`, and
|
|
252
|
+
`children`. For a private expense (visible only to you), send `isPrivate:true`;
|
|
253
|
+
the MCP tools expose this as `privateExpense`. The MCP tools attach at most one
|
|
254
|
+
receipt, sent as a one-element `fileIds` array.
|
|
255
|
+
|
|
256
|
+
**Update an expense** (write; full payload, not a patch — e.g. publish a
|
|
257
|
+
private expense by sending `isPrivate:false`). A field left out of the PUT is
|
|
258
|
+
erased, so GET the expense first and send back every field you are not
|
|
259
|
+
changing (the MCP's `ofw_update_expense` does this for you):
|
|
260
|
+
|
|
208
261
|
```sh
|
|
209
|
-
curl -s
|
|
262
|
+
curl -s "https://ofw.ourfamilywizard.com/pub/v2/expense/expenses/${EXPENSE_ID}" "${AUTH_HEADERS[@]}" | jq .
|
|
263
|
+
curl -s -X PUT "https://ofw.ourfamilywizard.com/pub/v2/expense/expenses/${EXPENSE_ID}" \
|
|
210
264
|
"${AUTH_HEADERS[@]}" -H 'Content-Type: application/json' \
|
|
211
|
-
--data '{
|
|
265
|
+
--data '{ …every current field…, "isPrivate":false }' | jq .
|
|
212
266
|
```
|
|
213
267
|
|
|
214
268
|
## 8. Journal
|