@auctra/mcp-gateway 0.1.8 → 0.1.10
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 +3 -0
- package/package.json +1 -1
- package/src/index.js +24 -3
- package/src/index.ts +24 -0
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Stage 0 MCP gateway adapter. Wrap MCP tool calls **and installs** with Auctra **Authority Gate** (`action.execute`) before execution.
|
|
4
4
|
|
|
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
|
+
|
|
5
7
|
```ts
|
|
6
8
|
import { Auctra } from "@auctra/sdk";
|
|
7
9
|
import {
|
|
@@ -9,6 +11,7 @@ import {
|
|
|
9
11
|
gateMcpInstall,
|
|
10
12
|
withAuctraGate,
|
|
11
13
|
declareMcpInstallMetadata,
|
|
14
|
+
REQUIRE_MCP_GATEWAY,
|
|
12
15
|
} from "@auctra/mcp-gateway";
|
|
13
16
|
|
|
14
17
|
const client = new Auctra({ apiKey: process.env.AUCTRA_API_KEY! });
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import { createHash, createHmac } from "node:crypto";
|
|
2
2
|
|
|
3
|
+
/** Org/env policy name (SEC-P0-002). */
|
|
4
|
+
export const REQUIRE_MCP_GATEWAY = "REQUIRE_MCP_GATEWAY";
|
|
5
|
+
|
|
6
|
+
export function mcpGatewayStamp() {
|
|
7
|
+
return {
|
|
8
|
+
auctra_mcp_gateway: true,
|
|
9
|
+
mcp_gateway: true,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function requireMcpGateway() {
|
|
14
|
+
const v = process.env.AUCTRA_REQUIRE_MCP_GATEWAY?.trim().toLowerCase();
|
|
15
|
+
return v === "1" || v === "true" || v === "yes";
|
|
16
|
+
}
|
|
17
|
+
|
|
3
18
|
export class McpToolBlockedError extends Error {
|
|
4
|
-
constructor(message, decision, evidence) {
|
|
19
|
+
constructor(message, decision, evidence, actionDecision = null) {
|
|
5
20
|
super(message);
|
|
6
21
|
this.name = "McpToolBlockedError";
|
|
7
22
|
this.decision = decision;
|
|
8
23
|
this.evidence = evidence;
|
|
24
|
+
this.actionDecision = actionDecision;
|
|
9
25
|
}
|
|
10
26
|
}
|
|
11
27
|
|
|
@@ -84,6 +100,7 @@ export function declareMcpInstallMetadata(input) {
|
|
|
84
100
|
hashMcpPackageManifest(input.manifestBody ?? { name, version: input.install.version ?? null });
|
|
85
101
|
const kind = input.install.kind ?? "mcp";
|
|
86
102
|
return {
|
|
103
|
+
...mcpGatewayStamp(),
|
|
87
104
|
mcp_install: {
|
|
88
105
|
name,
|
|
89
106
|
...(input.install.version ? { version: input.install.version } : {}),
|
|
@@ -130,7 +147,7 @@ export async function gateMcpInstall(input) {
|
|
|
130
147
|
if (result.decision !== "allowed") {
|
|
131
148
|
const evidenceId = evidenceIdFromResult(result);
|
|
132
149
|
const message = evidenceId ? `${result.reason} (evidence: ${evidenceId})` : result.reason;
|
|
133
|
-
throw new McpToolBlockedError(message, result.decision, result.evidence);
|
|
150
|
+
throw new McpToolBlockedError(message, result.decision, result.evidence, result.action_decision ?? null);
|
|
134
151
|
}
|
|
135
152
|
|
|
136
153
|
return { ...result, metadata };
|
|
@@ -163,6 +180,7 @@ export async function gateMcpToolCall(input) {
|
|
|
163
180
|
target: `mcp:${input.toolName}`,
|
|
164
181
|
description: `MCP tool ${input.toolName}`,
|
|
165
182
|
metadata: {
|
|
183
|
+
...mcpGatewayStamp(),
|
|
166
184
|
inputs: [
|
|
167
185
|
{
|
|
168
186
|
source: `mcp:${input.toolName}:invocation`,
|
|
@@ -178,7 +196,7 @@ export async function gateMcpToolCall(input) {
|
|
|
178
196
|
if (result.decision !== "allowed") {
|
|
179
197
|
const evidenceId = evidenceIdFromResult(result);
|
|
180
198
|
const message = evidenceId ? `${result.reason} (evidence: ${evidenceId})` : result.reason;
|
|
181
|
-
throw new McpToolBlockedError(message, result.decision, result.evidence);
|
|
199
|
+
throw new McpToolBlockedError(message, result.decision, result.evidence, result.action_decision ?? null);
|
|
182
200
|
}
|
|
183
201
|
|
|
184
202
|
const requireLease =
|
|
@@ -192,6 +210,7 @@ export async function gateMcpToolCall(input) {
|
|
|
192
210
|
"execution lease required but action.execute returned none — configure AUCTRA_EXECUTION_LEASE_SECRET",
|
|
193
211
|
"blocked",
|
|
194
212
|
result.evidence,
|
|
213
|
+
result.action_decision ?? null,
|
|
195
214
|
);
|
|
196
215
|
}
|
|
197
216
|
if (!input.client.executionLease?.consume) {
|
|
@@ -200,6 +219,7 @@ export async function gateMcpToolCall(input) {
|
|
|
200
219
|
"executionLease.consume client method required when AUCTRA_REQUIRE_EXECUTION_LEASE=1",
|
|
201
220
|
"blocked",
|
|
202
221
|
result.evidence,
|
|
222
|
+
result.action_decision ?? null,
|
|
203
223
|
);
|
|
204
224
|
}
|
|
205
225
|
} else {
|
|
@@ -212,6 +232,7 @@ export async function gateMcpToolCall(input) {
|
|
|
212
232
|
consumed.error ?? "execution lease consume failed",
|
|
213
233
|
"blocked",
|
|
214
234
|
result.evidence,
|
|
235
|
+
result.action_decision ?? null,
|
|
215
236
|
);
|
|
216
237
|
}
|
|
217
238
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
import { createHash, createHmac } from "node:crypto";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Org/env policy name — when set, MCP-shaped action.execute must carry the
|
|
5
|
+
* gateway stamp below (SEC-P0-002). Cloud also honors organization.requireMcpGateway.
|
|
6
|
+
*/
|
|
7
|
+
export const REQUIRE_MCP_GATEWAY = "REQUIRE_MCP_GATEWAY";
|
|
8
|
+
|
|
9
|
+
/** Metadata stamp proving the call came through @auctra/mcp-gateway. */
|
|
10
|
+
export function mcpGatewayStamp(): Record<string, true> {
|
|
11
|
+
return {
|
|
12
|
+
auctra_mcp_gateway: true,
|
|
13
|
+
mcp_gateway: true,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function requireMcpGateway(): boolean {
|
|
18
|
+
const v = process.env.AUCTRA_REQUIRE_MCP_GATEWAY?.trim().toLowerCase();
|
|
19
|
+
return v === "1" || v === "true" || v === "yes";
|
|
20
|
+
}
|
|
21
|
+
|
|
3
22
|
export type ExecuteActionClient = {
|
|
4
23
|
action: {
|
|
5
24
|
execute(input: {
|
|
@@ -194,6 +213,8 @@ export function declareMcpInstallMetadata(input: {
|
|
|
194
213
|
issuedAt?: string;
|
|
195
214
|
keyId?: string;
|
|
196
215
|
}): {
|
|
216
|
+
auctra_mcp_gateway: true;
|
|
217
|
+
mcp_gateway: true;
|
|
197
218
|
mcp_install: {
|
|
198
219
|
name: string;
|
|
199
220
|
version?: string;
|
|
@@ -208,6 +229,8 @@ export function declareMcpInstallMetadata(input: {
|
|
|
208
229
|
hashMcpPackageManifest(input.manifestBody ?? { name, version: input.install.version ?? null });
|
|
209
230
|
const kind = input.install.kind ?? "mcp";
|
|
210
231
|
return {
|
|
232
|
+
auctra_mcp_gateway: true as const,
|
|
233
|
+
mcp_gateway: true as const,
|
|
211
234
|
mcp_install: {
|
|
212
235
|
name,
|
|
213
236
|
...(input.install.version ? { version: input.install.version } : {}),
|
|
@@ -309,6 +332,7 @@ export async function gateMcpToolCall(input: McpToolGateInput) {
|
|
|
309
332
|
target: `mcp:${input.toolName}`,
|
|
310
333
|
description: `MCP tool ${input.toolName}`,
|
|
311
334
|
metadata: {
|
|
335
|
+
...mcpGatewayStamp(),
|
|
312
336
|
inputs: [
|
|
313
337
|
{
|
|
314
338
|
source: `mcp:${input.toolName}:invocation`,
|