@knowsuchagency/fulcrum 2.9.0 → 2.10.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/README.md CHANGED
@@ -156,11 +156,13 @@ Create documents with live preview. Generate charts and visualizations. The assi
156
156
 
157
157
  ### Calendar Integration
158
158
 
159
- Connect your calendars via CalDAV so the AI assistant knows your schedule. Google Calendar is supported out of the box with OAuth2.
159
+ Connect multiple calendar accounts via CalDAV so the AI assistant knows your schedule. Copy events between calendars across accounts.
160
160
 
161
+ - **Multiple accounts** — Add as many CalDAV accounts as you need
161
162
  - **Google Calendar** — OAuth2 flow, no password needed
162
163
  - **Any CalDAV server** — Nextcloud, Radicale, Baikal, iCloud
163
- - **Automatic sync** — Calendars sync on a configurable interval
164
+ - **Automatic sync** — Each account syncs independently on a configurable interval
165
+ - **One-way event copying** — Copy events between calendars across accounts via configurable rules
164
166
  - **Assistant awareness** — The AI assistant uses your calendar context for planning and scheduling
165
167
 
166
168
  Enable in Settings → Calendar Integration.
@@ -247,6 +249,7 @@ Both plugins include an MCP server with 60+ tools:
247
249
  | **Backup & Restore** | Snapshot database and settings; auto-safety-backup on restore |
248
250
  | **Settings** | View and update configuration; manage notification channels |
249
251
  | **Memory** | Store and search persistent knowledge with FTS5 full-text search |
252
+ | **Calendar** | Manage CalDAV accounts, sync calendars, configure event copy rules |
250
253
  | **Assistant** | Send messages via channels; query sweep history |
251
254
 
252
255
  Use `search_tools` to discover available tools by keyword or category.
