@integrity-labs/cloud-broker 0.4.5 → 0.5.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.
- package/dist/index.js +76 -22
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20996,7 +20996,6 @@ var BrokerClient = class {
|
|
|
20996
20996
|
host;
|
|
20997
20997
|
agentId;
|
|
20998
20998
|
runId;
|
|
20999
|
-
defaultSourceContext;
|
|
21000
20999
|
apiKey;
|
|
21001
21000
|
fetchImpl;
|
|
21002
21001
|
token;
|
|
@@ -21006,7 +21005,6 @@ var BrokerClient = class {
|
|
|
21006
21005
|
this.host = config2.host.replace(/\/+$/, "");
|
|
21007
21006
|
this.agentId = config2.agentId;
|
|
21008
21007
|
this.runId = config2.runId;
|
|
21009
|
-
this.defaultSourceContext = config2.defaultSourceContext;
|
|
21010
21008
|
this.apiKey = config2.apiKey;
|
|
21011
21009
|
this.fetchImpl = config2.fetchImpl ?? fetch;
|
|
21012
21010
|
this.token = config2.initialToken ?? "";
|
|
@@ -21122,13 +21120,7 @@ var BrokerClient = class {
|
|
|
21122
21120
|
if (!runId) {
|
|
21123
21121
|
throw makeBrokerError(400, "BrokerClient.requestAccess requires run_id (pass it in args, or set runId on BrokerClientConfig)");
|
|
21124
21122
|
}
|
|
21125
|
-
const
|
|
21126
|
-
const body = {
|
|
21127
|
-
...args,
|
|
21128
|
-
agent_id: agentId,
|
|
21129
|
-
run_id: runId,
|
|
21130
|
-
source_context: sourceContext
|
|
21131
|
-
};
|
|
21123
|
+
const body = { ...args, agent_id: agentId, run_id: runId };
|
|
21132
21124
|
return this.request("POST", "/aws/grants", { body });
|
|
21133
21125
|
}
|
|
21134
21126
|
pollGrant(args) {
|
|
@@ -21140,6 +21132,16 @@ var BrokerClient = class {
|
|
|
21140
21132
|
`/aws/grants/${encodeURIComponent(args.grant_id)}/release`
|
|
21141
21133
|
);
|
|
21142
21134
|
}
|
|
21135
|
+
// ENG-4779: fetch the AWS_* credentials persisted on the grant. Pre-4779
|
|
21136
|
+
// there was no path back to credentials for a route_to_approver grant —
|
|
21137
|
+
// they were minted inside mintAndActivateGrant and never returned. Now
|
|
21138
|
+
// they're encrypted on the row and decrypted here.
|
|
21139
|
+
getCredentials(args) {
|
|
21140
|
+
return this.request(
|
|
21141
|
+
"POST",
|
|
21142
|
+
`/aws/grants/${encodeURIComponent(args.grant_id)}/credentials`
|
|
21143
|
+
);
|
|
21144
|
+
}
|
|
21143
21145
|
};
|
|
21144
21146
|
|
|
21145
21147
|
// src/tool-schemas.ts
|
|
@@ -21199,11 +21201,59 @@ var pollGrantSchema = external_exports.object({
|
|
|
21199
21201
|
var releaseAccessSchema = external_exports.object({
|
|
21200
21202
|
grant_id: external_exports.string().uuid("grant_id must be a UUID")
|
|
21201
21203
|
});
|
|
21204
|
+
var getCredentialsSchema = external_exports.object({
|
|
21205
|
+
grant_id: external_exports.string().uuid("grant_id must be a UUID")
|
|
21206
|
+
});
|
|
21202
21207
|
var describeScopeShape = describeScopeSchema.shape;
|
|
21203
21208
|
var previewRequestShape = previewRequestSchema.shape;
|
|
21204
21209
|
var requestAccessShape = requestAccessSchema.shape;
|
|
21205
21210
|
var pollGrantShape = pollGrantSchema.shape;
|
|
21206
21211
|
var releaseAccessShape = releaseAccessSchema.shape;
|
|
21212
|
+
var getCredentialsShape = getCredentialsSchema.shape;
|
|
21213
|
+
|
|
21214
|
+
// package.json
|
|
21215
|
+
var package_default = {
|
|
21216
|
+
name: "@integrity-labs/cloud-broker",
|
|
21217
|
+
version: "0.5.0",
|
|
21218
|
+
description: "Cloud Access Broker \u2014 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 \u2014 STS AssumeRole under the hood); GCP, Azure, and Cloudflare land alongside in the same package as the broker grows.",
|
|
21219
|
+
type: "module",
|
|
21220
|
+
bin: {
|
|
21221
|
+
"cloud-broker": "./dist/index.js"
|
|
21222
|
+
},
|
|
21223
|
+
main: "dist/index.js",
|
|
21224
|
+
files: [
|
|
21225
|
+
"dist",
|
|
21226
|
+
"README.md"
|
|
21227
|
+
],
|
|
21228
|
+
repository: {
|
|
21229
|
+
type: "git",
|
|
21230
|
+
url: "https://github.com/Integrity-Labs/augmented.git",
|
|
21231
|
+
directory: "packages/cloud-broker"
|
|
21232
|
+
},
|
|
21233
|
+
publishConfig: {
|
|
21234
|
+
registry: "https://registry.npmjs.org",
|
|
21235
|
+
access: "public"
|
|
21236
|
+
},
|
|
21237
|
+
scripts: {
|
|
21238
|
+
build: "tsup",
|
|
21239
|
+
dev: "tsx watch src/index.ts",
|
|
21240
|
+
typecheck: "tsc --noEmit",
|
|
21241
|
+
test: "vitest run",
|
|
21242
|
+
clean: "rm -rf dist",
|
|
21243
|
+
"publish:templates": "bash cloudformation/publish.sh"
|
|
21244
|
+
},
|
|
21245
|
+
dependencies: {
|
|
21246
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
21247
|
+
zod: "^3.25.0"
|
|
21248
|
+
},
|
|
21249
|
+
devDependencies: {
|
|
21250
|
+
"@types/node": "^22.0.0",
|
|
21251
|
+
tsup: "^8.0.0",
|
|
21252
|
+
tsx: "^4.19.0",
|
|
21253
|
+
typescript: "^5.7.0",
|
|
21254
|
+
vitest: "^3.0.0"
|
|
21255
|
+
}
|
|
21256
|
+
};
|
|
21207
21257
|
|
|
21208
21258
|
// src/index.ts
|
|
21209
21259
|
var AGT_HOST = process.env.AGT_HOST;
|
|
@@ -21211,9 +21261,9 @@ var AGT_AGENT_ID = process.env.AGT_AGENT_ID;
|
|
|
21211
21261
|
var AGT_RUN_ID = process.env.AGT_RUN_ID ?? "";
|
|
21212
21262
|
var AGT_TOKEN = process.env.AGT_TOKEN ?? "";
|
|
21213
21263
|
var AGT_API_KEY = process.env.AGT_API_KEY ?? "";
|
|
21214
|
-
if (!AGT_HOST || !AGT_AGENT_ID || !AGT_TOKEN && !AGT_API_KEY) {
|
|
21264
|
+
if (!AGT_HOST || !AGT_AGENT_ID || !AGT_RUN_ID || !AGT_TOKEN && !AGT_API_KEY) {
|
|
21215
21265
|
console.error(
|
|
21216
|
-
"cloud-broker: missing env vars. Need AGT_HOST, AGT_AGENT_ID, and one of AGT_TOKEN or AGT_API_KEY."
|
|
21266
|
+
"cloud-broker: missing env vars. Need AGT_HOST, AGT_AGENT_ID, AGT_RUN_ID, and one of AGT_TOKEN or AGT_API_KEY."
|
|
21217
21267
|
);
|
|
21218
21268
|
process.exit(1);
|
|
21219
21269
|
}
|
|
@@ -21222,14 +21272,6 @@ if (process.env.AGT_TEAM_SLUG) {
|
|
|
21222
21272
|
"cloud-broker: AGT_TEAM_SLUG is set but no longer required (the API derives team from agent_id). Safe to remove from .mcp.json env block."
|
|
21223
21273
|
);
|
|
21224
21274
|
}
|
|
21225
|
-
var AGT_INBOUND_CHANNEL_TYPE = process.env.AGT_INBOUND_CHANNEL_TYPE ?? "";
|
|
21226
|
-
var AGT_INBOUND_CHANNEL_ID = process.env.AGT_INBOUND_CHANNEL_ID ?? "";
|
|
21227
|
-
var AGT_INBOUND_CHANNEL_THREAD_TS = process.env.AGT_INBOUND_CHANNEL_THREAD_TS ?? "";
|
|
21228
|
-
var defaultSourceContext = AGT_INBOUND_CHANNEL_TYPE && AGT_INBOUND_CHANNEL_ID ? {
|
|
21229
|
-
channel_type: AGT_INBOUND_CHANNEL_TYPE,
|
|
21230
|
-
channel_id: AGT_INBOUND_CHANNEL_ID,
|
|
21231
|
-
thread_ts: AGT_INBOUND_CHANNEL_THREAD_TS || void 0
|
|
21232
|
-
} : void 0;
|
|
21233
21275
|
var broker = new BrokerClient({
|
|
21234
21276
|
host: AGT_HOST,
|
|
21235
21277
|
agentId: AGT_AGENT_ID,
|
|
@@ -21237,7 +21279,6 @@ var broker = new BrokerClient({
|
|
|
21237
21279
|
// Empty string is treated as absent — the broker client only fills runId
|
|
21238
21280
|
// on requestAccess if a non-empty value is provided.
|
|
21239
21281
|
runId: AGT_RUN_ID || void 0,
|
|
21240
|
-
defaultSourceContext,
|
|
21241
21282
|
initialToken: AGT_TOKEN || void 0,
|
|
21242
21283
|
apiKey: AGT_API_KEY || void 0
|
|
21243
21284
|
});
|
|
@@ -21250,7 +21291,7 @@ function formatBrokerError(err) {
|
|
|
21250
21291
|
}
|
|
21251
21292
|
var server = new McpServer({
|
|
21252
21293
|
name: "cloud-broker",
|
|
21253
|
-
version:
|
|
21294
|
+
version: package_default.version
|
|
21254
21295
|
});
|
|
21255
21296
|
server.tool(
|
|
21256
21297
|
"describe_scope",
|
|
@@ -21280,7 +21321,7 @@ server.tool(
|
|
|
21280
21321
|
);
|
|
21281
21322
|
server.tool(
|
|
21282
21323
|
"request_access",
|
|
21283
|
-
|
|
21324
|
+
'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). source_context is optional but you SHOULD pass it whenever the request was triggered by an inbound channel message: extract { channel_type, channel_id, thread_ts? } from the `<channel>` tag in the conversation that triggered this. Slack: channel_type="slack", channel_id=tag\'s `channel`, thread_ts=tag\'s `thread_ts`. Telegram: channel_type="telegram", channel_id=tag\'s `chat_id`. Direct-chat: channel_type="direct-chat", channel_id=tag\'s `session_id`. Without source_context the resolution notification dead-ends in your direct-chat instead of threading back to the original conversation. 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. The notification body will include an "Original conversation:" line naming the channel/thread to reply in \u2014 complete the user\'s task there, not in direct-chat. 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.',
|
|
21284
21325
|
requestAccessShape,
|
|
21285
21326
|
async (args) => {
|
|
21286
21327
|
try {
|
|
@@ -21318,6 +21359,19 @@ server.tool(
|
|
|
21318
21359
|
}
|
|
21319
21360
|
}
|
|
21320
21361
|
);
|
|
21362
|
+
server.tool(
|
|
21363
|
+
"get_credentials",
|
|
21364
|
+
"Fetch the AWS credentials for an active grant. Call this AFTER request_access returns active (auto-approve) OR after the resolution-notification arrives (route_to_approver). Returns { grant_id, expires_at, credentials: { access_key_id, secret_access_key, session_token } }. Use them by prefixing your bash invocation, e.g. `AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... AWS_SESSION_TOKEN=... aws ec2 describe-instances`. The grant must still be active and unexpired \u2014 409 if already released, 410 if past expires_at. Safe to call multiple times within the TTL window; the credentials don't change. Call release_access when done.",
|
|
21365
|
+
getCredentialsShape,
|
|
21366
|
+
async (args) => {
|
|
21367
|
+
try {
|
|
21368
|
+
const result = await broker.getCredentials(args);
|
|
21369
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
21370
|
+
} catch (err) {
|
|
21371
|
+
return { content: [{ type: "text", text: formatBrokerError(err) }], isError: true };
|
|
21372
|
+
}
|
|
21373
|
+
}
|
|
21374
|
+
);
|
|
21321
21375
|
var transport = new StdioServerTransport();
|
|
21322
21376
|
await server.connect(transport);
|
|
21323
21377
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@integrity-labs/cloud-broker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
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": {
|