@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,15 @@
1
+ {
2
+ "id": "com.nimbus.cloud-logging",
3
+ "displayName": "GCP Cloud Logging",
4
+ "version": "0.1.0",
5
+ "description": "GCP Cloud Logging metadata connector (Tier-3, no-row-data). Indexes log routing SINK configuration metadata only — sink name, destination, filter expression, description, disabled flag, and create/update timestamps — via the gcloud CLI's `gcloud logging sinks list/describe` commands. Never reads log ENTRIES / row data: there is no `gcloud logging read` and no `gcloud logging entries list`. Reuses the existing GCP service-account credentials via the gcloud CLI. Read-only; no write tools.",
6
+ "author": "Nimbus",
7
+ "entrypoint": "dist/server.js",
8
+ "runtime": "bun",
9
+ "permissions": {
10
+ "network": ["logging.googleapis.com"]
11
+ },
12
+ "hitlRequired": [],
13
+ "syncInterval": 600,
14
+ "minNimbusVersion": "0.2.0"
15
+ }
@@ -0,0 +1,6 @@
1
+ import { runReadOnlyMcpConnector } from "../../../shared/run-read-only-mcp-connector.ts";
2
+ import { registerCloudLoggingTools } from "./tools.ts";
3
+
4
+ await runReadOnlyMcpConnector("nimbus-cloud-logging", (reg) => {
5
+ registerCloudLoggingTools(reg);
6
+ });
@@ -0,0 +1,115 @@
1
+ import { z } from "zod";
2
+ import { mcpJsonResult as jsonResult } from "../../../shared/mcp-tool-kit.ts";
3
+ import { nimbusSpawn } from "../../../shared/nimbus-spawn.ts";
4
+ import type { ZodToolRegistrar } from "../../../shared/run-read-only-mcp-connector.ts";
5
+ import { assertSafeCliArg } from "../../../shared/safe-cli-arg.ts";
6
+
7
+ /**
8
+ * GCP Cloud Logging (Tier-3, no-row-data) MCP tool surface. ALL tools index log
9
+ * routing SINK configuration metadata only (sink name, destination, filter
10
+ * expression, description, disabled flag, create/update timestamps). NONE read
11
+ * log ENTRIES / row data — there is NO `gcloud logging read`, NO
12
+ * `gcloud logging entries list`, NO tail. The names are introspected by the
13
+ * `assertNoRowDataTools` contract test, so they must never contain a row-data
14
+ * segment (read/entries/events/query/results/scan/tail/…). (`read` is not a
15
+ * denylisted segment, but the commands the tools shell out to are sinks-only.)
16
+ */
17
+ export const CLOUD_LOGGING_TOOL_NAMES = [
18
+ "cloud_logging_list",
19
+ "cloud_logging_get",
20
+ "cloud_logging_search",
21
+ ] as const;
22
+
23
+ function isRecord(v: unknown): v is Record<string, unknown> {
24
+ return v !== null && typeof v === "object" && !Array.isArray(v);
25
+ }
26
+
27
+ function strField(r: Record<string, unknown>, key: string): string {
28
+ const v = r[key];
29
+ return typeof v === "string" ? v : "";
30
+ }
31
+
32
+ function asArray(parsed: unknown): unknown[] {
33
+ return Array.isArray(parsed) ? parsed : [];
34
+ }
35
+
36
+ /** The configured GCP project id, if `GOOGLE_CLOUD_PROJECT` is set at spawn. */
37
+ function projectArgs(): string[] {
38
+ const project = process.env["GOOGLE_CLOUD_PROJECT"]?.trim();
39
+ return project !== undefined && project !== "" ? ["--project", project] : [];
40
+ }
41
+
42
+ /**
43
+ * Run `gcloud logging <args> --format json` and parse stdout. gcloud reads
44
+ * Application Default Credentials from `GOOGLE_APPLICATION_CREDENTIALS`
45
+ * natively from the process env injected at spawn time. Throws on non-zero exit.
46
+ */
47
+ async function gcloudLogging(args: string[]): Promise<unknown> {
48
+ const { code, stdout, stderr } = await nimbusSpawn(
49
+ ["gcloud", "logging", ...args, ...projectArgs(), "--format", "json"],
50
+ {},
51
+ );
52
+ const out = stdout.trim();
53
+ const err = stderr.trim();
54
+ if (code !== 0) {
55
+ throw new Error(`gcloud logging ${args[0] ?? ""} failed: ${err.slice(0, 400)}`);
56
+ }
57
+ return out === "" ? [] : (JSON.parse(out) as unknown);
58
+ }
59
+
60
+ function sinkMatches(entry: unknown, q: string): boolean {
61
+ if (!isRecord(entry)) {
62
+ return false;
63
+ }
64
+ const needle = q.toLowerCase();
65
+ return (
66
+ strField(entry, "name").toLowerCase().includes(needle) ||
67
+ strField(entry, "filter").toLowerCase().includes(needle) ||
68
+ strField(entry, "destination").toLowerCase().includes(needle)
69
+ );
70
+ }
71
+
72
+ /**
73
+ * Register the read-only, metadata-only Cloud Logging tools onto the given
74
+ * registrar. Shared between `server.ts` (live) and the contract test
75
+ * (introspection).
76
+ */
77
+ export function registerCloudLoggingTools(reg: ZodToolRegistrar): void {
78
+ reg(
79
+ "cloud_logging_list",
80
+ "List GCP Cloud Logging routing SINKS — METADATA ONLY (`gcloud logging sinks list`). Each entry carries `name`, `destination`, `filter`, `description`, `disabled`, `createTime`, and `updateTime`. Never reads log-entry contents / row data.",
81
+ z.object({}),
82
+ async () => {
83
+ return jsonResult(asArray(await gcloudLogging(["sinks", "list"])));
84
+ },
85
+ );
86
+
87
+ reg(
88
+ "cloud_logging_get",
89
+ "Fetch one Cloud Logging routing sink's configuration METADATA (`gcloud logging sinks describe <sink>`). Returns the sink's `name`, `destination`, `filter`, `description`, `disabled` flag, and create/update timestamps. No log-entry contents are returned — metadata only.",
90
+ z.object({
91
+ sinkName: z.string().min(1),
92
+ }),
93
+ async (p) => {
94
+ // `sinkName` is a bare positional to `gcloud logging sinks describe`; guard
95
+ // against argv flag smuggling (a value beginning with "-" would be parsed as
96
+ // a gcloud flag).
97
+ return jsonResult(
98
+ await gcloudLogging(["sinks", "describe", assertSafeCliArg(p.sinkName, "sinkName")]),
99
+ );
100
+ },
101
+ );
102
+
103
+ reg(
104
+ "cloud_logging_search",
105
+ "Substring search over Cloud Logging routing SINK names, filters, and destinations (case-insensitive) — METADATA ONLY. Returns a `{ matches: [...] }` envelope of `gcloud logging sinks list` metadata entries matching the query. Never reads log-entry contents / row data.",
106
+ z.object({
107
+ query: z.string().min(1),
108
+ }),
109
+ async (p) => {
110
+ const sinks = asArray(await gcloudLogging(["sinks", "list"]));
111
+ const matches = sinks.filter((s) => sinkMatches(s, p.query));
112
+ return jsonResult({ matches });
113
+ },
114
+ );
115
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "id": "com.nimbus.cloudwatch",
3
+ "displayName": "Amazon CloudWatch",
4
+ "version": "0.1.0",
5
+ "description": "Amazon CloudWatch Logs metadata connector (Tier-3, no-row-data). Indexes log-group metadata only — log-group name, ARN, retention, stored bytes, creation time, metric-filter count, and an optional stream count + last-event timestamp — via the AWS CLI's CloudWatch Logs describe commands. Never fetches log-event contents / row data: there is no get-log-events, no filter-log-events, no start-query, no get-query-results, and no tail. Reuses the existing AWS credentials via the aws CLI. Read-only; no write tools.",
6
+ "author": "Nimbus",
7
+ "entrypoint": "dist/server.js",
8
+ "runtime": "bun",
9
+ "permissions": {
10
+ "network": ["sts.amazonaws.com"]
11
+ },
12
+ "hitlRequired": [],
13
+ "syncInterval": 600,
14
+ "minNimbusVersion": "0.2.0"
15
+ }
@@ -0,0 +1,6 @@
1
+ import { runReadOnlyMcpConnector } from "../../../shared/run-read-only-mcp-connector.ts";
2
+ import { registerCloudwatchTools } from "./tools.ts";
3
+
4
+ await runReadOnlyMcpConnector("nimbus-cloudwatch", (reg) => {
5
+ registerCloudwatchTools(reg);
6
+ });
@@ -0,0 +1,144 @@
1
+ import { z } from "zod";
2
+ import { mcpJsonResult as jsonResult } from "../../../shared/mcp-tool-kit.ts";
3
+ import { nimbusSpawn } from "../../../shared/nimbus-spawn.ts";
4
+ import type { ZodToolRegistrar } from "../../../shared/run-read-only-mcp-connector.ts";
5
+ import { isSafeCliArg } from "../../../shared/safe-cli-arg.ts";
6
+
7
+ /**
8
+ * A log-group name / prefix passed as a value to the `aws logs` CLI. Rejected at
9
+ * the schema boundary if it begins with `-` (argv flag smuggling) or contains
10
+ * control characters.
11
+ */
12
+ const cliArg = z
13
+ .string()
14
+ .min(1)
15
+ .refine(isSafeCliArg, { message: 'must not start with "-" or contain control characters' });
16
+
17
+ /**
18
+ * Amazon CloudWatch Logs (Tier-3, no-row-data) MCP tool surface. ALL tools
19
+ * index log-GROUP metadata only (group name, ARN, retention, stored bytes,
20
+ * creation time, metric-filter count) plus optional stream METADATA (stream
21
+ * name, last-event timestamp, stored bytes). NONE fetch log-event contents /
22
+ * row data — there is NO `get-log-events`, NO `filter-log-events`, NO
23
+ * `start-query`, NO `get-query-results`, NO `tail`. The names are introspected
24
+ * by the `assertNoRowDataTools` contract test, so they must never contain a
25
+ * row-data segment (events/query/results/scan/tail/…).
26
+ */
27
+ export const CLOUDWATCH_TOOL_NAMES = [
28
+ "cloudwatch_list",
29
+ "cloudwatch_get",
30
+ "cloudwatch_search",
31
+ ] as const;
32
+
33
+ const LIMIT = "50";
34
+
35
+ function isRecord(v: unknown): v is Record<string, unknown> {
36
+ return v !== null && typeof v === "object" && !Array.isArray(v);
37
+ }
38
+
39
+ function strField(r: Record<string, unknown>, key: string): string {
40
+ const v = r[key];
41
+ return typeof v === "string" ? v : "";
42
+ }
43
+
44
+ function asArray(parsed: unknown, key: string): unknown[] {
45
+ if (!isRecord(parsed)) {
46
+ return [];
47
+ }
48
+ const arr = parsed[key];
49
+ return Array.isArray(arr) ? arr : [];
50
+ }
51
+
52
+ /**
53
+ * Run `aws logs <args> --output json` and parse stdout. The AWS CLI reads
54
+ * AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_DEFAULT_REGION / AWS_PROFILE
55
+ * natively from the process env injected at spawn time. Throws on non-zero exit.
56
+ */
57
+ async function logsCli(args: string[]): Promise<unknown> {
58
+ const { code, stdout, stderr } = await nimbusSpawn(
59
+ ["aws", "logs", ...args, "--output", "json"],
60
+ {},
61
+ );
62
+ const out = stdout.trim();
63
+ const err = stderr.trim();
64
+ if (code !== 0) {
65
+ throw new Error(`aws logs ${args[0] ?? ""} failed: ${err.slice(0, 400)}`);
66
+ }
67
+ return out === "" ? {} : (JSON.parse(out) as unknown);
68
+ }
69
+
70
+ function groupMatches(entry: unknown, q: string): boolean {
71
+ if (!isRecord(entry)) {
72
+ return false;
73
+ }
74
+ return strField(entry, "logGroupName").toLowerCase().includes(q.toLowerCase());
75
+ }
76
+
77
+ /**
78
+ * Register the read-only, metadata-only CloudWatch Logs tools onto the given
79
+ * registrar. Shared between `server.ts` (live) and the contract test
80
+ * (introspection).
81
+ */
82
+ export function registerCloudwatchTools(reg: ZodToolRegistrar): void {
83
+ reg(
84
+ "cloudwatch_list",
85
+ "List CloudWatch log GROUPS — METADATA ONLY (`aws logs describe-log-groups`). Each entry carries `logGroupName`, `arn`, `creationTime`, `retentionInDays`, `storedBytes`, and `metricFilterCount`. Optionally filter by a `prefix` on the log-group name. Never fetches log-event contents / row data.",
86
+ z.object({
87
+ prefix: cliArg.optional(),
88
+ }),
89
+ async (p) => {
90
+ const args = ["describe-log-groups", "--limit", LIMIT];
91
+ if (p.prefix !== undefined) {
92
+ args.push("--log-group-name-prefix", p.prefix);
93
+ }
94
+ return jsonResult(await logsCli(args));
95
+ },
96
+ );
97
+
98
+ reg(
99
+ "cloudwatch_get",
100
+ "Fetch one CloudWatch log group's METADATA plus a stream summary. Returns the matching `describe-log-groups` entry (name, ARN, retention, stored bytes, metric-filter count) and the group's `describe-log-streams` METADATA (stream names, last-event timestamps, stored bytes) ordered by last activity. No log-event contents are returned — metadata only.",
101
+ z.object({
102
+ logGroupName: cliArg,
103
+ }),
104
+ async (p) => {
105
+ const group = await logsCli([
106
+ "describe-log-groups",
107
+ "--log-group-name-prefix",
108
+ p.logGroupName,
109
+ "--limit",
110
+ LIMIT,
111
+ ]);
112
+ const match = asArray(group, "logGroups").find(
113
+ (g) => isRecord(g) && strField(g, "logGroupName") === p.logGroupName,
114
+ );
115
+ const streams = await logsCli([
116
+ "describe-log-streams",
117
+ "--log-group-name",
118
+ p.logGroupName,
119
+ "--order-by",
120
+ "LastEventTime",
121
+ "--descending",
122
+ "--limit",
123
+ LIMIT,
124
+ ]);
125
+ return jsonResult({
126
+ logGroup: match ?? null,
127
+ streams: asArray(streams, "logStreams"),
128
+ });
129
+ },
130
+ );
131
+
132
+ reg(
133
+ "cloudwatch_search",
134
+ "Substring search over CloudWatch log GROUP names (case-insensitive) — METADATA ONLY. Returns a `{ matches: [...] }` envelope of `describe-log-groups` metadata entries whose `logGroupName` contains the query. Never fetches log-event contents / row data.",
135
+ z.object({
136
+ query: z.string().min(1),
137
+ }),
138
+ async (p) => {
139
+ const root = await logsCli(["describe-log-groups", "--limit", LIMIT]);
140
+ const matches = asArray(root, "logGroups").filter((g) => groupMatches(g, p.query));
141
+ return jsonResult({ matches });
142
+ },
143
+ );
144
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "id": "com.nimbus.codemagic",
3
+ "displayName": "Codemagic",
4
+ "version": "0.1.0",
5
+ "description": "Codemagic REST connector (mobile CI/CD builds + apps). Read-only; surfaces build status, workflow id, branch and commit so the local index can correlate mobile CI runs back to PRs and incidents.",
6
+ "author": "Nimbus",
7
+ "entrypoint": "dist/server.js",
8
+ "runtime": "bun",
9
+ "permissions": {
10
+ "network": ["api.codemagic.io"]
11
+ },
12
+ "hitlRequired": [],
13
+ "syncInterval": 600,
14
+ "minNimbusVersion": "0.2.0"
15
+ }
@@ -0,0 +1,11 @@
1
+ import {
2
+ fieldsFromKeys,
3
+ makeQueryFilter,
4
+ type SearchMatchOptions,
5
+ } from "../../../shared/search-filter.ts";
6
+
7
+ export type CodemagicSearchMatchOptions = SearchMatchOptions;
8
+
9
+ export const filterCodemagicBuilds = makeQueryFilter(
10
+ fieldsFromKeys(["branch", "message", "workflowId", "status"]),
11
+ );
@@ -0,0 +1,74 @@
1
+ import { z } from "zod";
2
+ import { matchesResult } from "../../../shared/mcp-search-tool.ts";
3
+ import { mcpJsonResult as jsonResult } from "../../../shared/mcp-tool-kit.ts";
4
+ import { runReadOnlyMcpConnector } from "../../../shared/run-read-only-mcp-connector.ts";
5
+ import { filterCodemagicBuilds } from "./search-filter.ts";
6
+
7
+ const CODEMAGIC_API = "https://api.codemagic.io";
8
+
9
+ function authHeader(): Record<string, string> {
10
+ const t = process.env["CODEMAGIC_TOKEN"]?.trim();
11
+ if (t === undefined || t === "") {
12
+ throw new Error("CODEMAGIC_TOKEN is not set");
13
+ }
14
+ return { "x-auth-token": t, Accept: "application/json" };
15
+ }
16
+
17
+ async function codemagicGet(path: string): Promise<unknown> {
18
+ const res = await fetch(`${CODEMAGIC_API}${path}`, { headers: authHeader() });
19
+ const text = await res.text();
20
+ if (!res.ok) {
21
+ throw new Error(`Codemagic ${String(res.status)}: ${text.slice(0, 400)}`);
22
+ }
23
+ return JSON.parse(text) as unknown;
24
+ }
25
+
26
+ await runReadOnlyMcpConnector("nimbus-codemagic", (reg) => {
27
+ reg(
28
+ "codemagic_list",
29
+ "List Codemagic resources. When `appId` is omitted, returns the user's accessible apps via `/apps`. When `appId` is provided, returns the app's recent builds via `/builds?appId=<id>` (limit optional).",
30
+ z.object({
31
+ appId: z.string().min(1).optional(),
32
+ limit: z.number().int().min(1).max(50).optional(),
33
+ }),
34
+ async (p) => {
35
+ if (p.appId === undefined) {
36
+ return jsonResult(await codemagicGet("/apps"));
37
+ }
38
+ const limit = p.limit ?? 50;
39
+ return jsonResult(
40
+ await codemagicGet(`/builds?appId=${encodeURIComponent(p.appId)}&limit=${String(limit)}`),
41
+ );
42
+ },
43
+ );
44
+
45
+ reg(
46
+ "codemagic_get",
47
+ "Fetch a single Codemagic resource. When `buildId` is provided, returns the build via `/builds/<buildId>`. When omitted, returns the app via `/apps` filtered to `appId`.",
48
+ z.object({
49
+ appId: z.string().min(1),
50
+ buildId: z.string().min(1).optional(),
51
+ }),
52
+ async (p) => {
53
+ if (p.buildId === undefined) {
54
+ return jsonResult(await codemagicGet("/apps"));
55
+ }
56
+ return jsonResult(await codemagicGet(`/builds/${encodeURIComponent(p.buildId)}`));
57
+ },
58
+ );
59
+
60
+ reg(
61
+ "codemagic_search",
62
+ "Substring search across a Codemagic app's recent builds. Matches the query against `branch`, `message`, `workflowId`, and `status` (case-insensitive). Returns a `{ matches: [...] }` envelope.",
63
+ z.object({
64
+ appId: z.string().min(1),
65
+ query: z.string().min(1),
66
+ limit: z.number().int().min(1).max(200).optional(),
67
+ }),
68
+ async (p) => {
69
+ const root = await codemagicGet(`/builds?appId=${encodeURIComponent(p.appId)}&limit=50`);
70
+ const builds = (root as { builds?: unknown[] } | null)?.builds;
71
+ return matchesResult(builds, filterCodemagicBuilds, p);
72
+ },
73
+ );
74
+ });
@@ -0,0 +1,15 @@
1
+ {
2
+ "id": "com.nimbus.confluence",
3
+ "displayName": "Confluence",
4
+ "version": "0.1.0",
5
+ "description": "Confluence REST connector (spaces, pages, search). Tenant host (`*.atlassian.net`) comes from confluence.base_url; PR 1 static manifest lists the API gateway only. Mutations require Gateway HITL.",
6
+ "author": "Nimbus",
7
+ "entrypoint": "dist/server.js",
8
+ "runtime": "bun",
9
+ "permissions": {
10
+ "network": ["api.atlassian.com"]
11
+ },
12
+ "hitlRequired": ["write", "delete"],
13
+ "syncInterval": 300,
14
+ "minNimbusVersion": "0.2.0"
15
+ }
@@ -0,0 +1,25 @@
1
+ import { type KbCitation, markdownToConfluenceStorage } from "../../../shared/kb-markdown.ts";
2
+
3
+ export interface ConfluenceKbAppendInput {
4
+ spaceKey: string;
5
+ parentPageId: string;
6
+ title: string;
7
+ bodyMarkdown: string;
8
+ citations: readonly KbCitation[];
9
+ }
10
+
11
+ /** Build the `POST /content` request body for a tribal-knowledge KB page under a parent. */
12
+ export function buildConfluenceKbPageBody(input: ConfluenceKbAppendInput): Record<string, unknown> {
13
+ return {
14
+ type: "page",
15
+ title: input.title,
16
+ space: { key: input.spaceKey },
17
+ ancestors: [{ id: input.parentPageId }],
18
+ body: {
19
+ storage: {
20
+ value: markdownToConfluenceStorage(input.bodyMarkdown, input.citations),
21
+ representation: "storage",
22
+ },
23
+ },
24
+ };
25
+ }