@nimbus-dev/connectors 0.1.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.
Files changed (301) hide show
  1. package/LICENSE +662 -0
  2. package/NOTICE +40 -0
  3. package/README.md +111 -0
  4. package/connectors/airflow/nimbus.extension.json +16 -0
  5. package/connectors/airflow/src/search-filter.ts +38 -0
  6. package/connectors/airflow/src/server.ts +91 -0
  7. package/connectors/apple/nimbus.extension.json +40 -0
  8. package/connectors/apple/src/apple-mail-core.ts +43 -0
  9. package/connectors/apple/src/caldav-core.ts +116 -0
  10. package/connectors/apple/src/calendar-tools.ts +278 -0
  11. package/connectors/apple/src/server.ts +541 -0
  12. package/connectors/apple/src/tools.ts +138 -0
  13. package/connectors/argocd/nimbus.extension.json +16 -0
  14. package/connectors/argocd/src/search-filter.ts +24 -0
  15. package/connectors/argocd/src/server.ts +158 -0
  16. package/connectors/athena/nimbus.extension.json +15 -0
  17. package/connectors/athena/src/server.ts +6 -0
  18. package/connectors/athena/src/tools.ts +181 -0
  19. package/connectors/aws/nimbus.extension.json +21 -0
  20. package/connectors/aws/src/server.ts +191 -0
  21. package/connectors/azure/nimbus.extension.json +15 -0
  22. package/connectors/azure/src/server.ts +139 -0
  23. package/connectors/bigeye/nimbus.extension.json +16 -0
  24. package/connectors/bigeye/src/search-filter.ts +22 -0
  25. package/connectors/bigeye/src/server.ts +161 -0
  26. package/connectors/bigquery/nimbus.extension.json +15 -0
  27. package/connectors/bigquery/src/server.ts +6 -0
  28. package/connectors/bigquery/src/tools.ts +175 -0
  29. package/connectors/bitbucket/nimbus.extension.json +15 -0
  30. package/connectors/bitbucket/src/server.ts +252 -0
  31. package/connectors/bitrise/nimbus.extension.json +15 -0
  32. package/connectors/bitrise/src/search-filter.ts +11 -0
  33. package/connectors/bitrise/src/server.ts +83 -0
  34. package/connectors/canva/nimbus.extension.json +15 -0
  35. package/connectors/canva/src/search-filter.ts +23 -0
  36. package/connectors/canva/src/server.ts +77 -0
  37. package/connectors/circleci/nimbus.extension.json +15 -0
  38. package/connectors/circleci/src/server.ts +184 -0
  39. package/connectors/cloud-logging/nimbus.extension.json +15 -0
  40. package/connectors/cloud-logging/src/server.ts +6 -0
  41. package/connectors/cloud-logging/src/tools.ts +115 -0
  42. package/connectors/cloudwatch/nimbus.extension.json +15 -0
  43. package/connectors/cloudwatch/src/server.ts +6 -0
  44. package/connectors/cloudwatch/src/tools.ts +144 -0
  45. package/connectors/codemagic/nimbus.extension.json +15 -0
  46. package/connectors/codemagic/src/search-filter.ts +11 -0
  47. package/connectors/codemagic/src/server.ts +74 -0
  48. package/connectors/confluence/nimbus.extension.json +15 -0
  49. package/connectors/confluence/src/kb-append.ts +25 -0
  50. package/connectors/confluence/src/server.ts +309 -0
  51. package/connectors/dagster/nimbus.extension.json +16 -0
  52. package/connectors/dagster/src/search-filter.ts +53 -0
  53. package/connectors/dagster/src/server.ts +218 -0
  54. package/connectors/databricks/nimbus.extension.json +16 -0
  55. package/connectors/databricks/src/search-filter.ts +28 -0
  56. package/connectors/databricks/src/server.ts +81 -0
  57. package/connectors/datadog/nimbus.extension.json +15 -0
  58. package/connectors/datadog/src/server.ts +56 -0
  59. package/connectors/dataprofile/nimbus.extension.json +16 -0
  60. package/connectors/dataprofile/src/profile.ts +298 -0
  61. package/connectors/dataprofile/src/server.ts +6 -0
  62. package/connectors/dataprofile/src/tools.ts +69 -0
  63. package/connectors/dbt/nimbus.extension.json +16 -0
  64. package/connectors/dbt/src/search-filter.ts +28 -0
  65. package/connectors/dbt/src/server.ts +96 -0
  66. package/connectors/dependencytrack/nimbus.extension.json +16 -0
  67. package/connectors/dependencytrack/src/search-filter.ts +24 -0
  68. package/connectors/dependencytrack/src/server.ts +80 -0
  69. package/connectors/discord/nimbus.extension.json +15 -0
  70. package/connectors/discord/src/server.ts +93 -0
  71. package/connectors/elasticsearch/nimbus.extension.json +16 -0
  72. package/connectors/elasticsearch/src/server.ts +6 -0
  73. package/connectors/elasticsearch/src/tools.ts +110 -0
  74. package/connectors/fastmail/nimbus.extension.json +16 -0
  75. package/connectors/fastmail/src/jmap-core.ts +86 -0
  76. package/connectors/fastmail/src/server.ts +194 -0
  77. package/connectors/fastmail/src/tools.ts +143 -0
  78. package/connectors/figma/nimbus.extension.json +15 -0
  79. package/connectors/figma/src/search-filter.ts +24 -0
  80. package/connectors/figma/src/server.ts +117 -0
  81. package/connectors/firebase/nimbus.extension.json +15 -0
  82. package/connectors/firebase/src/search-filter.ts +30 -0
  83. package/connectors/firebase/src/server.ts +94 -0
  84. package/connectors/firebase/src/token.ts +41 -0
  85. package/connectors/flagsmith/nimbus.extension.json +15 -0
  86. package/connectors/flagsmith/src/search-filter.ts +29 -0
  87. package/connectors/flagsmith/src/server.ts +102 -0
  88. package/connectors/flux/nimbus.extension.json +16 -0
  89. package/connectors/flux/src/search-filter.ts +42 -0
  90. package/connectors/flux/src/server.ts +182 -0
  91. package/connectors/gcp/nimbus.extension.json +15 -0
  92. package/connectors/gcp/src/server.ts +140 -0
  93. package/connectors/github/nimbus.extension.json +15 -0
  94. package/connectors/github/src/server.ts +347 -0
  95. package/connectors/github-actions/nimbus.extension.json +15 -0
  96. package/connectors/github-actions/src/server.ts +213 -0
  97. package/connectors/gitlab/nimbus.extension.json +15 -0
  98. package/connectors/gitlab/src/server.ts +392 -0
  99. package/connectors/gmail/nimbus.extension.json +15 -0
  100. package/connectors/gmail/src/server.ts +277 -0
  101. package/connectors/google-drive/nimbus.extension.json +15 -0
  102. package/connectors/google-drive/src/drive-query.ts +3 -0
  103. package/connectors/google-drive/src/server.ts +531 -0
  104. package/connectors/google-meet/nimbus.extension.json +15 -0
  105. package/connectors/google-meet/src/server.ts +89 -0
  106. package/connectors/google-photos/nimbus.extension.json +15 -0
  107. package/connectors/google-photos/src/server.ts +139 -0
  108. package/connectors/grafana/nimbus.extension.json +15 -0
  109. package/connectors/grafana/src/server.ts +61 -0
  110. package/connectors/great-expectations/nimbus.extension.json +16 -0
  111. package/connectors/great-expectations/src/gx-parse.ts +292 -0
  112. package/connectors/great-expectations/src/server.ts +6 -0
  113. package/connectors/great-expectations/src/tools.ts +91 -0
  114. package/connectors/greenhouse/nimbus.extension.json +15 -0
  115. package/connectors/greenhouse/src/search-filter.ts +65 -0
  116. package/connectors/greenhouse/src/server.ts +67 -0
  117. package/connectors/hubspot/nimbus.extension.json +15 -0
  118. package/connectors/hubspot/src/search-filter.ts +28 -0
  119. package/connectors/hubspot/src/server.ts +81 -0
  120. package/connectors/iac/nimbus.extension.json +14 -0
  121. package/connectors/iac/src/server.ts +145 -0
  122. package/connectors/imap/nimbus.extension.json +16 -0
  123. package/connectors/imap/src/imap-core.ts +110 -0
  124. package/connectors/imap/src/server.ts +232 -0
  125. package/connectors/imap/src/tools.ts +40 -0
  126. package/connectors/intercom/nimbus.extension.json +15 -0
  127. package/connectors/intercom/src/search-filter.ts +46 -0
  128. package/connectors/intercom/src/server.ts +65 -0
  129. package/connectors/jenkins/nimbus.extension.json +15 -0
  130. package/connectors/jenkins/src/jenkins-api.ts +156 -0
  131. package/connectors/jenkins/src/server.ts +223 -0
  132. package/connectors/jira/nimbus.extension.json +15 -0
  133. package/connectors/jira/src/server.ts +309 -0
  134. package/connectors/kubernetes/nimbus.extension.json +15 -0
  135. package/connectors/kubernetes/src/server.ts +163 -0
  136. package/connectors/launchdarkly/nimbus.extension.json +15 -0
  137. package/connectors/launchdarkly/src/search-filter.ts +31 -0
  138. package/connectors/launchdarkly/src/server.ts +79 -0
  139. package/connectors/lever/nimbus.extension.json +15 -0
  140. package/connectors/lever/src/search-filter.ts +35 -0
  141. package/connectors/lever/src/server.ts +64 -0
  142. package/connectors/linear/nimbus.extension.json +15 -0
  143. package/connectors/linear/src/server.ts +467 -0
  144. package/connectors/localdb/nimbus.extension.json +16 -0
  145. package/connectors/localdb/src/server.ts +6 -0
  146. package/connectors/localdb/src/sql-scan.ts +158 -0
  147. package/connectors/localdb/src/tools.ts +67 -0
  148. package/connectors/looker/nimbus.extension.json +16 -0
  149. package/connectors/looker/src/search-filter.ts +22 -0
  150. package/connectors/looker/src/server.ts +254 -0
  151. package/connectors/mendeley/nimbus.extension.json +15 -0
  152. package/connectors/mendeley/src/search-filter.ts +68 -0
  153. package/connectors/mendeley/src/server.ts +59 -0
  154. package/connectors/mercury/nimbus.extension.json +15 -0
  155. package/connectors/mercury/src/search-filter.ts +11 -0
  156. package/connectors/mercury/src/server.ts +61 -0
  157. package/connectors/metabase/nimbus.extension.json +16 -0
  158. package/connectors/metabase/src/search-filter.ts +22 -0
  159. package/connectors/metabase/src/server.ts +83 -0
  160. package/connectors/miro/nimbus.extension.json +15 -0
  161. package/connectors/miro/src/search-filter.ts +24 -0
  162. package/connectors/miro/src/server.ts +76 -0
  163. package/connectors/mlflow/nimbus.extension.json +16 -0
  164. package/connectors/mlflow/src/search-filter.ts +38 -0
  165. package/connectors/mlflow/src/server.ts +167 -0
  166. package/connectors/monte-carlo/nimbus.extension.json +16 -0
  167. package/connectors/monte-carlo/src/search-filter.ts +11 -0
  168. package/connectors/monte-carlo/src/server.ts +241 -0
  169. package/connectors/netlify/nimbus.extension.json +15 -0
  170. package/connectors/netlify/src/search-filter.ts +37 -0
  171. package/connectors/netlify/src/server.ts +64 -0
  172. package/connectors/newrelic/nimbus.extension.json +15 -0
  173. package/connectors/newrelic/src/server.ts +48 -0
  174. package/connectors/notion/nimbus.extension.json +15 -0
  175. package/connectors/notion/src/kb-append.ts +23 -0
  176. package/connectors/notion/src/server.ts +343 -0
  177. package/connectors/obsidian/nimbus.extension.json +19 -0
  178. package/connectors/obsidian/src/server.ts +433 -0
  179. package/connectors/onedrive/nimbus.extension.json +15 -0
  180. package/connectors/onedrive/src/server.ts +256 -0
  181. package/connectors/outlook/nimbus.extension.json +15 -0
  182. package/connectors/outlook/src/server.ts +358 -0
  183. package/connectors/outlook/src/tool-scope-policy.ts +53 -0
  184. package/connectors/pagerduty/nimbus.extension.json +15 -0
  185. package/connectors/pagerduty/src/server.ts +140 -0
  186. package/connectors/pipedrive/nimbus.extension.json +15 -0
  187. package/connectors/pipedrive/src/search-filter.ts +11 -0
  188. package/connectors/pipedrive/src/server.ts +62 -0
  189. package/connectors/powerbi/nimbus.extension.json +16 -0
  190. package/connectors/powerbi/src/search-filter.ts +22 -0
  191. package/connectors/powerbi/src/server.ts +249 -0
  192. package/connectors/prefect/nimbus.extension.json +16 -0
  193. package/connectors/prefect/src/search-filter.ts +40 -0
  194. package/connectors/prefect/src/server.ts +94 -0
  195. package/connectors/protonmail/nimbus.extension.json +16 -0
  196. package/connectors/protonmail/src/mail-core.ts +96 -0
  197. package/connectors/protonmail/src/server.ts +231 -0
  198. package/connectors/protonmail/src/tools.ts +45 -0
  199. package/connectors/raindrop/nimbus.extension.json +15 -0
  200. package/connectors/raindrop/src/search-filter.ts +20 -0
  201. package/connectors/raindrop/src/server.ts +107 -0
  202. package/connectors/ramp/nimbus.extension.json +15 -0
  203. package/connectors/ramp/src/search-filter.ts +37 -0
  204. package/connectors/ramp/src/server.ts +109 -0
  205. package/connectors/readwise/nimbus.extension.json +15 -0
  206. package/connectors/readwise/src/search-filter.ts +64 -0
  207. package/connectors/readwise/src/server.ts +92 -0
  208. package/connectors/sagemaker/nimbus.extension.json +15 -0
  209. package/connectors/sagemaker/src/server.ts +6 -0
  210. package/connectors/sagemaker/src/tools.ts +121 -0
  211. package/connectors/salesforce/nimbus.extension.json +15 -0
  212. package/connectors/salesforce/src/search-filter.ts +23 -0
  213. package/connectors/salesforce/src/server.ts +94 -0
  214. package/connectors/semgrep/nimbus.extension.json +15 -0
  215. package/connectors/semgrep/src/search-filter.ts +31 -0
  216. package/connectors/semgrep/src/server.ts +108 -0
  217. package/connectors/sentry/nimbus.extension.json +15 -0
  218. package/connectors/sentry/src/server.ts +66 -0
  219. package/connectors/slack/nimbus.extension.json +15 -0
  220. package/connectors/slack/src/server.ts +360 -0
  221. package/connectors/snowflake/nimbus.extension.json +16 -0
  222. package/connectors/snowflake/src/search-filter.ts +26 -0
  223. package/connectors/snowflake/src/server.ts +236 -0
  224. package/connectors/snyk/nimbus.extension.json +15 -0
  225. package/connectors/snyk/src/search-filter.ts +28 -0
  226. package/connectors/snyk/src/server.ts +144 -0
  227. package/connectors/sonarqube/nimbus.extension.json +15 -0
  228. package/connectors/sonarqube/src/search-filter.ts +28 -0
  229. package/connectors/sonarqube/src/server.ts +115 -0
  230. package/connectors/stackoverflow/nimbus.extension.json +15 -0
  231. package/connectors/stackoverflow/src/search-filter.ts +52 -0
  232. package/connectors/stackoverflow/src/server.ts +81 -0
  233. package/connectors/storybook/nimbus.extension.json +16 -0
  234. package/connectors/storybook/src/server.ts +6 -0
  235. package/connectors/storybook/src/storybook-parse.ts +67 -0
  236. package/connectors/storybook/src/tools.ts +68 -0
  237. package/connectors/stripe/nimbus.extension.json +15 -0
  238. package/connectors/stripe/src/search-filter.ts +19 -0
  239. package/connectors/stripe/src/server.ts +65 -0
  240. package/connectors/superset/nimbus.extension.json +16 -0
  241. package/connectors/superset/src/search-filter.ts +22 -0
  242. package/connectors/superset/src/server.ts +119 -0
  243. package/connectors/tableau/nimbus.extension.json +16 -0
  244. package/connectors/tableau/src/search-filter.ts +22 -0
  245. package/connectors/tableau/src/server.ts +248 -0
  246. package/connectors/teams/nimbus.extension.json +20 -0
  247. package/connectors/teams/src/bot-send.ts +72 -0
  248. package/connectors/teams/src/server.ts +257 -0
  249. package/connectors/testflight/nimbus.extension.json +15 -0
  250. package/connectors/testflight/src/jwt.ts +27 -0
  251. package/connectors/testflight/src/search-filter.ts +30 -0
  252. package/connectors/testflight/src/server.ts +74 -0
  253. package/connectors/vercel/nimbus.extension.json +15 -0
  254. package/connectors/vercel/src/search-filter.ts +34 -0
  255. package/connectors/vercel/src/server.ts +79 -0
  256. package/connectors/vertex-ai/nimbus.extension.json +15 -0
  257. package/connectors/vertex-ai/src/server.ts +6 -0
  258. package/connectors/vertex-ai/src/tools.ts +145 -0
  259. package/connectors/wiz/nimbus.extension.json +15 -0
  260. package/connectors/wiz/src/search-filter.ts +50 -0
  261. package/connectors/wiz/src/server.ts +192 -0
  262. package/connectors/workday/nimbus.extension.json +19 -0
  263. package/connectors/workday/src/search-filter.ts +5 -0
  264. package/connectors/workday/src/server.ts +78 -0
  265. package/connectors/workday/src/tools.ts +1 -0
  266. package/connectors/zendesk/nimbus.extension.json +16 -0
  267. package/connectors/zendesk/src/search-filter.ts +11 -0
  268. package/connectors/zendesk/src/server.ts +77 -0
  269. package/connectors/zoom/nimbus.extension.json +15 -0
  270. package/connectors/zoom/src/encode-meeting-path.ts +5 -0
  271. package/connectors/zoom/src/recordings-window.ts +34 -0
  272. package/connectors/zoom/src/search-filter.ts +42 -0
  273. package/connectors/zoom/src/server.ts +98 -0
  274. package/connectors/zotero/nimbus.extension.json +15 -0
  275. package/connectors/zotero/src/search-filter.ts +81 -0
  276. package/connectors/zotero/src/server.ts +82 -0
  277. package/package.json +152 -0
  278. package/shared/atlassian-json-fetch.ts +42 -0
  279. package/shared/audit-chain.ts +133 -0
  280. package/shared/connector-mode.ts +60 -0
  281. package/shared/consent-kit.ts +323 -0
  282. package/shared/fetch-bearer-json.ts +18 -0
  283. package/shared/header-safe.ts +28 -0
  284. package/shared/imap-bodystructure.ts +113 -0
  285. package/shared/imap-mail-core.ts +57 -0
  286. package/shared/imap-tool-kit.ts +293 -0
  287. package/shared/join-api-path.ts +18 -0
  288. package/shared/kb-markdown.ts +142 -0
  289. package/shared/mcp-search-tool.ts +37 -0
  290. package/shared/mcp-tool-kit.ts +35 -0
  291. package/shared/nimbus-spawn.ts +128 -0
  292. package/shared/rest-tool-kit.ts +18 -0
  293. package/shared/run-cli-json.ts +55 -0
  294. package/shared/run-read-only-mcp-connector.ts +59 -0
  295. package/shared/safe-cli-arg.ts +55 -0
  296. package/shared/search-filter.ts +140 -0
  297. package/shared/strip-trailing-slashes.ts +7 -0
  298. package/shared/write-scope.ts +58 -0
  299. package/standalone/src/bin.ts +19 -0
  300. package/standalone/src/launcher.ts +186 -0
  301. package/standalone/tsconfig.json +8 -0
