@knowsuchagency/fulcrum 2.6.5 → 2.6.7
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/README.md +11 -0
- package/bin/fulcrum.js +194 -4
- package/dist/assets/index-Bajq2D5F.css +1 -0
- package/dist/assets/{index-CiL5sLnF.js → index-CabobZ3E.js} +167 -167
- package/dist/index.html +2 -2
- package/drizzle/0051_caldav_tables.sql +38 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +1 -1
- package/server/index.js +5309 -13
- package/dist/assets/index-Dj1Nhi4b.css +0 -1
package/README.md
CHANGED
|
@@ -153,6 +153,17 @@ Create documents with live preview. Generate charts and visualizations. The assi
|
|
|
153
153
|
|
|
154
154
|

|
|
155
155
|
|
|
156
|
+
### Calendar Integration
|
|
157
|
+
|
|
158
|
+
Connect your calendars via CalDAV so the AI assistant knows your schedule. Google Calendar is supported out of the box with OAuth2.
|
|
159
|
+
|
|
160
|
+
- **Google Calendar** — OAuth2 flow, no password needed
|
|
161
|
+
- **Any CalDAV server** — Nextcloud, Radicale, Baikal, iCloud
|
|
162
|
+
- **Automatic sync** — Calendars sync on a configurable interval
|
|
163
|
+
- **Assistant awareness** — The AI assistant uses your calendar context for planning and scheduling
|
|
164
|
+
|
|
165
|
+
Enable in Settings → Calendar Integration.
|
|
166
|
+
|
|
156
167
|
### Messaging Integrations
|
|
157
168
|
|
|
158
169
|
Chat with the AI assistant from anywhere via your favorite messaging platform.
|
package/bin/fulcrum.js
CHANGED
|
@@ -1541,6 +1541,48 @@ class FulcrumClient {
|
|
|
1541
1541
|
body: JSON.stringify(data)
|
|
1542
1542
|
});
|
|
1543
1543
|
}
|
|
1544
|
+
async getCaldavStatus() {
|
|
1545
|
+
return this.fetch("/api/caldav/status");
|
|
1546
|
+
}
|
|
1547
|
+
async listCalendars() {
|
|
1548
|
+
return this.fetch("/api/caldav/calendars");
|
|
1549
|
+
}
|
|
1550
|
+
async syncCalendars() {
|
|
1551
|
+
return this.fetch("/api/caldav/sync", { method: "POST" });
|
|
1552
|
+
}
|
|
1553
|
+
async listCalendarEvents(options) {
|
|
1554
|
+
const params = new URLSearchParams;
|
|
1555
|
+
if (options?.calendarId)
|
|
1556
|
+
params.set("calendarId", options.calendarId);
|
|
1557
|
+
if (options?.from)
|
|
1558
|
+
params.set("from", options.from);
|
|
1559
|
+
if (options?.to)
|
|
1560
|
+
params.set("to", options.to);
|
|
1561
|
+
if (options?.limit)
|
|
1562
|
+
params.set("limit", String(options.limit));
|
|
1563
|
+
const query = params.toString();
|
|
1564
|
+
return this.fetch(`/api/caldav/events${query ? `?${query}` : ""}`);
|
|
1565
|
+
}
|
|
1566
|
+
async getCalendarEvent(id) {
|
|
1567
|
+
return this.fetch(`/api/caldav/events/${id}`);
|
|
1568
|
+
}
|
|
1569
|
+
async createCalendarEvent(input) {
|
|
1570
|
+
return this.fetch("/api/caldav/events", {
|
|
1571
|
+
method: "POST",
|
|
1572
|
+
body: JSON.stringify(input)
|
|
1573
|
+
});
|
|
1574
|
+
}
|
|
1575
|
+
async updateCalendarEvent(id, updates) {
|
|
1576
|
+
return this.fetch(`/api/caldav/events/${id}`, {
|
|
1577
|
+
method: "PATCH",
|
|
1578
|
+
body: JSON.stringify(updates)
|
|
1579
|
+
});
|
|
1580
|
+
}
|
|
1581
|
+
async deleteCalendarEvent(id) {
|
|
1582
|
+
return this.fetch(`/api/caldav/events/${id}`, {
|
|
1583
|
+
method: "DELETE"
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1544
1586
|
async getAssistantStats() {
|
|
1545
1587
|
return this.fetch("/api/assistant/stats");
|
|
1546
1588
|
}
|
|
@@ -43378,7 +43420,8 @@ var init_types4 = __esm(() => {
|
|
|
43378
43420
|
"backup",
|
|
43379
43421
|
"email",
|
|
43380
43422
|
"messaging",
|
|
43381
|
-
"assistant"
|
|
43423
|
+
"assistant",
|
|
43424
|
+
"caldav"
|
|
43382
43425
|
]);
|
|
43383
43426
|
AgentTypeSchema = exports_external.enum(["claude", "opencode"]);
|
|
43384
43427
|
});
|
|
@@ -44081,6 +44124,55 @@ var init_registry = __esm(() => {
|
|
|
44081
44124
|
category: "assistant",
|
|
44082
44125
|
keywords: ["sweep", "last", "hourly", "morning", "evening", "ritual"],
|
|
44083
44126
|
defer_loading: false
|
|
44127
|
+
},
|
|
44128
|
+
{
|
|
44129
|
+
name: "list_calendars",
|
|
44130
|
+
description: "List all CalDAV calendars synced from the configured server",
|
|
44131
|
+
category: "caldav",
|
|
44132
|
+
keywords: ["calendar", "caldav", "list", "schedule"],
|
|
44133
|
+
defer_loading: true
|
|
44134
|
+
},
|
|
44135
|
+
{
|
|
44136
|
+
name: "sync_calendars",
|
|
44137
|
+
description: "Trigger a manual sync of all CalDAV calendars and events",
|
|
44138
|
+
category: "caldav",
|
|
44139
|
+
keywords: ["calendar", "caldav", "sync", "refresh", "update"],
|
|
44140
|
+
defer_loading: true
|
|
44141
|
+
},
|
|
44142
|
+
{
|
|
44143
|
+
name: "list_calendar_events",
|
|
44144
|
+
description: "List calendar events with optional filtering by calendar, date range, or limit",
|
|
44145
|
+
category: "caldav",
|
|
44146
|
+
keywords: ["calendar", "event", "list", "schedule", "appointment", "meeting"],
|
|
44147
|
+
defer_loading: true
|
|
44148
|
+
},
|
|
44149
|
+
{
|
|
44150
|
+
name: "get_calendar_event",
|
|
44151
|
+
description: "Get details of a specific calendar event by ID",
|
|
44152
|
+
category: "caldav",
|
|
44153
|
+
keywords: ["calendar", "event", "get", "details", "appointment"],
|
|
44154
|
+
defer_loading: true
|
|
44155
|
+
},
|
|
44156
|
+
{
|
|
44157
|
+
name: "create_calendar_event",
|
|
44158
|
+
description: "Create a new calendar event on a CalDAV calendar",
|
|
44159
|
+
category: "caldav",
|
|
44160
|
+
keywords: ["calendar", "event", "create", "new", "schedule", "appointment", "meeting"],
|
|
44161
|
+
defer_loading: true
|
|
44162
|
+
},
|
|
44163
|
+
{
|
|
44164
|
+
name: "update_calendar_event",
|
|
44165
|
+
description: "Update an existing calendar event",
|
|
44166
|
+
category: "caldav",
|
|
44167
|
+
keywords: ["calendar", "event", "update", "edit", "modify", "reschedule"],
|
|
44168
|
+
defer_loading: true
|
|
44169
|
+
},
|
|
44170
|
+
{
|
|
44171
|
+
name: "delete_calendar_event",
|
|
44172
|
+
description: "Delete a calendar event",
|
|
44173
|
+
category: "caldav",
|
|
44174
|
+
keywords: ["calendar", "event", "delete", "remove", "cancel"],
|
|
44175
|
+
defer_loading: true
|
|
44084
44176
|
}
|
|
44085
44177
|
];
|
|
44086
44178
|
});
|
|
@@ -45595,6 +45687,101 @@ var init_assistant_events = __esm(() => {
|
|
|
45595
45687
|
ChannelSchema = exports_external.enum(["email", "whatsapp", "discord", "telegram", "slack", "all"]);
|
|
45596
45688
|
});
|
|
45597
45689
|
|
|
45690
|
+
// cli/src/mcp/tools/caldav.ts
|
|
45691
|
+
var registerCaldavTools = (server, client) => {
|
|
45692
|
+
server.tool("list_calendars", "List all CalDAV calendars synced from the configured server.", {}, async () => {
|
|
45693
|
+
try {
|
|
45694
|
+
const calendars = await client.listCalendars();
|
|
45695
|
+
return formatSuccess(calendars);
|
|
45696
|
+
} catch (err) {
|
|
45697
|
+
return handleToolError(err);
|
|
45698
|
+
}
|
|
45699
|
+
});
|
|
45700
|
+
server.tool("sync_calendars", "Trigger a manual sync of all CalDAV calendars and events from the server.", {}, async () => {
|
|
45701
|
+
try {
|
|
45702
|
+
const result = await client.syncCalendars();
|
|
45703
|
+
return formatSuccess(result);
|
|
45704
|
+
} catch (err) {
|
|
45705
|
+
return handleToolError(err);
|
|
45706
|
+
}
|
|
45707
|
+
});
|
|
45708
|
+
server.tool("list_calendar_events", "List calendar events with optional filtering by calendar, date range, or limit.", {
|
|
45709
|
+
calendarId: exports_external.optional(exports_external.string()).describe("Filter by calendar ID"),
|
|
45710
|
+
from: exports_external.optional(exports_external.string()).describe("Start date filter (ISO format or iCal date)"),
|
|
45711
|
+
to: exports_external.optional(exports_external.string()).describe("End date filter (ISO format or iCal date)"),
|
|
45712
|
+
limit: exports_external.optional(exports_external.number()).describe("Maximum events to return")
|
|
45713
|
+
}, async ({ calendarId, from, to, limit }) => {
|
|
45714
|
+
try {
|
|
45715
|
+
const events = await client.listCalendarEvents({ calendarId, from, to, limit });
|
|
45716
|
+
return formatSuccess(events);
|
|
45717
|
+
} catch (err) {
|
|
45718
|
+
return handleToolError(err);
|
|
45719
|
+
}
|
|
45720
|
+
});
|
|
45721
|
+
server.tool("get_calendar_event", "Get details of a specific calendar event by ID.", {
|
|
45722
|
+
id: exports_external.string().describe("Event ID")
|
|
45723
|
+
}, async ({ id }) => {
|
|
45724
|
+
try {
|
|
45725
|
+
const event = await client.getCalendarEvent(id);
|
|
45726
|
+
return formatSuccess(event);
|
|
45727
|
+
} catch (err) {
|
|
45728
|
+
return handleToolError(err);
|
|
45729
|
+
}
|
|
45730
|
+
});
|
|
45731
|
+
server.tool("create_calendar_event", "Create a new calendar event on a CalDAV calendar.", {
|
|
45732
|
+
calendarId: exports_external.string().describe("Calendar ID to create the event in"),
|
|
45733
|
+
summary: exports_external.string().describe("Event title/summary"),
|
|
45734
|
+
dtstart: exports_external.string().describe("Start date/time (iCal format: 20250115T090000Z or 20250115 for all-day)"),
|
|
45735
|
+
dtend: exports_external.optional(exports_external.string()).describe("End date/time (iCal format)"),
|
|
45736
|
+
duration: exports_external.optional(exports_external.string()).describe("Duration (iCal format, e.g., PT1H for 1 hour)"),
|
|
45737
|
+
description: exports_external.optional(exports_external.string()).describe("Event description"),
|
|
45738
|
+
location: exports_external.optional(exports_external.string()).describe("Event location"),
|
|
45739
|
+
allDay: exports_external.optional(exports_external.boolean()).describe("Whether this is an all-day event"),
|
|
45740
|
+
recurrenceRule: exports_external.optional(exports_external.string()).describe("Recurrence rule (RRULE format)"),
|
|
45741
|
+
status: exports_external.optional(exports_external.string()).describe("Event status (TENTATIVE, CONFIRMED, CANCELLED)")
|
|
45742
|
+
}, async (input) => {
|
|
45743
|
+
try {
|
|
45744
|
+
const event = await client.createCalendarEvent(input);
|
|
45745
|
+
return formatSuccess(event);
|
|
45746
|
+
} catch (err) {
|
|
45747
|
+
return handleToolError(err);
|
|
45748
|
+
}
|
|
45749
|
+
});
|
|
45750
|
+
server.tool("update_calendar_event", "Update an existing calendar event.", {
|
|
45751
|
+
id: exports_external.string().describe("Event ID to update"),
|
|
45752
|
+
summary: exports_external.optional(exports_external.string()).describe("New event title/summary"),
|
|
45753
|
+
dtstart: exports_external.optional(exports_external.string()).describe("New start date/time"),
|
|
45754
|
+
dtend: exports_external.optional(exports_external.string()).describe("New end date/time"),
|
|
45755
|
+
duration: exports_external.optional(exports_external.string()).describe("New duration"),
|
|
45756
|
+
description: exports_external.optional(exports_external.string()).describe("New description"),
|
|
45757
|
+
location: exports_external.optional(exports_external.string()).describe("New location"),
|
|
45758
|
+
allDay: exports_external.optional(exports_external.boolean()).describe("Whether this is an all-day event"),
|
|
45759
|
+
recurrenceRule: exports_external.optional(exports_external.string()).describe("New recurrence rule"),
|
|
45760
|
+
status: exports_external.optional(exports_external.string()).describe("New status")
|
|
45761
|
+
}, async ({ id, ...updates }) => {
|
|
45762
|
+
try {
|
|
45763
|
+
const event = await client.updateCalendarEvent(id, updates);
|
|
45764
|
+
return formatSuccess(event);
|
|
45765
|
+
} catch (err) {
|
|
45766
|
+
return handleToolError(err);
|
|
45767
|
+
}
|
|
45768
|
+
});
|
|
45769
|
+
server.tool("delete_calendar_event", "Delete a calendar event from the CalDAV server.", {
|
|
45770
|
+
id: exports_external.string().describe("Event ID to delete")
|
|
45771
|
+
}, async ({ id }) => {
|
|
45772
|
+
try {
|
|
45773
|
+
const result = await client.deleteCalendarEvent(id);
|
|
45774
|
+
return formatSuccess(result);
|
|
45775
|
+
} catch (err) {
|
|
45776
|
+
return handleToolError(err);
|
|
45777
|
+
}
|
|
45778
|
+
});
|
|
45779
|
+
};
|
|
45780
|
+
var init_caldav = __esm(() => {
|
|
45781
|
+
init_zod2();
|
|
45782
|
+
init_utils();
|
|
45783
|
+
});
|
|
45784
|
+
|
|
45598
45785
|
// cli/src/mcp/tools/index.ts
|
|
45599
45786
|
function registerTools(server, client) {
|
|
45600
45787
|
registerCoreTools(server, client);
|
|
@@ -45609,6 +45796,7 @@ function registerTools(server, client) {
|
|
|
45609
45796
|
registerBackupTools(server, client);
|
|
45610
45797
|
registerEmailTools(server, client);
|
|
45611
45798
|
registerAssistantEventTools(server, client);
|
|
45799
|
+
registerCaldavTools(server, client);
|
|
45612
45800
|
}
|
|
45613
45801
|
var init_tools = __esm(() => {
|
|
45614
45802
|
init_core5();
|
|
@@ -45623,6 +45811,7 @@ var init_tools = __esm(() => {
|
|
|
45623
45811
|
init_backup();
|
|
45624
45812
|
init_email();
|
|
45625
45813
|
init_assistant_events();
|
|
45814
|
+
init_caldav();
|
|
45626
45815
|
init_types4();
|
|
45627
45816
|
});
|
|
45628
45817
|
|
|
@@ -45641,7 +45830,7 @@ async function runMcpServer(urlOverride, portOverride) {
|
|
|
45641
45830
|
const client = new FulcrumClient(urlOverride, portOverride);
|
|
45642
45831
|
const server = new McpServer({
|
|
45643
45832
|
name: "fulcrum",
|
|
45644
|
-
version: "2.6.
|
|
45833
|
+
version: "2.6.7"
|
|
45645
45834
|
});
|
|
45646
45835
|
registerTools(server, client);
|
|
45647
45836
|
const transport = new StdioServerTransport;
|
|
@@ -47990,7 +48179,7 @@ var marketplace_default = `{
|
|
|
47990
48179
|
"name": "fulcrum",
|
|
47991
48180
|
"source": "./",
|
|
47992
48181
|
"description": "Task orchestration for Claude Code",
|
|
47993
|
-
"version": "2.6.
|
|
48182
|
+
"version": "2.6.7",
|
|
47994
48183
|
"skills": [
|
|
47995
48184
|
"./skills/fulcrum"
|
|
47996
48185
|
],
|
|
@@ -49178,7 +49367,7 @@ function compareVersions(v1, v2) {
|
|
|
49178
49367
|
var package_default = {
|
|
49179
49368
|
name: "@knowsuchagency/fulcrum",
|
|
49180
49369
|
private: true,
|
|
49181
|
-
version: "2.6.
|
|
49370
|
+
version: "2.6.7",
|
|
49182
49371
|
description: "Harness Attention. Orchestrate Agents. Ship.",
|
|
49183
49372
|
license: "PolyForm-Perimeter-1.0.0",
|
|
49184
49373
|
type: "module",
|
|
@@ -49258,6 +49447,7 @@ var package_default = {
|
|
|
49258
49447
|
sonner: "^2.0.7",
|
|
49259
49448
|
"tailwind-merge": "^3.4.0",
|
|
49260
49449
|
tailwindcss: "^4.1.17",
|
|
49450
|
+
tsdav: "^2.1.6",
|
|
49261
49451
|
"tw-animate-css": "^1.4.0",
|
|
49262
49452
|
ws: "^8.18.3",
|
|
49263
49453
|
yaml: "^2.8.2"
|