@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,42 @@
1
+ import {
2
+ asRecord,
3
+ makeQueryFilter,
4
+ nestedString,
5
+ type SearchMatchOptions,
6
+ } from "../../../shared/search-filter.ts";
7
+
8
+ export type FluxSearchMatchOptions = SearchMatchOptions;
9
+
10
+ function readyConditionText(row: Record<string, unknown>): string {
11
+ const status = asRecord(row["status"]);
12
+ const conditions = status?.["conditions"];
13
+ if (!Array.isArray(conditions)) {
14
+ return "";
15
+ }
16
+ for (const entry of conditions) {
17
+ const c = asRecord(entry);
18
+ if (c === undefined) {
19
+ continue;
20
+ }
21
+ if (c["type"] === "Ready") {
22
+ const reason = typeof c["reason"] === "string" ? c["reason"] : "";
23
+ const message = typeof c["message"] === "string" ? c["message"] : "";
24
+ return `${reason} ${message}`;
25
+ }
26
+ }
27
+ return "";
28
+ }
29
+
30
+ function fieldsOf(item: unknown): readonly string[] | null {
31
+ const row = asRecord(item);
32
+ if (row === undefined) {
33
+ return null;
34
+ }
35
+ return [
36
+ nestedString(row, ["metadata", "name"]),
37
+ nestedString(row, ["metadata", "namespace"]),
38
+ readyConditionText(row),
39
+ ];
40
+ }
41
+
42
+ export const filterFluxResources = makeQueryFilter(fieldsOf);
@@ -0,0 +1,182 @@
1
+ import { FLUX_KINDS, type FluxKindEntry, trimTrailingSlash } from "@nimbus-dev/sdk";
2
+ import { z } from "zod";
3
+ import { type ConsentServer, createWriteToolRegistrar } from "../../../shared/consent-kit.ts";
4
+ import { fetchWithTimeout, mcpJsonResult as jsonResult } from "../../../shared/mcp-tool-kit.ts";
5
+ import {
6
+ runReadOnlyMcpConnector,
7
+ type ZodToolRegistrar,
8
+ } from "../../../shared/run-read-only-mcp-connector.ts";
9
+ import { filterFluxResources } from "./search-filter.ts";
10
+
11
+ const KIND_VALUES = FLUX_KINDS.map((e) => e.kind) as [string, ...string[]];
12
+
13
+ function kindEntry(kind: string): FluxKindEntry {
14
+ const found = FLUX_KINDS.find((e) => e.kind === kind);
15
+ if (found === undefined) {
16
+ throw new Error(`Unknown Flux kind: ${kind}`);
17
+ }
18
+ return found;
19
+ }
20
+
21
+ function apiBase(): string {
22
+ const v = process.env["FLUX_API_URL"]?.trim();
23
+ if (v === undefined || v === "") {
24
+ throw new Error("FLUX_API_URL is not set");
25
+ }
26
+ return trimTrailingSlash(v);
27
+ }
28
+
29
+ function authHeader(): Record<string, string> {
30
+ const t = process.env["FLUX_TOKEN"]?.trim();
31
+ if (t === undefined || t === "") {
32
+ throw new Error("FLUX_TOKEN is not set");
33
+ }
34
+ return { Authorization: `Bearer ${t}`, Accept: "application/json" };
35
+ }
36
+
37
+ async function agGet(path: string): Promise<unknown> {
38
+ const res = await fetchWithTimeout(`${apiBase()}${path}`, { headers: authHeader() });
39
+ const text = await res.text();
40
+ if (!res.ok) {
41
+ throw new Error(`Flux ${String(res.status)}: ${text.slice(0, 400)}`);
42
+ }
43
+ return JSON.parse(text) as unknown;
44
+ }
45
+
46
+ function itemsFrom(root: unknown): unknown[] {
47
+ if (Array.isArray(root)) {
48
+ return root;
49
+ }
50
+ const items = (root as { items?: unknown } | null)?.items;
51
+ return Array.isArray(items) ? items : [];
52
+ }
53
+
54
+ function listPath(entry: FluxKindEntry, namespace?: string): string {
55
+ const prefix = `/apis/${entry.group}/${entry.version}`;
56
+ if (namespace !== undefined && namespace !== "") {
57
+ return `${prefix}/namespaces/${encodeURIComponent(namespace)}/${entry.plural}`;
58
+ }
59
+ return `${prefix}/${entry.plural}`;
60
+ }
61
+
62
+ /** Request a reconcile by annotating reconcile.fluxcd.io/requestedAt on the CR (the same mechanism
63
+ * `flux reconcile` uses). Returns the RFC3339 timestamp written. Reuses kindEntry/listPath so the
64
+ * write path shares the read path's single source of truth — no new kind strings or version drift. */
65
+ async function fluxReconcile(kind: string, namespace: string, name: string): Promise<string> {
66
+ const entry = kindEntry(kind);
67
+ const path = `${listPath(entry, namespace)}/${encodeURIComponent(name)}`;
68
+ const requestedAt = new Date().toISOString();
69
+ const res = await fetchWithTimeout(`${apiBase()}${path}`, {
70
+ method: "PATCH",
71
+ headers: { ...authHeader(), "Content-Type": "application/merge-patch+json" },
72
+ body: JSON.stringify({
73
+ metadata: { annotations: { "reconcile.fluxcd.io/requestedAt": requestedAt } },
74
+ }),
75
+ });
76
+ const text = await res.text();
77
+ if (!res.ok) {
78
+ throw new Error(`Flux reconcile ${path} ${String(res.status)}: ${text.slice(0, 400)}`);
79
+ }
80
+ return requestedAt;
81
+ }
82
+
83
+ export function registerFluxTools(reg: ZodToolRegistrar, server: unknown): void {
84
+ // Despite the read-only helper's name, this connector exposes write tools. The consent
85
+ // kit needs the real server, which the helper now passes through as its second argument.
86
+ const registerWriteTool = createWriteToolRegistrar(server as ConsentServer, {
87
+ connector: "flux",
88
+ scopeEnv: "NIMBUS_MCP_FLUX_WRITE_SCOPE",
89
+ scopeKinds: ["namespace"],
90
+ });
91
+
92
+ reg(
93
+ "flux_list",
94
+ "List Flux Custom Resources of one `kind` (default `kustomization`). Reads the Kubernetes API: all-namespaces by default, or scoped to `namespace` when given. `limit` (default 200) caps the returned `items` client-side. Returns the raw Kubernetes List envelope.",
95
+ z.object({
96
+ kind: z.enum(KIND_VALUES).optional(),
97
+ namespace: z.string().optional(),
98
+ limit: z.number().int().min(1).max(500).optional(),
99
+ }),
100
+ async (p) => {
101
+ const entry = kindEntry(p.kind ?? "kustomization");
102
+ const root = await agGet(listPath(entry, p.namespace));
103
+ const items = itemsFrom(root);
104
+ const cap = p.limit ?? 200;
105
+ return jsonResult({ items: items.slice(0, cap) });
106
+ },
107
+ );
108
+
109
+ reg(
110
+ "flux_get",
111
+ "Fetch one Flux Custom Resource by `kind`, `namespace`, and `name` (`/apis/<group>/<version>/namespaces/<ns>/<plural>/<name>`). Throws when no such resource exists.",
112
+ z.object({
113
+ kind: z.enum(KIND_VALUES),
114
+ namespace: z.string().min(1),
115
+ name: z.string().min(1),
116
+ }),
117
+ async (p) => {
118
+ const entry = kindEntry(p.kind);
119
+ const path = `${listPath(entry, p.namespace)}/${encodeURIComponent(p.name)}`;
120
+ return jsonResult(await agGet(path));
121
+ },
122
+ );
123
+
124
+ reg(
125
+ "flux_search",
126
+ "Substring search across Flux Custom Resources of one `kind` (default `kustomization`). Lists the kind across all namespaces and matches the query (case-insensitive) against resource name, namespace, and the Ready condition's reason/message. Returns a `{ matches: [...] }` envelope.",
127
+ z.object({
128
+ query: z.string().min(1),
129
+ kind: z.enum(KIND_VALUES).optional(),
130
+ limit: z.number().int().min(1).max(200).optional(),
131
+ }),
132
+ async (p) => {
133
+ const entry = kindEntry(p.kind ?? "kustomization");
134
+ const root = await agGet(listPath(entry));
135
+ const matches = filterFluxResources(itemsFrom(root), {
136
+ query: p.query,
137
+ limit: p.limit,
138
+ });
139
+ return jsonResult({ matches });
140
+ },
141
+ );
142
+
143
+ registerWriteTool(
144
+ "flux_kustomization_reconcile",
145
+ {
146
+ mutates: "flux.kustomization.reconcile",
147
+ recoverable: true,
148
+ scopeTargetOf: (p) => ({ kind: "namespace", value: p.namespace }),
149
+ },
150
+ "Request a reconcile of a Flux Kustomization by annotating reconcile.fluxcd.io/requestedAt (PATCH the CR; requires HITL flux.kustomization.reconcile, and the SA's `patch` RBAC verb on kustomizations). Async — verify via the next metadata sync.",
151
+ z.object({ namespace: z.string().min(1), name: z.string().min(1) }),
152
+ async (p) =>
153
+ jsonResult({
154
+ status: "requested",
155
+ name: p.name,
156
+ requestedAt: await fluxReconcile("kustomization", p.namespace, p.name),
157
+ }),
158
+ );
159
+
160
+ registerWriteTool(
161
+ "flux_helmrelease_reconcile",
162
+ {
163
+ mutates: "flux.helmrelease.reconcile",
164
+ recoverable: true,
165
+ scopeTargetOf: (p) => ({ kind: "namespace", value: p.namespace }),
166
+ },
167
+ "Request a reconcile of a Flux HelmRelease by annotating reconcile.fluxcd.io/requestedAt (PATCH the CR; requires HITL flux.helmrelease.reconcile, and the SA's `patch` RBAC verb on helmreleases). Async — verify via the next metadata sync.",
168
+ z.object({ namespace: z.string().min(1), name: z.string().min(1) }),
169
+ async (p) =>
170
+ jsonResult({
171
+ status: "requested",
172
+ name: p.name,
173
+ requestedAt: await fluxReconcile("helm_release", p.namespace, p.name),
174
+ }),
175
+ );
176
+ }
177
+
178
+ export async function startConnector(): Promise<void> {
179
+ await runReadOnlyMcpConnector("nimbus-flux", registerFluxTools);
180
+ }
181
+
182
+ if (import.meta.main) await startConnector();
@@ -0,0 +1,15 @@
1
+ {
2
+ "id": "com.nimbus.gcp",
3
+ "displayName": "Google Cloud",
4
+ "version": "0.1.0",
5
+ "description": "GCP CLI connector (IAM control plane + OAuth). Service-specific googleapis.com hosts (storage, bigquery, etc.) are a known Task 14 follow-up. Mutations require Gateway HITL.",
6
+ "author": "Nimbus",
7
+ "entrypoint": "dist/server.js",
8
+ "runtime": "bun",
9
+ "permissions": {
10
+ "network": ["cloudresourcemanager.googleapis.com", "oauth2.googleapis.com"]
11
+ },
12
+ "hitlRequired": ["write", "delete"],
13
+ "syncInterval": 600,
14
+ "minNimbusVersion": "0.2.0"
15
+ }
@@ -0,0 +1,140 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { z } from "zod";
4
+ import {
5
+ createRegisterSimpleTool,
6
+ createZodToolRegistrar,
7
+ mcpJsonResult as jsonResult,
8
+ } from "../../../shared/mcp-tool-kit.ts";
9
+ import { runCliJson, runCliOk } from "../../../shared/run-cli-json.ts";
10
+
11
+ function gcloudEnv(): Record<string, string | undefined> {
12
+ const e = { ...process.env } as Record<string, string | undefined>;
13
+ const cf = process.env["GOOGLE_APPLICATION_CREDENTIALS"]?.trim();
14
+ if (cf !== undefined && cf !== "") {
15
+ e["GOOGLE_APPLICATION_CREDENTIALS"] = cf;
16
+ }
17
+ return e;
18
+ }
19
+
20
+ async function gcloudJson(args: string[]): Promise<unknown> {
21
+ const cmd = ["gcloud", ...args, "--format", "json"];
22
+ const r = await runCliJson(cmd, gcloudEnv());
23
+ if (!r.ok) {
24
+ throw new Error(r.message);
25
+ }
26
+ return r.data ?? {};
27
+ }
28
+
29
+ const mcp = new McpServer({ name: "nimbus-gcp", version: "0.1.0" });
30
+
31
+ import { createWriteToolRegistrar } from "../../../shared/consent-kit.ts";
32
+
33
+ const reg = createZodToolRegistrar(createRegisterSimpleTool(mcp));
34
+
35
+ /**
36
+ * Every MUTATING gcp tool goes through here. Outside the gateway this adds the
37
+ * consent gate, the write-scope allow-list, the mutation budget and the audit record; inside
38
+ * the gateway it is a pass-through, because executor.ts (I2) is the gate there.
39
+ */
40
+ const registerWriteTool = createWriteToolRegistrar(mcp, {
41
+ connector: "gcp",
42
+ scopeEnv: "NIMBUS_MCP_GCP_WRITE_SCOPE",
43
+ scopeKinds: ["project"],
44
+ });
45
+
46
+ reg(
47
+ "gcp_cloud_run_service_list",
48
+ "List Cloud Run services in a region.",
49
+ z.object({ projectId: z.string().min(1), region: z.string().min(1) }),
50
+ async (p) =>
51
+ jsonResult(
52
+ await gcloudJson([
53
+ "run",
54
+ "services",
55
+ "list",
56
+ `--project=${p.projectId}`,
57
+ `--region=${p.region}`,
58
+ ]),
59
+ ),
60
+ );
61
+
62
+ registerWriteTool(
63
+ "gcp_cloud_run_deploy",
64
+ {
65
+ mutates: "gcp.cloud_run.deploy",
66
+ recoverable: true,
67
+ scopeTargetOf: (p) => ({ kind: "project", value: p.projectId }),
68
+ },
69
+ "Deploy a container image to Cloud Run.",
70
+ z.object({
71
+ projectId: z.string().min(1),
72
+ region: z.string().min(1),
73
+ service: z.string().min(1),
74
+ image: z.string().min(1),
75
+ }),
76
+ async (p) => {
77
+ const r = await runCliOk(
78
+ [
79
+ "gcloud",
80
+ "run",
81
+ "deploy",
82
+ p.service,
83
+ `--project=${p.projectId}`,
84
+ `--region=${p.region}`,
85
+ `--image=${p.image}`,
86
+ "--quiet",
87
+ ],
88
+ gcloudEnv(),
89
+ );
90
+ if (!r.ok) {
91
+ throw new Error(r.message);
92
+ }
93
+ return jsonResult({ ok: true });
94
+ },
95
+ );
96
+
97
+ registerWriteTool(
98
+ "gcp_gke_workload_restart",
99
+ {
100
+ mutates: "gcp.gke.workload.restart",
101
+ recoverable: true,
102
+ scopeTargetOf: (p) => ({ kind: "project", value: p.projectId }),
103
+ },
104
+ "Restart a GKE deployment rollout via kubectl (uses current cluster credentials).",
105
+ z.object({
106
+ projectId: z.string().min(1),
107
+ location: z.string().min(1),
108
+ cluster: z.string().min(1),
109
+ namespace: z.string().min(1),
110
+ deployment: z.string().min(1),
111
+ }),
112
+ async (p) => {
113
+ const getCreds = await runCliOk(
114
+ [
115
+ "gcloud",
116
+ "container",
117
+ "clusters",
118
+ "get-credentials",
119
+ p.cluster,
120
+ `--project=${p.projectId}`,
121
+ `--zone=${p.location}`,
122
+ ],
123
+ gcloudEnv(),
124
+ );
125
+ if (!getCreds.ok) {
126
+ throw new Error(getCreds.message);
127
+ }
128
+ const r = await runCliOk(
129
+ ["kubectl", "rollout", "restart", "deployment", p.deployment, "-n", p.namespace],
130
+ gcloudEnv(),
131
+ );
132
+ if (!r.ok) {
133
+ throw new Error(r.message);
134
+ }
135
+ return jsonResult({ ok: true });
136
+ },
137
+ );
138
+
139
+ const transport = new StdioServerTransport();
140
+ await mcp.connect(transport);
@@ -0,0 +1,15 @@
1
+ {
2
+ "id": "com.nimbus.github",
3
+ "displayName": "GitHub",
4
+ "version": "0.1.0",
5
+ "description": "GitHub REST + GraphQL connector (PRs, issues, reviews, releases). Mutations require Gateway HITL.",
6
+ "author": "Nimbus",
7
+ "entrypoint": "dist/server.js",
8
+ "runtime": "bun",
9
+ "permissions": {
10
+ "network": ["api.github.com", "uploads.github.com", "raw.githubusercontent.com"]
11
+ },
12
+ "hitlRequired": ["write", "delete"],
13
+ "syncInterval": 300,
14
+ "minNimbusVersion": "0.2.0"
15
+ }