@integrity-labs/cloud-broker 0.4.1 → 0.4.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 (2) hide show
  1. package/dist/index.js +38 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -20995,6 +20995,7 @@ function makeBrokerError(status, message, detail) {
20995
20995
  var BrokerClient = class {
20996
20996
  host;
20997
20997
  agentId;
20998
+ runId;
20998
20999
  apiKey;
20999
21000
  fetchImpl;
21000
21001
  token;
@@ -21003,6 +21004,7 @@ var BrokerClient = class {
21003
21004
  constructor(config2) {
21004
21005
  this.host = config2.host.replace(/\/+$/, "");
21005
21006
  this.agentId = config2.agentId;
21007
+ this.runId = config2.runId;
21006
21008
  this.apiKey = config2.apiKey;
21007
21009
  this.fetchImpl = config2.fetchImpl ?? fetch;
21008
21010
  this.token = config2.initialToken ?? "";
@@ -21088,25 +21090,38 @@ var BrokerClient = class {
21088
21090
  }
21089
21091
  // ────────────────────────── tool-shaped wrappers ──────────────────────────
21090
21092
  describeScope(args) {
21091
- const query = { account_id: args.account_id };
21092
- if (this.agentId) query.agent_id = this.agentId;
21093
+ if (!this.agentId) {
21094
+ throw makeBrokerError(400, "BrokerClient.describeScope requires agentId \u2014 pass it in BrokerClientConfig");
21095
+ }
21093
21096
  return this.request(
21094
21097
  "GET",
21095
21098
  "/aws/scope",
21096
- { query }
21099
+ { query: { account_id: args.account_id, agent_id: this.agentId } }
21097
21100
  );
21098
21101
  }
21099
21102
  previewRequest(args) {
21103
+ if (!this.agentId) {
21104
+ throw makeBrokerError(400, "BrokerClient.previewRequest requires agentId \u2014 pass it in BrokerClientConfig");
21105
+ }
21100
21106
  const body = { ...args };
21101
- if (this.agentId && body.agent_id === void 0) body.agent_id = this.agentId;
21107
+ if (body.agent_id === void 0) body.agent_id = this.agentId;
21102
21108
  return this.request(
21103
21109
  "POST",
21104
21110
  "/aws/scope/preview",
21105
21111
  { body }
21106
21112
  );
21107
21113
  }
21108
- requestAccess(args) {
21109
- return this.request("POST", "/aws/grants", { body: args });
21114
+ async requestAccess(args) {
21115
+ const agentId = args.agent_id ?? this.agentId;
21116
+ const runId = args.run_id ?? this.runId;
21117
+ if (!agentId) {
21118
+ throw makeBrokerError(400, "BrokerClient.requestAccess requires agent_id (pass it in args, or set agentId on BrokerClientConfig)");
21119
+ }
21120
+ if (!runId) {
21121
+ throw makeBrokerError(400, "BrokerClient.requestAccess requires run_id (pass it in args, or set runId on BrokerClientConfig)");
21122
+ }
21123
+ const body = { ...args, agent_id: agentId, run_id: runId };
21124
+ return this.request("POST", "/aws/grants", { body });
21110
21125
  }
21111
21126
  pollGrant(args) {
21112
21127
  return this.request("GET", `/aws/grants/${encodeURIComponent(args.grant_id)}`);
@@ -21136,8 +21151,16 @@ var previewRequestSchema = external_exports.object({
21136
21151
  ttl_seconds: ttlSecondsSchema
21137
21152
  });
21138
21153
  var requestAccessSchema = external_exports.object({
21139
- agent_id: external_exports.string().uuid("agent_id must be a UUID"),
21140
- run_id: external_exports.string().uuid("run_id must be a UUID"),
21154
+ // ENG-4746: agent_id and run_id are optional. The MCP server fills them
21155
+ // from AGT_AGENT_ID / AGT_RUN_ID env at provision time, so the agent
21156
+ // doesn't need to know its own UUID. Pass them explicitly only to
21157
+ // attribute the grant to a different agent or run (e.g. delegated work).
21158
+ agent_id: external_exports.string().uuid("agent_id must be a UUID").optional().describe(
21159
+ "Optional. Defaults to the host MCP env (AGT_AGENT_ID). Pass explicitly only to attribute the grant to a different agent."
21160
+ ),
21161
+ run_id: external_exports.string().uuid("run_id must be a UUID").optional().describe(
21162
+ "Optional. Defaults to the host MCP env (AGT_RUN_ID). Pass explicitly only to attribute the grant to a different run."
21163
+ ),
21141
21164
  account_id: accountIdSchema,
21142
21165
  actions: actionListSchema,
21143
21166
  resources: resourceListSchema,
@@ -21163,6 +21186,7 @@ var releaseAccessShape = releaseAccessSchema.shape;
21163
21186
  // src/index.ts
21164
21187
  var AGT_HOST = process.env.AGT_HOST;
21165
21188
  var AGT_AGENT_ID = process.env.AGT_AGENT_ID;
21189
+ var AGT_RUN_ID = process.env.AGT_RUN_ID ?? "";
21166
21190
  var AGT_TOKEN = process.env.AGT_TOKEN ?? "";
21167
21191
  var AGT_API_KEY = process.env.AGT_API_KEY ?? "";
21168
21192
  if (!AGT_HOST || !AGT_AGENT_ID || !AGT_TOKEN && !AGT_API_KEY) {
@@ -21179,6 +21203,10 @@ if (process.env.AGT_TEAM_SLUG) {
21179
21203
  var broker = new BrokerClient({
21180
21204
  host: AGT_HOST,
21181
21205
  agentId: AGT_AGENT_ID,
21206
+ // ENG-4746: thread AGT_RUN_ID through so request_access can default it.
21207
+ // Empty string is treated as absent — the broker client only fills runId
21208
+ // on requestAccess if a non-empty value is provided.
21209
+ runId: AGT_RUN_ID || void 0,
21182
21210
  initialToken: AGT_TOKEN || void 0,
21183
21211
  apiKey: AGT_API_KEY || void 0
21184
21212
  });
@@ -21221,7 +21249,7 @@ server.tool(
21221
21249
  );
21222
21250
  server.tool(
21223
21251
  "request_access",
21224
- 'Request scoped, TTL-bounded AWS credentials for the current task. Returns { grant_id, status, secret_ref?, expires_at?, denial_reason? }. status="active" means credentials are ready; status="pending" means a human approver was paged and you should poll_grant; status="denied" means the request was rejected (denial_reason explains).',
21252
+ 'Request scoped, TTL-bounded AWS credentials for the current task. agent_id and run_id are optional \u2014 the broker fills them from the host MCP env (AGT_AGENT_ID / AGT_RUN_ID). Only pass them explicitly to attribute the grant to a different agent or run. Returns { grant_id, status, secret_ref?, expires_at?, denial_reason?, notification_status?, notification_failure_reason? }. status="active" means credentials are ready, use them now. status="denied" means the request was rejected (denial_reason explains). status="pending" means approval is still outstanding \u2014 DO NOT poll. The broker pushes the resolution to you via direct-chat the moment a human approves or denies, so save the grant_id, return control, and resume when the inbound message arrives. Only check notification_status if you need to flag a setup issue to the user: "sent" means a human was paged; "failed" or "not_attempted" means no human was paged (typically channel_not_found because the approval-bot is not a member of the configured channel) \u2014 quote grant_id + notification_failure_reason and recommend manual escalation. poll_grant exists as an escape hatch for explicit re-checks but the autonomous flow does not need it.',
21225
21253
  requestAccessShape,
21226
21254
  async (args) => {
21227
21255
  try {
@@ -21235,7 +21263,7 @@ server.tool(
21235
21263
  );
21236
21264
  server.tool(
21237
21265
  "poll_grant",
21238
- 'Single-shot status check for a grant. Use this when request_access returned status="pending"; back-off ~10s between polls. Returns { grant_id, status, secret_ref?, expires_at?, denial_reason? }.',
21266
+ "Single-shot status check for a grant. The broker pushes resolution updates to you via direct-chat automatically \u2014 you do NOT need to poll in the normal flow. Use this only as an escape hatch: explicit re-check after a notification, or if you suspect a notification was lost (e.g. you got `request_access` returning pending more than ~5 minutes ago and have heard nothing). Returns { grant_id, status, secret_ref?, expires_at?, denial_reason? }.",
21239
21267
  pollGrantShape,
21240
21268
  async (args) => {
21241
21269
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/cloud-broker",
3
- "version": "0.4.1",
3
+ "version": "0.4.4",
4
4
  "description": "Cloud Access Broker — MCP server that mints scoped, TTL-bounded cloud credentials per agent task. v1 ships AWS support (request_access, poll_grant, release_access, describe_scope, preview_request — STS AssumeRole under the hood); GCP, Azure, and Cloudflare land alongside in the same package as the broker grows.",
5
5
  "type": "module",
6
6
  "bin": {