@@ -0,0 +1,278 @@
1
+ import { type ConsentServer, createWriteToolRegistrar } from "../../../shared/consent-kit.ts";
2
+ /**
3
+ * Apple Calendar tool handlers (read + write) over an injected CalDavClient.
4
+ *
5
+ * All three tools are registered here and wired into registerAppleTools in Task C3.
6
+ * The real CalDavClient (tsdav) lives in server.ts (coverage-excluded); this module
7
+ * depends only on the injectable interface, making it fully unit-testable.
8
+ */
9
+
10
+ import { buildVEvent } from "@nimbus-dev/sdk";
11
+ import { z } from "zod";
12
+ import { createRegisterSimpleTool, mcpJsonResult } from "../../../shared/mcp-tool-kit.ts";
13
+ import { capPreview } from "./apple-mail-core.ts";
14
+ import {
15
+ type CalDavClient,
16
+ type CalendarRef,
17
+ clampInstances,
18
+ selectCalendars,
19
+ } from "./caldav-core.ts";
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // Config shape (calendar subsection)
23
+ // ---------------------------------------------------------------------------
24
+
25
+ export interface CalendarToolConfig {
26
+ readonly include?: readonly string[];
27
+ readonly exclude?: readonly string[];
28
+ /** Maximum events returned across all calendars (default: 200). */
29
+ readonly maxInstances?: number;
30
+ }
31
+
32
+ // ---------------------------------------------------------------------------
33
+ // Zod arg schemas
34
+ // ---------------------------------------------------------------------------
35
+
36
+ const listArgs = z.object({
37
+ startUtc: z.string().min(1),
38
+ endUtc: z.string().min(1),
39
+ calendar: z.string().min(1).optional(),
40
+ });
41
+
42
+ const createArgs = z.object({
43
+ calendar: z.string().min(1).optional(),
44
+ summary: z.string().min(1).max(1000),
45
+ start: z.string().min(1),
46
+ end: z.string().min(1),
47
+ description: z.string().max(10_000).optional(),
48
+ location: z.string().max(500).optional(),
49
+ attendees: z.array(z.email()).optional(),
50
+ uid: z.string().min(1).optional(),
51
+ });
52
+
53
+ const deleteArgs = z.object({
54
+ href: z.string().min(1),
55
+ });
56
+
57
+ // ---------------------------------------------------------------------------
58
+ // ViewEvent — the shape returned to the LLM
59
+ // ---------------------------------------------------------------------------
60
+
61
+ interface ViewEvent {
62
+ href: string;
63
+ uid: string;
64
+ summary: string | null;
65
+ start: string | null;
66
+ end: string | null;
67
+ allDay: boolean;
68
+ location: string | null;
69
+ organizer: string | null;
70
+ status: string | null;
71
+ attendees: readonly string[];
72
+ rrule: string | null;
73
+ notes: string;
74
+ calendar: string;
75
+ }
76
+
77
+ const DEFAULT_MAX_INSTANCES = 200;
78
+
79
+ // ---------------------------------------------------------------------------
80
+ // registerAppleCalendarTools
81
+ // ---------------------------------------------------------------------------
82
+
83
+ /**
84
+ * Register the three iCloud Calendar tools onto an MCP server.
85
+ *
86
+ * @param server - The MCP server instance.
87
+ * @param options - Injected dependencies: the CalDAV client, a `now` factory
88
+ * (returns the current UTC timestamp in iCalendar DTSTAMP
89
+ * format, e.g. "20260601T090000Z"), and optional config.
90
+ */
91
+ export function registerAppleCalendarTools(
92
+ // Widened: the consent kit needs the real server surface, not just the `.tool` shim.
93
+ server: ConsentServer & { tool: (...args: never) => unknown },
94
+ options: {
95
+ calendar: CalDavClient;
96
+ now: () => string;
97
+ config?: CalendarToolConfig | undefined;
98
+ },
99
+ ): void {
100
+ const { calendar, now, config } = options;
101
+ const maxInstances = config?.maxInstances ?? DEFAULT_MAX_INSTANCES;
102
+ const registerSimpleTool = createRegisterSimpleTool(server);
103
+
104
+ // -------------------------------------------------------------------------
105
+ // apple_calendar_list
106
+ // -------------------------------------------------------------------------
107
+
108
+ registerSimpleTool(
109
+ "apple_calendar_list",
110
+ "List events across iCloud Calendar within a UTC time window. Returns event summaries, start/end times, location, organizer, attendee emails, and a <=2000-char notes preview. NEVER returns full event descriptions beyond the capped preview.",
111
+ listArgs.shape,
112
+ async (args: unknown) => {
113
+ const parsed = listArgs.safeParse(args);
114
+ if (!parsed.success) {
115
+ throw new Error(parsed.error.message);
116
+ }
117
+
118
+ const window = { startUtc: parsed.data.startUtc, endUtc: parsed.data.endUtc };
119
+
120
+ let allCals = await calendar.listCalendars();
121
+
122
+ // Filter by caller-supplied single calendar name or global config
123
+ if (parsed.data.calendar === undefined) {
124
+ allCals = selectCalendars(allCals, {
125
+ include: config?.include,
126
+ exclude: config?.exclude,
127
+ });
128
+ } else {
129
+ allCals = selectCalendars(allCals, { include: [parsed.data.calendar] });
130
+ }
131
+
132
+ const items: ViewEvent[] = [];
133
+
134
+ for (const cal of allCals) {
135
+ const rows = await calendar.listEvents(cal, window);
136
+ const clamped = clampInstances(rows, maxInstances - items.length);
137
+
138
+ for (const { href, event } of clamped) {
139
+ items.push({
140
+ href,
141
+ uid: event.uid,
142
+ summary: event.summary,
143
+ start: event.start,
144
+ end: event.end,
145
+ allDay: event.allDay,
146
+ location: event.location,
147
+ organizer: event.organizer,
148
+ status: event.status,
149
+ attendees: event.attendees,
150
+ rrule: event.rrule,
151
+ notes: capPreview(event.description ?? ""),
152
+ calendar: cal.displayName,
153
+ });
154
+ }
155
+
156
+ if (items.length >= maxInstances) {
157
+ break;
158
+ }
159
+ }
160
+
161
+ return mcpJsonResult({ items });
162
+ },
163
+ );
164
+
165
+ // -------------------------------------------------------------------------
166
+ // apple_calendar_event_create
167
+ // -------------------------------------------------------------------------
168
+
169
+ const registerWriteTool = createWriteToolRegistrar(server, {
170
+ connector: "apple",
171
+ scopeEnv: "NIMBUS_MCP_APPLE_WRITE_SCOPE",
172
+ scopeKinds: ["calendar"],
173
+ });
174
+
175
+ registerWriteTool(
176
+ "apple_calendar_event_create",
177
+ {
178
+ mutates: "apple.calendar.event.create",
179
+ recoverable: true,
180
+ scopeTargetOf: (p) => ({ kind: "calendar", value: p.calendar ?? "default" }),
181
+ },
182
+ "Create a new event in iCloud Calendar via CalDAV PUT.",
183
+ createArgs,
184
+ async (parsedData) => {
185
+ const parsed = { success: true as const, data: parsedData };
186
+
187
+ // Resolve the target calendar
188
+ let targetCal: CalendarRef | undefined;
189
+ const allCals = await calendar.listCalendars();
190
+
191
+ if (parsed.data.calendar === undefined) {
192
+ const selected = selectCalendars(allCals, {
193
+ include: config?.include,
194
+ exclude: config?.exclude,
195
+ });
196
+ targetCal = selected[0];
197
+ if (targetCal === undefined) {
198
+ throw new Error("No calendar available to create the event in");
199
+ }
200
+ } else {
201
+ targetCal = selectCalendars(allCals, { include: [parsed.data.calendar] })[0];
202
+ if (targetCal === undefined) {
203
+ throw new Error(`Calendar "${parsed.data.calendar}" not found`);
204
+ }
205
+ }
206
+
207
+ // Capture a single timestamp so the derived UID and the DTSTAMP never
208
+ // diverge (the injected now() returns a fresh value on each call).
209
+ const stamp = now();
210
+ // Determine UID: caller may supply one (for deterministic tests; Zod
211
+ // rejects ""); otherwise derive from the captured stamp + summary to
212
+ // avoid a non-pure Date.now().
213
+ const uid =
214
+ parsed.data.uid ??
215
+ `nimbus-${stamp}-${parsed.data.summary.slice(0, 40).replace(/\s+/g, "-")}`;
216
+
217
+ // Build the VEVENT ICS string
218
+ const buildInput: {
219
+ uid: string;
220
+ summary: string;
221
+ start: string;
222
+ end: string;
223
+ description?: string;
224
+ location?: string;
225
+ attendees?: readonly string[];
226
+ } = {
227
+ uid,
228
+ summary: parsed.data.summary,
229
+ start: parsed.data.start,
230
+ end: parsed.data.end,
231
+ };
232
+ if (parsed.data.description !== undefined) {
233
+ buildInput.description = parsed.data.description;
234
+ }
235
+ if (parsed.data.location !== undefined) {
236
+ buildInput.location = parsed.data.location;
237
+ }
238
+ if (parsed.data.attendees !== undefined && parsed.data.attendees.length > 0) {
239
+ buildInput.attendees = parsed.data.attendees;
240
+ }
241
+
242
+ const ics = buildVEvent(buildInput, stamp);
243
+
244
+ // PUT the event to the CalDAV server
245
+ const { href } = await calendar.putEvent(targetCal, uid, ics);
246
+
247
+ return mcpJsonResult({ uid, href });
248
+ },
249
+ );
250
+
251
+ // -------------------------------------------------------------------------
252
+ // apple_calendar_event_delete
253
+ // -------------------------------------------------------------------------
254
+
255
+ registerWriteTool(
256
+ "apple_calendar_event_delete",
257
+ {
258
+ mutates: "apple.calendar.event.delete",
259
+ // A deleted CalDAV event is gone from the server; the href is all that identifies it
260
+ // afterwards, so it IS the pre-state.
261
+ recoverable: false,
262
+ capturePreState: (p) => Promise.resolve({ href: p.href }),
263
+ scopeTargetOf: (p) => ({ kind: "calendar", value: p.href }),
264
+ },
265
+ "Delete an event from iCloud Calendar via CalDAV DELETE by href.",
266
+ deleteArgs,
267
+ async (parsedData) => {
268
+ const parsed = { success: true as const, data: parsedData };
269
+
270
+ await calendar.deleteEvent(parsed.data.href);
271
+
272
+ return mcpJsonResult({ deleted: true });
273
+ },
274
+ );
275
+ }
276
+
277
+ // Re-export the types needed by tests and tools.ts
278
+ export type { CalDavClient, CalendarRef };