@auctra/mcp-gateway 0.1.11 → 0.1.13
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/README.md +4 -0
- package/package.json +1 -1
- package/src/index.js +52 -39
- package/src/index.ts +53 -37
package/README.md
CHANGED
|
@@ -4,6 +4,8 @@ Stage 0 MCP gateway adapter. Wrap MCP tool calls **and installs** with Auctra **
|
|
|
4
4
|
|
|
5
5
|
**REQUIRE_MCP_GATEWAY:** Production orgs (Startup+) default `require_mcp_gateway=true`. MCP-shaped `action.execute` without this package’s stamp (`auctra_mcp_gateway`) is blocked. Set `AUCTRA_REQUIRE_MCP_GATEWAY=1` for a global fail-closed override.
|
|
6
6
|
|
|
7
|
+
**Before the gateway:** register the agent with a sponsor, issue authority for the tool's action type, and `createIntent`. Pass `claimedIntentId` and `intentAnchorToken`. A payment-shaped tool also needs provenance on the execute metadata. The full field list is `docs/onboarding/quick-start.md`. ALLOW still does not run the tool until the lease is consumed.
|
|
8
|
+
|
|
7
9
|
```ts
|
|
8
10
|
import { Auctra } from "@auctra/sdk";
|
|
9
11
|
import {
|
|
@@ -21,6 +23,8 @@ await gateMcpToolCall({
|
|
|
21
23
|
agentId: "agent-uuid",
|
|
22
24
|
toolName: "send_email",
|
|
23
25
|
args: { to: "vendor@example.com" },
|
|
26
|
+
claimedIntentId: "intent-uuid",
|
|
27
|
+
intentAnchorToken: "anchor-token-from-createIntent",
|
|
24
28
|
});
|
|
25
29
|
|
|
26
30
|
const sendEmail = withAuctraGate({
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -29,6 +29,55 @@ function resolveActionType(input) {
|
|
|
29
29
|
return input.actionType ?? input.actionTypeMap?.[input.toolName] ?? "execute_tool";
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
function isSupportedProductionConfig() {
|
|
33
|
+
if (process.env.NODE_ENV === "production") return true;
|
|
34
|
+
return Boolean(process.env.AUCTRA_EXECUTION_LEASE_SECRET?.trim());
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Lab/dev escape only. Ignored when NODE_ENV=production or
|
|
39
|
+
* AUCTRA_EXECUTION_LEASE_SECRET is set — those are supported production signals.
|
|
40
|
+
*/
|
|
41
|
+
export function allowMcpWithoutLease() {
|
|
42
|
+
if (isSupportedProductionConfig()) return false;
|
|
43
|
+
const v = process.env.AUCTRA_ALLOW_MCP_WITHOUT_LEASE?.trim().toLowerCase();
|
|
44
|
+
return v === "1" || v === "true" || v === "yes";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function assertConsumedExecutionLease(input, result) {
|
|
48
|
+
if (allowMcpWithoutLease()) return;
|
|
49
|
+
const leaseToken = result.execution_lease?.token;
|
|
50
|
+
if (!leaseToken) {
|
|
51
|
+
throw new McpToolBlockedError(
|
|
52
|
+
"execution lease required but action.execute returned none — configure AUCTRA_EXECUTION_LEASE_SECRET",
|
|
53
|
+
"blocked",
|
|
54
|
+
result.evidence,
|
|
55
|
+
result.action_decision ?? null,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
if (!input.client.executionLease?.consume) {
|
|
59
|
+
throw new McpToolBlockedError(
|
|
60
|
+
"executionLease.consume client method required after ALLOW",
|
|
61
|
+
"blocked",
|
|
62
|
+
result.evidence,
|
|
63
|
+
result.action_decision ?? null,
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
const consumed = await input.client.executionLease.consume({
|
|
67
|
+
lease: leaseToken,
|
|
68
|
+
expectedActionType: resolveActionType(input),
|
|
69
|
+
expectedRequestFingerprint: result.execution_lease?.request_fingerprint,
|
|
70
|
+
});
|
|
71
|
+
if (!consumed.ok) {
|
|
72
|
+
throw new McpToolBlockedError(
|
|
73
|
+
consumed.error ?? "execution lease consume failed",
|
|
74
|
+
"blocked",
|
|
75
|
+
result.evidence,
|
|
76
|
+
result.action_decision ?? null,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
32
81
|
function evidenceIdFromResult(result) {
|
|
33
82
|
return result.evidence_payload?.evidence_id ?? result.action_request_id ?? null;
|
|
34
83
|
}
|
|
@@ -199,45 +248,9 @@ export async function gateMcpToolCall(input) {
|
|
|
199
248
|
throw new McpToolBlockedError(message, result.decision, result.evidence, result.action_decision ?? null);
|
|
200
249
|
}
|
|
201
250
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
Boolean(process.env.AUCTRA_EXECUTION_LEASE_SECRET?.trim()));
|
|
206
|
-
const leaseToken = result.execution_lease?.token;
|
|
207
|
-
if (requireLease || leaseToken) {
|
|
208
|
-
if (!leaseToken) {
|
|
209
|
-
throw new McpToolBlockedError(
|
|
210
|
-
"execution lease required but action.execute returned none — configure AUCTRA_EXECUTION_LEASE_SECRET",
|
|
211
|
-
"blocked",
|
|
212
|
-
result.evidence,
|
|
213
|
-
result.action_decision ?? null,
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
if (!input.client.executionLease?.consume) {
|
|
217
|
-
if (requireLease) {
|
|
218
|
-
throw new McpToolBlockedError(
|
|
219
|
-
"executionLease.consume client method required when AUCTRA_REQUIRE_EXECUTION_LEASE=1",
|
|
220
|
-
"blocked",
|
|
221
|
-
result.evidence,
|
|
222
|
-
result.action_decision ?? null,
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
} else {
|
|
226
|
-
const consumed = await input.client.executionLease.consume({
|
|
227
|
-
lease: leaseToken,
|
|
228
|
-
expectedActionType: resolveActionType(input),
|
|
229
|
-
expectedRequestFingerprint: result.execution_lease?.request_fingerprint,
|
|
230
|
-
});
|
|
231
|
-
if (!consumed.ok) {
|
|
232
|
-
throw new McpToolBlockedError(
|
|
233
|
-
consumed.error ?? "execution lease consume failed",
|
|
234
|
-
"blocked",
|
|
235
|
-
result.evidence,
|
|
236
|
-
result.action_decision ?? null,
|
|
237
|
-
);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
251
|
+
// Default fail-closed (P5-F-007). AUCTRA_REQUIRE_EXECUTION_LEASE remains a
|
|
252
|
+
// recognized alias; AUCTRA_ALLOW_MCP_WITHOUT_LEASE=1 is the only opt-out.
|
|
253
|
+
await assertConsumedExecutionLease(input, result);
|
|
241
254
|
|
|
242
255
|
return result;
|
|
243
256
|
}
|
package/src/index.ts
CHANGED
|
@@ -52,7 +52,7 @@ export type ExecuteActionClient = {
|
|
|
52
52
|
evidence_payload?: { evidence_id?: string };
|
|
53
53
|
}>;
|
|
54
54
|
};
|
|
55
|
-
/**
|
|
55
|
+
/** Required after ALLOW. Lab opt-out is ignored in supported production configs. */
|
|
56
56
|
executionLease?: {
|
|
57
57
|
consume(input: {
|
|
58
58
|
lease: string;
|
|
@@ -123,6 +123,55 @@ function resolveActionType(input: McpToolGateInput) {
|
|
|
123
123
|
return input.actionType ?? input.actionTypeMap?.[input.toolName] ?? "execute_tool";
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
function isSupportedProductionConfig(): boolean {
|
|
127
|
+
if (process.env.NODE_ENV === "production") return true;
|
|
128
|
+
return Boolean(process.env.AUCTRA_EXECUTION_LEASE_SECRET?.trim());
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Lab/dev escape only. Ignored when NODE_ENV=production or
|
|
133
|
+
* AUCTRA_EXECUTION_LEASE_SECRET is set — those are supported production signals.
|
|
134
|
+
*/
|
|
135
|
+
export function allowMcpWithoutLease(): boolean {
|
|
136
|
+
if (isSupportedProductionConfig()) return false;
|
|
137
|
+
const v = process.env.AUCTRA_ALLOW_MCP_WITHOUT_LEASE?.trim().toLowerCase();
|
|
138
|
+
return v === "1" || v === "true" || v === "yes";
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function assertConsumedExecutionLease(
|
|
142
|
+
input: McpToolGateInput,
|
|
143
|
+
result: Awaited<ReturnType<ExecuteActionClient["action"]["execute"]>>,
|
|
144
|
+
) {
|
|
145
|
+
if (allowMcpWithoutLease()) return;
|
|
146
|
+
const leaseToken = result.execution_lease?.token;
|
|
147
|
+
if (!leaseToken) {
|
|
148
|
+
throw new McpToolBlockedError(
|
|
149
|
+
"execution lease required but action.execute returned none — configure AUCTRA_EXECUTION_LEASE_SECRET",
|
|
150
|
+
"blocked",
|
|
151
|
+
result.evidence,
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
if (!input.client.executionLease?.consume) {
|
|
155
|
+
throw new McpToolBlockedError(
|
|
156
|
+
"executionLease.consume client method required after ALLOW",
|
|
157
|
+
"blocked",
|
|
158
|
+
result.evidence,
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
const consumed = await input.client.executionLease.consume({
|
|
162
|
+
lease: leaseToken,
|
|
163
|
+
expectedActionType: resolveActionType(input),
|
|
164
|
+
expectedRequestFingerprint: result.execution_lease?.request_fingerprint,
|
|
165
|
+
});
|
|
166
|
+
if (!consumed.ok) {
|
|
167
|
+
throw new McpToolBlockedError(
|
|
168
|
+
consumed.error ?? "execution lease consume failed",
|
|
169
|
+
"blocked",
|
|
170
|
+
result.evidence,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
126
175
|
function evidenceIdFromResult(
|
|
127
176
|
result: Awaited<ReturnType<ExecuteActionClient["action"]["execute"]>>,
|
|
128
177
|
) {
|
|
@@ -353,42 +402,9 @@ export async function gateMcpToolCall(input: McpToolGateInput) {
|
|
|
353
402
|
throw new McpToolBlockedError(message, result.decision, result.evidence);
|
|
354
403
|
}
|
|
355
404
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
Boolean(process.env.AUCTRA_EXECUTION_LEASE_SECRET?.trim()));
|
|
360
|
-
const leaseToken = result.execution_lease?.token;
|
|
361
|
-
if (requireLease || leaseToken) {
|
|
362
|
-
if (!leaseToken) {
|
|
363
|
-
throw new McpToolBlockedError(
|
|
364
|
-
"execution lease required but action.execute returned none — configure AUCTRA_EXECUTION_LEASE_SECRET",
|
|
365
|
-
"blocked",
|
|
366
|
-
result.evidence,
|
|
367
|
-
);
|
|
368
|
-
}
|
|
369
|
-
if (!input.client.executionLease?.consume) {
|
|
370
|
-
if (requireLease) {
|
|
371
|
-
throw new McpToolBlockedError(
|
|
372
|
-
"executionLease.consume client method required when AUCTRA_REQUIRE_EXECUTION_LEASE=1",
|
|
373
|
-
"blocked",
|
|
374
|
-
result.evidence,
|
|
375
|
-
);
|
|
376
|
-
}
|
|
377
|
-
} else {
|
|
378
|
-
const consumed = await input.client.executionLease.consume({
|
|
379
|
-
lease: leaseToken,
|
|
380
|
-
expectedActionType: resolveActionType(input),
|
|
381
|
-
expectedRequestFingerprint: result.execution_lease?.request_fingerprint,
|
|
382
|
-
});
|
|
383
|
-
if (!consumed.ok) {
|
|
384
|
-
throw new McpToolBlockedError(
|
|
385
|
-
consumed.error ?? "execution lease consume failed",
|
|
386
|
-
"blocked",
|
|
387
|
-
result.evidence,
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
}
|
|
405
|
+
// Default fail-closed (P5-F-007). AUCTRA_REQUIRE_EXECUTION_LEASE remains a
|
|
406
|
+
// recognized alias; AUCTRA_ALLOW_MCP_WITHOUT_LEASE=1 is the only opt-out.
|
|
407
|
+
await assertConsumedExecutionLease(input, result);
|
|
392
408
|
|
|
393
409
|
return result;
|
|
394
410
|
}
|