@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,163 @@
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 requireKubeconfigPath(): string {
12
+ const p = process.env["KUBECONFIG"]?.trim();
13
+ if (p === undefined || p === "") {
14
+ throw new Error("KUBECONFIG env must be set to a kubeconfig file path");
15
+ }
16
+ return p;
17
+ }
18
+
19
+ function kubectlBase(): string[] {
20
+ const args = ["kubectl"];
21
+ const ctx = process.env["KUBE_CONTEXT"]?.trim();
22
+ if (ctx !== undefined && ctx !== "") {
23
+ args.push("--context", ctx);
24
+ }
25
+ return args;
26
+ }
27
+
28
+ function kubeEnv(): Record<string, string | undefined> {
29
+ return { KUBECONFIG: requireKubeconfigPath() };
30
+ }
31
+
32
+ async function kubectlJson(rest: string[]): Promise<unknown> {
33
+ const cmd = [...kubectlBase(), ...rest, "-o", "json"];
34
+ const r = await runCliJson(cmd, kubeEnv());
35
+ if (!r.ok) {
36
+ throw new Error(r.message);
37
+ }
38
+ return r.data;
39
+ }
40
+
41
+ const optionalNamespaceSchema = z.object({ namespace: z.string().min(1).optional() });
42
+
43
+ async function k8sListNamespacedResource(p: { namespace?: string | undefined }, resource: string) {
44
+ const ns = p.namespace ?? "default";
45
+ const data = await kubectlJson(["get", resource, "-n", ns]);
46
+ return jsonResult(data ?? {});
47
+ }
48
+
49
+ const mcp = new McpServer({ name: "nimbus-kubernetes", version: "0.1.0" });
50
+
51
+ import { createWriteToolRegistrar } from "../../../shared/consent-kit.ts";
52
+
53
+ const reg = createZodToolRegistrar(createRegisterSimpleTool(mcp));
54
+
55
+ /**
56
+ * Every MUTATING kubernetes tool goes through here. Outside the gateway this adds the
57
+ * consent gate, the write-scope allow-list, the mutation budget and the audit record; inside
58
+ * the gateway it is a pass-through, because executor.ts (I2) is the gate there.
59
+ */
60
+ const registerWriteTool = createWriteToolRegistrar(mcp, {
61
+ connector: "kubernetes",
62
+ scopeEnv: "NIMBUS_MCP_KUBERNETES_WRITE_SCOPE",
63
+ scopeKinds: ["namespace"],
64
+ });
65
+
66
+ reg(
67
+ "k8s_pod_list",
68
+ "List pods in a namespace (default namespace: default).",
69
+ optionalNamespaceSchema,
70
+ (p) => k8sListNamespacedResource(p, "pods"),
71
+ );
72
+
73
+ reg("k8s_deployment_list", "List deployments in a namespace.", optionalNamespaceSchema, (p) =>
74
+ k8sListNamespacedResource(p, "deployments"),
75
+ );
76
+
77
+ reg("k8s_event_list", "List events in a namespace.", optionalNamespaceSchema, (p) =>
78
+ k8sListNamespacedResource(p, "events"),
79
+ );
80
+
81
+ registerWriteTool(
82
+ "k8s_rollout_restart",
83
+ {
84
+ mutates: "kubernetes.rollout.restart",
85
+ recoverable: true,
86
+ scopeTargetOf: (p) => ({ kind: "namespace", value: p.namespace ?? "default" }),
87
+ },
88
+ "Restart a rollout (e.g. deployment).",
89
+ z.object({
90
+ namespace: z.string().min(1).optional(),
91
+ resourceType: z.string().min(1),
92
+ name: z.string().min(1),
93
+ }),
94
+ async (p) => {
95
+ const ns = p.namespace ?? "default";
96
+ const cmd = [...kubectlBase(), "rollout", "restart", p.resourceType, p.name, "-n", ns];
97
+ const r = await runCliOk(cmd, kubeEnv());
98
+ if (!r.ok) {
99
+ throw new Error(r.message);
100
+ }
101
+ return jsonResult({ ok: true });
102
+ },
103
+ );
104
+
105
+ registerWriteTool(
106
+ "k8s_pod_delete",
107
+ {
108
+ mutates: "kubernetes.pod.delete",
109
+ // A deleted pod is not restorable; its identity is all that remains to record.
110
+ recoverable: false,
111
+ capturePreState: (p) => Promise.resolve({ namespace: p.namespace, podName: p.podName }),
112
+ scopeTargetOf: (p) => ({ kind: "namespace", value: p.namespace ?? "default" }),
113
+ },
114
+ "Delete a pod.",
115
+ z.object({
116
+ namespace: z.string().min(1).optional(),
117
+ podName: z.string().min(1),
118
+ }),
119
+ async (p) => {
120
+ const ns = p.namespace ?? "default";
121
+ const cmd = [...kubectlBase(), "delete", "pod", p.podName, "-n", ns];
122
+ const r = await runCliOk(cmd, kubeEnv());
123
+ if (!r.ok) {
124
+ throw new Error(r.message);
125
+ }
126
+ return jsonResult({ ok: true });
127
+ },
128
+ );
129
+
130
+ registerWriteTool(
131
+ "k8s_deployment_scale",
132
+ {
133
+ mutates: "kubernetes.deployment.scale",
134
+ recoverable: true,
135
+ scopeTargetOf: (p) => ({ kind: "namespace", value: p.namespace ?? "default" }),
136
+ },
137
+ "Scale a deployment.",
138
+ z.object({
139
+ namespace: z.string().min(1).optional(),
140
+ deploymentName: z.string().min(1),
141
+ replicas: z.number().int().min(0),
142
+ }),
143
+ async (p) => {
144
+ const ns = p.namespace ?? "default";
145
+ const cmd = [
146
+ ...kubectlBase(),
147
+ "scale",
148
+ "deployment",
149
+ p.deploymentName,
150
+ `-n`,
151
+ ns,
152
+ `--replicas=${String(p.replicas)}`,
153
+ ];
154
+ const r = await runCliOk(cmd, kubeEnv());
155
+ if (!r.ok) {
156
+ throw new Error(r.message);
157
+ }
158
+ return jsonResult({ ok: true });
159
+ },
160
+ );
161
+
162
+ const transport = new StdioServerTransport();
163
+ await mcp.connect(transport);
@@ -0,0 +1,15 @@
1
+ {
2
+ "id": "com.nimbus.launchdarkly",
3
+ "displayName": "LaunchDarkly",
4
+ "version": "0.1.0",
5
+ "description": "LaunchDarkly feature-flag connector (read-only). Surfaces flag key, name, kind, tags, per-environment on/off state, maintainer, and timestamps into the local index as `launchdarkly:feature_flag` items — useful for incident correlation (\"was this flag enabled when the alert fired?\"). API-token auth. Regional / federal instances override `launchdarkly.base_url`; the SaaS host (app.launchdarkly.com) is the only one in the static sandbox manifest today (Task 14 runtime-merge follow-up). The `launchdarkly.flag.toggle` write tool is a deferred Phase 8 follow-up.",
6
+ "author": "Nimbus",
7
+ "entrypoint": "dist/server.js",
8
+ "runtime": "bun",
9
+ "permissions": {
10
+ "network": ["app.launchdarkly.com"]
11
+ },
12
+ "hitlRequired": [],
13
+ "syncInterval": 600,
14
+ "minNimbusVersion": "0.2.0"
15
+ }
@@ -0,0 +1,31 @@
1
+ import {
2
+ asObjectish,
3
+ makeQueryFilter,
4
+ type SearchMatchOptions,
5
+ stringField,
6
+ } from "../../../shared/search-filter.ts";
7
+
8
+ export type LaunchDarklySearchMatchOptions = SearchMatchOptions;
9
+
10
+ function tagsString(row: Record<string, unknown>): string {
11
+ const tags = row["tags"];
12
+ if (!Array.isArray(tags)) {
13
+ return "";
14
+ }
15
+ return tags.filter((t): t is string => typeof t === "string").join(" ");
16
+ }
17
+
18
+ function fieldsOf(item: unknown): readonly string[] | null {
19
+ const row = asObjectish(item);
20
+ if (row === undefined) {
21
+ return null;
22
+ }
23
+ return [
24
+ stringField(row, "key"),
25
+ stringField(row, "name"),
26
+ stringField(row, "description"),
27
+ tagsString(row),
28
+ ];
29
+ }
30
+
31
+ export const filterLaunchDarklyFlags = makeQueryFilter(fieldsOf);
@@ -0,0 +1,79 @@
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 { filterLaunchDarklyFlags } from "./search-filter.ts";
6
+
7
+ const DEFAULT_BASE = "https://app.launchdarkly.com";
8
+
9
+ function baseUrl(): string {
10
+ const v = process.env["LAUNCHDARKLY_BASE_URL"]?.trim();
11
+ return v === undefined || v === "" ? DEFAULT_BASE : v;
12
+ }
13
+
14
+ function authHeader(): Record<string, string> {
15
+ const t = process.env["LAUNCHDARKLY_TOKEN"]?.trim();
16
+ if (t === undefined || t === "") {
17
+ throw new Error("LAUNCHDARKLY_TOKEN is not set");
18
+ }
19
+ return { Authorization: t, Accept: "application/json" };
20
+ }
21
+
22
+ async function ldGet(path: string): Promise<unknown> {
23
+ const res = await fetch(`${baseUrl()}/api/v2${path}`, { headers: authHeader() });
24
+ const text = await res.text();
25
+ if (!res.ok) {
26
+ throw new Error(`LaunchDarkly ${String(res.status)}: ${text.slice(0, 400)}`);
27
+ }
28
+ return JSON.parse(text) as unknown;
29
+ }
30
+
31
+ await runReadOnlyMcpConnector("nimbus-launchdarkly", (reg) => {
32
+ reg(
33
+ "launchdarkly_list",
34
+ "List LaunchDarkly projects, or feature flags for a project. Without `projectKey`, returns the account's projects (`/projects`). With `projectKey`, returns that project's flags (`/flags/{projectKey}`), capped at `limit` (default 100).",
35
+ z.object({
36
+ projectKey: z.string().min(1).optional(),
37
+ limit: z.number().int().min(1).max(500).optional(),
38
+ }),
39
+ async (p) => {
40
+ if (p.projectKey === undefined) {
41
+ return jsonResult(await ldGet("/projects"));
42
+ }
43
+ const search = new URLSearchParams({ summary: "true", limit: String(p.limit ?? 100) });
44
+ return jsonResult(
45
+ await ldGet(`/flags/${encodeURIComponent(p.projectKey)}?${search.toString()}`),
46
+ );
47
+ },
48
+ );
49
+
50
+ reg(
51
+ "launchdarkly_get",
52
+ "Fetch one LaunchDarkly feature flag by project key + flag key. Throws when no match is found.",
53
+ z.object({
54
+ projectKey: z.string().min(1),
55
+ flagKey: z.string().min(1),
56
+ }),
57
+ async (p) => {
58
+ return jsonResult(
59
+ await ldGet(`/flags/${encodeURIComponent(p.projectKey)}/${encodeURIComponent(p.flagKey)}`),
60
+ );
61
+ },
62
+ );
63
+
64
+ reg(
65
+ "launchdarkly_search",
66
+ "Substring search across a project's feature flags. Matches the query against flag key, name, description, and tags (case-insensitive). Returns a `{ matches: [...] }` envelope.",
67
+ z.object({
68
+ projectKey: z.string().min(1),
69
+ query: z.string().min(1),
70
+ limit: z.number().int().min(1).max(200).optional(),
71
+ }),
72
+ async (p) => {
73
+ const search = new URLSearchParams({ summary: "true", limit: "500" });
74
+ const root = await ldGet(`/flags/${encodeURIComponent(p.projectKey)}?${search.toString()}`);
75
+ const flags = (root as { items?: unknown[] } | null)?.items;
76
+ return matchesResult(flags, filterLaunchDarklyFlags, p);
77
+ },
78
+ );
79
+ });
@@ -0,0 +1,15 @@
1
+ {
2
+ "id": "com.nimbus.lever",
3
+ "displayName": "Lever",
4
+ "version": "0.1.0",
5
+ "description": "Lever connector (read-only). Surfaces the company's published Lever job postings as `lever:posting` items in the local index — the posting title, the team/department/location/commitment/level categories, the workflow state, tags, the hosted job-page URL and apply URL, and the requisition code. Useful for answering recruiting questions (\"which backend roles are open?\", \"find the posting for the staff SRE position\") without leaving Nimbus. HTTP Basic auth where the Lever API key is the username and the password is empty (`Authorization: Basic base64(<api_key>:)` — the trailing colon is the empty password; never logged). The SaaS host (api.lever.co) is fixed. Lever paginates `/v1/postings` with a `hasNext` flag plus a `next` offset cursor, returning the `{ data, hasNext, next }` envelope. `createdAt` / `updatedAt` are epoch MILLISECONDS (passed through verbatim on index — NO parse, NO ×1000). Opportunities / candidates are deliberately deferred (candidate PII; out of scope for v1) — v1 indexes job postings only.",
6
+ "author": "Nimbus",
7
+ "entrypoint": "dist/server.js",
8
+ "runtime": "bun",
9
+ "permissions": {
10
+ "network": ["api.lever.co"]
11
+ },
12
+ "hitlRequired": [],
13
+ "syncInterval": 600,
14
+ "minNimbusVersion": "0.2.0"
15
+ }
@@ -0,0 +1,35 @@
1
+ import {
2
+ asObjectish,
3
+ makeQueryFilter,
4
+ type SearchMatchOptions,
5
+ stringField,
6
+ tagText,
7
+ } from "../../../shared/search-filter.ts";
8
+
9
+ export type LeverSearchMatchOptions = SearchMatchOptions;
10
+
11
+ function categoryField(row: Record<string, unknown>, key: string): string {
12
+ const cats = row["categories"];
13
+ if (cats === null || typeof cats !== "object" || Array.isArray(cats)) {
14
+ return "";
15
+ }
16
+ const v = (cats as Record<string, unknown>)[key];
17
+ return typeof v === "string" ? v : "";
18
+ }
19
+
20
+ function fieldsOf(item: unknown): readonly string[] | null {
21
+ const row = asObjectish(item);
22
+ if (row === undefined) {
23
+ return null;
24
+ }
25
+ return [
26
+ stringField(row, "text"),
27
+ stringField(row, "state"),
28
+ categoryField(row, "team"),
29
+ categoryField(row, "department"),
30
+ categoryField(row, "location"),
31
+ tagText(row),
32
+ ];
33
+ }
34
+
35
+ export const filterLeverPostings = makeQueryFilter(fieldsOf);
@@ -0,0 +1,64 @@
1
+ import { z } from "zod";
2
+ import { matchesResult, searchToolInputSchema } from "../../../shared/mcp-search-tool.ts";
3
+ import {
4
+ encodeBasicAuthHeader,
5
+ mcpJsonResult as jsonResult,
6
+ } from "../../../shared/mcp-tool-kit.ts";
7
+ import { runReadOnlyMcpConnector } from "../../../shared/run-read-only-mcp-connector.ts";
8
+ import { filterLeverPostings } from "./search-filter.ts";
9
+
10
+ const BASE = "https://api.lever.co";
11
+
12
+ function apiKey(): string {
13
+ const t = process.env["LEVER_API_KEY"]?.trim();
14
+ if (t === undefined || t === "") {
15
+ throw new Error("LEVER_API_KEY is not set");
16
+ }
17
+ return t;
18
+ }
19
+
20
+ function authHeader(): Record<string, string> {
21
+ return { Authorization: encodeBasicAuthHeader(apiKey(), ""), Accept: "application/json" };
22
+ }
23
+
24
+ async function leverGet(path: string): Promise<unknown> {
25
+ const res = await fetch(`${BASE}${path}`, { headers: authHeader() });
26
+ const text = await res.text();
27
+ if (!res.ok) {
28
+ throw new Error(`Lever ${String(res.status)}: ${text.slice(0, 400)}`);
29
+ }
30
+ return JSON.parse(text) as unknown;
31
+ }
32
+
33
+ await runReadOnlyMcpConnector("nimbus-lever", (reg) => {
34
+ reg(
35
+ "lever_list",
36
+ "List the company's published Lever job postings (`GET /v1/postings?limit=100`). Returns the offset-cursor envelope `{ data: [...], hasNext: boolean, next?: string }` — `data` holds the posting objects.",
37
+ z.object({}),
38
+ async () => {
39
+ return jsonResult(await leverGet(`/v1/postings?limit=100`));
40
+ },
41
+ );
42
+
43
+ reg(
44
+ "lever_get",
45
+ "Fetch one Lever job posting by its id (`GET /v1/postings/{id}`). Returns the `{ data: {...} }` envelope. Throws when no match is found.",
46
+ z.object({
47
+ id: z.string().min(1),
48
+ }),
49
+ async (p) => {
50
+ return jsonResult(await leverGet(`/v1/postings/${encodeURIComponent(p.id)}`));
51
+ },
52
+ );
53
+
54
+ reg(
55
+ "lever_search",
56
+ "Substring search across the company's Lever job postings (first page only). Matches the query against the posting text (title), state, and the team/department/location categories and tags (case-insensitive). Returns a `{ matches: [...] }` envelope.",
57
+ searchToolInputSchema(100),
58
+ async (p) => {
59
+ const root = await leverGet(`/v1/postings?limit=100`);
60
+ const data = (root as { data?: unknown[] } | null)?.data;
61
+ return matchesResult(data, filterLeverPostings, p);
62
+ },
63
+ );
64
+ });
@@ -0,0 +1,15 @@
1
+ {
2
+ "id": "com.nimbus.linear",
3
+ "displayName": "Linear",
4
+ "version": "0.1.0",
5
+ "description": "Linear GraphQL connector (issues, projects, cycles). Mutations require Gateway HITL.",
6
+ "author": "Nimbus",
7
+ "entrypoint": "dist/server.js",
8
+ "runtime": "bun",
9
+ "permissions": {
10
+ "network": ["api.linear.app"]
11
+ },
12
+ "hitlRequired": ["write", "delete"],
13
+ "syncInterval": 300,
14
+ "minNimbusVersion": "0.2.0"
15
+ }