package/bin/fulcrum.js CHANGED
@@ -1518,8 +1518,39 @@ class FulcrumClient {
1518
1518
  async getCaldavStatus() {
1519
1519
  return this.fetch("/api/caldav/status");
1520
1520
  }
1521
- async listCalendars() {
1522
- return this.fetch("/api/caldav/calendars");
1521
+ async listCalendars(accountId) {
1522
+ const params = accountId ? `?accountId=${accountId}` : "";
1523
+ return this.fetch(`/api/caldav/calendars${params}`);
1524
+ }
1525
+ async listCaldavAccounts() {
1526
+ return this.fetch("/api/caldav/accounts");
1527
+ }
1528
+ async createCaldavAccount(input) {
1529
+ return this.fetch("/api/caldav/accounts", {
1530
+ method: "POST",
1531
+ body: JSON.stringify(input)
1532
+ });
1533
+ }
1534
+ async deleteCaldavAccount(id) {
1535
+ return this.fetch(`/api/caldav/accounts/${id}`, { method: "DELETE" });
1536
+ }
1537
+ async syncCaldavAccount(id) {
1538
+ return this.fetch(`/api/caldav/accounts/${id}/sync`, { method: "POST" });
1539
+ }
1540
+ async listCaldavCopyRules() {
1541
+ return this.fetch("/api/caldav/copy-rules");
1542
+ }
1543
+ async createCaldavCopyRule(input) {
1544
+ return this.fetch("/api/caldav/copy-rules", {
1545
+ method: "POST",
1546
+ body: JSON.stringify(input)
1547
+ });
1548
+ }
1549
+ async deleteCaldavCopyRule(id) {
1550
+ return this.fetch(`/api/caldav/copy-rules/${id}`, { method: "DELETE" });
1551
+ }
1552
+ async executeCaldavCopyRule(id) {
1553
+ return this.fetch(`/api/caldav/copy-rules/${id}/execute`, { method: "POST" });
1523
1554
  }
1524
1555
  async syncCalendars() {
1525
1556
  return this.fetch("/api/caldav/sync", { method: "POST" });
@@ -44097,6 +44128,62 @@ var init_registry = __esm(() => {
44097
44128
  keywords: ["sweep", "last", "hourly", "morning", "evening", "ritual"],
44098
44129
  defer_loading: false
44099
44130
  },
44131
+ {
44132
+ name: "list_caldav_accounts",
44133
+ description: "List all CalDAV accounts configured for calendar sync",
44134
+ category: "caldav",
44135
+ keywords: ["caldav", "account", "list", "calendar", "google", "nextcloud"],
44136
+ defer_loading: true
44137
+ },
44138
+ {
44139
+ name: "create_caldav_account",
44140
+ description: "Create a new CalDAV account with basic authentication",
44141
+ category: "caldav",
44142
+ keywords: ["caldav", "account", "create", "add", "calendar", "connect"],
44143
+ defer_loading: true
44144
+ },
44145
+ {
44146
+ name: "delete_caldav_account",
44147
+ description: "Delete a CalDAV account and all its calendars and events",
44148
+ category: "caldav",
44149
+ keywords: ["caldav", "account", "delete", "remove", "disconnect"],
44150
+ defer_loading: true
44151
+ },
44152
+ {
44153
+ name: "sync_caldav_account",
44154
+ description: "Trigger a manual sync for a specific CalDAV account",
44155
+ category: "caldav",
44156
+ keywords: ["caldav", "account", "sync", "refresh", "calendar"],
44157
+ defer_loading: true
44158
+ },
44159
+ {
44160
+ name: "list_caldav_copy_rules",
44161
+ description: "List all CalDAV copy rules for one-way event replication between calendars",
44162
+ category: "caldav",
44163
+ keywords: ["caldav", "copy", "rule", "list", "replicate", "sync", "calendar"],
44164
+ defer_loading: true
44165
+ },
44166
+ {
44167
+ name: "create_caldav_copy_rule",
44168
+ description: "Create a copy rule to replicate events from one calendar to another",
44169
+ category: "caldav",
44170
+ keywords: ["caldav", "copy", "rule", "create", "replicate", "calendar"],
44171
+ defer_loading: true
44172
+ },
44173
+ {
44174
+ name: "delete_caldav_copy_rule",
44175
+ description: "Delete a CalDAV copy rule",
44176
+ category: "caldav",
44177
+ keywords: ["caldav", "copy", "rule", "delete", "remove"],
44178
+ defer_loading: true
44179
+ },
44180
+ {
44181
+ name: "execute_caldav_copy_rule",
44182
+ description: "Manually execute a copy rule to replicate events now",
44183
+ category: "caldav",
44184
+ keywords: ["caldav", "copy", "rule", "execute", "run", "replicate"],
44185
+ defer_loading: true
44186
+ },
44100
44187
  {
44101
44188
  name: "list_calendars",
44102
44189
  description: "List all CalDAV calendars synced from the configured server",
@@ -45611,9 +45698,93 @@ var init_assistant = __esm(() => {
45611
45698
 
45612
45699
  // cli/src/mcp/tools/caldav.ts
45613
45700
  var registerCaldavTools = (server, client) => {
45614
- server.tool("list_calendars", "List all CalDAV calendars synced from the configured server.", {}, async () => {
45701
+ server.tool("list_caldav_accounts", "List all CalDAV accounts configured for calendar sync.", {}, async () => {
45702
+ try {
45703
+ const accounts = await client.listCaldavAccounts();
45704
+ return formatSuccess(accounts);
45705
+ } catch (err) {
45706
+ return handleToolError(err);
45707
+ }
45708
+ });
45709
+ server.tool("create_caldav_account", "Create a new CalDAV account with basic authentication.", {
45710
+ name: exports_external.string().describe("Display name for the account"),
45711
+ serverUrl: exports_external.string().describe("CalDAV server URL"),
45712
+ username: exports_external.string().describe("Username for authentication"),
45713
+ password: exports_external.string().describe("Password for authentication"),
45714
+ syncIntervalMinutes: exports_external.optional(exports_external.number()).describe("Sync interval in minutes (default: 15)")
45715
+ }, async (input) => {
45716
+ try {
45717
+ const account = await client.createCaldavAccount(input);
45718
+ return formatSuccess(account);
45719
+ } catch (err) {
45720
+ return handleToolError(err);
45721
+ }
45722
+ });
45723
+ server.tool("delete_caldav_account", "Delete a CalDAV account and all its calendars and events.", {
45724
+ id: exports_external.string().describe("Account ID to delete")
45725
+ }, async ({ id }) => {
45726
+ try {
45727
+ const result = await client.deleteCaldavAccount(id);
45728
+ return formatSuccess(result);
45729
+ } catch (err) {
45730
+ return handleToolError(err);
45731
+ }
45732
+ });
45733
+ server.tool("sync_caldav_account", "Trigger a manual sync for a specific CalDAV account.", {
45734
+ id: exports_external.string().describe("Account ID to sync")
45735
+ }, async ({ id }) => {
45736
+ try {
45737
+ const result = await client.syncCaldavAccount(id);
45738
+ return formatSuccess(result);
45739
+ } catch (err) {
45740
+ return handleToolError(err);
45741
+ }
45742
+ });
45743
+ server.tool("list_caldav_copy_rules", "List all CalDAV copy rules for one-way event replication between calendars.", {}, async () => {
45744
+ try {
45745
+ const rules = await client.listCaldavCopyRules();
45746
+ return formatSuccess(rules);
45747
+ } catch (err) {
45748
+ return handleToolError(err);
45749
+ }
45750
+ });
45751
+ server.tool("create_caldav_copy_rule", "Create a copy rule to replicate events from one calendar to another.", {
45752
+ sourceCalendarId: exports_external.string().describe("Source calendar ID"),
45753
+ destCalendarId: exports_external.string().describe("Destination calendar ID"),
45754
+ name: exports_external.optional(exports_external.string()).describe("Optional label for the rule")
45755
+ }, async (input) => {
45756
+ try {
45757
+ const rule = await client.createCaldavCopyRule(input);
45758
+ return formatSuccess(rule);
45759
+ } catch (err) {
45760
+ return handleToolError(err);
45761
+ }
45762
+ });
45763
+ server.tool("delete_caldav_copy_rule", "Delete a CalDAV copy rule.", {
45764
+ id: exports_external.string().describe("Copy rule ID to delete")
45765
+ }, async ({ id }) => {
45766
+ try {
45767
+ const result = await client.deleteCaldavCopyRule(id);
45768
+ return formatSuccess(result);
45769
+ } catch (err) {
45770
+ return handleToolError(err);
45771
+ }
45772
+ });
45773
+ server.tool("execute_caldav_copy_rule", "Manually execute a copy rule to replicate events now.", {
45774
+ id: exports_external.string().describe("Copy rule ID to execute")
45775
+ }, async ({ id }) => {
45776
+ try {
45777
+ const result = await client.executeCaldavCopyRule(id);
45778
+ return formatSuccess(result);
45779
+ } catch (err) {
45780
+ return handleToolError(err);
45781
+ }
45782
+ });
45783
+ server.tool("list_calendars", "List all CalDAV calendars synced from the configured server.", {
45784
+ accountId: exports_external.optional(exports_external.string()).describe("Filter by account ID")
45785
+ }, async ({ accountId }) => {
45615
45786
  try {
45616
- const calendars = await client.listCalendars();
45787
+ const calendars = await client.listCalendars(accountId);
45617
45788
  return formatSuccess(calendars);
45618
45789
  } catch (err) {
45619
45790
  return handleToolError(err);
@@ -45800,7 +45971,7 @@ async function runMcpServer(urlOverride, portOverride) {
45800
45971
  const client = new FulcrumClient(urlOverride, portOverride);
45801
45972
  const server = new McpServer({
45802
45973
  name: "fulcrum",
45803
- version: "2.9.0"
45974
+ version: "2.10.0"
45804
45975
  });
45805
45976
  registerTools(server, client);
45806
45977
  const transport = new StdioServerTransport;
@@ -48149,7 +48320,7 @@ var marketplace_default = `{
48149
48320
  "name": "fulcrum",
48150
48321
  "source": "./",
48151
48322
  "description": "Task orchestration for Claude Code",
48152
- "version": "2.9.0",
48323
+ "version": "2.10.0",
48153
48324
  "skills": [
48154
48325
  "./skills/fulcrum"
48155
48326
  ],
@@ -49337,7 +49508,7 @@ function compareVersions(v1, v2) {
49337
49508
  var package_default = {
49338
49509
  name: "@knowsuchagency/fulcrum",
49339
49510
  private: true,
49340
- version: "2.9.0",
49511
+ version: "2.10.0",
49341
49512
  description: "Harness Attention. Orchestrate Agents. Ship.",
49342
49513
  license: "PolyForm-Perimeter-1.0.0",
49343
49514
  type: "module",