@astrasyncai/verification-gateway 4.5.0 → 4.5.1
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/adapters/express.js +1 -1
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +1 -1
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +3 -394
- package/dist/adapters/mcp.d.ts +3 -394
- package/dist/adapters/mcp.js +1 -1
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +1 -1
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.js +1 -1
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +1 -1
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.js +1 -1
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +1 -1
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.js +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs +1 -1
- package/dist/agent/index.mjs.map +1 -1
- package/dist/bin/astrasync-claude-hook.js +1 -1
- package/dist/bin/astrasync-codex-hook.js +1 -1
- package/dist/bin/astrasync-guard.js +1 -1
- package/dist/bin/astrasync.js +2 -1
- package/dist/browser/background.js +1 -1
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +1 -1
- package/dist/browser/background.mjs.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/cli/index.mjs.map +1 -1
- package/dist/codex/index.js +1 -1
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +1 -1
- package/dist/codex/index.mjs.map +1 -1
- package/dist/cursor/extension.js +1 -1
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +1 -1
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/edge-config.js +1 -1
- package/dist/edge-config.js.map +1 -1
- package/dist/edge-config.mjs +1 -1
- package/dist/edge-config.mjs.map +1 -1
- package/dist/edge-core/index.js +1 -1
- package/dist/edge-core/index.js.map +1 -1
- package/dist/edge-core/index.mjs +1 -1
- package/dist/edge-core/index.mjs.map +1 -1
- package/dist/gateway/gateway.js +1 -1
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +1 -1
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7 -1
- package/dist/index.mjs.map +1 -1
- package/dist/mcp--DgKOwfu.d.ts +396 -0
- package/dist/mcp-BgBJu4Jl.d.mts +396 -0
- package/dist/registration/index.js +2 -1
- package/dist/registration/index.js.map +1 -1
- package/dist/registration/index.mjs +2 -1
- package/dist/registration/index.mjs.map +1 -1
- package/dist/transport/index.js +1 -1
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/index.mjs +1 -1
- package/dist/transport/index.mjs.map +1 -1
- package/dist/verify.js +1 -1
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +1 -1
- package/dist/verify.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
import { Request, Response, RequestHandler } from 'express';
|
|
2
|
+
import { a as AccessLevel, G as GatewayConfig, x as VerificationResult } from './types-DwSfO7Sb.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* X-Astra-Verified-Hop — cross-hop verify-access dedupe marker.
|
|
6
|
+
*
|
|
7
|
+
* Header carrying upstream verify-access proof so an inner-hop endpoint can
|
|
8
|
+
* dedupe (skip verify-access when the same ASTRA-id was already verified a
|
|
9
|
+
* few ms earlier). Emitted by the MCP adapter toward tool fetches and by the
|
|
10
|
+
* edge gateway toward the origin at authenticate/authorize depth. Value
|
|
11
|
+
* format:
|
|
12
|
+
*
|
|
13
|
+
* {astraId};{sessionId};{checkedAt-ms}
|
|
14
|
+
*
|
|
15
|
+
* Receivers MUST validate that `checkedAt` is recent (≤ 60s window
|
|
16
|
+
* recommended) and that `astraId` matches the agent identity claimed on the
|
|
17
|
+
* inner hop. The header alone is NOT proof-of-identity — it's an UNSIGNED
|
|
18
|
+
* dedupe advisory: trust it (`trustVerifiedHop`) only where every network
|
|
19
|
+
* path to the inner hop crosses a stripping gateway or an equivalent trusted
|
|
20
|
+
* boundary, exactly like the unsigned X-AstraSync-* attestation headers.
|
|
21
|
+
* Pair with the existing X-Astra-Id auth.
|
|
22
|
+
*/
|
|
23
|
+
declare const MCP_VERIFIED_HOP_HEADER = "X-Astra-Verified-Hop";
|
|
24
|
+
/** Default acceptable age (ms) for an X-Astra-Verified-Hop header. */
|
|
25
|
+
declare const MCP_VERIFIED_HOP_MAX_AGE_MS = 60000;
|
|
26
|
+
interface VerifiedHopMarker {
|
|
27
|
+
astraId: string;
|
|
28
|
+
sessionId?: string;
|
|
29
|
+
checkedAt: number;
|
|
30
|
+
}
|
|
31
|
+
declare function serializeVerifiedHop(marker: VerifiedHopMarker): string;
|
|
32
|
+
declare function parseVerifiedHop(value: string | undefined | null): VerifiedHopMarker | null;
|
|
33
|
+
/**
|
|
34
|
+
* Returns true when `marker.astraId` matches the inner-hop's claimed
|
|
35
|
+
* ASTRA-id AND the marker is recent enough. Inner-hop middleware uses this
|
|
36
|
+
* to skip a duplicate verify-access call.
|
|
37
|
+
*/
|
|
38
|
+
declare function isVerifiedHopValidFor(marker: VerifiedHopMarker | null, expectedAstraId: string, opts?: {
|
|
39
|
+
maxAgeMs?: number;
|
|
40
|
+
now?: number;
|
|
41
|
+
}): boolean;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* MCP server-side helpers — companion to `transport/mcp.ts` (which handles the
|
|
45
|
+
* agent-side `_meta.astrasync` block).
|
|
46
|
+
*
|
|
47
|
+
* Surfaces a body-aware policy hook the existing `createMiddleware` couldn't
|
|
48
|
+
* provide — MCP traffic is JSON-RPC over a single endpoint (`/mcp`), so the
|
|
49
|
+
* default route-pattern gating is too coarse: every request looks the same
|
|
50
|
+
* URL-wise, but `initialize` is low-risk handshake while `tools/call` of a
|
|
51
|
+
* payment tool is high-risk. Cohort-3 beta merchants flagged this 🟡 in the
|
|
52
|
+
* v2.9.5 round.
|
|
53
|
+
*
|
|
54
|
+
* What lives here:
|
|
55
|
+
* - `parseMcpJsonRpc(body)` — peels JSON-RPC method + tool name + agent
|
|
56
|
+
* id without committing to a particular MCP
|
|
57
|
+
* server framework.
|
|
58
|
+
* - `mcpToPdlss(parsed)` — canonical mapping JSON-RPC method → PDLSS
|
|
59
|
+
* purpose / action / resource. Doc-stable
|
|
60
|
+
* so audits can correlate.
|
|
61
|
+
* - `mcpRiskTier(parsed)` — recommended `minAccessLevel` per method
|
|
62
|
+
* so a single MCP middleware can split
|
|
63
|
+
* `initialize` / `tools/list` (low gate)
|
|
64
|
+
* from `tools/call` (high gate).
|
|
65
|
+
* - `MCP_VERIFIED_HOP_HEADER` — header convention for the dedupe pattern
|
|
66
|
+
* when an MCP tool calls an inner REST hop.
|
|
67
|
+
* - `serialize/parseVerifiedHop` helpers.
|
|
68
|
+
*
|
|
69
|
+
* The Express MCP adapter is in `adapters/mcp.ts` and consumes these.
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Output of `parseMcpJsonRpc`. Self-describing so the middleware doesn't have
|
|
74
|
+
* to re-introspect the body to figure out gating.
|
|
75
|
+
*/
|
|
76
|
+
interface ParsedMcpRequest {
|
|
77
|
+
/** JSON-RPC method (e.g. `tools/call`, `initialize`, `tools/list`). */
|
|
78
|
+
method: string;
|
|
79
|
+
/** Set when method === 'tools/call'; the tool name from `params.name`. */
|
|
80
|
+
toolName?: string;
|
|
81
|
+
/** Initialize-specific protocolVersion handshake info, when present. */
|
|
82
|
+
protocolVersion?: string;
|
|
83
|
+
/**
|
|
84
|
+
* Agent id read from the body, in priority order:
|
|
85
|
+
* 1. `params._meta.astrasync.agentId` (the canonical SDK location, see
|
|
86
|
+
* `transport/mcp.ts → setMcpMeta`)
|
|
87
|
+
* 2. `params.arguments.agent_id` (legacy / hand-written tool callers)
|
|
88
|
+
* Header-supplied id (X-Astra-Id) is read separately by the adapter and
|
|
89
|
+
* compared to this for the mismatch check.
|
|
90
|
+
*/
|
|
91
|
+
agentIdFromBody?: string;
|
|
92
|
+
/**
|
|
93
|
+
* Purpose extracted from the MCP body
|
|
94
|
+
* with the symmetric precedence chain. Sourced from `_meta.astrasync.purpose`
|
|
95
|
+
* (canonical SDK location) OR `params.arguments.purpose` (legacy /
|
|
96
|
+
* conventional callers). The discriminator is on `purposeSourceFromBody`.
|
|
97
|
+
* Adapter combines this with the `X-Astra-Purpose` header (header wins)
|
|
98
|
+
* before mapping; final fallback at `mcpToPdlss` is `undefined`.
|
|
99
|
+
*/
|
|
100
|
+
purposeFromBody?: string;
|
|
101
|
+
/** Which body location resolved `purposeFromBody`. */
|
|
102
|
+
purposeSourceFromBody?: 'meta' | 'tool_argument';
|
|
103
|
+
/**
|
|
104
|
+
* Action extracted from the MCP body with the same
|
|
105
|
+
* symmetric chain as purpose. Sourced from `_meta.astrasync.action`
|
|
106
|
+
* (canonical) OR `params.arguments.action` (legacy). Adapter combines
|
|
107
|
+
* with the `X-Astra-Action` header (header wins) before mapping; final
|
|
108
|
+
* fallback at `mcpToPdlss` is the transport-layer default
|
|
109
|
+
* (`tools/call:<toolname>` or just `<method>`).
|
|
110
|
+
*/
|
|
111
|
+
actionFromBody?: string;
|
|
112
|
+
/** Which body location resolved `actionFromBody`. */
|
|
113
|
+
actionSourceFromBody?: 'meta' | 'tool_argument';
|
|
114
|
+
/** True for handshake methods that must succeed before any tool call. */
|
|
115
|
+
isInitialize: boolean;
|
|
116
|
+
/** True for `tools/call`. */
|
|
117
|
+
isToolCall: boolean;
|
|
118
|
+
/** True for low-risk introspection (`tools/list`, `prompts/list`, etc.). */
|
|
119
|
+
isIntrospection: boolean;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Peel the JSON-RPC envelope. Returns `null` if the body isn't a JSON-RPC
|
|
123
|
+
* request (callers can short-circuit with a 400 or treat as untyped traffic).
|
|
124
|
+
*
|
|
125
|
+
* Accepts both single-request and notification shapes. Batch requests are
|
|
126
|
+
* NOT supported here — the verify-access contract is single-agent-per-call;
|
|
127
|
+
* a batch body should be split before policy gating.
|
|
128
|
+
*/
|
|
129
|
+
declare function parseMcpJsonRpc(body: unknown): ParsedMcpRequest | null;
|
|
130
|
+
/**
|
|
131
|
+
* PDLSS mapping for an MCP request. The platform's PDLSS taxonomy is
|
|
132
|
+
* `purpose / action / resource`; for MCP traffic the audit-useful dimensions
|
|
133
|
+
* are the JSON-RPC method and (for `tools/call`) the tool name.
|
|
134
|
+
*
|
|
135
|
+
* v2.5.0 rules:
|
|
136
|
+
* - `resource` defaults to the HTTP request path (e.g. `/mcp`). Per-tool
|
|
137
|
+
* overrides via `toolGates` config let merchants map tools to specific
|
|
138
|
+
* backend resources (e.g. `/api/catalog`).
|
|
139
|
+
* - `purpose` defaults to `undefined` (backend evaluator applies
|
|
140
|
+
* skip-when-undefined). Per-tool overrides via `toolGates` config let
|
|
141
|
+
* merchants declare the semantic purpose each tool fulfils.
|
|
142
|
+
* - `action` comes only from declarations (toolGate config, header, or
|
|
143
|
+
* body). For `tools/call` with none declared it is `undefined` —
|
|
144
|
+
* evaluation is purpose-only, because a raw tool name is a transport
|
|
145
|
+
* token, not a PDLSS action, and sending it as one guarantees an
|
|
146
|
+
* action-policy mismatch. For other JSON-RPC methods the method string
|
|
147
|
+
* is used.
|
|
148
|
+
*/
|
|
149
|
+
interface McpPdlssMapping {
|
|
150
|
+
purpose: string | undefined;
|
|
151
|
+
/**
|
|
152
|
+
* `undefined` when a `tools/call` request declared no action anywhere —
|
|
153
|
+
* the verify-access call then evaluates purpose-only. Tool names never
|
|
154
|
+
* travel as PDLSS actions.
|
|
155
|
+
*/
|
|
156
|
+
action: string | undefined;
|
|
157
|
+
resource: string;
|
|
158
|
+
purposeSource: 'header' | 'meta' | 'tool_argument' | 'tool_gate' | undefined;
|
|
159
|
+
actionSource: 'header' | 'meta' | 'tool_argument' | 'tool_gate' | 'transport_layer' | undefined;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* v2.5.0 — PDLSS field derivation for MCP requests.
|
|
163
|
+
*
|
|
164
|
+
* Purpose precedence:
|
|
165
|
+
* - If `toolGate.purpose` is provided, it is authoritative (header/body ignored).
|
|
166
|
+
* - Otherwise: header → body `_meta` → body `arguments` → `undefined`.
|
|
167
|
+
*
|
|
168
|
+
* Resource precedence:
|
|
169
|
+
* - `toolGate.resource` if provided, else `requestPath`.
|
|
170
|
+
*
|
|
171
|
+
* Action precedence (3.1.0 — toolGate override added for
|
|
172
|
+
* symmetry with purpose; 4.1.0 — the bare-tool-name fallback for
|
|
173
|
+
* `tools/call` was removed):
|
|
174
|
+
* - `toolGate.action` authoritative → header → body `_meta` → body
|
|
175
|
+
* `arguments` → then: `undefined` for `tools/call` (purpose-only
|
|
176
|
+
* evaluation — tool names are transport tokens, never PDLSS actions),
|
|
177
|
+
* or the JSON-RPC method string for other methods (transport_layer).
|
|
178
|
+
*
|
|
179
|
+
* @param requestPath The HTTP request path (e.g. '/mcp'). Required.
|
|
180
|
+
* @param toolGate Resolved per-tool config from `toolGates`, if present.
|
|
181
|
+
*/
|
|
182
|
+
declare function mcpToPdlss(parsed: ParsedMcpRequest, requestPath: string, headerPurpose?: string, headerAction?: string, toolGate?: {
|
|
183
|
+
purpose?: string;
|
|
184
|
+
action?: string;
|
|
185
|
+
resource?: string;
|
|
186
|
+
}): McpPdlssMapping;
|
|
187
|
+
/**
|
|
188
|
+
* Recommended minimum access level per method type. The MCP middleware uses
|
|
189
|
+
* this to split low-risk handshake / introspection traffic from high-risk
|
|
190
|
+
* tool execution.
|
|
191
|
+
*
|
|
192
|
+
* - `initialize` / `notifications/initialized` → `none` (handshake must work for unregistered probes)
|
|
193
|
+
* - `tools/list` / `prompts/list` / `resources/list` → `none` (introspection is public-surface)
|
|
194
|
+
* - `ping` → `none`
|
|
195
|
+
* - `resources/read` → `read-only`
|
|
196
|
+
* - `tools/call` → `standard` (default — overridable per-tool)
|
|
197
|
+
* - everything else → `standard` (least-privilege fallback)
|
|
198
|
+
*/
|
|
199
|
+
declare function mcpRiskTier(parsed: ParsedMcpRequest): AccessLevel;
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* AstraSync Universal Verification Gateway — MCP middleware
|
|
203
|
+
*
|
|
204
|
+
* Express-shaped middleware tailored to the JSON-RPC body of an MCP
|
|
205
|
+
* (Model Context Protocol) endpoint. Closes the cohort-3 gaps the default
|
|
206
|
+
* `createMiddleware` couldn't:
|
|
207
|
+
*
|
|
208
|
+
* (a) **Body-aware gating**. All MCP traffic targets the same `/mcp` URL.
|
|
209
|
+
* The default route-pattern matcher can't tell `initialize` (low risk)
|
|
210
|
+
* from `tools/call start_checkout` (high risk). This middleware peels
|
|
211
|
+
* the JSON-RPC body and applies a per-method risk tier.
|
|
212
|
+
*
|
|
213
|
+
* (b) **PDLSS mapping**. Derives purpose, action, and resource from
|
|
214
|
+
* `toolGates` config and request context. See `transport/mcp-server.ts`
|
|
215
|
+
* `mcpToPdlss()` for the exact mapping.
|
|
216
|
+
*
|
|
217
|
+
* (c) **Inner-hop dedupe**. Outbound responses set
|
|
218
|
+
* `X-Astra-Verified-Hop` so a downstream REST endpoint that the tool
|
|
219
|
+
* calls can skip a duplicate verify-access. The receiving REST
|
|
220
|
+
* middleware checks `parseVerifiedHop` and skips when valid.
|
|
221
|
+
*
|
|
222
|
+
* (d) **Header-vs-body identity precedence**. Reads ASTRA-id from
|
|
223
|
+
* `X-Astra-Id` first, body second. If both are present and disagree,
|
|
224
|
+
* returns a structured 400 by default (configurable). Pre-fix,
|
|
225
|
+
* integrators had to re-discover this on their own.
|
|
226
|
+
*
|
|
227
|
+
* Usage:
|
|
228
|
+
*
|
|
229
|
+
* ```typescript
|
|
230
|
+
* import express from 'express';
|
|
231
|
+
* import { createMcpMiddleware } from '@astrasyncai/verification-gateway/mcp';
|
|
232
|
+
*
|
|
233
|
+
* const app = express();
|
|
234
|
+
* app.use(express.json());
|
|
235
|
+
*
|
|
236
|
+
* app.post(
|
|
237
|
+
* '/mcp',
|
|
238
|
+
* createMcpMiddleware({
|
|
239
|
+
* apiBaseUrl: 'https://astrasync.ai/api',
|
|
240
|
+
* apiKey: process.env.ASTRASYNC_API_KEY,
|
|
241
|
+
* // Per-tool gates — tools not listed get the default tier from
|
|
242
|
+
* // `mcpRiskTier` (`tools/call` → 'standard'). Use the object form:
|
|
243
|
+
* // gated tools need a PDLSS purpose (and ideally an action).
|
|
244
|
+
* toolGates: {
|
|
245
|
+
* browse_catalog: { minAccessLevel: 'read-only', purpose: 'shopping' },
|
|
246
|
+
* start_checkout: {
|
|
247
|
+
* minAccessLevel: 'standard',
|
|
248
|
+
* purpose: 'shopping',
|
|
249
|
+
* action: 'shopping.purchase',
|
|
250
|
+
* },
|
|
251
|
+
* },
|
|
252
|
+
* }),
|
|
253
|
+
* yourMcpServerHandler,
|
|
254
|
+
* );
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
|
|
258
|
+
declare global {
|
|
259
|
+
namespace Express {
|
|
260
|
+
interface Request {
|
|
261
|
+
mcpRequest?: ParsedMcpRequest;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Extended per-tool gate with optional PDLSS purpose + action + resource
|
|
267
|
+
* overrides.
|
|
268
|
+
*
|
|
269
|
+
* When `purpose` is set, it is authoritative for that tool — the agent's
|
|
270
|
+
* `X-Astra-Purpose` header is ignored. This lets the merchant declare what
|
|
271
|
+
* semantic purpose each tool fulfils rather than trusting agent self-declaration.
|
|
272
|
+
*
|
|
273
|
+
* When `action` is set (symmetric with `purpose`), it is
|
|
274
|
+
* authoritative over `X-Astra-Action` / body declarations, letting the
|
|
275
|
+
* merchant pin a dotted-verb action (e.g. `shopping.search`) for a tool
|
|
276
|
+
* whose callers would otherwise leave the action undeclared (purpose-only
|
|
277
|
+
* evaluation — raw tool names never travel as PDLSS actions).
|
|
278
|
+
*
|
|
279
|
+
* When `resource` is set, it overrides the default (`req.path`) for that
|
|
280
|
+
* tool's verify-access call — e.g. mapping `list_products` to `/api/catalog`.
|
|
281
|
+
*/
|
|
282
|
+
interface ToolGateConfig {
|
|
283
|
+
minAccessLevel: AccessLevel;
|
|
284
|
+
purpose?: string;
|
|
285
|
+
action?: string;
|
|
286
|
+
resource?: string;
|
|
287
|
+
}
|
|
288
|
+
interface McpMiddlewareOptions extends GatewayConfig {
|
|
289
|
+
/**
|
|
290
|
+
* Per-tool gating for `tools/call` invocations. Tools not listed inherit
|
|
291
|
+
* the default tier from `mcpRiskTier` (`tools/call` → `'standard'`).
|
|
292
|
+
*
|
|
293
|
+
* Use the **object form** — it lets the merchant declare the PDLSS
|
|
294
|
+
* `purpose` (required for any gated tool: the backend rejects gated calls
|
|
295
|
+
* with no resolvable purpose) and pin a dotted-verb `action`:
|
|
296
|
+
* ```typescript
|
|
297
|
+
* toolGates: {
|
|
298
|
+
* list_products: { minAccessLevel: 'read-only',
|
|
299
|
+
* purpose: 'shopping',
|
|
300
|
+
* action: 'shopping.search',
|
|
301
|
+
* resource: '/api/catalog' },
|
|
302
|
+
* start_checkout: { minAccessLevel: 'standard',
|
|
303
|
+
* purpose: 'shopping',
|
|
304
|
+
* action: 'shopping.purchase',
|
|
305
|
+
* resource: '/api/checkout/*' },
|
|
306
|
+
* }
|
|
307
|
+
* ```
|
|
308
|
+
*
|
|
309
|
+
* The bare access-level string shorthand (`browse_catalog: 'read-only'`)
|
|
310
|
+
* is a legacy form and a known footgun: it carries no purpose, so the call
|
|
311
|
+
* only succeeds when the AGENT declares one (an `X-Astra-Purpose` header
|
|
312
|
+
* or `params._meta.astrasync.purpose`) — otherwise it fails fast with a
|
|
313
|
+
* `PDLSS_PURPOSE_REQUIRED` 400. It also declares no action, so evaluation
|
|
314
|
+
* is purpose-only (the SDK never sends the raw tool name as the PDLSS
|
|
315
|
+
* action). `createMcpMiddleware` logs a warning at construction for every
|
|
316
|
+
* bare-string gate.
|
|
317
|
+
*
|
|
318
|
+
* When `tools/call` arrives for a tool not declared in `toolGates`, the SDK
|
|
319
|
+
* falls back to a risk-tier default based on the method classification
|
|
320
|
+
* (`mcpRiskTier`). For `tools/call` the fallback is `'standard'`. Best
|
|
321
|
+
* practice: declare every tool you expose explicitly.
|
|
322
|
+
*
|
|
323
|
+
* The action axis for non-tools/call MCP methods (`tools/list`,
|
|
324
|
+
* `resources/list`, `prompts/list`, etc.) is the literal JSON-RPC method
|
|
325
|
+
* name (e.g. `'tools/list'`). Merchants gating MCP traffic by action should
|
|
326
|
+
* declare per-tool gates in `toolGates`, not endpoint-level `allowedActions`
|
|
327
|
+
* — the latter applies to REST-style action values, not MCP method strings.
|
|
328
|
+
*/
|
|
329
|
+
toolGates?: Record<string, AccessLevel | ToolGateConfig>;
|
|
330
|
+
/**
|
|
331
|
+
* Per-method override (e.g. tighten `tools/list` to `'read-only'` if you
|
|
332
|
+
* don't want unregistered probes seeing your tool catalogue). Matches by
|
|
333
|
+
* exact JSON-RPC method string.
|
|
334
|
+
*/
|
|
335
|
+
methodGates?: Record<string, AccessLevel>;
|
|
336
|
+
/**
|
|
337
|
+
* What to do when the agent id supplied in the X-Astra-Id header
|
|
338
|
+
* disagrees with the agent id in the JSON-RPC body
|
|
339
|
+
* (`params._meta.astrasync.agentId` or `params.arguments.agent_id`).
|
|
340
|
+
*
|
|
341
|
+
* - `'reject'` (default) — return 400 `AGENT_ID_MISMATCH`. Safest.
|
|
342
|
+
* - `'prefer-header'` — log + verify against the header value. Keeps
|
|
343
|
+
* bodies that were authored before X-Astra-Id was the canonical
|
|
344
|
+
* identity slot working.
|
|
345
|
+
* - `'prefer-body'` — log + verify against the body value. Useful in
|
|
346
|
+
* reverse-proxy setups that strip auth headers.
|
|
347
|
+
*/
|
|
348
|
+
onAgentIdMismatch?: 'reject' | 'prefer-header' | 'prefer-body';
|
|
349
|
+
/** Skip verification + dedupe entirely. For testing. */
|
|
350
|
+
skip?: boolean;
|
|
351
|
+
/** Custom denied handler. Defaults to a structured JSON-RPC error response. */
|
|
352
|
+
onDenied?: (result: VerificationResult, req: Request, res: Response) => void;
|
|
353
|
+
/**
|
|
354
|
+
* If `true`, trust an inbound `X-Astra-Verified-Hop` header to skip
|
|
355
|
+
* verify-access when it carries a recent marker for the resolved agent.
|
|
356
|
+
*
|
|
357
|
+
* **DEFAULT FLIPPED TO `false` in SDK 2.4.13.** The marker
|
|
358
|
+
* is plaintext semicolon-delimited with no HMAC, so any client that sets
|
|
359
|
+
* the header (with the right format + fresh timestamp + matching ASTRA-id)
|
|
360
|
+
* skipped verify-access entirely. The per-process verify-access result
|
|
361
|
+
* cache already dedupes legitimate repeat calls — this optimization
|
|
362
|
+
* provided no additional savings, only a bypass surface.
|
|
363
|
+
*
|
|
364
|
+
* Set this to `true` ONLY if you control every upstream MCP hop that sets
|
|
365
|
+
* the header AND you trust the network path between hops (mTLS, internal
|
|
366
|
+
* VPC, etc.). For most installs, leave at the safe default.
|
|
367
|
+
*
|
|
368
|
+
* A future SDK release will either remove this option entirely OR add
|
|
369
|
+
* HMAC signing to the marker.
|
|
370
|
+
*/
|
|
371
|
+
trustVerifiedHop?: boolean;
|
|
372
|
+
/** Window for accepting an upstream verified-hop marker. Default 60_000ms. */
|
|
373
|
+
verifiedHopMaxAgeMs?: number;
|
|
374
|
+
/**
|
|
375
|
+
* Automatically record grant/deny decisions for every MCP call. Default
|
|
376
|
+
* `true` — matches the express adapter.
|
|
377
|
+
*/
|
|
378
|
+
recordDecisions?: boolean;
|
|
379
|
+
/** Forward runtime challenge (default `true`). */
|
|
380
|
+
enableRuntimeChallenge?: boolean;
|
|
381
|
+
/**
|
|
382
|
+
* Posture when the MCP middleware itself throws an internal error.
|
|
383
|
+
* Default `'open'` for backward compatibility in SDK 2.4.13. Shadow logs
|
|
384
|
+
* record what WOULD be denied with `failOnError: 'closed'` so merchants
|
|
385
|
+
* can grep correlationId for impact analysis during the observation
|
|
386
|
+
* window. Default flips to `'closed'` in a follow-up release.
|
|
387
|
+
*/
|
|
388
|
+
failOnError?: 'open' | 'closed';
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Create the MCP middleware. Attach AFTER `express.json()` — the body must
|
|
392
|
+
* already be a parsed object.
|
|
393
|
+
*/
|
|
394
|
+
declare function createMcpMiddleware(options: McpMiddlewareOptions): RequestHandler;
|
|
395
|
+
|
|
396
|
+
export { MCP_VERIFIED_HOP_HEADER as M, type ParsedMcpRequest as P, type ToolGateConfig as T, type VerifiedHopMarker as V, MCP_VERIFIED_HOP_MAX_AGE_MS as a, type McpMiddlewareOptions as b, createMcpMiddleware as c, mcpToPdlss as d, parseVerifiedHop as e, isVerifiedHopValidFor as i, mcpRiskTier as m, parseMcpJsonRpc as p, serializeVerifiedHop as s };
|