@nimbus-dev/connectors 0.2.2 → 0.2.4

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 (46) hide show
  1. package/README.md +5 -3
  2. package/connectors/apple/src/server.ts +5 -1
  3. package/connectors/athena/src/tools.ts +12 -10
  4. package/connectors/aws/src/server.ts +5 -1
  5. package/connectors/aws/src/tools.ts +9 -7
  6. package/connectors/azure/src/server.ts +5 -1
  7. package/connectors/azure/src/tools.ts +10 -9
  8. package/connectors/bitbucket/src/server.ts +5 -1
  9. package/connectors/circleci/src/server.ts +5 -1
  10. package/connectors/cloud-logging/src/tools.ts +5 -8
  11. package/connectors/cloudwatch/src/tools.ts +6 -5
  12. package/connectors/confluence/src/server.ts +5 -1
  13. package/connectors/fastmail/src/server.ts +5 -1
  14. package/connectors/gcp/src/server.ts +5 -1
  15. package/connectors/gcp/src/tools.ts +11 -11
  16. package/connectors/github/src/server.ts +2 -0
  17. package/connectors/github-actions/src/server.ts +5 -1
  18. package/connectors/gitlab/src/server.ts +5 -1
  19. package/connectors/gmail/src/server.ts +5 -1
  20. package/connectors/google-drive/src/server.ts +5 -1
  21. package/connectors/iac/src/server.ts +5 -1
  22. package/connectors/iac/src/tools.ts +83 -25
  23. package/connectors/imap/src/server.ts +5 -1
  24. package/connectors/jenkins/src/server.ts +5 -1
  25. package/connectors/jira/src/server.ts +5 -1
  26. package/connectors/kubernetes/src/server.ts +5 -1
  27. package/connectors/kubernetes/src/tools.ts +9 -8
  28. package/connectors/linear/src/server.ts +5 -1
  29. package/connectors/notion/src/server.ts +5 -1
  30. package/connectors/obsidian/src/server.ts +5 -1
  31. package/connectors/onedrive/src/server.ts +5 -1
  32. package/connectors/outlook/src/server.ts +5 -1
  33. package/connectors/pagerduty/src/server.ts +5 -1
  34. package/connectors/protonmail/src/server.ts +5 -1
  35. package/connectors/sagemaker/src/tools.ts +5 -5
  36. package/connectors/slack/src/server.ts +5 -1
  37. package/connectors/teams/src/server.ts +5 -1
  38. package/package.json +1 -1
  39. package/shared/audit-chain.ts +588 -28
  40. package/shared/cli-json-kit.ts +35 -6
  41. package/shared/consent-kit.ts +115 -38
  42. package/shared/nimbus-spawn.ts +114 -27
  43. package/shared/run-read-only-mcp-connector.ts +7 -1
  44. package/shared/safe-cli-arg.ts +119 -17
  45. package/shared/windows-batch-args.ts +274 -0
  46. package/shared/write-budget.ts +100 -0
package/README.md CHANGED
@@ -21,7 +21,9 @@ Run standalone, a connector gives you:
21
21
  parameters in front of you, and does nothing unless you approve.
22
22
  - **A write-scope allow-list**, enforced by the server and unreachable by the model.
23
23
  - **A mutation budget** per session, which caps a runaway agent loop.
