ofw-mcp 2.0.10 → 2.0.11
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/dist/bundle.js +25 -6
- package/dist/cache.js +10 -4
- package/dist/index.js +1 -1
- package/dist/tools/messages.js +34 -1
- package/package.json +1 -1
- 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.0.
|
|
9
|
+
"version": "2.0.11"
|
|
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.0.
|
|
17
|
+
"version": "2.0.11",
|
|
18
18
|
"author": {
|
|
19
19
|
"name": "Chris Chall"
|
|
20
20
|
},
|
package/dist/bundle.js
CHANGED
|
@@ -31379,12 +31379,14 @@ function listAttachmentsForMessage(messageId) {
|
|
|
31379
31379
|
function upsertAttachmentForMessage(input) {
|
|
31380
31380
|
const { db } = openCache();
|
|
31381
31381
|
const existing = db.prepare("SELECT message_ids_json FROM attachments WHERE file_id = ?").get(input.fileId);
|
|
31382
|
+
const prior = existing ? JSON.parse(existing.message_ids_json) : [];
|
|
31382
31383
|
let messageIds;
|
|
31383
|
-
if (
|
|
31384
|
-
|
|
31385
|
-
|
|
31384
|
+
if (input.messageId === 0) {
|
|
31385
|
+
messageIds = prior;
|
|
31386
|
+
} else if (prior.includes(input.messageId)) {
|
|
31387
|
+
messageIds = prior;
|
|
31386
31388
|
} else {
|
|
31387
|
-
messageIds = [input.messageId];
|
|
31389
|
+
messageIds = [...prior, input.messageId];
|
|
31388
31390
|
}
|
|
31389
31391
|
db.prepare(
|
|
31390
31392
|
`INSERT INTO attachments (
|
|
@@ -31621,6 +31623,13 @@ var MIME_BY_EXT = {
|
|
|
31621
31623
|
function mimeFromName(name) {
|
|
31622
31624
|
return MIME_BY_EXT[extname(name).toLowerCase()] ?? "application/octet-stream";
|
|
31623
31625
|
}
|
|
31626
|
+
function listDataHintsAtFiles(listData) {
|
|
31627
|
+
if (typeof listData !== "object" || listData === null) return false;
|
|
31628
|
+
const ld = listData;
|
|
31629
|
+
if (typeof ld.files === "number") return ld.files > 0;
|
|
31630
|
+
if (Array.isArray(ld.files)) return ld.files.length > 0;
|
|
31631
|
+
return false;
|
|
31632
|
+
}
|
|
31624
31633
|
function registerMessageTools(server2, client2) {
|
|
31625
31634
|
server2.registerTool("ofw_list_message_folders", {
|
|
31626
31635
|
description: "List OurFamilyWizard message folders (inbox, sent, etc.) and their unread counts. Returns folder IDs needed to call ofw_list_messages. Does NOT return message content.",
|
|
@@ -31680,7 +31689,17 @@ function registerMessageTools(server2, client2) {
|
|
|
31680
31689
|
const id = Number(args.messageId);
|
|
31681
31690
|
const cached2 = getMessage(id);
|
|
31682
31691
|
if (cached2 && cached2.body !== null) {
|
|
31683
|
-
|
|
31692
|
+
let attachments2 = listAttachmentsForMessage(id);
|
|
31693
|
+
if (attachments2.length === 0 && listDataHintsAtFiles(cached2.listData)) {
|
|
31694
|
+
try {
|
|
31695
|
+
const detail2 = await client2.request("GET", `/pub/v3/messages/${id}`);
|
|
31696
|
+
if (Array.isArray(detail2.files) && detail2.files.length > 0) {
|
|
31697
|
+
await fetchAttachmentMetaForMessage(client2, id, detail2.files);
|
|
31698
|
+
attachments2 = listAttachmentsForMessage(id);
|
|
31699
|
+
}
|
|
31700
|
+
} catch {
|
|
31701
|
+
}
|
|
31702
|
+
}
|
|
31684
31703
|
return { content: [{ type: "text", text: JSON.stringify({ ...cached2, attachments: attachments2 }, null, 2) }] };
|
|
31685
31704
|
}
|
|
31686
31705
|
const detail = await client2.request("GET", `/pub/v3/messages/${encodeURIComponent(args.messageId)}`);
|
|
@@ -32161,7 +32180,7 @@ process.emit = function(event, ...args) {
|
|
|
32161
32180
|
}
|
|
32162
32181
|
return originalEmit(event, ...args);
|
|
32163
32182
|
};
|
|
32164
|
-
var server = new McpServer({ name: "ofw", version: "2.0.
|
|
32183
|
+
var server = new McpServer({ name: "ofw", version: "2.0.11" });
|
|
32165
32184
|
registerUserTools(server, client);
|
|
32166
32185
|
registerMessageTools(server, client);
|
|
32167
32186
|
registerCalendarTools(server, client);
|
package/dist/cache.js
CHANGED
|
@@ -295,13 +295,19 @@ export function upsertAttachmentForMessage(input) {
|
|
|
295
295
|
const { db } = openCache();
|
|
296
296
|
const existing = db.prepare('SELECT message_ids_json FROM attachments WHERE file_id = ?')
|
|
297
297
|
.get(input.fileId);
|
|
298
|
+
// messageId === 0 is the "metadata-only, not yet linked to a message"
|
|
299
|
+
// sentinel used by upload-without-send and download-by-id. Don't
|
|
300
|
+
// pollute the array with it — leave the list empty / unchanged.
|
|
301
|
+
const prior = existing ? JSON.parse(existing.message_ids_json) : [];
|
|
298
302
|
let messageIds;
|
|
299
|
-
if (
|
|
300
|
-
|
|
301
|
-
|
|
303
|
+
if (input.messageId === 0) {
|
|
304
|
+
messageIds = prior;
|
|
305
|
+
}
|
|
306
|
+
else if (prior.includes(input.messageId)) {
|
|
307
|
+
messageIds = prior;
|
|
302
308
|
}
|
|
303
309
|
else {
|
|
304
|
-
messageIds = [input.messageId];
|
|
310
|
+
messageIds = [...prior, input.messageId];
|
|
305
311
|
}
|
|
306
312
|
db.prepare(`INSERT INTO attachments (
|
|
307
313
|
file_id, file_name, label, mime_type, size_bytes,
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import { registerMessageTools } from './tools/messages.js';
|
|
|
17
17
|
import { registerCalendarTools } from './tools/calendar.js';
|
|
18
18
|
import { registerExpenseTools } from './tools/expenses.js';
|
|
19
19
|
import { registerJournalTools } from './tools/journal.js';
|
|
20
|
-
const server = new McpServer({ name: 'ofw', version: '2.0.
|
|
20
|
+
const server = new McpServer({ name: 'ofw', version: '2.0.11' });
|
|
21
21
|
registerUserTools(server, client);
|
|
22
22
|
registerMessageTools(server, client);
|
|
23
23
|
registerCalendarTools(server, client);
|
package/dist/tools/messages.js
CHANGED
|
@@ -31,6 +31,20 @@ const MIME_BY_EXT = {
|
|
|
31
31
|
function mimeFromName(name) {
|
|
32
32
|
return MIME_BY_EXT[extname(name).toLowerCase()] ?? 'application/octet-stream';
|
|
33
33
|
}
|
|
34
|
+
// The list endpoint payload (cached as `listData`) reports attachments via
|
|
35
|
+
// `files: <count>` (a number) — the actual fileIds only appear on the detail
|
|
36
|
+
// endpoint as `files: [number, ...]`. Some intermediate shapes return an
|
|
37
|
+
// array on the list too. Treat any of those as "this message has files".
|
|
38
|
+
function listDataHintsAtFiles(listData) {
|
|
39
|
+
if (typeof listData !== 'object' || listData === null)
|
|
40
|
+
return false;
|
|
41
|
+
const ld = listData;
|
|
42
|
+
if (typeof ld.files === 'number')
|
|
43
|
+
return ld.files > 0;
|
|
44
|
+
if (Array.isArray(ld.files))
|
|
45
|
+
return ld.files.length > 0;
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
34
48
|
export function registerMessageTools(server, client) {
|
|
35
49
|
server.registerTool('ofw_list_message_folders', {
|
|
36
50
|
description: 'List OurFamilyWizard message folders (inbox, sent, etc.) and their unread counts. Returns folder IDs needed to call ofw_list_messages. Does NOT return message content.',
|
|
@@ -94,7 +108,26 @@ export function registerMessageTools(server, client) {
|
|
|
94
108
|
const id = Number(args.messageId);
|
|
95
109
|
const cached = getMessage(id);
|
|
96
110
|
if (cached && cached.body !== null) {
|
|
97
|
-
|
|
111
|
+
let attachments = listAttachmentsForMessage(id);
|
|
112
|
+
// Lazy attachment backfill. The list-endpoint payload (stored in
|
|
113
|
+
// listData) hints at attachments via `files: <count>` but doesn't
|
|
114
|
+
// expose the fileIds — those live only on /pub/v3/messages/{id}.
|
|
115
|
+
// For messages bodied before attachment caching existed, the
|
|
116
|
+
// attachments table is empty even though OFW has files. Re-hit
|
|
117
|
+
// detail to harvest fileIds (idempotent: body is already cached so
|
|
118
|
+
// OFW state isn't changing).
|
|
119
|
+
if (attachments.length === 0 && listDataHintsAtFiles(cached.listData)) {
|
|
120
|
+
try {
|
|
121
|
+
const detail = await client.request('GET', `/pub/v3/messages/${id}`);
|
|
122
|
+
if (Array.isArray(detail.files) && detail.files.length > 0) {
|
|
123
|
+
await fetchAttachmentMetaForMessage(client, id, detail.files);
|
|
124
|
+
attachments = listAttachmentsForMessage(id);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// Backfill is best-effort. Fall through with whatever we have.
|
|
129
|
+
}
|
|
130
|
+
}
|
|
98
131
|
return { content: [{ type: 'text', text: JSON.stringify({ ...cached, attachments }, null, 2) }] };
|
|
99
132
|
}
|
|
100
133
|
const detail = await client.request('GET', `/pub/v3/messages/${encodeURIComponent(args.messageId)}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ofw-mcp",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.11",
|
|
4
4
|
"mcpName": "io.github.chrischall/ofw-mcp",
|
|
5
5
|
"description": "OurFamilyWizard MCP server for Claude — developed and maintained by AI (Claude Code)",
|
|
6
6
|
"author": "Claude Code (AI) <https://www.anthropic.com/claude>",
|
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.0.
|
|
9
|
+
"version": "2.0.11",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "ofw-mcp",
|
|
14
|
-
"version": "2.0.
|
|
14
|
+
"version": "2.0.11",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|