ofw-mcp 2.15.1 → 2.16.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 +5 -0
- package/dist/auth-password.js +7 -3
- package/dist/bundle.js +6728 -2203
- package/dist/client.js +4 -1
- package/dist/index.js +1 -1
- package/dist/protocol.js +35 -0
- package/package.json +3 -3
- package/server.json +2 -2
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "OurFamilyWizard tools for Claude Code",
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.16.0"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"displayName": "OurFamilyWizard",
|
|
15
15
|
"source": "./",
|
|
16
16
|
"description": "OurFamilyWizard co-parenting tools for Claude — messages, calendar, expenses, and journal via MCP",
|
|
17
|
-
"version": "2.
|
|
17
|
+
"version": "2.16.0",
|
|
18
18
|
"author": {
|
|
19
19
|
"name": "Chris Chall"
|
|
20
20
|
},
|
package/README.md
CHANGED
|
@@ -251,6 +251,10 @@ By default nothing changes: reads behave exactly as they always have. Two contro
|
|
|
251
251
|
|
|
252
252
|
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`.
|
|
253
253
|
|
|
254
|
+
### Egress allowlist
|
|
255
|
+
|
|
256
|
+
Every outbound request passes its constructed URL through a host check before `fetch` — the server refuses to contact any host other than `ofw.ourfamilywizard.com`. Today it always passes, and that is the point: it makes "this server only ever talks to OFW" a structural invariant rather than a code-review promise, so a later refactor or a compromised dependency that pointed a request elsewhere throws instead of carrying your bearer token or messages off-host. It is a pre-flight check on the URL we build, not a redirect-following egress filter.
|
|
257
|
+
|
|
254
258
|
## Troubleshooting
|
|
255
259
|
|
|
256
260
|
**"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"*.
|
|
@@ -271,6 +275,7 @@ Calendar events sit between the two message tiers: they have no draft stage (a c
|
|
|
271
275
|
- They are passed to the server as environment variables and never logged
|
|
272
276
|
- The server authenticates with OFW using the same login flow as the web app
|
|
273
277
|
- Use a strong, unique OFW password
|
|
278
|
+
- Outbound requests are host-allowlisted to `ofw.ourfamilywizard.com` (see [Egress allowlist](#egress-allowlist))
|
|
274
279
|
|
|
275
280
|
## Development
|
|
276
281
|
|
package/dist/auth-password.js
CHANGED
|
@@ -9,10 +9,12 @@
|
|
|
9
9
|
// This file exists as a standalone helper (not a method on `OFWClient`) so
|
|
10
10
|
// `resolveAuth()` in `./auth.ts` can call it without a Client instance, and
|
|
11
11
|
// so tests can mock it at the module boundary.
|
|
12
|
-
import { BASE_URL, OFW_PROTOCOL_HEADERS, OFW_TOKEN_TTL_MS } from './protocol.js';
|
|
12
|
+
import { BASE_URL, OFW_PROTOCOL_HEADERS, OFW_TOKEN_TTL_MS, assertOfwUrl } from './protocol.js';
|
|
13
13
|
export async function loginWithPassword(username, password) {
|
|
14
14
|
// Step 1: get a SESSION cookie (Spring Security refuses the POST without it).
|
|
15
|
-
const
|
|
15
|
+
const initUrl = `${BASE_URL}/ofw/login.form`;
|
|
16
|
+
assertOfwUrl(initUrl);
|
|
17
|
+
const initResponse = await fetch(initUrl, {
|
|
16
18
|
headers: { ...OFW_PROTOCOL_HEADERS },
|
|
17
19
|
redirect: 'manual',
|
|
18
20
|
});
|
|
@@ -24,7 +26,9 @@ export async function loginWithPassword(username, password) {
|
|
|
24
26
|
.map((c) => c.split(';')[0])
|
|
25
27
|
.join('; ');
|
|
26
28
|
// Step 2: submit the form.
|
|
27
|
-
const
|
|
29
|
+
const loginUrl = `${BASE_URL}/ofw/login`;
|
|
30
|
+
assertOfwUrl(loginUrl);
|
|
31
|
+
const response = await fetch(loginUrl, {
|
|
28
32
|
method: 'POST',
|
|
29
33
|
headers: {
|
|
30
34
|
...OFW_PROTOCOL_HEADERS,
|