24
- - **A local, hash-chained, append-only audit log**, when `NIMBUS_MCP_AUDIT_LOG` is set.
24
+ - **A local, hash-chained, append-only audit log**, when `NIMBUS_MCP_AUDIT_LOG` is set — one file
25
+ can serve every connector you run, within the bounds
26
+ [Configuration](./docs/configuration.md#the-audit-log) lists.
25
27
 
26
28
  It does **not** give you the process sandbox, OS-keychain credential storage, the egress ledger, or
27
29
  owner-controlled consent. Those are properties of the Nimbus gateway and no published package can
@@ -62,8 +64,8 @@ Full matrix, versions tested, and the provenance of each claim:
62
64
  ```
63
65
 
64
66
  Credentials come from the environment. There is no Vault outside the gateway, so whoever writes this
65
- config holds the secret. Every variable, and the two behaviours that look like bugs and are not, are
66
- in [Configuration](./docs/configuration.md).
67
+ config holds the secret. Every variable, and the three behaviours that look like bugs and are not,
68
+ are in [Configuration](./docs/configuration.md).
67
69
 
68
70
  Each connector has its own README at `connectors/<id>/README.md`. Most list their tools and
69
71
  credentials, but some — `github`, `slack` and `jira` among them — are still only a short gateway
@@ -12,6 +12,7 @@
12
12
 
13
13
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
14
14
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
15
+ import { CONSENT_SERVER_CAPABILITIES } from "../../../shared/consent-kit.ts";
15
16
  import { requireProcessEnv } from "../../../shared/mcp-tool-kit.ts";
16
17
  import {
17
18
  createAppleCalDavClient,
@@ -39,7 +40,10 @@ try {
39
40
  // non-fatal; listEvents/list tools will re-discover on demand
40
41
  }
41
42
 
42
- const server = new McpServer({ name: "nimbus-apple", version: "0.1.0" });
43
+ const server = new McpServer(
44
+ { name: "nimbus-apple", version: "0.1.0" },
45
+ { capabilities: CONSENT_SERVER_CAPABILITIES },
46
+ );
43
47
 
44
48
  registerAppleTools(server, {
45
49
  client: createAppleImapClient(email, appPw),
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import {
3
3
  asArray,
4
- cliArg,
4
+ awsCliArg,
5
5
  createCliJsonRunner,
6
6
  isRecord,
7
7
  strField,
@@ -12,8 +12,10 @@ import type { ZodToolRegistrar } from "../../../shared/run-read-only-mcp-connect
12
12
 
13
13
  /**
14
14
  * A catalog / database / table name passed as a value to the `aws athena` CLI.
15
- * Rejected at the schema boundary if it begins with `-` (argv flag smuggling) or
16
- * contains control characters.
15
+ * Rejected at the schema boundary (`awsCliArg`) if it begins with `-` (argv flag
16
+ * smuggling), contains control characters, or starts with a prefix that makes the
17
+ * CLI read the value from a file or a URL instead — `file://<path>` as a table name
18
+ * would send that file to AWS, and an error can quote it back.
17
19
  */
18
20
 
19
21
  /**
@@ -70,8 +72,8 @@ export function registerAthenaTools(reg: ZodToolRegistrar): void {
70
72
  "athena_list",
71
73
  "List Athena data catalogs, the databases in a catalog, or the tables in a database — METADATA ONLY. With no arguments, lists data catalogs (`aws athena list-data-catalogs`). With `catalog` set, lists that catalog's databases (`aws athena list-databases`). With `catalog` + `database` set, lists that database's table metadata (`aws athena list-table-metadata`) — each entry carries `Name`, `TableType`, `Columns`, and `PartitionKeys`. Never runs a query or returns row/cell data.",
72
74
  z.object({
73
- catalog: cliArg.optional(),
74
- database: cliArg.optional(),
75
+ catalog: awsCliArg.optional(),
76
+ database: awsCliArg.optional(),
75
77
  }),
76
78
  async (p) => {
77
79
  if (p.catalog === undefined) {
@@ -100,9 +102,9 @@ export function registerAthenaTools(reg: ZodToolRegistrar): void {
100
102
  "athena_get",
101
103
  "Fetch one Athena table's schema + METADATA (`aws athena get-table-metadata`). Returns the table object including `Columns` (column names + types only), `PartitionKeys`, `TableType`, `Parameters`, and timestamps. No cell values or query results are returned — schema/metadata only.",
102
104
  z.object({
103
- catalog: cliArg,
104
- database: cliArg,
105
- table: cliArg,
105
+ catalog: awsCliArg,
106
+ database: awsCliArg,
107
+ table: awsCliArg,
106
108
  }),
107
109
  async (p) => {
108
110
  return jsonResult(
@@ -123,8 +125,8 @@ export function registerAthenaTools(reg: ZodToolRegistrar): void {
123
125
  "athena_search",
124
126
  "Substring search over Athena catalog, database, and table NAMES (case-insensitive) — METADATA ONLY. With no `catalog`, searches data-catalog names. With `catalog` set (no `database`), searches that catalog's database names. With `catalog` + `database` set, searches that database's table names. Returns a `{ matches: [...] }` envelope of metadata entries. Never runs a query or samples row data.",
125
127
  z.object({
126
- catalog: cliArg.optional(),
127
- database: cliArg.optional(),
128
+ catalog: awsCliArg.optional(),
129
+ database: awsCliArg.optional(),
128
130
  query: z.string().min(1),
129
131
  }),
130
132
  async (p) => {
@@ -1,8 +1,12 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CONSENT_SERVER_CAPABILITIES } from "../../../shared/consent-kit.ts";
3
4
  import { registerAwsTools } from "./tools.ts";
4
5
 
5
- const mcp = new McpServer({ name: "nimbus-aws", version: "0.1.0" });
6
+ const mcp = new McpServer(
7
+ { name: "nimbus-aws", version: "0.1.0" },
8
+ { capabilities: CONSENT_SERVER_CAPABILITIES },
9
+ );
6
10
 
7
11
  registerAwsTools(mcp);
8
12
 
@@ -2,6 +2,7 @@ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
4
  import { z } from "zod";
5
+ import { awsCliArg } from "../../../shared/cli-json-kit.ts";
5
6
  import type { ConsentServer } from "../../../shared/consent-kit.ts";
6
7
  import { createWriteToolRegistrar } from "../../../shared/consent-kit.ts";
7
8
  import {
@@ -66,7 +67,7 @@ export function registerAwsTools(
66
67
  reg(
67
68
  "aws_ecs_service_list",
68
69
  "List ECS services in a cluster.",
69
- z.object({ cluster: z.string().min(1) }),
70
+ z.object({ cluster: awsCliArg }),
70
71
  async (p) => jsonResult(await awsJson(["ecs", "list-services", "--cluster", p.cluster])),
71
72
  );
72
73
 
@@ -83,9 +84,9 @@ export function registerAwsTools(
83
84
  },
84
85
  "Update ECS service (e.g. new task definition).",
85
86
  z.object({
86
- cluster: z.string().min(1),
87
- service: z.string().min(1),
88
- taskDefinition: z.string().min(1),
87
+ cluster: awsCliArg,
88
+ service: awsCliArg,
89
+ taskDefinition: awsCliArg,
89
90
  }),
90
91
  async (p) => {
91
92
  const cmd = [
@@ -114,7 +115,8 @@ export function registerAwsTools(
114
115
  },
115
116
  "Invoke a Lambda function.",
116
117
  z.object({
117
- functionName: z.string().min(1),
118
+ functionName: awsCliArg,
119
+ // Written to a temp file the CLI is pointed at with file://, never passed as an argument.
118
120
  payloadJson: z.string().optional(),
119
121
  }),
120
122
  async (p) => {
@@ -167,7 +169,7 @@ export function registerAwsTools(
167
169
  scopeTargetOf: (p) => ({ kind: "instance", value: p.instanceIds }),
168
170
  },
169
171
  "Stop EC2 instances.",
170
- z.object({ instanceIds: z.string().min(1) }),
172
+ z.object({ instanceIds: awsCliArg }),
171
173
  async (p) => {
172
174
  await runCliOkThrowing(
173
175
  ["aws", "ec2", "stop-instances", "--instance-ids", p.instanceIds],
@@ -185,7 +187,7 @@ export function registerAwsTools(
185
187
  scopeTargetOf: (p) => ({ kind: "instance", value: p.instanceIds }),
186
188
  },
187
189
  "Start EC2 instances.",
188
- z.object({ instanceIds: z.string().min(1) }),
190
+ z.object({ instanceIds: awsCliArg }),
189
191
  async (p) => {
190
192
  await runCliOkThrowing(
191
193
  ["aws", "ec2", "start-instances", "--instance-ids", p.instanceIds],
@@ -1,8 +1,12 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CONSENT_SERVER_CAPABILITIES } from "../../../shared/consent-kit.ts";
3
4
  import { registerAzureTools } from "./tools.ts";
4
5
 
5
- const mcp = new McpServer({ name: "nimbus-azure", version: "0.1.0" });
6
+ const mcp = new McpServer(
7
+ { name: "nimbus-azure", version: "0.1.0" },
8
+ { capabilities: CONSENT_SERVER_CAPABILITIES },
9
+ );
6
10
 
7
11
  registerAzureTools(mcp);
8
12
 
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { azCliArg } from "../../../shared/cli-json-kit.ts";
2
3
  import type { ConsentServer } from "../../../shared/consent-kit.ts";
3
4
  import { createWriteToolRegistrar } from "../../../shared/consent-kit.ts";
4
5
  import {
@@ -44,8 +45,8 @@ export function registerAzureTools(
44
45
  "azure_app_service_list",
45
46
  "List App Services in a resource group.",
46
47
  z.object({
47
- subscriptionId: z.string().min(1),
48
- resourceGroup: z.string().min(1),
48
+ subscriptionId: azCliArg,
49
+ resourceGroup: azCliArg,
49
50
  }),
50
51
  async (p) =>
51
52
  jsonResult(
@@ -69,9 +70,9 @@ export function registerAzureTools(
69
70
  },
70
71
  "Restart an App Service.",
71
72
  z.object({
72
- subscriptionId: z.string().min(1),
73
- resourceGroup: z.string().min(1),
74
- name: z.string().min(1),
73
+ subscriptionId: azCliArg,
74
+ resourceGroup: azCliArg,
75
+ name: azCliArg,
75
76
  }),
76
77
  async (p) => {
77
78
  await runCliOkThrowing(
@@ -101,10 +102,10 @@ export function registerAzureTools(
101
102
  },
102
103
  "Scale an AKS node pool.",
103
104
  z.object({
104
- subscriptionId: z.string().min(1),
105
- resourceGroup: z.string().min(1),
106
- clusterName: z.string().min(1),
107
- poolName: z.string().min(1),
105
+ subscriptionId: azCliArg,
106
+ resourceGroup: azCliArg,
107
+ clusterName: azCliArg,
108
+ poolName: azCliArg,
108
109
  nodeCount: z.number().int().min(0),
109
110
  }),
110
111
  async (p) => {
@@ -1,8 +1,12 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CONSENT_SERVER_CAPABILITIES } from "../../../shared/consent-kit.ts";
3
4
  import { registerBitbucketTools } from "./tools.ts";
4
5
 
5
- const server = new McpServer({ name: "nimbus-bitbucket", version: "0.1.0" });
6
+ const server = new McpServer(
7
+ { name: "nimbus-bitbucket", version: "0.1.0" },
8
+ { capabilities: CONSENT_SERVER_CAPABILITIES },
9
+ );
6
10
 
7
11
  registerBitbucketTools(server);
8
12
 
@@ -1,8 +1,12 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CONSENT_SERVER_CAPABILITIES } from "../../../shared/consent-kit.ts";
3
4
  import { registerCircleciTools } from "./tools.ts";
4
5
 
5
- const mcp = new McpServer({ name: "nimbus-circleci", version: "0.1.0" });
6
+ const mcp = new McpServer(
7
+ { name: "nimbus-circleci", version: "0.1.0" },
8
+ { capabilities: CONSENT_SERVER_CAPABILITIES },
9
+ );
6
10
 
7
11
  registerCircleciTools(mcp);
8
12
 
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import {
3
+ cliArg,
3
4
  createCliJsonRunner,
4
5
  gcloudProjectArgs,
5
6
  isRecord,
@@ -8,7 +9,6 @@ import {
8
9
  import { mcpJsonResult as jsonResult } from "../../../shared/mcp-tool-kit.ts";
9
10
  import { nimbusSpawn } from "../../../shared/nimbus-spawn.ts";
10
11
  import type { ZodToolRegistrar } from "../../../shared/run-read-only-mcp-connector.ts";
11
- import { assertSafeCliArg } from "../../../shared/safe-cli-arg.ts";
12
12
 
13
13
  /**
14
14
  * GCP Cloud Logging (Tier-3, no-row-data) MCP tool surface. ALL tools index log
@@ -75,15 +75,12 @@ export function registerCloudLoggingTools(reg: ZodToolRegistrar): void {
75
75
  "cloud_logging_get",
76
76
  "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.",
77
77
  z.object({
78
- sinkName: z.string().min(1),
78
+ // A bare positional to `gcloud logging sinks describe`, so it is refused here, at the
79
+ // schema, if gcloud would misread it: a value starting with "-" would be parsed as a flag.
80
+ sinkName: cliArg,
79
81
  }),
80
82
  async (p) => {
81
- // `sinkName` is a bare positional to `gcloud logging sinks describe`; guard
82
- // against argv flag smuggling (a value beginning with "-" would be parsed as
83
- // a gcloud flag).
84
- return jsonResult(
85
- await gcloudLogging(["sinks", "describe", assertSafeCliArg(p.sinkName, "sinkName")]),
86
- );
83
+ return jsonResult(await gcloudLogging(["sinks", "describe", p.sinkName]));
87
84
  },
88
85
  );
89
86
 
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import {
3
3
  asArray,
4
- cliArg,
4
+ awsCliArg,
5
5
  createCliJsonRunner,
6
6
  isRecord,
7
7
  strField,
@@ -12,8 +12,9 @@ import type { ZodToolRegistrar } from "../../../shared/run-read-only-mcp-connect
12
12
 
13
13
  /**
14
14
  * A log-group name / prefix passed as a value to the `aws logs` CLI. Rejected at
15
- * the schema boundary if it begins with `-` (argv flag smuggling) or contains
16
- * control characters.
15
+ * the schema boundary (`awsCliArg`) if it begins with `-` (argv flag smuggling),
16
+ * contains control characters, or starts with a prefix that makes the CLI read the
17
+ * value from a file or a URL instead.
17
18
  */
18
19
 
19
20
  /**
@@ -65,7 +66,7 @@ export function registerCloudwatchTools(reg: ZodToolRegistrar): void {
65
66
  "cloudwatch_list",
66
67
  "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.",
67
68
  z.object({
68
- prefix: cliArg.optional(),
69
+ prefix: awsCliArg.optional(),
69
70
  }),
70
71
  async (p) => {
71
72
  const args = ["describe-log-groups", "--limit", LIMIT];
@@ -80,7 +81,7 @@ export function registerCloudwatchTools(reg: ZodToolRegistrar): void {
80
81
  "cloudwatch_get",
81
82
  "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.",
82
83
  z.object({
83
- logGroupName: cliArg,
84
+ logGroupName: awsCliArg,
84
85
  }),
85
86
  async (p) => {
86
87
  const group = await logsCli([
@@ -1,8 +1,12 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CONSENT_SERVER_CAPABILITIES } from "../../../shared/consent-kit.ts";
3
4
  import { registerConfluenceTools } from "./tools.ts";
4
5
 
5
- const server = new McpServer({ name: "nimbus-confluence", version: "0.1.0" });
6
+ const server = new McpServer(
7
+ { name: "nimbus-confluence", version: "0.1.0" },
8
+ { capabilities: CONSENT_SERVER_CAPABILITIES },
9
+ );
6
10
 
7
11
  registerConfluenceTools(server);
8
12
 
@@ -1,9 +1,13 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CONSENT_SERVER_CAPABILITIES } from "../../../shared/consent-kit.ts";
3
4
  import { createFetchJmapClient } from "./jmap-client.ts";
4
5
  import { registerFastmailTools } from "./tools.ts";
5
6
 
6
- const server = new McpServer({ name: "nimbus-fastmail", version: "0.1.0" });
7
+ const server = new McpServer(
8
+ { name: "nimbus-fastmail", version: "0.1.0" },
9
+ { capabilities: CONSENT_SERVER_CAPABILITIES },
10
+ );
7
11
  registerFastmailTools(server, createFetchJmapClient());
8
12
 
9
13
  await server.connect(new StdioServerTransport());
@@ -1,8 +1,12 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CONSENT_SERVER_CAPABILITIES } from "../../../shared/consent-kit.ts";
3
4
  import { registerGcpTools } from "./tools.ts";
4
5
 
5
- const mcp = new McpServer({ name: "nimbus-gcp", version: "0.1.0" });
6
+ const mcp = new McpServer(
7
+ { name: "nimbus-gcp", version: "0.1.0" },
8
+ { capabilities: CONSENT_SERVER_CAPABILITIES },
9
+ );
6
10
 
7
11
  registerGcpTools(mcp);
8
12
 
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { gcloudEnv } from "../../../shared/cli-json-kit.ts";
2
+ import { cliArg, gcloudEnv } from "../../../shared/cli-json-kit.ts";
3
3
  import type { ConsentServer } from "../../../shared/consent-kit.ts";
4
4
  import { createWriteToolRegistrar } from "../../../shared/consent-kit.ts";
5
5
  import {
@@ -40,7 +40,7 @@ export function registerGcpTools(
40
40
  reg(
41
41
  "gcp_cloud_run_service_list",
42
42
  "List Cloud Run services in a region.",
43
- z.object({ projectId: z.string().min(1), region: z.string().min(1) }),
43
+ z.object({ projectId: cliArg, region: cliArg }),
44
44
  async (p) =>
45
45
  jsonResult(
46
46
  await gcloudJson([
@@ -62,10 +62,10 @@ export function registerGcpTools(
62
62
  },
63
63
  "Deploy a container image to Cloud Run.",
64
64
  z.object({
65
- projectId: z.string().min(1),
66
- region: z.string().min(1),
67
- service: z.string().min(1),
68
- image: z.string().min(1),
65
+ projectId: cliArg,
66
+ region: cliArg,
67
+ service: cliArg,
68
+ image: cliArg,
69
69
  }),
70
70
  async (p) => {
71
71
  await runCliOkThrowing(
@@ -94,11 +94,11 @@ export function registerGcpTools(
94
94
  },
95
95
  "Restart a GKE deployment rollout via kubectl (uses current cluster credentials).",
96
96
  z.object({
97
- projectId: z.string().min(1),
98
- location: z.string().min(1),
99
- cluster: z.string().min(1),
100
- namespace: z.string().min(1),
101
- deployment: z.string().min(1),
97
+ projectId: cliArg,
98
+ location: cliArg,
99
+ cluster: cliArg,
100
+ namespace: cliArg,
101
+ deployment: cliArg,
102
102
  }),
103
103
  async (p) => {
104
104
  await runCliOkThrowing(
@@ -1,10 +1,12 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CONSENT_SERVER_CAPABILITIES } from "../../../shared/consent-kit.ts";
3
4
  import { registerGithubTools } from "./tools.ts";
4
5
 
5
6
  const server = new McpServer(
6
7
  { name: "nimbus-github", version: "0.1.0" },
7
8
  {
9
+ capabilities: CONSENT_SERVER_CAPABILITIES,
8
10
  // Machine-readable security tiering, so a client can surface it rather than relying on a
9
11
  // human having read the NOTICE file.
10
12
  instructions:
@@ -1,8 +1,12 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CONSENT_SERVER_CAPABILITIES } from "../../../shared/consent-kit.ts";
3
4
  import { registerGithubActionsTools } from "./tools.ts";
4
5
 
5
- const mcp = new McpServer({ name: "nimbus-github-actions", version: "0.1.0" });
6
+ const mcp = new McpServer(
7
+ { name: "nimbus-github-actions", version: "0.1.0" },
8
+ { capabilities: CONSENT_SERVER_CAPABILITIES },
9
+ );
6
10
 
7
11
  registerGithubActionsTools(mcp);
8
12
 
@@ -1,8 +1,12 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CONSENT_SERVER_CAPABILITIES } from "../../../shared/consent-kit.ts";
3
4
  import { registerGitlabTools } from "./tools.ts";
4
5
 
5
- const server = new McpServer({ name: "nimbus-gitlab", version: "0.1.0" });
6
+ const server = new McpServer(
7
+ { name: "nimbus-gitlab", version: "0.1.0" },
8
+ { capabilities: CONSENT_SERVER_CAPABILITIES },
9
+ );
6
10
 
7
11
  registerGitlabTools(server);
8
12
 
@@ -1,8 +1,12 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CONSENT_SERVER_CAPABILITIES } from "../../../shared/consent-kit.ts";
3
4
  import { registerGmailTools } from "./tools.ts";
4
5
 
5
- const server = new McpServer({ name: "nimbus-gmail", version: "0.1.0" });
6
+ const server = new McpServer(
7
+ { name: "nimbus-gmail", version: "0.1.0" },
8
+ { capabilities: CONSENT_SERVER_CAPABILITIES },
9
+ );
6
10
 
7
11
  registerGmailTools(server);
8
12
 
@@ -1,8 +1,12 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CONSENT_SERVER_CAPABILITIES } from "../../../shared/consent-kit.ts";
3
4
  import { registerGoogleDriveTools } from "./tools.ts";
4
5
 
5
- const server = new McpServer({ name: "nimbus-google-drive", version: "0.1.0" });
6
+ const server = new McpServer(
7
+ { name: "nimbus-google-drive", version: "0.1.0" },
8
+ { capabilities: CONSENT_SERVER_CAPABILITIES },
9
+ );
6
10
 
7
11
  registerGoogleDriveTools(server);
8
12
 
@@ -1,8 +1,12 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CONSENT_SERVER_CAPABILITIES } from "../../../shared/consent-kit.ts";
3
4
  import { registerIacTools } from "./tools.ts";
4
5
 
5
- const mcp = new McpServer({ name: "nimbus-iac", version: "0.1.0" });
6
+ const mcp = new McpServer(
7
+ { name: "nimbus-iac", version: "0.1.0" },
8
+ { capabilities: CONSENT_SERVER_CAPABILITIES },
9
+ );
6
10
 
7
11
  registerIacTools(mcp);
8
12